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