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