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