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