1 //===-- CompactUnwindInfo.cpp ---------------------------------------------===// 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/Debugger.h" 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/Section.h" 13 #include "lldb/Symbol/ObjectFile.h" 14 #include "lldb/Symbol/UnwindPlan.h" 15 #include "lldb/Target/Process.h" 16 #include "lldb/Target/Target.h" 17 #include "lldb/Utility/ArchSpec.h" 18 #include "lldb/Utility/DataBufferHeap.h" 19 #include "lldb/Utility/LLDBLog.h" 20 #include "lldb/Utility/Log.h" 21 #include "lldb/Utility/StreamString.h" 22 23 #include "llvm/Support/MathExtras.h" 24 25 #include <algorithm> 26 #include <memory> 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 namespace lldb_private { 32 33 // Constants from <mach-o/compact_unwind_encoding.h> 34 35 FLAGS_ANONYMOUS_ENUM(){ 36 UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000, 37 UNWIND_PERSONALITY_MASK = 0x30000000, 38 }; 39 40 FLAGS_ANONYMOUS_ENUM(){ 41 UNWIND_X86_MODE_MASK = 0x0F000000, 42 UNWIND_X86_MODE_EBP_FRAME = 0x01000000, 43 UNWIND_X86_MODE_STACK_IMMD = 0x02000000, 44 UNWIND_X86_MODE_STACK_IND = 0x03000000, 45 UNWIND_X86_MODE_DWARF = 0x04000000, 46 47 UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, 48 UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, 49 50 UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, 51 UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, 52 UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 53 UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 54 55 UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, 56 }; 57 58 enum { 59 UNWIND_X86_REG_NONE = 0, 60 UNWIND_X86_REG_EBX = 1, 61 UNWIND_X86_REG_ECX = 2, 62 UNWIND_X86_REG_EDX = 3, 63 UNWIND_X86_REG_EDI = 4, 64 UNWIND_X86_REG_ESI = 5, 65 UNWIND_X86_REG_EBP = 6, 66 }; 67 68 FLAGS_ANONYMOUS_ENUM(){ 69 UNWIND_X86_64_MODE_MASK = 0x0F000000, 70 UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, 71 UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, 72 UNWIND_X86_64_MODE_STACK_IND = 0x03000000, 73 UNWIND_X86_64_MODE_DWARF = 0x04000000, 74 75 UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, 76 UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, 77 78 UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, 79 UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, 80 UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 81 UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 82 83 UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, 84 }; 85 86 enum { 87 UNWIND_X86_64_REG_NONE = 0, 88 UNWIND_X86_64_REG_RBX = 1, 89 UNWIND_X86_64_REG_R12 = 2, 90 UNWIND_X86_64_REG_R13 = 3, 91 UNWIND_X86_64_REG_R14 = 4, 92 UNWIND_X86_64_REG_R15 = 5, 93 UNWIND_X86_64_REG_RBP = 6, 94 }; 95 96 FLAGS_ANONYMOUS_ENUM(){ 97 UNWIND_ARM64_MODE_MASK = 0x0F000000, 98 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, 99 UNWIND_ARM64_MODE_DWARF = 0x03000000, 100 UNWIND_ARM64_MODE_FRAME = 0x04000000, 101 102 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, 103 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, 104 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, 105 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, 106 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, 107 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, 108 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, 109 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, 110 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, 111 112 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, 113 UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, 114 }; 115 116 FLAGS_ANONYMOUS_ENUM(){ 117 UNWIND_ARM_MODE_MASK = 0x0F000000, 118 UNWIND_ARM_MODE_FRAME = 0x01000000, 119 UNWIND_ARM_MODE_FRAME_D = 0x02000000, 120 UNWIND_ARM_MODE_DWARF = 0x04000000, 121 122 UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, 123 124 UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, 125 UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, 126 UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, 127 128 UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, 129 UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, 130 UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, 131 UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, 132 UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, 133 134 UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, 135 136 UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, 137 }; 138 } 139 140 #ifndef UNWIND_SECOND_LEVEL_REGULAR 141 #define UNWIND_SECOND_LEVEL_REGULAR 2 142 #endif 143 144 #ifndef UNWIND_SECOND_LEVEL_COMPRESSED 145 #define UNWIND_SECOND_LEVEL_COMPRESSED 3 146 #endif 147 148 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET 149 #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) 150 #endif 151 152 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX 153 #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) \ 154 ((entry >> 24) & 0xFF) 155 #endif 156 157 #define EXTRACT_BITS(value, mask) \ 158 ((value >> \ 159 llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ 160 (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1)) 161 162 // constructor 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 // destructor 171 172 CompactUnwindInfo::~CompactUnwindInfo() = default; 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 = GetLog(LLDBLog::Unwind); 188 if (log && log->GetVerbose()) { 189 StreamString strm; 190 addr.Dump( 191 &strm, nullptr, 192 Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, 193 Address::DumpStyle::DumpStyleFileAddress, 194 arch.GetAddressByteSize()); 195 LLDB_LOGF(log, "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 arch.GetTriple().getArch() == llvm::Triple::aarch64_32) { 220 return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr); 221 } 222 if (arch.GetTriple().getArch() == llvm::Triple::x86) { 223 return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr); 224 } 225 if (arch.GetTriple().getArch() == llvm::Triple::arm || 226 arch.GetTriple().getArch() == llvm::Triple::thumb) { 227 return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr); 228 } 229 } 230 } 231 return false; 232 } 233 234 bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) { 235 if (m_section_sp.get() == nullptr) 236 return false; 237 238 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 239 return true; 240 241 ScanIndex(process_sp); 242 243 return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; 244 } 245 246 void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) { 247 std::lock_guard<std::mutex> guard(m_mutex); 248 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 249 return; 250 251 // We can't read the index for some reason. 252 if (m_indexes_computed == eLazyBoolNo) { 253 return; 254 } 255 256 Log *log = GetLog(LLDBLog::Unwind); 257 if (log) 258 m_objfile.GetModule()->LogMessage( 259 log, "Reading compact unwind first-level indexes"); 260 261 if (!m_unwindinfo_data_computed) { 262 if (m_section_sp->IsEncrypted()) { 263 // Can't get section contents of a protected/encrypted section until we 264 // have a live process and can read them out of memory. 265 if (process_sp.get() == nullptr) 266 return; 267 m_section_contents_if_encrypted = 268 std::make_shared<DataBufferHeap>(m_section_sp->GetByteSize(), 0); 269 Status error; 270 if (process_sp->ReadMemory( 271 m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()), 272 m_section_contents_if_encrypted->GetBytes(), 273 m_section_sp->GetByteSize(), 274 error) == m_section_sp->GetByteSize() && 275 error.Success()) { 276 m_unwindinfo_data.SetAddressByteSize( 277 process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); 278 m_unwindinfo_data.SetByteOrder( 279 process_sp->GetTarget().GetArchitecture().GetByteOrder()); 280 m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0); 281 } 282 } else { 283 m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data); 284 } 285 if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) 286 return; 287 m_unwindinfo_data_computed = true; 288 } 289 290 if (m_unwindinfo_data.GetByteSize() > 0) { 291 offset_t offset = 0; 292 293 // struct unwind_info_section_header 294 // { 295 // uint32_t version; // UNWIND_SECTION_VERSION 296 // uint32_t commonEncodingsArraySectionOffset; 297 // uint32_t commonEncodingsArrayCount; 298 // uint32_t personalityArraySectionOffset; 299 // uint32_t personalityArrayCount; 300 // uint32_t indexSectionOffset; 301 // uint32_t indexCount; 302 303 m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); 304 m_unwind_header.common_encodings_array_offset = 305 m_unwindinfo_data.GetU32(&offset); 306 m_unwind_header.common_encodings_array_count = 307 m_unwindinfo_data.GetU32(&offset); 308 m_unwind_header.personality_array_offset = 309 m_unwindinfo_data.GetU32(&offset); 310 m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); 311 uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); 312 313 uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); 314 315 if (m_unwind_header.common_encodings_array_offset > 316 m_unwindinfo_data.GetByteSize() || 317 m_unwind_header.personality_array_offset > 318 m_unwindinfo_data.GetByteSize() || 319 indexSectionOffset > m_unwindinfo_data.GetByteSize() || 320 offset > m_unwindinfo_data.GetByteSize()) { 321 Debugger::ReportError( 322 "Invalid offset encountered in compact unwind info, skipping"); 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.SetUnwindPlanForSignalTrap(eLazyBoolNo); 743 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 744 745 unwind_plan.SetLSDAAddress(function_info.lsda_address); 746 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 747 748 UnwindPlan::RowSP row(new UnwindPlan::Row); 749 750 const int wordsize = 8; 751 int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; 752 switch (mode) { 753 case UNWIND_X86_64_MODE_RBP_FRAME: { 754 row->GetCFAValue().SetIsRegisterPlusOffset( 755 translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP), 756 2 * wordsize); 757 row->SetOffset(0); 758 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp, 759 wordsize * -2, true); 760 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 761 wordsize * -1, true); 762 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 763 764 uint32_t saved_registers_offset = 765 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); 766 767 uint32_t saved_registers_locations = 768 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); 769 770 saved_registers_offset += 2; 771 772 for (int i = 0; i < 5; i++) { 773 uint32_t regnum = saved_registers_locations & 0x7; 774 switch (regnum) { 775 case UNWIND_X86_64_REG_NONE: 776 break; 777 case UNWIND_X86_64_REG_RBX: 778 case UNWIND_X86_64_REG_R12: 779 case UNWIND_X86_64_REG_R13: 780 case UNWIND_X86_64_REG_R14: 781 case UNWIND_X86_64_REG_R15: 782 row->SetRegisterLocationToAtCFAPlusOffset( 783 translate_to_eh_frame_regnum_x86_64(regnum), 784 wordsize * -saved_registers_offset, true); 785 break; 786 } 787 saved_registers_offset--; 788 saved_registers_locations >>= 3; 789 } 790 unwind_plan.AppendRow(row); 791 return true; 792 } break; 793 794 case UNWIND_X86_64_MODE_STACK_IND: { 795 // The clang in Xcode 6 is emitting incorrect compact unwind encodings for 796 // this style of unwind. It was fixed in llvm r217020. The clang in Xcode 797 // 7 has this fixed. 798 return false; 799 } break; 800 801 case UNWIND_X86_64_MODE_STACK_IMMD: { 802 uint32_t stack_size = EXTRACT_BITS(function_info.encoding, 803 UNWIND_X86_64_FRAMELESS_STACK_SIZE); 804 uint32_t register_count = EXTRACT_BITS( 805 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); 806 uint32_t permutation = EXTRACT_BITS( 807 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); 808 809 if (mode == UNWIND_X86_64_MODE_STACK_IND && 810 function_info.valid_range_offset_start != 0) { 811 uint32_t stack_adjust = EXTRACT_BITS( 812 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); 813 814 // offset into the function instructions; 0 == beginning of first 815 // instruction 816 uint32_t offset_to_subl_insn = EXTRACT_BITS( 817 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); 818 819 SectionList *sl = m_objfile.GetSectionList(); 820 if (sl) { 821 ProcessSP process_sp = target.GetProcessSP(); 822 if (process_sp) { 823 Address subl_payload_addr(function_info.valid_range_offset_start, sl); 824 subl_payload_addr.Slide(offset_to_subl_insn); 825 Status error; 826 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( 827 subl_payload_addr.GetLoadAddress(&target), 4, 0, error); 828 if (large_stack_size != 0 && error.Success()) { 829 // Got the large stack frame size correctly - use it 830 stack_size = large_stack_size + (stack_adjust * wordsize); 831 } else { 832 return false; 833 } 834 } else { 835 return false; 836 } 837 } else { 838 return false; 839 } 840 } 841 842 int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND 843 ? stack_size 844 : stack_size * wordsize; 845 row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset); 846 847 row->SetOffset(0); 848 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 849 wordsize * -1, true); 850 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 851 852 if (register_count > 0) { 853 854 // We need to include (up to) 6 registers in 10 bits. That would be 18 855 // bits if we just used 3 bits per reg to indicate the order they're 856 // saved on the stack. 857 // 858 // This is done with Lehmer code permutation, e.g. see 859 // http://stackoverflow.com/questions/1506078/fast-permutation-number- 860 // permutation-mapping-algorithms 861 int permunreg[6] = {0, 0, 0, 0, 0, 0}; 862 863 // This decodes the variable-base number in the 10 bits and gives us the 864 // Lehmer code sequence which can then be decoded. 865 866 switch (register_count) { 867 case 6: 868 permunreg[0] = permutation / 120; // 120 == 5! 869 permutation -= (permunreg[0] * 120); 870 permunreg[1] = permutation / 24; // 24 == 4! 871 permutation -= (permunreg[1] * 24); 872 permunreg[2] = permutation / 6; // 6 == 3! 873 permutation -= (permunreg[2] * 6); 874 permunreg[3] = permutation / 2; // 2 == 2! 875 permutation -= (permunreg[3] * 2); 876 permunreg[4] = permutation; // 1 == 1! 877 permunreg[5] = 0; 878 break; 879 case 5: 880 permunreg[0] = permutation / 120; 881 permutation -= (permunreg[0] * 120); 882 permunreg[1] = permutation / 24; 883 permutation -= (permunreg[1] * 24); 884 permunreg[2] = permutation / 6; 885 permutation -= (permunreg[2] * 6); 886 permunreg[3] = permutation / 2; 887 permutation -= (permunreg[3] * 2); 888 permunreg[4] = permutation; 889 break; 890 case 4: 891 permunreg[0] = permutation / 60; 892 permutation -= (permunreg[0] * 60); 893 permunreg[1] = permutation / 12; 894 permutation -= (permunreg[1] * 12); 895 permunreg[2] = permutation / 3; 896 permutation -= (permunreg[2] * 3); 897 permunreg[3] = permutation; 898 break; 899 case 3: 900 permunreg[0] = permutation / 20; 901 permutation -= (permunreg[0] * 20); 902 permunreg[1] = permutation / 4; 903 permutation -= (permunreg[1] * 4); 904 permunreg[2] = permutation; 905 break; 906 case 2: 907 permunreg[0] = permutation / 5; 908 permutation -= (permunreg[0] * 5); 909 permunreg[1] = permutation; 910 break; 911 case 1: 912 permunreg[0] = permutation; 913 break; 914 } 915 916 // Decode the Lehmer code for this permutation of the registers v. 917 // http://en.wikipedia.org/wiki/Lehmer_code 918 919 int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 920 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 921 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE}; 922 bool used[7] = {false, false, false, false, false, false, false}; 923 for (uint32_t i = 0; i < register_count; i++) { 924 int renum = 0; 925 for (int j = 1; j < 7; j++) { 926 if (!used[j]) { 927 if (renum == permunreg[i]) { 928 registers[i] = j; 929 used[j] = true; 930 break; 931 } 932 renum++; 933 } 934 } 935 } 936 937 uint32_t saved_registers_offset = 1; 938 saved_registers_offset++; 939 940 for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { 941 switch (registers[i]) { 942 case UNWIND_X86_64_REG_NONE: 943 break; 944 case UNWIND_X86_64_REG_RBX: 945 case UNWIND_X86_64_REG_R12: 946 case UNWIND_X86_64_REG_R13: 947 case UNWIND_X86_64_REG_R14: 948 case UNWIND_X86_64_REG_R15: 949 case UNWIND_X86_64_REG_RBP: 950 row->SetRegisterLocationToAtCFAPlusOffset( 951 translate_to_eh_frame_regnum_x86_64(registers[i]), 952 wordsize * -saved_registers_offset, true); 953 saved_registers_offset++; 954 break; 955 } 956 } 957 } 958 unwind_plan.AppendRow(row); 959 return true; 960 } break; 961 962 case UNWIND_X86_64_MODE_DWARF: { 963 return false; 964 } break; 965 966 case 0: { 967 return false; 968 } break; 969 } 970 return false; 971 } 972 973 enum i386_eh_regnum { 974 eax = 0, 975 ecx = 1, 976 edx = 2, 977 ebx = 3, 978 ebp = 4, 979 esp = 5, 980 esi = 6, 981 edi = 7, 982 eip = 8 // this is officially the Return Address register number, but close 983 // enough 984 }; 985 986 // Convert the compact_unwind_info.h register numbering scheme to 987 // eRegisterKindEHFrame (eh_frame) register numbering scheme. 988 uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) { 989 switch (unwind_regno) { 990 case UNWIND_X86_REG_EBX: 991 return i386_eh_regnum::ebx; 992 case UNWIND_X86_REG_ECX: 993 return i386_eh_regnum::ecx; 994 case UNWIND_X86_REG_EDX: 995 return i386_eh_regnum::edx; 996 case UNWIND_X86_REG_EDI: 997 return i386_eh_regnum::edi; 998 case UNWIND_X86_REG_ESI: 999 return i386_eh_regnum::esi; 1000 case UNWIND_X86_REG_EBP: 1001 return i386_eh_regnum::ebp; 1002 default: 1003 return LLDB_INVALID_REGNUM; 1004 } 1005 } 1006 1007 bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target, 1008 FunctionInfo &function_info, 1009 UnwindPlan &unwind_plan, 1010 Address pc_or_function_start) { 1011 unwind_plan.SetSourceName("compact unwind info"); 1012 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1013 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1014 unwind_plan.SetUnwindPlanForSignalTrap(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.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1312 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1313 1314 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1315 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1316 1317 UnwindPlan::RowSP row(new UnwindPlan::Row); 1318 1319 const int wordsize = 8; 1320 int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; 1321 1322 if (mode == UNWIND_ARM64_MODE_DWARF) 1323 return false; 1324 1325 if (mode == UNWIND_ARM64_MODE_FRAMELESS) { 1326 row->SetOffset(0); 1327 1328 uint32_t stack_size = 1329 (EXTRACT_BITS(function_info.encoding, 1330 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 1331 16; 1332 1333 // Our previous Call Frame Address is the stack pointer plus the stack size 1334 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size); 1335 1336 // Our previous PC is in the LR 1337 row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, 1338 true); 1339 1340 unwind_plan.AppendRow(row); 1341 return true; 1342 } 1343 1344 // Should not be possible 1345 if (mode != UNWIND_ARM64_MODE_FRAME) 1346 return false; 1347 1348 // mode == UNWIND_ARM64_MODE_FRAME 1349 1350 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize); 1351 row->SetOffset(0); 1352 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2, 1353 true); 1354 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1, 1355 true); 1356 row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true); 1357 1358 int reg_pairs_saved_count = 1; 1359 1360 uint32_t saved_register_bits = function_info.encoding & 0xfff; 1361 1362 if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) { 1363 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1364 cfa_offset -= wordsize; 1365 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset, 1366 true); 1367 cfa_offset -= wordsize; 1368 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset, 1369 true); 1370 reg_pairs_saved_count++; 1371 } 1372 1373 if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) { 1374 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1375 cfa_offset -= wordsize; 1376 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset, 1377 true); 1378 cfa_offset -= wordsize; 1379 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset, 1380 true); 1381 reg_pairs_saved_count++; 1382 } 1383 1384 if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) { 1385 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1386 cfa_offset -= wordsize; 1387 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset, 1388 true); 1389 cfa_offset -= wordsize; 1390 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset, 1391 true); 1392 reg_pairs_saved_count++; 1393 } 1394 1395 if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) { 1396 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1397 cfa_offset -= wordsize; 1398 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset, 1399 true); 1400 cfa_offset -= wordsize; 1401 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset, 1402 true); 1403 reg_pairs_saved_count++; 1404 } 1405 1406 if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) { 1407 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1408 cfa_offset -= wordsize; 1409 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset, 1410 true); 1411 cfa_offset -= wordsize; 1412 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset, 1413 true); 1414 reg_pairs_saved_count++; 1415 } 1416 1417 // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits 1418 // off the stack; 1419 // not sure if we have a good way to represent the 64-bitness of these saves. 1420 1421 if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) { 1422 reg_pairs_saved_count++; 1423 } 1424 if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) { 1425 reg_pairs_saved_count++; 1426 } 1427 if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) { 1428 reg_pairs_saved_count++; 1429 } 1430 if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) { 1431 reg_pairs_saved_count++; 1432 } 1433 1434 unwind_plan.AppendRow(row); 1435 return true; 1436 } 1437 1438 bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target, 1439 FunctionInfo &function_info, 1440 UnwindPlan &unwind_plan, 1441 Address pc_or_function_start) { 1442 unwind_plan.SetSourceName("compact unwind info"); 1443 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1444 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1445 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1446 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1447 1448 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1449 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1450 1451 UnwindPlan::RowSP row(new UnwindPlan::Row); 1452 1453 const int wordsize = 4; 1454 int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; 1455 1456 if (mode == UNWIND_ARM_MODE_DWARF) 1457 return false; 1458 1459 uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding, 1460 UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * 1461 wordsize; 1462 1463 row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7, 1464 (2 * wordsize) + stack_adjust); 1465 row->SetOffset(0); 1466 row->SetRegisterLocationToAtCFAPlusOffset( 1467 arm_r7, (wordsize * -2) - stack_adjust, true); 1468 row->SetRegisterLocationToAtCFAPlusOffset( 1469 arm_pc, (wordsize * -1) - stack_adjust, true); 1470 row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true); 1471 1472 int cfa_offset = -stack_adjust - (2 * wordsize); 1473 1474 uint32_t saved_register_bits = function_info.encoding & 0xff; 1475 1476 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) { 1477 cfa_offset -= wordsize; 1478 row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true); 1479 } 1480 1481 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) { 1482 cfa_offset -= wordsize; 1483 row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true); 1484 } 1485 1486 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) { 1487 cfa_offset -= wordsize; 1488 row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true); 1489 } 1490 1491 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) { 1492 cfa_offset -= wordsize; 1493 row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true); 1494 } 1495 1496 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) { 1497 cfa_offset -= wordsize; 1498 row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true); 1499 } 1500 1501 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) { 1502 cfa_offset -= wordsize; 1503 row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true); 1504 } 1505 1506 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) { 1507 cfa_offset -= wordsize; 1508 row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true); 1509 } 1510 1511 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) { 1512 cfa_offset -= wordsize; 1513 row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true); 1514 } 1515 1516 if (mode == UNWIND_ARM_MODE_FRAME_D) { 1517 uint32_t d_reg_bits = 1518 EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); 1519 switch (d_reg_bits) { 1520 case 0: 1521 // vpush {d8} 1522 cfa_offset -= 8; 1523 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1524 break; 1525 case 1: 1526 // vpush {d10} 1527 // vpush {d8} 1528 cfa_offset -= 8; 1529 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1530 cfa_offset -= 8; 1531 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1532 break; 1533 case 2: 1534 // vpush {d12} 1535 // vpush {d10} 1536 // vpush {d8} 1537 cfa_offset -= 8; 1538 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1539 cfa_offset -= 8; 1540 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1541 cfa_offset -= 8; 1542 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1543 break; 1544 case 3: 1545 // vpush {d14} 1546 // vpush {d12} 1547 // vpush {d10} 1548 // vpush {d8} 1549 cfa_offset -= 8; 1550 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1551 cfa_offset -= 8; 1552 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1553 cfa_offset -= 8; 1554 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1555 cfa_offset -= 8; 1556 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1557 break; 1558 case 4: 1559 // vpush {d14} 1560 // vpush {d12} 1561 // sp = (sp - 24) & (-16); 1562 // vst {d8, d9, d10} 1563 cfa_offset -= 8; 1564 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1565 cfa_offset -= 8; 1566 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1567 1568 // FIXME we don't have a way to represent reg saves at an specific 1569 // alignment short of 1570 // coming up with some DWARF location description. 1571 1572 break; 1573 case 5: 1574 // vpush {d14} 1575 // sp = (sp - 40) & (-16); 1576 // vst {d8, d9, d10, d11} 1577 // vst {d12} 1578 1579 cfa_offset -= 8; 1580 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1581 1582 // FIXME we don't have a way to represent reg saves at an specific 1583 // alignment short of 1584 // coming up with some DWARF location description. 1585 1586 break; 1587 case 6: 1588 // sp = (sp - 56) & (-16); 1589 // vst {d8, d9, d10, d11} 1590 // vst {d12, d13, d14} 1591 1592 // FIXME we don't have a way to represent reg saves at an specific 1593 // alignment short of 1594 // coming up with some DWARF location description. 1595 1596 break; 1597 case 7: 1598 // sp = (sp - 64) & (-16); 1599 // vst {d8, d9, d10, d11} 1600 // vst {d12, d13, d14, d15} 1601 1602 // FIXME we don't have a way to represent reg saves at an specific 1603 // alignment short of 1604 // coming up with some DWARF location description. 1605 1606 break; 1607 } 1608 } 1609 1610 unwind_plan.AppendRow(row); 1611 return true; 1612 } 1613