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