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