brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.2 KiB · b490045 Raw
1032 lines · cpp
1//===-- DWARFCallFrameInfo.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/DWARFCallFrameInfo.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/Module.h"12#include "lldb/Core/Section.h"13#include "lldb/Core/dwarf.h"14#include "lldb/Host/Host.h"15#include "lldb/Symbol/ObjectFile.h"16#include "lldb/Symbol/UnwindPlan.h"17#include "lldb/Target/RegisterContext.h"18#include "lldb/Target/Thread.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/LLDBLog.h"21#include "lldb/Utility/Log.h"22#include "lldb/Utility/Timer.h"23#include "llvm/BinaryFormat/Dwarf.h"24#include <cstdint>25#include <cstring>26#include <list>27#include <optional>28 29using namespace lldb;30using namespace lldb_private;31using namespace llvm::dwarf;32 33// GetDwarfEHPtr34//35// Used for calls when the value type is specified by a DWARF EH Frame pointer36// encoding.37static uint64_t38GetGNUEHPointer(const DataExtractor &DE, lldb::offset_t *offset_ptr,39                uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr,40                addr_t data_addr) //, BSDRelocs *data_relocs) const41{42  if (eh_ptr_enc == DW_EH_PE_omit)43    return ULLONG_MAX; // Value isn't in the buffer...44 45  uint64_t baseAddress = 0;46  uint64_t addressValue = 0;47  const uint32_t addr_size = DE.GetAddressByteSize();48  assert(addr_size == 4 || addr_size == 8);49 50  bool signExtendValue = false;51  // Decode the base part or adjust our offset52  switch (eh_ptr_enc & 0x70) {53  case DW_EH_PE_pcrel:54    signExtendValue = true;55    baseAddress = *offset_ptr;56    if (pc_rel_addr != LLDB_INVALID_ADDRESS)57      baseAddress += pc_rel_addr;58    //      else59    //          Log::GlobalWarning ("PC relative pointer encoding found with60    //          invalid pc relative address.");61    break;62 63  case DW_EH_PE_textrel:64    signExtendValue = true;65    if (text_addr != LLDB_INVALID_ADDRESS)66      baseAddress = text_addr;67    //      else68    //          Log::GlobalWarning ("text relative pointer encoding being69    //          decoded with invalid text section address, setting base address70    //          to zero.");71    break;72 73  case DW_EH_PE_datarel:74    signExtendValue = true;75    if (data_addr != LLDB_INVALID_ADDRESS)76      baseAddress = data_addr;77    //      else78    //          Log::GlobalWarning ("data relative pointer encoding being79    //          decoded with invalid data section address, setting base address80    //          to zero.");81    break;82 83  case DW_EH_PE_funcrel:84    signExtendValue = true;85    break;86 87  case DW_EH_PE_aligned: {88    // SetPointerSize should be called prior to extracting these so the pointer89    // size is cached90    assert(addr_size != 0);91    if (addr_size) {92      // Align to a address size boundary first93      uint32_t alignOffset = *offset_ptr % addr_size;94      if (alignOffset)95        offset_ptr += addr_size - alignOffset;96    }97  } break;98 99  default:100    break;101  }102 103  // Decode the value part104  switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) {105  case DW_EH_PE_absptr: {106    addressValue = DE.GetAddress(offset_ptr);107    //          if (data_relocs)108    //              addressValue = data_relocs->Relocate(*offset_ptr -109    //              addr_size, *this, addressValue);110  } break;111  case DW_EH_PE_uleb128:112    addressValue = DE.GetULEB128(offset_ptr);113    break;114  case DW_EH_PE_udata2:115    addressValue = DE.GetU16(offset_ptr);116    break;117  case DW_EH_PE_udata4:118    addressValue = DE.GetU32(offset_ptr);119    break;120  case DW_EH_PE_udata8:121    addressValue = DE.GetU64(offset_ptr);122    break;123  case DW_EH_PE_sleb128:124    addressValue = DE.GetSLEB128(offset_ptr);125    break;126  case DW_EH_PE_sdata2:127    addressValue = (int16_t)DE.GetU16(offset_ptr);128    break;129  case DW_EH_PE_sdata4:130    addressValue = (int32_t)DE.GetU32(offset_ptr);131    break;132  case DW_EH_PE_sdata8:133    addressValue = (int64_t)DE.GetU64(offset_ptr);134    break;135  default:136    // Unhandled encoding type137    assert(eh_ptr_enc);138    break;139  }140 141  // Since we promote everything to 64 bit, we may need to sign extend142  if (signExtendValue && addr_size < sizeof(baseAddress)) {143    uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);144    if (sign_bit & addressValue) {145      uint64_t mask = ~sign_bit + 1;146      addressValue |= mask;147    }148  }149  return baseAddress + addressValue;150}151 152// Check if the given cie_id value indicates a CIE (Common Information Entry)153// as opposed to an FDE (Frame Description Entry).154static bool IsCIEMarker(uint64_t cie_id, bool is_64bit,155                        DWARFCallFrameInfo::Type type) {156  // Check eh_frame CIE marker157  if (type == DWARFCallFrameInfo::EH)158    return cie_id == 0;159 160  // Check debug_frame CIE marker161  // DWARF64162  if (is_64bit)163    return cie_id == llvm::dwarf::DW64_CIE_ID;164 165  // DWARF32166  return cie_id == llvm::dwarf::DW_CIE_ID;167}168 169DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,170                                       SectionSP &section_sp, Type type)171    : m_objfile(objfile), m_section_sp(section_sp), m_type(type) {}172 173std::unique_ptr<UnwindPlan>174DWARFCallFrameInfo::GetUnwindPlan(const Address &addr) {175  return GetUnwindPlan({AddressRange(addr, 1)}, addr);176}177 178std::unique_ptr<UnwindPlan>179DWARFCallFrameInfo::GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges,180                                  const Address &addr) {181  FDEEntryMap::Entry fde_entry;182 183  // Make sure that the Address we're searching for is the same object file as184  // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.185  ModuleSP module_sp = addr.GetModule();186  if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||187      module_sp->GetObjectFile() != &m_objfile)188    return nullptr;189 190  std::vector<AddressRange> valid_ranges;191 192  auto result = std::make_unique<UnwindPlan>(GetRegisterKind());193  result->SetSourceName(m_type == EH ? "eh_frame CFI" : "DWARF CFI");194  // In theory the debug_frame info should be valid at all call sites195  // ("asynchronous unwind info" as it is sometimes called) but in practice196  // gcc et al all emit call frame info for the prologue and call sites, but197  // not for the epilogue or all the other locations during the function198  // reliably.199  result->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);200  result->SetSourcedFromCompiler(eLazyBoolYes);201  result->SetUnwindPlanForSignalTrap(eLazyBoolNo);202  for (const AddressRange &range : ranges) {203    std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range);204    if (!entry)205      continue;206    std::optional<FDE> fde = ParseFDE(entry->data, addr);207    if (!fde)208      continue;209    int64_t slide =210        fde->range.GetBaseAddress().GetFileAddress() - addr.GetFileAddress();211    valid_ranges.push_back(std::move(fde->range));212    if (fde->for_signal_trap)213      result->SetUnwindPlanForSignalTrap(eLazyBoolYes);214    result->SetReturnAddressRegister(fde->return_addr_reg_num);215    for (UnwindPlan::Row &row : fde->rows) {216      row.SlideOffset(slide);217      result->AppendRow(std::move(row));218    }219  }220  result->SetPlanValidAddressRanges(std::move(valid_ranges));221  if (result->GetRowCount() == 0)222    return nullptr;223  return result;224}225 226bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {227 228  // Make sure that the Address we're searching for is the same object file as229  // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.230  ModuleSP module_sp = addr.GetModule();231  if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||232      module_sp->GetObjectFile() != &m_objfile)233    return false;234 235  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())236    return false;237  GetFDEIndex();238  FDEEntryMap::Entry *fde_entry =239      m_fde_index.FindEntryThatContains(addr.GetFileAddress());240  if (!fde_entry)241    return false;242 243  range = AddressRange(fde_entry->base, fde_entry->size,244                       m_objfile.GetSectionList());245  return true;246}247 248std::optional<DWARFCallFrameInfo::FDEEntryMap::Entry>249DWARFCallFrameInfo::GetFirstFDEEntryInRange(const AddressRange &range) {250  if (!m_section_sp || m_section_sp->IsEncrypted())251    return std::nullopt;252 253  GetFDEIndex();254 255  addr_t start_file_addr = range.GetBaseAddress().GetFileAddress();256  const FDEEntryMap::Entry *fde =257      m_fde_index.FindEntryThatContainsOrFollows(start_file_addr);258  if (fde && fde->DoesIntersect(259                 FDEEntryMap::Range(start_file_addr, range.GetByteSize())))260    return *fde;261 262  return std::nullopt;263}264 265void DWARFCallFrameInfo::GetFunctionAddressAndSizeVector(266    FunctionAddressAndSizeVector &function_info) {267  GetFDEIndex();268  const size_t count = m_fde_index.GetSize();269  function_info.Clear();270  if (count > 0)271    function_info.Reserve(count);272  for (size_t i = 0; i < count; ++i) {273    const FDEEntryMap::Entry *func_offset_data_entry =274        m_fde_index.GetEntryAtIndex(i);275    if (func_offset_data_entry) {276      FunctionAddressAndSizeVector::Entry function_offset_entry(277          func_offset_data_entry->base, func_offset_data_entry->size);278      function_info.Append(function_offset_entry);279    }280  }281}282 283const DWARFCallFrameInfo::CIE *284DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) {285  cie_map_t::iterator pos = m_cie_map.find(cie_offset);286 287  if (pos != m_cie_map.end()) {288    // Parse and cache the CIE289    if (pos->second == nullptr)290      pos->second = ParseCIE(cie_offset);291 292    return pos->second.get();293  }294  return nullptr;295}296 297DWARFCallFrameInfo::CIESP298DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {299  CIESP cie_sp(new CIE(cie_offset));300  lldb::offset_t offset = cie_offset;301  if (!m_cfi_data_initialized)302    GetCFIData();303  uint32_t length = m_cfi_data.GetU32(&offset);304  dw_offset_t cie_id, end_offset;305  bool is_64bit = (length == llvm::dwarf::DW_LENGTH_DWARF64);306  if (is_64bit) {307    length = m_cfi_data.GetU64(&offset);308    cie_id = m_cfi_data.GetU64(&offset);309    end_offset = cie_offset + length + 12;310  } else {311    cie_id = m_cfi_data.GetU32(&offset);312    end_offset = cie_offset + length + 4;313  }314 315  // Check if this is a CIE or FDE based on the CIE ID marker316  if (length > 0 && IsCIEMarker(cie_id, is_64bit, m_type)) {317    size_t i;318    //    cie.offset = cie_offset;319    //    cie.length = length;320    //    cie.cieID = cieID;321    cie_sp->ptr_encoding = DW_EH_PE_absptr; // default322    cie_sp->version = m_cfi_data.GetU8(&offset);323    if (cie_sp->version > CFI_VERSION4) {324      Debugger::ReportError(325          llvm::formatv("CIE parse error: CFI version {0} is not supported",326                        cie_sp->version));327      return nullptr;328    }329 330    for (i = 0; i < CFI_AUG_MAX_SIZE; ++i) {331      cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset);332      if (cie_sp->augmentation[i] == '\0') {333        // Zero out remaining bytes in augmentation string334        for (size_t j = i + 1; j < CFI_AUG_MAX_SIZE; ++j)335          cie_sp->augmentation[j] = '\0';336 337        break;338      }339    }340 341    if (i == CFI_AUG_MAX_SIZE &&342        cie_sp->augmentation[CFI_AUG_MAX_SIZE - 1] != '\0') {343      Debugger::ReportError(llvm::formatv(344          "CIE parse error: CIE augmentation string was too large "345          "for the fixed sized buffer of {0} bytes.",346          CFI_AUG_MAX_SIZE));347      return nullptr;348    }349 350    // m_cfi_data uses address size from target architecture of the process may351    // ignore these fields?352    if (m_type == DWARF && cie_sp->version >= CFI_VERSION4) {353      cie_sp->address_size = m_cfi_data.GetU8(&offset);354      cie_sp->segment_size = m_cfi_data.GetU8(&offset);355    }356 357    cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset);358    cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset);359 360    cie_sp->return_addr_reg_num =361        m_type == DWARF && cie_sp->version >= CFI_VERSION3362            ? static_cast<uint32_t>(m_cfi_data.GetULEB128(&offset))363            : m_cfi_data.GetU8(&offset);364 365    if (cie_sp->augmentation[0]) {366      // Get the length of the eh_frame augmentation data which starts with a367      // ULEB128 length in bytes368      const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);369      const size_t aug_data_end = offset + aug_data_len;370      const size_t aug_str_len = strlen(cie_sp->augmentation);371      // A 'z' may be present as the first character of the string.372      // If present, the Augmentation Data field shall be present. The contents373      // of the Augmentation Data shall be interpreted according to other374      // characters in the Augmentation String.375      if (cie_sp->augmentation[0] == 'z') {376        // Extract the Augmentation Data377        size_t aug_str_idx = 0;378        for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) {379          char aug = cie_sp->augmentation[aug_str_idx];380          switch (aug) {381          case 'L':382            // Indicates the presence of one argument in the Augmentation Data383            // of the CIE, and a corresponding argument in the Augmentation384            // Data of the FDE. The argument in the Augmentation Data of the385            // CIE is 1-byte and represents the pointer encoding used for the386            // argument in the Augmentation Data of the FDE, which is the387            // address of a language-specific data area (LSDA). The size of the388            // LSDA pointer is specified by the pointer encoding used.389            cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset);390            break;391 392          case 'P':393            // Indicates the presence of two arguments in the Augmentation Data394            // of the CIE. The first argument is 1-byte and represents the395            // pointer encoding used for the second argument, which is the396            // address of a personality routine handler. The size of the397            // personality routine pointer is specified by the pointer encoding398            // used.399            //400            // The address of the personality function will be stored at this401            // location.  Pre-execution, it will be all zero's so don't read it402            // until we're trying to do an unwind & the reloc has been403            // resolved.404            {405              uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);406              const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();407              cie_sp->personality_loc = GetGNUEHPointer(408                  m_cfi_data, &offset, arg_ptr_encoding, pc_rel_addr,409                  LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);410            }411            break;412 413          case 'R':414            // A 'R' may be present at any position after the415            // first character of the string. The Augmentation Data shall416            // include a 1 byte argument that represents the pointer encoding417            // for the address pointers used in the FDE. Example: 0x1B ==418            // DW_EH_PE_pcrel | DW_EH_PE_sdata4419            cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);420            break;421          }422        }423      } else if (strcmp(cie_sp->augmentation, "eh") == 0) {424        // If the Augmentation string has the value "eh", then the EH Data425        // field shall be present426      }427 428      // Set the offset to be the end of the augmentation data just in case we429      // didn't understand any of the data.430      offset = (uint32_t)aug_data_end;431    }432 433    if (end_offset > offset) {434      cie_sp->inst_offset = offset;435      cie_sp->inst_length = end_offset - offset;436    }437    while (offset < end_offset) {438      uint8_t inst = m_cfi_data.GetU8(&offset);439      uint8_t primary_opcode = inst & 0xC0;440      uint8_t extended_opcode = inst & 0x3F;441 442      if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode,443                                   cie_sp->data_align, offset,444                                   cie_sp->initial_row))445        break; // Stop if we hit an unrecognized opcode446    }447  }448 449  return cie_sp;450}451 452void DWARFCallFrameInfo::GetCFIData() {453  if (!m_cfi_data_initialized) {454    Log *log = GetLog(LLDBLog::Unwind);455    if (log)456      m_objfile.GetModule()->LogMessage(log, "Reading EH frame info");457    m_objfile.ReadSectionData(m_section_sp.get(), m_cfi_data);458    m_cfi_data_initialized = true;459  }460}461// Scan through the eh_frame or debug_frame section looking for FDEs and noting462// the start/end addresses of the functions and a pointer back to the463// function's FDE for later expansion. Internalize CIEs as we come across them.464 465void DWARFCallFrameInfo::GetFDEIndex() {466  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())467    return;468 469  if (m_fde_index_initialized)470    return;471 472  std::lock_guard<std::mutex> guard(m_fde_index_mutex);473 474  if (m_fde_index_initialized) // if two threads hit the locker475    return;476 477  LLDB_SCOPED_TIMERF("%s", m_objfile.GetFileSpec().GetFilename().AsCString(""));478 479  bool clear_address_zeroth_bit = false;480  if (ArchSpec arch = m_objfile.GetArchitecture()) {481    if (arch.GetTriple().getArch() == llvm::Triple::arm ||482        arch.GetTriple().getArch() == llvm::Triple::thumb)483      clear_address_zeroth_bit = true;484  }485 486  lldb::offset_t offset = 0;487  if (!m_cfi_data_initialized)488    GetCFIData();489  while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) {490    const dw_offset_t current_entry = offset;491    dw_offset_t cie_id, next_entry, cie_offset;492    uint32_t len = m_cfi_data.GetU32(&offset);493    bool is_64bit = (len == llvm::dwarf::DW_LENGTH_DWARF64);494    if (is_64bit) {495      len = m_cfi_data.GetU64(&offset);496      cie_id = m_cfi_data.GetU64(&offset);497      next_entry = current_entry + len + 12;498      cie_offset = current_entry + 12 - cie_id;499    } else {500      cie_id = m_cfi_data.GetU32(&offset);501      next_entry = current_entry + len + 4;502      cie_offset = current_entry + 4 - cie_id;503    }504 505    if (next_entry > m_cfi_data.GetByteSize() + 1) {506      Debugger::ReportError(llvm::formatv("Invalid fde/cie next entry offset "507                                          "of {0:x} found in cie/fde at {1:x}",508                                          next_entry, current_entry));509      // Don't trust anything in this eh_frame section if we find blatantly510      // invalid data.511      m_fde_index.Clear();512      m_fde_index_initialized = true;513      return;514    }515 516    // Check if this is a CIE or FDE based on the CIE ID marker517    if (IsCIEMarker(cie_id, is_64bit, m_type) || len == 0) {518      auto cie_sp = ParseCIE(current_entry);519      if (!cie_sp) {520        // Cannot parse, the reason is already logged521        m_fde_index.Clear();522        m_fde_index_initialized = true;523        return;524      }525 526      m_cie_map[current_entry] = std::move(cie_sp);527      offset = next_entry;528      continue;529    }530 531    if (m_type == DWARF)532      cie_offset = cie_id;533 534    if (cie_offset > m_cfi_data.GetByteSize()) {535      Debugger::ReportError(llvm::formatv("Invalid cie offset of {0:x} "536                                          "found in cie/fde at {1:x}",537                                          cie_offset, current_entry));538      // Don't trust anything in this eh_frame section if we find blatantly539      // invalid data.540      m_fde_index.Clear();541      m_fde_index_initialized = true;542      return;543    }544 545    const CIE *cie = GetCIE(cie_offset);546    if (cie) {547      const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();548      const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;549      const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;550 551      lldb::addr_t addr =552          GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,553                          text_addr, data_addr);554      if (clear_address_zeroth_bit)555        addr &= ~1ull;556 557      lldb::addr_t length = GetGNUEHPointer(558          m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,559          pc_rel_addr, text_addr, data_addr);560      FDEEntryMap::Entry fde(addr, length, current_entry);561      m_fde_index.Append(fde);562    } else {563      Debugger::ReportError(llvm::formatv(564          "unable to find CIE at {0:x} for cie_id = {1:x} for entry at {2:x}.",565          cie_offset, cie_id, current_entry));566    }567    offset = next_entry;568  }569  m_fde_index.Sort();570  m_fde_index_initialized = true;571}572 573std::optional<DWARFCallFrameInfo::FDE>574DWARFCallFrameInfo::ParseFDE(dw_offset_t dwarf_offset,575                             const Address &startaddr) {576  Log *log = GetLog(LLDBLog::Unwind);577  lldb::offset_t offset = dwarf_offset;578  lldb::offset_t current_entry = offset;579 580  if (!m_section_sp || m_section_sp->IsEncrypted())581    return std::nullopt;582 583  if (!m_cfi_data_initialized)584    GetCFIData();585 586  uint32_t length = m_cfi_data.GetU32(&offset);587  dw_offset_t cie_offset;588  bool is_64bit = (length == llvm::dwarf::DW_LENGTH_DWARF64);589  if (is_64bit) {590    length = m_cfi_data.GetU64(&offset);591    cie_offset = m_cfi_data.GetU64(&offset);592  } else {593    cie_offset = m_cfi_data.GetU32(&offset);594  }595 596  // FDE entries with zeroth cie_offset may occur for debug_frame.597  assert(!(m_type == EH && 0 == cie_offset) &&598         cie_offset !=599             (is_64bit ? llvm::dwarf::DW64_CIE_ID : llvm::dwarf::DW_CIE_ID));600 601  // Translate the CIE_id from the eh_frame format, which is relative to the602  // FDE offset, into a __eh_frame section offset603  if (m_type == EH)604    cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;605 606  const CIE *cie = GetCIE(cie_offset);607  assert(cie != nullptr);608 609  const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);610 611  const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();612  const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;613  const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;614  lldb::addr_t range_base =615      GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,616                      text_addr, data_addr);617  lldb::addr_t range_len = GetGNUEHPointer(618      m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,619      pc_rel_addr, text_addr, data_addr);620  AddressRange range(range_base, m_objfile.GetAddressByteSize(),621                     m_objfile.GetSectionList());622  range.SetByteSize(range_len);623 624  // Skip the LSDA, if present.625  if (cie->augmentation[0] == 'z')626    offset += (uint32_t)m_cfi_data.GetULEB128(&offset);627 628  FDE fde;629  fde.for_signal_trap = strchr(cie->augmentation, 'S') != nullptr;630  fde.range = range;631  fde.return_addr_reg_num = cie->return_addr_reg_num;632 633  uint32_t code_align = cie->code_align;634  int32_t data_align = cie->data_align;635 636  UnwindPlan::Row row = cie->initial_row;637  std::vector<UnwindPlan::Row> stack;638 639  UnwindPlan::Row::AbstractRegisterLocation reg_location;640  while (m_cfi_data.ValidOffset(offset) && offset < end_offset) {641    uint8_t inst = m_cfi_data.GetU8(&offset);642    uint8_t primary_opcode = inst & 0xC0;643    uint8_t extended_opcode = inst & 0x3F;644 645    if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, data_align,646                                 offset, row)) {647      if (primary_opcode) {648        switch (primary_opcode) {649        case DW_CFA_advance_loc: // (Row Creation Instruction)650        { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta651          // takes a single argument that represents a constant delta. The652          // required action is to create a new table row with a location value653          // that is computed by taking the current entry's location value and654          // adding (delta * code_align). All other values in the new row are655          // initially identical to the current row.656          fde.rows.push_back(row);657          row.SlideOffset(extended_opcode * code_align);658          break;659        }660 661        case DW_CFA_restore: { // 0xC0 - high 2 bits are 0x3, lower 6 bits are662                               // register663          // takes a single argument that represents a register number. The664          // required action is to change the rule for the indicated register665          // to the rule assigned it by the initial_instructions in the CIE.666          uint32_t reg_num = extended_opcode;667          // We only keep enough register locations around to unwind what is in668          // our thread, and these are organized by the register index in that669          // state, so we need to convert our eh_frame register number from the670          // EH frame info, to a register index671 672          if (fde.rows[0].GetRegisterInfo(reg_num, reg_location))673            row.SetRegisterInfo(reg_num, reg_location);674          else {675            // If the register was not set in the first row, remove the676            // register info to keep the unmodified value from the caller.677            row.RemoveRegisterInfo(reg_num);678          }679          break;680        }681        }682      } else {683        switch (extended_opcode) {684        case DW_CFA_set_loc: // 0x1 (Row Creation Instruction)685        {686          // DW_CFA_set_loc takes a single argument that represents an address.687          // The required action is to create a new table row using the688          // specified address as the location. All other values in the new row689          // are initially identical to the current row. The new location value690          // should always be greater than the current one.691          fde.rows.push_back(row);692          row.SetOffset(m_cfi_data.GetAddress(&offset) -693                        startaddr.GetFileAddress());694          break;695        }696 697        case DW_CFA_advance_loc1: // 0x2 (Row Creation Instruction)698        {699          // takes a single uword argument that represents a constant delta.700          // This instruction is identical to DW_CFA_advance_loc except for the701          // encoding and size of the delta argument.702          fde.rows.push_back(row);703          row.SlideOffset(m_cfi_data.GetU8(&offset) * code_align);704          break;705        }706 707        case DW_CFA_advance_loc2: // 0x3 (Row Creation Instruction)708        {709          // takes a single uword argument that represents a constant delta.710          // This instruction is identical to DW_CFA_advance_loc except for the711          // encoding and size of the delta argument.712          fde.rows.push_back(row);713          row.SlideOffset(m_cfi_data.GetU16(&offset) * code_align);714          break;715        }716 717        case DW_CFA_advance_loc4: // 0x4 (Row Creation Instruction)718        {719          // takes a single uword argument that represents a constant delta.720          // This instruction is identical to DW_CFA_advance_loc except for the721          // encoding and size of the delta argument.722          fde.rows.push_back(row);723          row.SlideOffset(m_cfi_data.GetU32(&offset) * code_align);724          break;725        }726 727        case DW_CFA_restore_extended: // 0x6728        {729          // takes a single unsigned LEB128 argument that represents a register730          // number. This instruction is identical to DW_CFA_restore except for731          // the encoding and size of the register argument.732          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);733          if (fde.rows[0].GetRegisterInfo(reg_num, reg_location))734            row.SetRegisterInfo(reg_num, reg_location);735          break;736        }737 738        case DW_CFA_remember_state: // 0xA739        {740          // These instructions define a stack of information. Encountering the741          // DW_CFA_remember_state instruction means to save the rules for742          // every register on the current row on the stack. Encountering the743          // DW_CFA_restore_state instruction means to pop the set of rules off744          // the stack and place them in the current row. (This operation is745          // useful for compilers that move epilogue code into the body of a746          // function.)747          stack.push_back(row);748          break;749        }750 751        case DW_CFA_restore_state: // 0xB752        {753          // These instructions define a stack of information. Encountering the754          // DW_CFA_remember_state instruction means to save the rules for755          // every register on the current row on the stack. Encountering the756          // DW_CFA_restore_state instruction means to pop the set of rules off757          // the stack and place them in the current row. (This operation is758          // useful for compilers that move epilogue code into the body of a759          // function.)760          if (stack.empty()) {761            LLDB_LOG(log,762                     "DWARFCallFrameInfo::{0}(dwarf_offset: "763                     "{1:x16}, startaddr: [{2:x16}] encountered "764                     "DW_CFA_restore_state but state stack "765                     "is empty. Corrupt unwind info?",766                     __FUNCTION__, dwarf_offset, startaddr.GetFileAddress());767            break;768          }769          int64_t offset = row.GetOffset();770          row = std::move(stack.back());771          stack.pop_back();772          row.SetOffset(offset);773          break;774        }775 776        case DW_CFA_GNU_args_size: // 0x2e777        {778          // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128779          // operand representing an argument size. This instruction specifies780          // the total of the size of the arguments which have been pushed onto781          // the stack.782 783          // TODO: Figure out how we should handle this.784          m_cfi_data.GetULEB128(&offset);785          break;786        }787 788        case DW_CFA_val_offset: { // 0x14789          // takes two unsigned LEB128 operands representing a register number790          // and a factored offset. The required action is to change the rule791          // for the register indicated by the register number to be a792          // val_offset(N) rule where the value of N is factored_offset*793          // data_alignment_factor794          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);795          int32_t op_offset =796              (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;797          reg_location.SetIsCFAPlusOffset(op_offset);798          row.SetRegisterInfo(reg_num, reg_location);799          break;800        }801        case DW_CFA_val_offset_sf: { // 0x15802          // takes two operands: an unsigned LEB128 value representing a803          // register number and a signed LEB128 factored offset. This804          // instruction is identical to DW_CFA_val_offset except that the805          // second operand is signed and factored. The resulting offset is806          // factored_offset* data_alignment_factor.807          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);808          int32_t op_offset =809              (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;810          reg_location.SetIsCFAPlusOffset(op_offset);811          row.SetRegisterInfo(reg_num, reg_location);812          break;813        }814        default:815          break;816        }817      }818    }819  }820  fde.rows.push_back(row);821  return fde;822}823 824bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,825                                                 uint8_t extended_opcode,826                                                 int32_t data_align,827                                                 lldb::offset_t &offset,828                                                 UnwindPlan::Row &row) {829  UnwindPlan::Row::AbstractRegisterLocation reg_location;830 831  if (primary_opcode) {832    switch (primary_opcode) {833    case DW_CFA_offset: { // 0x80 - high 2 bits are 0x2, lower 6 bits are834                          // register835      // takes two arguments: an unsigned LEB128 constant representing a836      // factored offset and a register number. The required action is to837      // change the rule for the register indicated by the register number to838      // be an offset(N) rule with a value of (N = factored offset *839      // data_align).840      uint8_t reg_num = extended_opcode;841      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;842      reg_location.SetAtCFAPlusOffset(op_offset);843      row.SetRegisterInfo(reg_num, reg_location);844      return true;845    }846    }847  } else {848    switch (extended_opcode) {849    case DW_CFA_nop: // 0x0850      return true;851 852    case DW_CFA_offset_extended: // 0x5853    {854      // takes two unsigned LEB128 arguments representing a register number and855      // a factored offset. This instruction is identical to DW_CFA_offset856      // except for the encoding and size of the register argument.857      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);858      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;859      UnwindPlan::Row::AbstractRegisterLocation reg_location;860      reg_location.SetAtCFAPlusOffset(op_offset);861      row.SetRegisterInfo(reg_num, reg_location);862      return true;863    }864 865    case DW_CFA_undefined: // 0x7866    {867      // takes a single unsigned LEB128 argument that represents a register868      // number. The required action is to set the rule for the specified869      // register to undefined.870      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);871      UnwindPlan::Row::AbstractRegisterLocation reg_location;872      reg_location.SetUndefined();873      row.SetRegisterInfo(reg_num, reg_location);874      return true;875    }876 877    case DW_CFA_same_value: // 0x8878    {879      // takes a single unsigned LEB128 argument that represents a register880      // number. The required action is to set the rule for the specified881      // register to same value.882      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);883      UnwindPlan::Row::AbstractRegisterLocation reg_location;884      reg_location.SetSame();885      row.SetRegisterInfo(reg_num, reg_location);886      return true;887    }888 889    case DW_CFA_register: // 0x9890    {891      // takes two unsigned LEB128 arguments representing register numbers. The892      // required action is to set the rule for the first register to be the893      // second register.894      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);895      uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);896      UnwindPlan::Row::AbstractRegisterLocation reg_location;897      reg_location.SetInRegister(other_reg_num);898      row.SetRegisterInfo(reg_num, reg_location);899      return true;900    }901 902    case DW_CFA_def_cfa: // 0xC    (CFA Definition Instruction)903    {904      // Takes two unsigned LEB128 operands representing a register number and905      // a (non-factored) offset. The required action is to define the current906      // CFA rule to use the provided register and offset.907      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);908      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);909      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);910      return true;911    }912 913    case DW_CFA_def_cfa_register: // 0xD    (CFA Definition Instruction)914    {915      // takes a single unsigned LEB128 argument representing a register916      // number. The required action is to define the current CFA rule to use917      // the provided register (but to keep the old offset).918      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);919      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num,920                                                row.GetCFAValue().GetOffset());921      return true;922    }923 924    case DW_CFA_def_cfa_offset: // 0xE    (CFA Definition Instruction)925    {926      // Takes a single unsigned LEB128 operand representing a (non-factored)927      // offset. The required action is to define the current CFA rule to use928      // the provided offset (but to keep the old register).929      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);930      row.GetCFAValue().SetIsRegisterPlusOffset(931          row.GetCFAValue().GetRegisterNumber(), op_offset);932      return true;933    }934 935    case DW_CFA_def_cfa_expression: // 0xF    (CFA Definition Instruction)936    {937      size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset);938      const uint8_t *block_data =939          static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));940      row.GetCFAValue().SetIsDWARFExpression(block_data, block_len);941      return true;942    }943 944    case DW_CFA_expression: // 0x10945    {946      // Takes two operands: an unsigned LEB128 value representing a register947      // number, and a DW_FORM_block value representing a DWARF expression. The948      // required action is to change the rule for the register indicated by949      // the register number to be an expression(E) rule where E is the DWARF950      // expression. That is, the DWARF expression computes the address. The951      // value of the CFA is pushed on the DWARF evaluation stack prior to952      // execution of the DWARF expression.953      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);954      uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);955      const uint8_t *block_data =956          static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));957      UnwindPlan::Row::AbstractRegisterLocation reg_location;958      reg_location.SetAtDWARFExpression(block_data, block_len);959      row.SetRegisterInfo(reg_num, reg_location);960      return true;961    }962 963    case DW_CFA_offset_extended_sf: // 0x11964    {965      // takes two operands: an unsigned LEB128 value representing a register966      // number and a signed LEB128 factored offset. This instruction is967      // identical to DW_CFA_offset_extended except that the second operand is968      // signed and factored.969      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);970      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;971      UnwindPlan::Row::AbstractRegisterLocation reg_location;972      reg_location.SetAtCFAPlusOffset(op_offset);973      row.SetRegisterInfo(reg_num, reg_location);974      return true;975    }976 977    case DW_CFA_def_cfa_sf: // 0x12   (CFA Definition Instruction)978    {979      // Takes two operands: an unsigned LEB128 value representing a register980      // number and a signed LEB128 factored offset. This instruction is981      // identical to DW_CFA_def_cfa except that the second operand is signed982      // and factored.983      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);984      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;985      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);986      return true;987    }988 989    case DW_CFA_def_cfa_offset_sf: // 0x13   (CFA Definition Instruction)990    {991      // takes a signed LEB128 operand representing a factored offset. This992      // instruction is identical to  DW_CFA_def_cfa_offset except that the993      // operand is signed and factored.994      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;995      uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber();996      row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset);997      return true;998    }999 1000    case DW_CFA_val_expression: // 0x161001    {1002      // takes two operands: an unsigned LEB128 value representing a register1003      // number, and a DW_FORM_block value representing a DWARF expression. The1004      // required action is to change the rule for the register indicated by1005      // the register number to be a val_expression(E) rule where E is the1006      // DWARF expression. That is, the DWARF expression computes the value of1007      // the given register. The value of the CFA is pushed on the DWARF1008      // evaluation stack prior to execution of the DWARF expression.1009      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);1010      uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);1011      const uint8_t *block_data =1012          (const uint8_t *)m_cfi_data.GetData(&offset, block_len);1013      reg_location.SetIsDWARFExpression(block_data, block_len);1014      row.SetRegisterInfo(reg_num, reg_location);1015      return true;1016    }1017    }1018  }1019  return false;1020}1021 1022void DWARFCallFrameInfo::ForEachFDEEntries(1023    const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback) {1024  GetFDEIndex();1025 1026  for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) {1027    const FDEEntryMap::Entry &entry = m_fde_index.GetEntryRef(i);1028    if (!callback(entry.base, entry.size, entry.data))1029      break;1030  }1031}1032