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