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