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 LLDB_LOGF(log, "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.SetUnwindPlanForSignalTrap(eLazyBoolNo); 741 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 742 743 unwind_plan.SetLSDAAddress(function_info.lsda_address); 744 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 745 746 UnwindPlan::RowSP row(new UnwindPlan::Row); 747 748 const int wordsize = 8; 749 int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; 750 switch (mode) { 751 case UNWIND_X86_64_MODE_RBP_FRAME: { 752 row->GetCFAValue().SetIsRegisterPlusOffset( 753 translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP), 754 2 * wordsize); 755 row->SetOffset(0); 756 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp, 757 wordsize * -2, true); 758 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 759 wordsize * -1, true); 760 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 761 762 uint32_t saved_registers_offset = 763 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); 764 765 uint32_t saved_registers_locations = 766 EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); 767 768 saved_registers_offset += 2; 769 770 for (int i = 0; i < 5; i++) { 771 uint32_t regnum = saved_registers_locations & 0x7; 772 switch (regnum) { 773 case UNWIND_X86_64_REG_NONE: 774 break; 775 case UNWIND_X86_64_REG_RBX: 776 case UNWIND_X86_64_REG_R12: 777 case UNWIND_X86_64_REG_R13: 778 case UNWIND_X86_64_REG_R14: 779 case UNWIND_X86_64_REG_R15: 780 row->SetRegisterLocationToAtCFAPlusOffset( 781 translate_to_eh_frame_regnum_x86_64(regnum), 782 wordsize * -saved_registers_offset, true); 783 break; 784 } 785 saved_registers_offset--; 786 saved_registers_locations >>= 3; 787 } 788 unwind_plan.AppendRow(row); 789 return true; 790 } break; 791 792 case UNWIND_X86_64_MODE_STACK_IND: { 793 // The clang in Xcode 6 is emitting incorrect compact unwind encodings for 794 // this style of unwind. It was fixed in llvm r217020. The clang in Xcode 795 // 7 has this fixed. 796 return false; 797 } break; 798 799 case UNWIND_X86_64_MODE_STACK_IMMD: { 800 uint32_t stack_size = EXTRACT_BITS(function_info.encoding, 801 UNWIND_X86_64_FRAMELESS_STACK_SIZE); 802 uint32_t register_count = EXTRACT_BITS( 803 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); 804 uint32_t permutation = EXTRACT_BITS( 805 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); 806 807 if (mode == UNWIND_X86_64_MODE_STACK_IND && 808 function_info.valid_range_offset_start != 0) { 809 uint32_t stack_adjust = EXTRACT_BITS( 810 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); 811 812 // offset into the function instructions; 0 == beginning of first 813 // instruction 814 uint32_t offset_to_subl_insn = EXTRACT_BITS( 815 function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); 816 817 SectionList *sl = m_objfile.GetSectionList(); 818 if (sl) { 819 ProcessSP process_sp = target.GetProcessSP(); 820 if (process_sp) { 821 Address subl_payload_addr(function_info.valid_range_offset_start, sl); 822 subl_payload_addr.Slide(offset_to_subl_insn); 823 Status error; 824 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( 825 subl_payload_addr.GetLoadAddress(&target), 4, 0, error); 826 if (large_stack_size != 0 && error.Success()) { 827 // Got the large stack frame size correctly - use it 828 stack_size = large_stack_size + (stack_adjust * wordsize); 829 } else { 830 return false; 831 } 832 } else { 833 return false; 834 } 835 } else { 836 return false; 837 } 838 } 839 840 int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND 841 ? stack_size 842 : stack_size * wordsize; 843 row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset); 844 845 row->SetOffset(0); 846 row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, 847 wordsize * -1, true); 848 row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); 849 850 if (register_count > 0) { 851 852 // We need to include (up to) 6 registers in 10 bits. That would be 18 853 // bits if we just used 3 bits per reg to indicate the order they're 854 // saved on the stack. 855 // 856 // This is done with Lehmer code permutation, e.g. see 857 // http://stackoverflow.com/questions/1506078/fast-permutation-number- 858 // permutation-mapping-algorithms 859 int permunreg[6] = {0, 0, 0, 0, 0, 0}; 860 861 // This decodes the variable-base number in the 10 bits and gives us the 862 // Lehmer code sequence which can then be decoded. 863 864 switch (register_count) { 865 case 6: 866 permunreg[0] = permutation / 120; // 120 == 5! 867 permutation -= (permunreg[0] * 120); 868 permunreg[1] = permutation / 24; // 24 == 4! 869 permutation -= (permunreg[1] * 24); 870 permunreg[2] = permutation / 6; // 6 == 3! 871 permutation -= (permunreg[2] * 6); 872 permunreg[3] = permutation / 2; // 2 == 2! 873 permutation -= (permunreg[3] * 2); 874 permunreg[4] = permutation; // 1 == 1! 875 permunreg[5] = 0; 876 break; 877 case 5: 878 permunreg[0] = permutation / 120; 879 permutation -= (permunreg[0] * 120); 880 permunreg[1] = permutation / 24; 881 permutation -= (permunreg[1] * 24); 882 permunreg[2] = permutation / 6; 883 permutation -= (permunreg[2] * 6); 884 permunreg[3] = permutation / 2; 885 permutation -= (permunreg[3] * 2); 886 permunreg[4] = permutation; 887 break; 888 case 4: 889 permunreg[0] = permutation / 60; 890 permutation -= (permunreg[0] * 60); 891 permunreg[1] = permutation / 12; 892 permutation -= (permunreg[1] * 12); 893 permunreg[2] = permutation / 3; 894 permutation -= (permunreg[2] * 3); 895 permunreg[3] = permutation; 896 break; 897 case 3: 898 permunreg[0] = permutation / 20; 899 permutation -= (permunreg[0] * 20); 900 permunreg[1] = permutation / 4; 901 permutation -= (permunreg[1] * 4); 902 permunreg[2] = permutation; 903 break; 904 case 2: 905 permunreg[0] = permutation / 5; 906 permutation -= (permunreg[0] * 5); 907 permunreg[1] = permutation; 908 break; 909 case 1: 910 permunreg[0] = permutation; 911 break; 912 } 913 914 // Decode the Lehmer code for this permutation of the registers v. 915 // http://en.wikipedia.org/wiki/Lehmer_code 916 917 int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 918 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, 919 UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE}; 920 bool used[7] = {false, false, false, false, false, false, false}; 921 for (uint32_t i = 0; i < register_count; i++) { 922 int renum = 0; 923 for (int j = 1; j < 7; j++) { 924 if (!used[j]) { 925 if (renum == permunreg[i]) { 926 registers[i] = j; 927 used[j] = true; 928 break; 929 } 930 renum++; 931 } 932 } 933 } 934 935 uint32_t saved_registers_offset = 1; 936 saved_registers_offset++; 937 938 for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { 939 switch (registers[i]) { 940 case UNWIND_X86_64_REG_NONE: 941 break; 942 case UNWIND_X86_64_REG_RBX: 943 case UNWIND_X86_64_REG_R12: 944 case UNWIND_X86_64_REG_R13: 945 case UNWIND_X86_64_REG_R14: 946 case UNWIND_X86_64_REG_R15: 947 case UNWIND_X86_64_REG_RBP: 948 row->SetRegisterLocationToAtCFAPlusOffset( 949 translate_to_eh_frame_regnum_x86_64(registers[i]), 950 wordsize * -saved_registers_offset, true); 951 saved_registers_offset++; 952 break; 953 } 954 } 955 } 956 unwind_plan.AppendRow(row); 957 return true; 958 } break; 959 960 case UNWIND_X86_64_MODE_DWARF: { 961 return false; 962 } break; 963 964 case 0: { 965 return false; 966 } break; 967 } 968 return false; 969 } 970 971 enum i386_eh_regnum { 972 eax = 0, 973 ecx = 1, 974 edx = 2, 975 ebx = 3, 976 ebp = 4, 977 esp = 5, 978 esi = 6, 979 edi = 7, 980 eip = 8 // this is officially the Return Address register number, but close 981 // enough 982 }; 983 984 // Convert the compact_unwind_info.h register numbering scheme to 985 // eRegisterKindEHFrame (eh_frame) register numbering scheme. 986 uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) { 987 switch (unwind_regno) { 988 case UNWIND_X86_REG_EBX: 989 return i386_eh_regnum::ebx; 990 case UNWIND_X86_REG_ECX: 991 return i386_eh_regnum::ecx; 992 case UNWIND_X86_REG_EDX: 993 return i386_eh_regnum::edx; 994 case UNWIND_X86_REG_EDI: 995 return i386_eh_regnum::edi; 996 case UNWIND_X86_REG_ESI: 997 return i386_eh_regnum::esi; 998 case UNWIND_X86_REG_EBP: 999 return i386_eh_regnum::ebp; 1000 default: 1001 return LLDB_INVALID_REGNUM; 1002 } 1003 } 1004 1005 bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target, 1006 FunctionInfo &function_info, 1007 UnwindPlan &unwind_plan, 1008 Address pc_or_function_start) { 1009 unwind_plan.SetSourceName("compact unwind info"); 1010 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1011 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1012 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1013 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1014 1015 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1016 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1017 1018 UnwindPlan::RowSP row(new UnwindPlan::Row); 1019 1020 const int wordsize = 4; 1021 int mode = function_info.encoding & UNWIND_X86_MODE_MASK; 1022 switch (mode) { 1023 case UNWIND_X86_MODE_EBP_FRAME: { 1024 row->GetCFAValue().SetIsRegisterPlusOffset( 1025 translate_to_eh_frame_regnum_i386(UNWIND_X86_REG_EBP), 2 * wordsize); 1026 row->SetOffset(0); 1027 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::ebp, 1028 wordsize * -2, true); 1029 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, 1030 wordsize * -1, true); 1031 row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); 1032 1033 uint32_t saved_registers_offset = 1034 EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); 1035 1036 uint32_t saved_registers_locations = 1037 EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); 1038 1039 saved_registers_offset += 2; 1040 1041 for (int i = 0; i < 5; i++) { 1042 uint32_t regnum = saved_registers_locations & 0x7; 1043 switch (regnum) { 1044 case UNWIND_X86_REG_NONE: 1045 break; 1046 case UNWIND_X86_REG_EBX: 1047 case UNWIND_X86_REG_ECX: 1048 case UNWIND_X86_REG_EDX: 1049 case UNWIND_X86_REG_EDI: 1050 case UNWIND_X86_REG_ESI: 1051 row->SetRegisterLocationToAtCFAPlusOffset( 1052 translate_to_eh_frame_regnum_i386(regnum), 1053 wordsize * -saved_registers_offset, true); 1054 break; 1055 } 1056 saved_registers_offset--; 1057 saved_registers_locations >>= 3; 1058 } 1059 unwind_plan.AppendRow(row); 1060 return true; 1061 } break; 1062 1063 case UNWIND_X86_MODE_STACK_IND: 1064 case UNWIND_X86_MODE_STACK_IMMD: { 1065 uint32_t stack_size = 1066 EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1067 uint32_t register_count = EXTRACT_BITS( 1068 function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); 1069 uint32_t permutation = EXTRACT_BITS( 1070 function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); 1071 1072 if (mode == UNWIND_X86_MODE_STACK_IND && 1073 function_info.valid_range_offset_start != 0) { 1074 uint32_t stack_adjust = EXTRACT_BITS(function_info.encoding, 1075 UNWIND_X86_FRAMELESS_STACK_ADJUST); 1076 1077 // offset into the function instructions; 0 == beginning of first 1078 // instruction 1079 uint32_t offset_to_subl_insn = 1080 EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1081 1082 SectionList *sl = m_objfile.GetSectionList(); 1083 if (sl) { 1084 ProcessSP process_sp = target.GetProcessSP(); 1085 if (process_sp) { 1086 Address subl_payload_addr(function_info.valid_range_offset_start, sl); 1087 subl_payload_addr.Slide(offset_to_subl_insn); 1088 Status error; 1089 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( 1090 subl_payload_addr.GetLoadAddress(&target), 4, 0, error); 1091 if (large_stack_size != 0 && error.Success()) { 1092 // Got the large stack frame size correctly - use it 1093 stack_size = large_stack_size + (stack_adjust * wordsize); 1094 } else { 1095 return false; 1096 } 1097 } else { 1098 return false; 1099 } 1100 } else { 1101 return false; 1102 } 1103 } 1104 1105 int32_t offset = 1106 mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize; 1107 row->GetCFAValue().SetIsRegisterPlusOffset(i386_eh_regnum::esp, offset); 1108 row->SetOffset(0); 1109 row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, 1110 wordsize * -1, true); 1111 row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); 1112 1113 if (register_count > 0) { 1114 1115 // We need to include (up to) 6 registers in 10 bits. That would be 18 1116 // bits if we just used 3 bits per reg to indicate the order they're 1117 // saved on the stack. 1118 // 1119 // This is done with Lehmer code permutation, e.g. see 1120 // http://stackoverflow.com/questions/1506078/fast-permutation-number- 1121 // permutation-mapping-algorithms 1122 int permunreg[6] = {0, 0, 0, 0, 0, 0}; 1123 1124 // This decodes the variable-base number in the 10 bits and gives us the 1125 // Lehmer code sequence which can then be decoded. 1126 1127 switch (register_count) { 1128 case 6: 1129 permunreg[0] = permutation / 120; // 120 == 5! 1130 permutation -= (permunreg[0] * 120); 1131 permunreg[1] = permutation / 24; // 24 == 4! 1132 permutation -= (permunreg[1] * 24); 1133 permunreg[2] = permutation / 6; // 6 == 3! 1134 permutation -= (permunreg[2] * 6); 1135 permunreg[3] = permutation / 2; // 2 == 2! 1136 permutation -= (permunreg[3] * 2); 1137 permunreg[4] = permutation; // 1 == 1! 1138 permunreg[5] = 0; 1139 break; 1140 case 5: 1141 permunreg[0] = permutation / 120; 1142 permutation -= (permunreg[0] * 120); 1143 permunreg[1] = permutation / 24; 1144 permutation -= (permunreg[1] * 24); 1145 permunreg[2] = permutation / 6; 1146 permutation -= (permunreg[2] * 6); 1147 permunreg[3] = permutation / 2; 1148 permutation -= (permunreg[3] * 2); 1149 permunreg[4] = permutation; 1150 break; 1151 case 4: 1152 permunreg[0] = permutation / 60; 1153 permutation -= (permunreg[0] * 60); 1154 permunreg[1] = permutation / 12; 1155 permutation -= (permunreg[1] * 12); 1156 permunreg[2] = permutation / 3; 1157 permutation -= (permunreg[2] * 3); 1158 permunreg[3] = permutation; 1159 break; 1160 case 3: 1161 permunreg[0] = permutation / 20; 1162 permutation -= (permunreg[0] * 20); 1163 permunreg[1] = permutation / 4; 1164 permutation -= (permunreg[1] * 4); 1165 permunreg[2] = permutation; 1166 break; 1167 case 2: 1168 permunreg[0] = permutation / 5; 1169 permutation -= (permunreg[0] * 5); 1170 permunreg[1] = permutation; 1171 break; 1172 case 1: 1173 permunreg[0] = permutation; 1174 break; 1175 } 1176 1177 // Decode the Lehmer code for this permutation of the registers v. 1178 // http://en.wikipedia.org/wiki/Lehmer_code 1179 1180 int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, 1181 UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, 1182 UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE}; 1183 bool used[7] = {false, false, false, false, false, false, false}; 1184 for (uint32_t i = 0; i < register_count; i++) { 1185 int renum = 0; 1186 for (int j = 1; j < 7; j++) { 1187 if (!used[j]) { 1188 if (renum == permunreg[i]) { 1189 registers[i] = j; 1190 used[j] = true; 1191 break; 1192 } 1193 renum++; 1194 } 1195 } 1196 } 1197 1198 uint32_t saved_registers_offset = 1; 1199 saved_registers_offset++; 1200 1201 for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { 1202 switch (registers[i]) { 1203 case UNWIND_X86_REG_NONE: 1204 break; 1205 case UNWIND_X86_REG_EBX: 1206 case UNWIND_X86_REG_ECX: 1207 case UNWIND_X86_REG_EDX: 1208 case UNWIND_X86_REG_EDI: 1209 case UNWIND_X86_REG_ESI: 1210 case UNWIND_X86_REG_EBP: 1211 row->SetRegisterLocationToAtCFAPlusOffset( 1212 translate_to_eh_frame_regnum_i386(registers[i]), 1213 wordsize * -saved_registers_offset, true); 1214 saved_registers_offset++; 1215 break; 1216 } 1217 } 1218 } 1219 1220 unwind_plan.AppendRow(row); 1221 return true; 1222 } break; 1223 1224 case UNWIND_X86_MODE_DWARF: { 1225 return false; 1226 } break; 1227 } 1228 return false; 1229 } 1230 1231 // DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" 1232 // doc by ARM 1233 1234 enum arm64_eh_regnum { 1235 x19 = 19, 1236 x20 = 20, 1237 x21 = 21, 1238 x22 = 22, 1239 x23 = 23, 1240 x24 = 24, 1241 x25 = 25, 1242 x26 = 26, 1243 x27 = 27, 1244 x28 = 28, 1245 1246 fp = 29, 1247 ra = 30, 1248 sp = 31, 1249 pc = 32, 1250 1251 // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s 1252 // for the 64-bit fp regs. Normally in DWARF it's context sensitive - so it 1253 // knows it is fetching a 32- or 64-bit quantity from reg v8 to indicate s0 1254 // or d0 - but the unwinder is operating at a lower level and we'd try to 1255 // fetch 128 bits if we were told that v8 were stored on the stack... 1256 v8 = 72, 1257 v9 = 73, 1258 v10 = 74, 1259 v11 = 75, 1260 v12 = 76, 1261 v13 = 77, 1262 v14 = 78, 1263 v15 = 79, 1264 }; 1265 1266 enum arm_eh_regnum { 1267 arm_r0 = 0, 1268 arm_r1 = 1, 1269 arm_r2 = 2, 1270 arm_r3 = 3, 1271 arm_r4 = 4, 1272 arm_r5 = 5, 1273 arm_r6 = 6, 1274 arm_r7 = 7, 1275 arm_r8 = 8, 1276 arm_r9 = 9, 1277 arm_r10 = 10, 1278 arm_r11 = 11, 1279 arm_r12 = 12, 1280 1281 arm_sp = 13, 1282 arm_lr = 14, 1283 arm_pc = 15, 1284 1285 arm_d0 = 256, 1286 arm_d1 = 257, 1287 arm_d2 = 258, 1288 arm_d3 = 259, 1289 arm_d4 = 260, 1290 arm_d5 = 261, 1291 arm_d6 = 262, 1292 arm_d7 = 263, 1293 arm_d8 = 264, 1294 arm_d9 = 265, 1295 arm_d10 = 266, 1296 arm_d11 = 267, 1297 arm_d12 = 268, 1298 arm_d13 = 269, 1299 arm_d14 = 270, 1300 }; 1301 1302 bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target, 1303 FunctionInfo &function_info, 1304 UnwindPlan &unwind_plan, 1305 Address pc_or_function_start) { 1306 unwind_plan.SetSourceName("compact unwind info"); 1307 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1308 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1309 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1310 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1311 1312 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1313 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1314 1315 UnwindPlan::RowSP row(new UnwindPlan::Row); 1316 1317 const int wordsize = 8; 1318 int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; 1319 1320 if (mode == UNWIND_ARM64_MODE_DWARF) 1321 return false; 1322 1323 if (mode == UNWIND_ARM64_MODE_FRAMELESS) { 1324 row->SetOffset(0); 1325 1326 uint32_t stack_size = 1327 (EXTRACT_BITS(function_info.encoding, 1328 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 1329 16; 1330 1331 // Our previous Call Frame Address is the stack pointer plus the stack size 1332 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size); 1333 1334 // Our previous PC is in the LR 1335 row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, 1336 true); 1337 1338 unwind_plan.AppendRow(row); 1339 return true; 1340 } 1341 1342 // Should not be possible 1343 if (mode != UNWIND_ARM64_MODE_FRAME) 1344 return false; 1345 1346 // mode == UNWIND_ARM64_MODE_FRAME 1347 1348 row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize); 1349 row->SetOffset(0); 1350 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2, 1351 true); 1352 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1, 1353 true); 1354 row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true); 1355 1356 int reg_pairs_saved_count = 1; 1357 1358 uint32_t saved_register_bits = function_info.encoding & 0xfff; 1359 1360 if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) { 1361 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1362 cfa_offset -= wordsize; 1363 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset, 1364 true); 1365 cfa_offset -= wordsize; 1366 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset, 1367 true); 1368 reg_pairs_saved_count++; 1369 } 1370 1371 if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) { 1372 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1373 cfa_offset -= wordsize; 1374 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset, 1375 true); 1376 cfa_offset -= wordsize; 1377 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset, 1378 true); 1379 reg_pairs_saved_count++; 1380 } 1381 1382 if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) { 1383 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1384 cfa_offset -= wordsize; 1385 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset, 1386 true); 1387 cfa_offset -= wordsize; 1388 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset, 1389 true); 1390 reg_pairs_saved_count++; 1391 } 1392 1393 if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) { 1394 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1395 cfa_offset -= wordsize; 1396 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset, 1397 true); 1398 cfa_offset -= wordsize; 1399 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset, 1400 true); 1401 reg_pairs_saved_count++; 1402 } 1403 1404 if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) { 1405 int cfa_offset = reg_pairs_saved_count * -2 * wordsize; 1406 cfa_offset -= wordsize; 1407 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset, 1408 true); 1409 cfa_offset -= wordsize; 1410 row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset, 1411 true); 1412 reg_pairs_saved_count++; 1413 } 1414 1415 // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits 1416 // off the stack; 1417 // not sure if we have a good way to represent the 64-bitness of these saves. 1418 1419 if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) { 1420 reg_pairs_saved_count++; 1421 } 1422 if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) { 1423 reg_pairs_saved_count++; 1424 } 1425 if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) { 1426 reg_pairs_saved_count++; 1427 } 1428 if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) { 1429 reg_pairs_saved_count++; 1430 } 1431 1432 unwind_plan.AppendRow(row); 1433 return true; 1434 } 1435 1436 bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target, 1437 FunctionInfo &function_info, 1438 UnwindPlan &unwind_plan, 1439 Address pc_or_function_start) { 1440 unwind_plan.SetSourceName("compact unwind info"); 1441 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); 1442 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); 1443 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 1444 unwind_plan.SetRegisterKind(eRegisterKindEHFrame); 1445 1446 unwind_plan.SetLSDAAddress(function_info.lsda_address); 1447 unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); 1448 1449 UnwindPlan::RowSP row(new UnwindPlan::Row); 1450 1451 const int wordsize = 4; 1452 int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; 1453 1454 if (mode == UNWIND_ARM_MODE_DWARF) 1455 return false; 1456 1457 uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding, 1458 UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * 1459 wordsize; 1460 1461 row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7, 1462 (2 * wordsize) + stack_adjust); 1463 row->SetOffset(0); 1464 row->SetRegisterLocationToAtCFAPlusOffset( 1465 arm_r7, (wordsize * -2) - stack_adjust, true); 1466 row->SetRegisterLocationToAtCFAPlusOffset( 1467 arm_pc, (wordsize * -1) - stack_adjust, true); 1468 row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true); 1469 1470 int cfa_offset = -stack_adjust - (2 * wordsize); 1471 1472 uint32_t saved_register_bits = function_info.encoding & 0xff; 1473 1474 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) { 1475 cfa_offset -= wordsize; 1476 row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true); 1477 } 1478 1479 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) { 1480 cfa_offset -= wordsize; 1481 row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true); 1482 } 1483 1484 if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) { 1485 cfa_offset -= wordsize; 1486 row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true); 1487 } 1488 1489 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) { 1490 cfa_offset -= wordsize; 1491 row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true); 1492 } 1493 1494 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) { 1495 cfa_offset -= wordsize; 1496 row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true); 1497 } 1498 1499 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) { 1500 cfa_offset -= wordsize; 1501 row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true); 1502 } 1503 1504 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) { 1505 cfa_offset -= wordsize; 1506 row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true); 1507 } 1508 1509 if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) { 1510 cfa_offset -= wordsize; 1511 row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true); 1512 } 1513 1514 if (mode == UNWIND_ARM_MODE_FRAME_D) { 1515 uint32_t d_reg_bits = 1516 EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); 1517 switch (d_reg_bits) { 1518 case 0: 1519 // vpush {d8} 1520 cfa_offset -= 8; 1521 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1522 break; 1523 case 1: 1524 // vpush {d10} 1525 // vpush {d8} 1526 cfa_offset -= 8; 1527 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1528 cfa_offset -= 8; 1529 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1530 break; 1531 case 2: 1532 // vpush {d12} 1533 // vpush {d10} 1534 // vpush {d8} 1535 cfa_offset -= 8; 1536 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1537 cfa_offset -= 8; 1538 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1539 cfa_offset -= 8; 1540 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1541 break; 1542 case 3: 1543 // vpush {d14} 1544 // vpush {d12} 1545 // vpush {d10} 1546 // vpush {d8} 1547 cfa_offset -= 8; 1548 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1549 cfa_offset -= 8; 1550 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1551 cfa_offset -= 8; 1552 row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); 1553 cfa_offset -= 8; 1554 row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); 1555 break; 1556 case 4: 1557 // vpush {d14} 1558 // vpush {d12} 1559 // sp = (sp - 24) & (-16); 1560 // vst {d8, d9, d10} 1561 cfa_offset -= 8; 1562 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1563 cfa_offset -= 8; 1564 row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); 1565 1566 // FIXME we don't have a way to represent reg saves at an specific 1567 // alignment short of 1568 // coming up with some DWARF location description. 1569 1570 break; 1571 case 5: 1572 // vpush {d14} 1573 // sp = (sp - 40) & (-16); 1574 // vst {d8, d9, d10, d11} 1575 // vst {d12} 1576 1577 cfa_offset -= 8; 1578 row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); 1579 1580 // FIXME we don't have a way to represent reg saves at an specific 1581 // alignment short of 1582 // coming up with some DWARF location description. 1583 1584 break; 1585 case 6: 1586 // sp = (sp - 56) & (-16); 1587 // vst {d8, d9, d10, d11} 1588 // vst {d12, d13, d14} 1589 1590 // FIXME we don't have a way to represent reg saves at an specific 1591 // alignment short of 1592 // coming up with some DWARF location description. 1593 1594 break; 1595 case 7: 1596 // sp = (sp - 64) & (-16); 1597 // vst {d8, d9, d10, d11} 1598 // vst {d12, d13, d14, d15} 1599 1600 // FIXME we don't have a way to represent reg saves at an specific 1601 // alignment short of 1602 // coming up with some DWARF location description. 1603 1604 break; 1605 } 1606 } 1607 1608 unwind_plan.AppendRow(row); 1609 return true; 1610 } 1611