CompactUnwindInfo.cpp revision 341825
1//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Symbol/CompactUnwindInfo.h" 11#include "lldb/Core/Module.h" 12#include "lldb/Core/Section.h" 13#include "lldb/Symbol/ObjectFile.h" 14#include "lldb/Symbol/UnwindPlan.h" 15#include "lldb/Target/Process.h" 16#include "lldb/Target/Target.h" 17#include "lldb/Utility/ArchSpec.h" 18#include "lldb/Utility/DataBufferHeap.h" 19#include "lldb/Utility/Log.h" 20#include "lldb/Utility/StreamString.h" 21#include <algorithm> 22 23#include "llvm/Support/MathExtras.h" 24 25using namespace lldb; 26using namespace lldb_private; 27 28namespace lldb_private { 29 30// Constants from <mach-o/compact_unwind_encoding.h> 31 32FLAGS_ANONYMOUS_ENUM(){ 33 UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000, 34 UNWIND_PERSONALITY_MASK = 0x30000000, 35}; 36 37FLAGS_ANONYMOUS_ENUM(){ 38 UNWIND_X86_MODE_MASK = 0x0F000000, 39 UNWIND_X86_MODE_EBP_FRAME = 0x01000000, 40 UNWIND_X86_MODE_STACK_IMMD = 0x02000000, 41 UNWIND_X86_MODE_STACK_IND = 0x03000000, 42 UNWIND_X86_MODE_DWARF = 0x04000000, 43 44 UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, 45 UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, 46 47 UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, 48 UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, 49 UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 50 UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 51 52 UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, 53}; 54 55enum { 56 UNWIND_X86_REG_NONE = 0, 57 UNWIND_X86_REG_EBX = 1, 58 UNWIND_X86_REG_ECX = 2, 59 UNWIND_X86_REG_EDX = 3, 60 UNWIND_X86_REG_EDI = 4, 61 UNWIND_X86_REG_ESI = 5, 62 UNWIND_X86_REG_EBP = 6, 63}; 64 65FLAGS_ANONYMOUS_ENUM(){ 66 UNWIND_X86_64_MODE_MASK = 0x0F000000, 67 UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, 68 UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, 69 UNWIND_X86_64_MODE_STACK_IND = 0x03000000, 70 UNWIND_X86_64_MODE_DWARF = 0x04000000, 71 72 UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, 73 UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, 74 75 UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, 76 UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, 77 UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 78 UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 79 80 UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, 81}; 82 83enum { 84 UNWIND_X86_64_REG_NONE = 0, 85 UNWIND_X86_64_REG_RBX = 1, 86 UNWIND_X86_64_REG_R12 = 2, 87 UNWIND_X86_64_REG_R13 = 3, 88 UNWIND_X86_64_REG_R14 = 4, 89 UNWIND_X86_64_REG_R15 = 5, 90 UNWIND_X86_64_REG_RBP = 6, 91}; 92 93FLAGS_ANONYMOUS_ENUM(){ 94 UNWIND_ARM64_MODE_MASK = 0x0F000000, 95 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, 96 UNWIND_ARM64_MODE_DWARF = 0x03000000, 97 UNWIND_ARM64_MODE_FRAME = 0x04000000, 98 99 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, 100 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, 101 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, 102 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, 103 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, 104 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, 105 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, 106 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, 107 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, 108 109 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, 110 UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, 111}; 112 113FLAGS_ANONYMOUS_ENUM(){ 114 UNWIND_ARM_MODE_MASK = 0x0F000000, 115 UNWIND_ARM_MODE_FRAME = 0x01000000, 116 UNWIND_ARM_MODE_FRAME_D = 0x02000000, 117 UNWIND_ARM_MODE_DWARF = 0x04000000, 118 119 UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, 120 121 UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, 122 UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, 123 UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, 124 125 UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, 126 UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, 127 UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, 128 UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, 129 UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, 130 131 UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, 132 133 UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, 134}; 135} 136 137#ifndef UNWIND_SECOND_LEVEL_REGULAR 138#define UNWIND_SECOND_LEVEL_REGULAR 2 139#endif 140 141#ifndef UNWIND_SECOND_LEVEL_COMPRESSED 142#define UNWIND_SECOND_LEVEL_COMPRESSED 3 143#endif 144 145#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET 146#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) 147#endif 148 149#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX 150#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) \ 151 ((entry >> 24) & 0xFF) 152#endif 153 154#define EXTRACT_BITS(value, mask) \ 155 ((value >> \ 156 llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ 157 (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1)) 158 159//---------------------- 160// constructor 161//---------------------- 162 163CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP §ion_sp) 164 : m_objfile(objfile), m_section_sp(section_sp), 165 m_section_contents_if_encrypted(), m_mutex(), m_indexes(), 166 m_indexes_computed(eLazyBoolCalculate), m_unwindinfo_data(), 167 m_unwindinfo_data_computed(false), m_unwind_header() {} 168 169//---------------------- 170// destructor 171//---------------------- 172 173CompactUnwindInfo::~CompactUnwindInfo() {} 174 175bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr, 176 UnwindPlan &unwind_plan) { 177 if (!IsValid(target.GetProcessSP())) { 178 return false; 179 } 180 FunctionInfo function_info; 181 if (GetCompactUnwindInfoForFunction(target, addr, function_info)) { 182 // shortcut return for functions that have no compact unwind 183 if (function_info.encoding == 0) 184 return false; 185 186 ArchSpec arch; 187 if (m_objfile.GetArchitecture(arch)) { 188 189 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 190 if (log && log->GetVerbose()) { 191 StreamString strm; 192 addr.Dump( 193 &strm, NULL, 194 Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, 195 Address::DumpStyle::DumpStyleFileAddress, 196 arch.GetAddressByteSize()); 197 log->Printf("Got compact unwind encoding 0x%x for function %s", 198 function_info.encoding, strm.GetData()); 199 } 200 201 if (function_info.valid_range_offset_start != 0 && 202 function_info.valid_range_offset_end != 0) { 203 SectionList *sl = m_objfile.GetSectionList(); 204 if (sl) { 205 addr_t func_range_start_file_addr = 206 function_info.valid_range_offset_start + 207 m_objfile.GetHeaderAddress().GetFileAddress(); 208 AddressRange func_range(func_range_start_file_addr, 209 function_info.valid_range_offset_end - 210 function_info.valid_range_offset_start, 211 sl); 212 unwind_plan.SetPlanValidAddressRange(func_range); 213 } 214 } 215 216 if (arch.GetTriple().getArch() == llvm::Triple::x86_64) { 217 return CreateUnwindPlan_x86_64(target, function_info, unwind_plan, 218 addr); 219 } 220 if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { 221 return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr); 222 } 223 if (arch.GetTriple().getArch() == llvm::Triple::x86) { 224 return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr); 225 } 226 if (arch.GetTriple().getArch() == llvm::Triple::arm || 227 arch.GetTriple().getArch() == llvm::Triple::thumb) { 228 return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr); 229 } 230 } 231 } 232 return false; 233} 234 235bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) { 236 if (m_section_sp.get() == nullptr) 237 return false; 238 239 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 240 return true; 241 242 ScanIndex(process_sp); 243 244 return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; 245} 246 247void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) { 248 std::lock_guard<std::mutex> guard(m_mutex); 249 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 250 return; 251 252 // We can't read the index for some reason. 253 if (m_indexes_computed == eLazyBoolNo) { 254 return; 255 } 256 257 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); 258 if (log) 259 m_objfile.GetModule()->LogMessage( 260 log, "Reading compact unwind first-level indexes"); 261 262 if (m_unwindinfo_data_computed == false) { 263 if (m_section_sp->IsEncrypted()) { 264 // Can't get section contents of a protected/encrypted section until we 265 // have a live process and can read them out of memory. 266 if (process_sp.get() == nullptr) 267 return; 268 m_section_contents_if_encrypted.reset( 269 new DataBufferHeap(m_section_sp->GetByteSize(), 0)); 270 Status error; 271 if (process_sp->ReadMemory( 272 m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()), 273 m_section_contents_if_encrypted->GetBytes(), 274 m_section_sp->GetByteSize(), 275 error) == m_section_sp->GetByteSize() && 276 error.Success()) { 277 m_unwindinfo_data.SetAddressByteSize( 278 process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); 279 m_unwindinfo_data.SetByteOrder( 280 process_sp->GetTarget().GetArchitecture().GetByteOrder()); 281 m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0); 282 } 283 } else { 284 m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data); 285 } 286 if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) 287 return; 288 m_unwindinfo_data_computed = true; 289 } 290 291 if (m_unwindinfo_data.GetByteSize() > 0) { 292 offset_t offset = 0; 293 294 // struct unwind_info_section_header 295 // { 296 // uint32_t version; // UNWIND_SECTION_VERSION 297 // uint32_t commonEncodingsArraySectionOffset; 298 // uint32_t commonEncodingsArrayCount; 299 // uint32_t personalityArraySectionOffset; 300 // uint32_t personalityArrayCount; 301 // uint32_t indexSectionOffset; 302 // uint32_t indexCount; 303 304 m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); 305 m_unwind_header.common_encodings_array_offset = 306 m_unwindinfo_data.GetU32(&offset); 307 m_unwind_header.common_encodings_array_count = 308 m_unwindinfo_data.GetU32(&offset); 309 m_unwind_header.personality_array_offset = 310 m_unwindinfo_data.GetU32(&offset); 311 m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); 312 uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); 313 314 uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); 315 316 if (m_unwind_header.common_encodings_array_offset > 317 m_unwindinfo_data.GetByteSize() || 318 m_unwind_header.personality_array_offset > 319 m_unwindinfo_data.GetByteSize() || 320 indexSectionOffset > m_unwindinfo_data.GetByteSize() || 321 offset > m_unwindinfo_data.GetByteSize()) { 322 Host::SystemLog(Host::eSystemLogError, "error: Invalid offset " 323 "encountered in compact unwind " 324 "info, skipping\n"); 325 // don't trust anything from this compact_unwind section if it looks 326 // blatantly invalid data in the header. 327 m_indexes_computed = eLazyBoolNo; 328 return; 329 } 330 331 // Parse the basic information from the indexes We wait to scan the second 332 // level page info until it's needed 333 334 // struct unwind_info_section_header_index_entry { 335 // uint32_t functionOffset; 336 // uint32_t secondLevelPagesSectionOffset; 337 // uint32_t lsdaIndexArraySectionOffset; 338 // }; 339 340 bool clear_address_zeroth_bit = false; 341 ArchSpec arch; 342 if (m_objfile.GetArchitecture(arch)) { 343 if (arch.GetTriple().getArch() == llvm::Triple::arm || 344 arch.GetTriple().getArch() == llvm::Triple::thumb) 345 clear_address_zeroth_bit = true; 346 } 347 348 offset = indexSectionOffset; 349 for (uint32_t idx = 0; idx < indexCount; idx++) { 350 uint32_t function_offset = 351 m_unwindinfo_data.GetU32(&offset); // functionOffset 352 uint32_t second_level_offset = 353 m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset 354 uint32_t lsda_offset = 355 m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset 356 357 if (second_level_offset > m_section_sp->GetByteSize() || 358 lsda_offset > m_section_sp->GetByteSize()) { 359 m_indexes_computed = eLazyBoolNo; 360 } 361 362 if (clear_address_zeroth_bit) 363 function_offset &= ~1ull; 364 365 UnwindIndex this_index; 366 this_index.function_offset = function_offset; 367 this_index.second_level = second_level_offset; 368 this_index.lsda_array_start = lsda_offset; 369 370 if (m_indexes.size() > 0) { 371 m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; 372 } 373 374 if (second_level_offset == 0) { 375 this_index.sentinal_entry = true; 376 } 377 378 m_indexes.push_back(this_index); 379 } 380 m_indexes_computed = eLazyBoolYes; 381 } else { 382 m_indexes_computed = eLazyBoolNo; 383 } 384} 385 386uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset(uint32_t lsda_offset, 387 uint32_t lsda_count, 388 uint32_t function_offset) { 389 // struct unwind_info_section_header_lsda_index_entry { 390 // uint32_t functionOffset; 391 // uint32_t lsdaOffset; 392 // }; 393 394 offset_t first_entry = lsda_offset; 395 uint32_t low = 0; 396 uint32_t high = lsda_count; 397 while (low < high) { 398 uint32_t mid = (low + high) / 2; 399 offset_t offset = first_entry + (mid * 8); 400 uint32_t mid_func_offset = 401 m_unwindinfo_data.GetU32(&offset); // functionOffset 402 uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset 403 if (mid_func_offset == function_offset) { 404 return mid_lsda_offset; 405 } 406 if (mid_func_offset < function_offset) { 407 low = mid + 1; 408 } else { 409 high = mid; 410 } 411 } 412 return 0; 413} 414 415lldb::offset_t CompactUnwindInfo::BinarySearchRegularSecondPage( 416 uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, 417 uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) { 418 // typedef uint32_t compact_unwind_encoding_t; 419 // struct unwind_info_regular_second_level_entry { 420 // uint32_t functionOffset; 421 // compact_unwind_encoding_t encoding; 422 423 offset_t first_entry = entry_page_offset; 424 425 uint32_t low = 0; 426 uint32_t high = entry_count; 427 uint32_t last = high - 1; 428 while (low < high) { 429 uint32_t mid = (low + high) / 2; 430 offset_t offset = first_entry + (mid * 8); 431 uint32_t mid_func_offset = 432 m_unwindinfo_data.GetU32(&offset); // functionOffset 433 uint32_t next_func_offset = 0; 434 if (mid < last) { 435 offset = first_entry + ((mid + 1) * 8); 436 next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset 437 } 438 if (mid_func_offset <= function_offset) { 439 if (mid == last || (next_func_offset > function_offset)) { 440 if (entry_func_start_offset) 441 *entry_func_start_offset = mid_func_offset; 442 if (mid != last && entry_func_end_offset) 443 *entry_func_end_offset = next_func_offset; 444 return first_entry + (mid * 8); 445 } else { 446 low = mid + 1; 447 } 448 } else { 449 high = mid; 450 } 451 } 452 return LLDB_INVALID_OFFSET; 453} 454 455uint32_t CompactUnwindInfo::BinarySearchCompressedSecondPage( 456 uint32_t entry_page_offset, uint32_t entry_count, 457 uint32_t function_offset_to_find, uint32_t function_offset_base, 458 uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) { 459 offset_t first_entry = entry_page_offset; 460 461 uint32_t low = 0; 462 uint32_t high = entry_count; 463 uint32_t last = high - 1; 464 while (low < high) { 465 uint32_t mid = (low + high) / 2; 466 offset_t offset = first_entry + (mid * 4); 467 uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry 468 uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry); 469 mid_func_offset += function_offset_base; 470 uint32_t next_func_offset = 0; 471 if (mid < last) { 472 offset = first_entry + ((mid + 1) * 4); 473 uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry 474 next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(next_entry); 475 next_func_offset += function_offset_base; 476 } 477 if (mid_func_offset <= function_offset_to_find) { 478 if (mid == last || (next_func_offset > function_offset_to_find)) { 479 if (entry_func_start_offset) 480 *entry_func_start_offset = mid_func_offset; 481 if (mid != last && entry_func_end_offset) 482 *entry_func_end_offset = next_func_offset; 483 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry); 484 } else { 485 low = mid + 1; 486 } 487 } else { 488 high = mid; 489 } 490 } 491 492 return UINT32_MAX; 493} 494 495bool CompactUnwindInfo::GetCompactUnwindInfoForFunction( 496 Target &target, Address address, FunctionInfo &unwind_info) { 497 unwind_info.encoding = 0; 498 unwind_info.lsda_address.Clear(); 499 unwind_info.personality_ptr_address.Clear(); 500 501 if (!IsValid(target.GetProcessSP())) 502 return false; 503 504 addr_t text_section_file_address = LLDB_INVALID_ADDRESS; 505 SectionList *sl = m_objfile.GetSectionList(); 506 if (sl) { 507 SectionSP text_sect = sl->FindSectionByType(eSectionTypeCode, true); 508 if (text_sect.get()) { 509 text_section_file_address = text_sect->GetFileAddress(); 510 } 511 } 512 if (text_section_file_address == LLDB_INVALID_ADDRESS) 513 return false; 514 515 addr_t function_offset = 516 address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); 517 518 UnwindIndex key; 519 key.function_offset = function_offset; 520 521 std::vector<UnwindIndex>::const_iterator it; 522 it = std::lower_bound(m_indexes.begin(), m_indexes.end(), key); 523 if (it == m_indexes.end()) { 524 return false; 525 } 526 527 if (it->function_offset != key.function_offset) { 528 if (it != m_indexes.begin()) 529 --it; 530 } 531 532 if (it->sentinal_entry == true) { 533 return false; 534 } 535 536 auto next_it = it + 1; 537 if (next_it != m_indexes.end()) { 538 // initialize the function offset end range to be the start of the next 539 // index offset. If we find an entry which is at the end of the index 540 // table, this will establish the range end. 541 unwind_info.valid_range_offset_end = next_it->function_offset; 542 } 543 544 offset_t second_page_offset = it->second_level; 545 offset_t lsda_array_start = it->lsda_array_start; 546 offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; 547 548 offset_t offset = second_page_offset; 549 uint32_t kind = m_unwindinfo_data.GetU32( 550 &offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED 551 552 if (kind == UNWIND_SECOND_LEVEL_REGULAR) { 553 // struct unwind_info_regular_second_level_page_header { 554 // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR 555 // uint16_t entryPageOffset; 556 // uint16_t entryCount; 557 558 // typedef uint32_t compact_unwind_encoding_t; 559 // struct unwind_info_regular_second_level_entry { 560 // uint32_t functionOffset; 561 // compact_unwind_encoding_t encoding; 562 563 uint16_t entry_page_offset = 564 m_unwindinfo_data.GetU16(&offset); // entryPageOffset 565 uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount 566 567 offset_t entry_offset = BinarySearchRegularSecondPage( 568 second_page_offset + entry_page_offset, entry_count, function_offset, 569 &unwind_info.valid_range_offset_start, 570 &unwind_info.valid_range_offset_end); 571 if (entry_offset == LLDB_INVALID_OFFSET) { 572 return false; 573 } 574 entry_offset += 4; // skip over functionOffset 575 unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding 576 if (unwind_info.encoding & UNWIND_HAS_LSDA) { 577 SectionList *sl = m_objfile.GetSectionList(); 578 if (sl) { 579 uint32_t lsda_offset = GetLSDAForFunctionOffset( 580 lsda_array_start, lsda_array_count, function_offset); 581 addr_t objfile_header_file_address = 582 m_objfile.GetHeaderAddress().GetFileAddress(); 583 unwind_info.lsda_address.ResolveAddressUsingFileSections( 584 objfile_header_file_address + lsda_offset, sl); 585 } 586 } 587 if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) { 588 uint32_t personality_index = 589 EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK); 590 591 if (personality_index > 0) { 592 personality_index--; 593 if (personality_index < m_unwind_header.personality_array_count) { 594 offset_t offset = m_unwind_header.personality_array_offset; 595 offset += 4 * personality_index; 596 SectionList *sl = m_objfile.GetSectionList(); 597 if (sl) { 598 uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); 599 addr_t objfile_header_file_address = 600 m_objfile.GetHeaderAddress().GetFileAddress(); 601 unwind_info.personality_ptr_address.ResolveAddressUsingFileSections( 602 objfile_header_file_address + personality_offset, sl); 603 } 604 } 605 } 606 } 607 return true; 608 } else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) { 609 // struct unwind_info_compressed_second_level_page_header { 610 // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED 611 // uint16_t entryPageOffset; // offset from this 2nd lvl page 612 // idx to array of entries 613 // // (an entry has a function 614 // offset and index into the 615 // encodings) 616 // // NB function offset from the 617 // entry in the compressed page 618 // // must be added to the index's 619 // functionOffset value. 620 // uint16_t entryCount; 621 // uint16_t encodingsPageOffset; // offset from this 2nd lvl page 622 // idx to array of encodings 623 // uint16_t encodingsCount; 624 625 uint16_t entry_page_offset = 626 m_unwindinfo_data.GetU16(&offset); // entryPageOffset 627 uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount 628 uint16_t encodings_page_offset = 629 m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset 630 uint16_t encodings_count = 631 m_unwindinfo_data.GetU16(&offset); // encodingsCount 632 633 uint32_t encoding_index = BinarySearchCompressedSecondPage( 634 second_page_offset + entry_page_offset, entry_count, function_offset, 635 it->function_offset, &unwind_info.valid_range_offset_start, 636 &unwind_info.valid_range_offset_end); 637 if (encoding_index == UINT32_MAX || 638 encoding_index >= 639 encodings_count + m_unwind_header.common_encodings_array_count) { 640 return false; 641 } 642 uint32_t encoding = 0; 643 if (encoding_index < m_unwind_header.common_encodings_array_count) { 644 offset = m_unwind_header.common_encodings_array_offset + 645 (encoding_index * sizeof(uint32_t)); 646 encoding = m_unwindinfo_data.GetU32( 647 &offset); // encoding entry from the commonEncodingsArray 648 } else { 649 uint32_t page_specific_entry_index = 650 encoding_index - m_unwind_header.common_encodings_array_count; 651 offset = second_page_offset + encodings_page_offset + 652 (page_specific_entry_index * sizeof(uint32_t)); 653 encoding = m_unwindinfo_data.GetU32( 654 &offset); // encoding entry from the page-specific encoding array 655 } 656 if (encoding == 0) 657 return false; 658 659 unwind_info.encoding = encoding; 660 if (unwind_info.encoding & UNWIND_HAS_LSDA) { 661 SectionList *sl = m_objfile.GetSectionList(); 662 if (sl) { 663 uint32_t lsda_offset = GetLSDAForFunctionOffset( 664 lsda_array_start, lsda_array_count, function_offset); 665 addr_t objfile_header_file_address = 666 m_objfile.GetHeaderAddress().GetFileAddress(); 667 unwind_info.lsda_address.ResolveAddressUsingFileSections( 668 objfile_header_file_address + lsda_offset, sl); 669 } 670 } 671 if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) { 672 uint32_t personality_index = 673 EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK); 674 675 if (personality_index > 0) { 676 personality_index--; 677 if (personality_index < m_unwind_header.personality_array_count) { 678 offset_t offset = m_unwind_header.personality_array_offset; 679 offset += 4 * personality_index; 680 SectionList *sl = m_objfile.GetSectionList(); 681 if (sl) { 682 uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); 683 addr_t objfile_header_file_address = 684 m_objfile.GetHeaderAddress().GetFileAddress(); 685 unwind_info.personality_ptr_address.ResolveAddressUsingFileSections( 686 objfile_header_file_address + personality_offset, sl); 687 } 688 } 689 } 690 } 691 return true; 692 } 693 return false; 694} 695 696enum x86_64_eh_regnum { 697 rax = 0, 698 rdx = 1, 699 rcx = 2, 700 rbx = 3, 701 rsi = 4, 702 rdi = 5, 703 rbp = 6, 704 rsp = 7, 705 r8 = 8, 706 r9 = 9, 707 r10 = 10, 708 r11 = 11, 709 r12 = 12, 710 r13 = 13, 711 r14 = 14, 712 r15 = 15, 713 rip = 16 // this is officially the Return Address register number, but close 714 // enough 715}; 716 717// Convert the compact_unwind_info.h register numbering scheme to 718// eRegisterKindEHFrame (eh_frame) register numbering scheme. 719uint32_t translate_to_eh_frame_regnum_x86_64(uint32_t unwind_regno) { 720 switch (unwind_regno) { 721 case UNWIND_X86_64_REG_RBX: 722 return x86_64_eh_regnum::rbx; 723 case UNWIND_X86_64_REG_R12: 724 return x86_64_eh_regnum::r12; 725 case UNWIND_X86_64_REG_R13: 726 return x86_64_eh_regnum::r13; 727 case UNWIND_X86_64_REG_R14: 728 return x86_64_eh_regnum::r14; 729 case UNWIND_X86_64_REG_R15: 730 return x86_64_eh_regnum::r15; 731 case UNWIND_X86_64_REG_RBP: 732 return x86_64_eh_regnum::rbp; 733 default: 734 return LLDB_INVALID_REGNUM; 735 } 736} 737 738bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target, 739 FunctionInfo &function_info, 740 UnwindPlan &unwind_plan, 741 Address pc_or_function_start) { 742 unwind_plan.SetSourceName("compact unwind info"); 743 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 744 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 745 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 746 747 unwind_plan.SetLSDAAddress(function_info.lsda_address); 748 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 749 750 UnwindPlan::RowSP row(new UnwindPlan::Row); 751 752 const int wordsize = 8; 753 int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; 754 switch (mode) { 755 case UNWIND_X86_64_MODE_RBP_FRAME: { 756 row->GetCFAValue().SetIsRegisterPlusOffset( 757 translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP), 758 2 * wordsize); 759 row->SetOffset(0); 760 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp, 761 wordsize * -2, true); 762 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 763 wordsize * -1, true); 764 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 765 766 uint32_t saved_registers_offset = 767 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); 768 769 uint32_t saved_registers_locations = 770 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); 771 772 saved_registers_offset += 2; 773 774 for (int i = 0; i < 5; i++) { 775 uint32_t regnum = saved_registers_locations & 0x7; 776 switch (regnum) { 777 case UNWIND_X86_64_REG_NONE: 778 break; 779 case UNWIND_X86_64_REG_RBX: 780 case UNWIND_X86_64_REG_R12: 781 case UNWIND_X86_64_REG_R13: 782 case UNWIND_X86_64_REG_R14: 783 case UNWIND_X86_64_REG_R15: 784 row->SetRegisterLocationToAtCFAPlusOffset( 785 translate_to_eh_frame_regnum_x86_64(regnum), 786 wordsize * -saved_registers_offset, true); 787 break; 788 } 789 saved_registers_offset--; 790 saved_registers_locations >>= 3; 791 } 792 unwind_plan.AppendRow(row); 793 return true; 794 } break; 795 796 case UNWIND_X86_64_MODE_STACK_IND: { 797 // The clang in Xcode 6 is emitting incorrect compact unwind encodings for 798 // this style of unwind. It was fixed in llvm r217020. The clang in Xcode 799 // 7 has this fixed. 800 return false; 801 } break; 802 803 case UNWIND_X86_64_MODE_STACK_IMMD: { 804 uint32_t stack_size = EXTRACT_BITS(function_info.encoding, 805 UNWIND_X86_64_FRAMELESS_STACK_SIZE); 806 uint32_t register_count = EXTRACT_BITS( 807 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); 808 uint32_t permutation = EXTRACT_BITS( 809 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); 810 811 if (mode == UNWIND_X86_64_MODE_STACK_IND && 812 function_info.valid_range_offset_start != 0) { 813 uint32_t stack_adjust = EXTRACT_BITS( 814 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); 815 816 // offset into the function instructions; 0 == beginning of first 817 // instruction 818 uint32_t offset_to_subl_insn = EXTRACT_BITS( 819 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); 820 821 SectionList *sl = m_objfile.GetSectionList(); 822 if (sl) { 823 ProcessSP process_sp = target.GetProcessSP(); 824 if (process_sp) { 825 Address subl_payload_addr(function_info.valid_range_offset_start, sl); 826 subl_payload_addr.Slide(offset_to_subl_insn); 827 Status error; 828 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( 829 subl_payload_addr.GetLoadAddress(&target), 4, 0, error); 830 if (large_stack_size != 0 && error.Success()) { 831 // Got the large stack frame size correctly - use it 832 stack_size = large_stack_size + (stack_adjust * wordsize); 833 } else { 834 return false; 835 } 836 } else { 837 return false; 838 } 839 } else { 840 return false; 841 } 842 } 843 844 int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND 845 ? stack_size 846 : stack_size * wordsize; 847 row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset); 848 849 row->SetOffset(0); 850 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 851 wordsize * -1, true); 852 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 853 854 if (register_count > 0) { 855 856 // We need to include (up to) 6 registers in 10 bits. That would be 18 857 // bits if we just used 3 bits per reg to indicate the order they're 858 // saved on the stack. 859 // 860 // This is done with Lehmer code permutation, e.g. see 861 // http://stackoverflow.com/questions/1506078/fast-permutation-number- 862 // permutation-mapping-algorithms 863 int permunreg[6] = {0, 0, 0, 0, 0, 0}; 864 865 // This decodes the variable-base number in the 10 bits and gives us the 866 // Lehmer code sequence which can then be decoded. 867 868 switch (register_count) { 869 case 6: 870 permunreg[0] = permutation / 120; // 120 == 5! 871 permutation -= (permunreg[0] * 120); 872 permunreg[1] = permutation / 24; // 24 == 4! 873 permutation -= (permunreg[1] * 24); 874 permunreg[2] = permutation / 6; // 6 == 3! 875 permutation -= (permunreg[2] * 6); 876 permunreg[3] = permutation / 2; // 2 == 2! 877 permutation -= (permunreg[3] * 2); 878 permunreg[4] = permutation; // 1 == 1! 879 permunreg[5] = 0; 880 break; 881 case 5: 882 permunreg[0] = permutation / 120; 883 permutation -= (permunreg[0] * 120); 884 permunreg[1] = permutation / 24; 885 permutation -= (permunreg[1] * 24); 886 permunreg[2] = permutation / 6; 887 permutation -= (permunreg[2] * 6); 888 permunreg[3] = permutation / 2; 889 permutation -= (permunreg[3] * 2); 890 permunreg[4] = permutation; 891 break; 892 case 4: 893 permunreg[0] = permutation / 60; 894 permutation -= (permunreg[0] * 60); 895 permunreg[1] = permutation / 12; 896 permutation -= (permunreg[1] * 12); 897 permunreg[2] = permutation / 3; 898 permutation -= (permunreg[2] * 3); 899 permunreg[3] = permutation; 900 break; 901 case 3: 902 permunreg[0] = permutation / 20; 903 permutation -= (permunreg[0] * 20); 904 permunreg[1] = permutation / 4; 905 permutation -= (permunreg[1] * 4); 906 permunreg[2] = permutation; 907 break; 908 case 2: 909 permunreg[0] = permutation / 5; 910 permutation -= (permunreg[0] * 5); 911 permunreg[1] = permutation; 912 break; 913 case 1: 914 permunreg[0] = permutation; 915 break; 916 } 917 918 // Decode the Lehmer code for this permutation of the registers v. 919 // http://en.wikipedia.org/wiki/Lehmer_code 920 921 int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 922 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 923 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE}; 924 bool used[7] = {false, false, false, false, false, false, false}; 925 for (uint32_t i = 0; i < register_count; i++) { 926 int renum = 0; 927 for (int j = 1; j < 7; j++) { 928 if (used[j] == false) { 929 if (renum == permunreg[i]) { 930 registers[i] = j; 931 used[j] = true; 932 break; 933 } 934 renum++; 935 } 936 } 937 } 938 939 uint32_t saved_registers_offset = 1; 940 saved_registers_offset++; 941 942 for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { 943 switch (registers[i]) { 944 case UNWIND_X86_64_REG_NONE: 945 break; 946 case UNWIND_X86_64_REG_RBX: 947 case UNWIND_X86_64_REG_R12: 948 case UNWIND_X86_64_REG_R13: 949 case UNWIND_X86_64_REG_R14: 950 case UNWIND_X86_64_REG_R15: 951 case UNWIND_X86_64_REG_RBP: 952 row->SetRegisterLocationToAtCFAPlusOffset( 953 translate_to_eh_frame_regnum_x86_64(registers[i]), 954 wordsize * -saved_registers_offset, true); 955 saved_registers_offset++; 956 break; 957 } 958 } 959 } 960 unwind_plan.AppendRow(row); 961 return true; 962 } break; 963 964 case UNWIND_X86_64_MODE_DWARF: { 965 return false; 966 } break; 967 968 case 0: { 969 return false; 970 } break; 971 } 972 return false; 973} 974 975enum i386_eh_regnum { 976 eax = 0, 977 ecx = 1, 978 edx = 2, 979 ebx = 3, 980 ebp = 4, 981 esp = 5, 982 esi = 6, 983 edi = 7, 984 eip = 8 // this is officially the Return Address register number, but close 985 // enough 986}; 987 988// Convert the compact_unwind_info.h register numbering scheme to 989// eRegisterKindEHFrame (eh_frame) register numbering scheme. 990uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) { 991 switch (unwind_regno) { 992 case UNWIND_X86_REG_EBX: 993 return i386_eh_regnum::ebx; 994 case UNWIND_X86_REG_ECX: 995 return i386_eh_regnum::ecx; 996 case UNWIND_X86_REG_EDX: 997 return i386_eh_regnum::edx; 998 case UNWIND_X86_REG_EDI: 999 return i386_eh_regnum::edi; 1000 case UNWIND_X86_REG_ESI: 1001 return i386_eh_regnum::esi; 1002 case UNWIND_X86_REG_EBP: 1003 return i386_eh_regnum::ebp; 1004 default: 1005 return LLDB_INVALID_REGNUM; 1006 } 1007} 1008 1009bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target, 1010 FunctionInfo &function_info, 1011 UnwindPlan &unwind_plan, 1012 Address pc_or_function_start) { 1013 unwind_plan.SetSourceName("compact unwind info"); 1014 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1015 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1016 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1017 1018 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1019 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1020 1021 UnwindPlan::RowSP row(new UnwindPlan::Row); 1022 1023 const int wordsize = 4; 1024 int mode = function_info.encoding & UNWIND_X86_MODE_MASK; 1025 switch (mode) { 1026 case UNWIND_X86_MODE_EBP_FRAME: { 1027 row->GetCFAValue().SetIsRegisterPlusOffset( 1028 translate_to_eh_frame_regnum_i386(UNWIND_X86_REG_EBP), 2 * wordsize); 1029 row->SetOffset(0); 1030 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::ebp, 1031 wordsize * -2, true); 1032 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, 1033 wordsize * -1, true); 1034 row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); 1035 1036 uint32_t saved_registers_offset = 1037 EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); 1038 1039 uint32_t saved_registers_locations = 1040 EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); 1041 1042 saved_registers_offset += 2; 1043 1044 for (int i = 0; i < 5; i++) { 1045 uint32_t regnum = saved_registers_locations & 0x7; 1046 switch (regnum) { 1047 case UNWIND_X86_REG_NONE: 1048 break; 1049 case UNWIND_X86_REG_EBX: 1050 case UNWIND_X86_REG_ECX: 1051 case UNWIND_X86_REG_EDX: 1052 case UNWIND_X86_REG_EDI: 1053 case UNWIND_X86_REG_ESI: 1054 row->SetRegisterLocationToAtCFAPlusOffset( 1055 translate_to_eh_frame_regnum_i386(regnum), 1056 wordsize * -saved_registers_offset, true); 1057 break; 1058 } 1059 saved_registers_offset--; 1060 saved_registers_locations >>= 3; 1061 } 1062 unwind_plan.AppendRow(row); 1063 return true; 1064 } break; 1065 1066 case UNWIND_X86_MODE_STACK_IND: 1067 case UNWIND_X86_MODE_STACK_IMMD: { 1068 uint32_t stack_size = 1069 EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1070 uint32_t register_count = EXTRACT_BITS( 1071 function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); 1072 uint32_t permutation = EXTRACT_BITS( 1073 function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); 1074 1075 if (mode == UNWIND_X86_MODE_STACK_IND && 1076 function_info.valid_range_offset_start != 0) { 1077 uint32_t stack_adjust = EXTRACT_BITS(function_info.encoding, 1078 UNWIND_X86_FRAMELESS_STACK_ADJUST); 1079 1080 // offset into the function instructions; 0 == beginning of first 1081 // instruction 1082 uint32_t offset_to_subl_insn = 1083 EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1084 1085 SectionList *sl = m_objfile.GetSectionList(); 1086 if (sl) { 1087 ProcessSP process_sp = target.GetProcessSP(); 1088 if (process_sp) { 1089 Address subl_payload_addr(function_info.valid_range_offset_start, sl); 1090 subl_payload_addr.Slide(offset_to_subl_insn); 1091 Status error; 1092 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( 1093 subl_payload_addr.GetLoadAddress(&target), 4, 0, error); 1094 if (large_stack_size != 0 && error.Success()) { 1095 // Got the large stack frame size correctly - use it 1096 stack_size = large_stack_size + (stack_adjust * wordsize); 1097 } else { 1098 return false; 1099 } 1100 } else { 1101 return false; 1102 } 1103 } else { 1104 return false; 1105 } 1106 } 1107 1108 int32_t offset = 1109 mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize; 1110 row->GetCFAValue().SetIsRegisterPlusOffset(i386_eh_regnum::esp, offset); 1111 row->SetOffset(0); 1112 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, 1113 wordsize * -1, true); 1114 row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); 1115 1116 if (register_count > 0) { 1117 1118 // We need to include (up to) 6 registers in 10 bits. That would be 18 1119 // bits if we just used 3 bits per reg to indicate the order they're 1120 // saved on the stack. 1121 // 1122 // This is done with Lehmer code permutation, e.g. see 1123 // http://stackoverflow.com/questions/1506078/fast-permutation-number- 1124 // permutation-mapping-algorithms 1125 int permunreg[6] = {0, 0, 0, 0, 0, 0}; 1126 1127 // This decodes the variable-base number in the 10 bits and gives us the 1128 // Lehmer code sequence which can then be decoded. 1129 1130 switch (register_count) { 1131 case 6: 1132 permunreg[0] = permutation / 120; // 120 == 5! 1133 permutation -= (permunreg[0] * 120); 1134 permunreg[1] = permutation / 24; // 24 == 4! 1135 permutation -= (permunreg[1] * 24); 1136 permunreg[2] = permutation / 6; // 6 == 3! 1137 permutation -= (permunreg[2] * 6); 1138 permunreg[3] = permutation / 2; // 2 == 2! 1139 permutation -= (permunreg[3] * 2); 1140 permunreg[4] = permutation; // 1 == 1! 1141 permunreg[5] = 0; 1142 break; 1143 case 5: 1144 permunreg[0] = permutation / 120; 1145 permutation -= (permunreg[0] * 120); 1146 permunreg[1] = permutation / 24; 1147 permutation -= (permunreg[1] * 24); 1148 permunreg[2] = permutation / 6; 1149 permutation -= (permunreg[2] * 6); 1150 permunreg[3] = permutation / 2; 1151 permutation -= (permunreg[3] * 2); 1152 permunreg[4] = permutation; 1153 break; 1154 case 4: 1155 permunreg[0] = permutation / 60; 1156 permutation -= (permunreg[0] * 60); 1157 permunreg[1] = permutation / 12; 1158 permutation -= (permunreg[1] * 12); 1159 permunreg[2] = permutation / 3; 1160 permutation -= (permunreg[2] * 3); 1161 permunreg[3] = permutation; 1162 break; 1163 case 3: 1164 permunreg[0] = permutation / 20; 1165 permutation -= (permunreg[0] * 20); 1166 permunreg[1] = permutation / 4; 1167 permutation -= (permunreg[1] * 4); 1168 permunreg[2] = permutation; 1169 break; 1170 case 2: 1171 permunreg[0] = permutation / 5; 1172 permutation -= (permunreg[0] * 5); 1173 permunreg[1] = permutation; 1174 break; 1175 case 1: 1176 permunreg[0] = permutation; 1177 break; 1178 } 1179 1180 // Decode the Lehmer code for this permutation of the registers v. 1181 // http://en.wikipedia.org/wiki/Lehmer_code 1182 1183 int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, 1184 UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, 1185 UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE}; 1186 bool used[7] = {false, false, false, false, false, false, false}; 1187 for (uint32_t i = 0; i < register_count; i++) { 1188 int renum = 0; 1189 for (int j = 1; j < 7; j++) { 1190 if (used[j] == false) { 1191 if (renum == permunreg[i]) { 1192 registers[i] = j; 1193 used[j] = true; 1194 break; 1195 } 1196 renum++; 1197 } 1198 } 1199 } 1200 1201 uint32_t saved_registers_offset = 1; 1202 saved_registers_offset++; 1203 1204 for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { 1205 switch (registers[i]) { 1206 case UNWIND_X86_REG_NONE: 1207 break; 1208 case UNWIND_X86_REG_EBX: 1209 case UNWIND_X86_REG_ECX: 1210 case UNWIND_X86_REG_EDX: 1211 case UNWIND_X86_REG_EDI: 1212 case UNWIND_X86_REG_ESI: 1213 case UNWIND_X86_REG_EBP: 1214 row->SetRegisterLocationToAtCFAPlusOffset( 1215 translate_to_eh_frame_regnum_i386(registers[i]), 1216 wordsize * -saved_registers_offset, true); 1217 saved_registers_offset++; 1218 break; 1219 } 1220 } 1221 } 1222 1223 unwind_plan.AppendRow(row); 1224 return true; 1225 } break; 1226 1227 case UNWIND_X86_MODE_DWARF: { 1228 return false; 1229 } break; 1230 } 1231 return false; 1232} 1233 1234// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" 1235// doc by ARM 1236 1237enum arm64_eh_regnum { 1238 x19 = 19, 1239 x20 = 20, 1240 x21 = 21, 1241 x22 = 22, 1242 x23 = 23, 1243 x24 = 24, 1244 x25 = 25, 1245 x26 = 26, 1246 x27 = 27, 1247 x28 = 28, 1248 1249 fp = 29, 1250 ra = 30, 1251 sp = 31, 1252 pc = 32, 1253 1254 // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s 1255 // for the 64-bit fp regs. Normally in DWARF it's context sensitive - so it 1256 // knows it is fetching a 32- or 64-bit quantity from reg v8 to indicate s0 1257 // or d0 - but the unwinder is operating at a lower level and we'd try to 1258 // fetch 128 bits if we were told that v8 were stored on the stack... 1259 v8 = 72, 1260 v9 = 73, 1261 v10 = 74, 1262 v11 = 75, 1263 v12 = 76, 1264 v13 = 77, 1265 v14 = 78, 1266 v15 = 79, 1267}; 1268 1269enum arm_eh_regnum { 1270 arm_r0 = 0, 1271 arm_r1 = 1, 1272 arm_r2 = 2, 1273 arm_r3 = 3, 1274 arm_r4 = 4, 1275 arm_r5 = 5, 1276 arm_r6 = 6, 1277 arm_r7 = 7, 1278 arm_r8 = 8, 1279 arm_r9 = 9, 1280 arm_r10 = 10, 1281 arm_r11 = 11, 1282 arm_r12 = 12, 1283 1284 arm_sp = 13, 1285 arm_lr = 14, 1286 arm_pc = 15, 1287 1288 arm_d0 = 256, 1289 arm_d1 = 257, 1290 arm_d2 = 258, 1291 arm_d3 = 259, 1292 arm_d4 = 260, 1293 arm_d5 = 261, 1294 arm_d6 = 262, 1295 arm_d7 = 263, 1296 arm_d8 = 264, 1297 arm_d9 = 265, 1298 arm_d10 = 266, 1299 arm_d11 = 267, 1300 arm_d12 = 268, 1301 arm_d13 = 269, 1302 arm_d14 = 270, 1303}; 1304 1305bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target, 1306 FunctionInfo &function_info, 1307 UnwindPlan &unwind_plan, 1308 Address pc_or_function_start) { 1309 unwind_plan.SetSourceName("compact unwind info"); 1310 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1311 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1312 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1313 1314 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1315 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1316 1317 UnwindPlan::RowSP row(new UnwindPlan::Row); 1318 1319 const int wordsize = 8; 1320 int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; 1321 1322 if (mode == UNWIND_ARM64_MODE_DWARF) 1323 return false; 1324 1325 if (mode == UNWIND_ARM64_MODE_FRAMELESS) { 1326 row->SetOffset(0); 1327 1328 uint32_t stack_size = 1329 (EXTRACT_BITS(function_info.encoding, 1330 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 1331 16; 1332 1333 // Our previous Call Frame Address is the stack pointer plus the stack size 1334 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size); 1335 1336 // Our previous PC is in the LR 1337 row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, 1338 true); 1339 1340 unwind_plan.AppendRow(row); 1341 return true; 1342 } 1343 1344 // Should not be possible 1345 if (mode != UNWIND_ARM64_MODE_FRAME) 1346 return false; 1347 1348 // mode == UNWIND_ARM64_MODE_FRAME 1349 1350 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize); 1351 row->SetOffset(0); 1352 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2, 1353 true); 1354 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1, 1355 true); 1356 row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true); 1357 1358 int reg_pairs_saved_count = 1; 1359 1360 uint32_t saved_register_bits = function_info.encoding & 0xfff; 1361 1362 if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) { 1363 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1364 cfa_offset -= wordsize; 1365 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset, 1366 true); 1367 cfa_offset -= wordsize; 1368 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset, 1369 true); 1370 reg_pairs_saved_count++; 1371 } 1372 1373 if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) { 1374 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1375 cfa_offset -= wordsize; 1376 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset, 1377 true); 1378 cfa_offset -= wordsize; 1379 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset, 1380 true); 1381 reg_pairs_saved_count++; 1382 } 1383 1384 if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) { 1385 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1386 cfa_offset -= wordsize; 1387 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset, 1388 true); 1389 cfa_offset -= wordsize; 1390 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset, 1391 true); 1392 reg_pairs_saved_count++; 1393 } 1394 1395 if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) { 1396 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1397 cfa_offset -= wordsize; 1398 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset, 1399 true); 1400 cfa_offset -= wordsize; 1401 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset, 1402 true); 1403 reg_pairs_saved_count++; 1404 } 1405 1406 if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) { 1407 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1408 cfa_offset -= wordsize; 1409 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset, 1410 true); 1411 cfa_offset -= wordsize; 1412 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset, 1413 true); 1414 reg_pairs_saved_count++; 1415 } 1416 1417 // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits 1418 // off the stack; 1419 // not sure if we have a good way to represent the 64-bitness of these saves. 1420 1421 if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) { 1422 reg_pairs_saved_count++; 1423 } 1424 if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) { 1425 reg_pairs_saved_count++; 1426 } 1427 if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) { 1428 reg_pairs_saved_count++; 1429 } 1430 if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) { 1431 reg_pairs_saved_count++; 1432 } 1433 1434 unwind_plan.AppendRow(row); 1435 return true; 1436} 1437 1438bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target, 1439 FunctionInfo &function_info, 1440 UnwindPlan &unwind_plan, 1441 Address pc_or_function_start) { 1442 unwind_plan.SetSourceName("compact unwind info"); 1443 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1444 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1445 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1446 1447 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1448 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1449 1450 UnwindPlan::RowSP row(new UnwindPlan::Row); 1451 1452 const int wordsize = 4; 1453 int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; 1454 1455 if (mode == UNWIND_ARM_MODE_DWARF) 1456 return false; 1457 1458 uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding, 1459 UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * 1460 wordsize; 1461 1462 row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7, 1463 (2 * wordsize) + stack_adjust); 1464 row->SetOffset(0); 1465 row->SetRegisterLocationToAtCFAPlusOffset( 1466 arm_r7, (wordsize * -2) - stack_adjust, true); 1467 row->SetRegisterLocationToAtCFAPlusOffset( 1468 arm_pc, (wordsize * -1) - stack_adjust, true); 1469 row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true); 1470 1471 int cfa_offset = -stack_adjust - (2 * wordsize); 1472 1473 uint32_t saved_register_bits = function_info.encoding & 0xff; 1474 1475 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) { 1476 cfa_offset -= wordsize; 1477 row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true); 1478 } 1479 1480 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) { 1481 cfa_offset -= wordsize; 1482 row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true); 1483 } 1484 1485 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) { 1486 cfa_offset -= wordsize; 1487 row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true); 1488 } 1489 1490 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) { 1491 cfa_offset -= wordsize; 1492 row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true); 1493 } 1494 1495 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) { 1496 cfa_offset -= wordsize; 1497 row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true); 1498 } 1499 1500 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) { 1501 cfa_offset -= wordsize; 1502 row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true); 1503 } 1504 1505 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) { 1506 cfa_offset -= wordsize; 1507 row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true); 1508 } 1509 1510 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) { 1511 cfa_offset -= wordsize; 1512 row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true); 1513 } 1514 1515 if (mode == UNWIND_ARM_MODE_FRAME_D) { 1516 uint32_t d_reg_bits = 1517 EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); 1518 switch (d_reg_bits) { 1519 case 0: 1520 // vpush {d8} 1521 cfa_offset -= 8; 1522 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1523 break; 1524 case 1: 1525 // vpush {d10} 1526 // vpush {d8} 1527 cfa_offset -= 8; 1528 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1529 cfa_offset -= 8; 1530 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1531 break; 1532 case 2: 1533 // vpush {d12} 1534 // vpush {d10} 1535 // vpush {d8} 1536 cfa_offset -= 8; 1537 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1538 cfa_offset -= 8; 1539 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1540 cfa_offset -= 8; 1541 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1542 break; 1543 case 3: 1544 // vpush {d14} 1545 // vpush {d12} 1546 // vpush {d10} 1547 // vpush {d8} 1548 cfa_offset -= 8; 1549 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1550 cfa_offset -= 8; 1551 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1552 cfa_offset -= 8; 1553 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1554 cfa_offset -= 8; 1555 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1556 break; 1557 case 4: 1558 // vpush {d14} 1559 // vpush {d12} 1560 // sp = (sp - 24) & (-16); 1561 // vst {d8, d9, d10} 1562 cfa_offset -= 8; 1563 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1564 cfa_offset -= 8; 1565 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1566 1567 // FIXME we don't have a way to represent reg saves at an specific 1568 // alignment short of 1569 // coming up with some DWARF location description. 1570 1571 break; 1572 case 5: 1573 // vpush {d14} 1574 // sp = (sp - 40) & (-16); 1575 // vst {d8, d9, d10, d11} 1576 // vst {d12} 1577 1578 cfa_offset -= 8; 1579 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1580 1581 // FIXME we don't have a way to represent reg saves at an specific 1582 // alignment short of 1583 // coming up with some DWARF location description. 1584 1585 break; 1586 case 6: 1587 // sp = (sp - 56) & (-16); 1588 // vst {d8, d9, d10, d11} 1589 // vst {d12, d13, d14} 1590 1591 // FIXME we don't have a way to represent reg saves at an specific 1592 // alignment short of 1593 // coming up with some DWARF location description. 1594 1595 break; 1596 case 7: 1597 // sp = (sp - 64) & (-16); 1598 // vst {d8, d9, d10, d11} 1599 // vst {d12, d13, d14, d15} 1600 1601 // FIXME we don't have a way to represent reg saves at an specific 1602 // alignment short of 1603 // coming up with some DWARF location description. 1604 1605 break; 1606 } 1607 } 1608 1609 unwind_plan.AppendRow(row); 1610 return true; 1611} 1612