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