brintos

brintos / llvm-project-archived public Read only

0
0
Text · 54.3 KiB · cdbbeb5 Raw
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 &section_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