brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.9 KiB · dbb2a39 Raw
669 lines · cpp
1//===-- DWARFFormValue.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 <cassert>10#include <optional>11 12#include "lldb/Core/Module.h"13#include "lldb/Core/dwarf.h"14#include "lldb/Symbol/ObjectFile.h"15#include "lldb/Utility/Stream.h"16 17#include "DWARFDebugInfo.h"18#include "DWARFFormValue.h"19#include "DWARFUnit.h"20 21using namespace lldb_private;22using namespace lldb_private::plugin::dwarf;23using namespace llvm::dwarf;24 25void DWARFFormValue::Clear() {26  m_unit = nullptr;27  m_form = dw_form_t(0);28  m_value = ValueType();29}30 31bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,32                                  lldb::offset_t *offset_ptr) {33  if (m_form == DW_FORM_implicit_const)34    return true;35 36  bool indirect = false;37  bool is_block = false;38  m_value.data = nullptr;39  // Read the value for the form into value and follow and DW_FORM_indirect40  // instances we run into41  do {42    indirect = false;43    switch (m_form) {44    case DW_FORM_addr:45      assert(m_unit);46      m_value.uval =47          data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_unit));48      break;49    case DW_FORM_block1:50      m_value.uval = data.GetU8(offset_ptr);51      is_block = true;52      break;53    case DW_FORM_block2:54      m_value.uval = data.GetU16(offset_ptr);55      is_block = true;56      break;57    case DW_FORM_block4:58      m_value.uval = data.GetU32(offset_ptr);59      is_block = true;60      break;61    case DW_FORM_data16:62      m_value.uval = 16;63      is_block = true;64      break;65    case DW_FORM_exprloc:66    case DW_FORM_block:67      m_value.uval = data.GetULEB128(offset_ptr);68      is_block = true;69      break;70    case DW_FORM_string:71      m_value.cstr = data.GetCStr(offset_ptr);72      break;73    case DW_FORM_sdata:74      m_value.sval = data.GetSLEB128(offset_ptr);75      break;76    case DW_FORM_strp:77    case DW_FORM_line_strp:78    case DW_FORM_sec_offset:79      assert(m_unit);80      m_value.uval = data.GetMaxU64(81          offset_ptr, m_unit->GetFormParams().getDwarfOffsetByteSize());82      break;83    case DW_FORM_addrx1:84    case DW_FORM_strx1:85    case DW_FORM_ref1:86    case DW_FORM_data1:87    case DW_FORM_flag:88      m_value.uval = data.GetU8(offset_ptr);89      break;90    case DW_FORM_addrx2:91    case DW_FORM_strx2:92    case DW_FORM_ref2:93    case DW_FORM_data2:94      m_value.uval = data.GetU16(offset_ptr);95      break;96    case DW_FORM_addrx3:97    case DW_FORM_strx3:98      m_value.uval = data.GetMaxU64(offset_ptr, 3);99      break;100    case DW_FORM_addrx4:101    case DW_FORM_strx4:102    case DW_FORM_ref4:103    case DW_FORM_data4:104      m_value.uval = data.GetU32(offset_ptr);105      break;106    case DW_FORM_data8:107    case DW_FORM_ref8:108    case DW_FORM_ref_sig8:109      m_value.uval = data.GetU64(offset_ptr);110      break;111    case DW_FORM_addrx:112    case DW_FORM_loclistx:113    case DW_FORM_rnglistx:114    case DW_FORM_strx:115    case DW_FORM_udata:116    case DW_FORM_ref_udata:117    case DW_FORM_GNU_str_index:118    case DW_FORM_GNU_addr_index:119      m_value.uval = data.GetULEB128(offset_ptr);120      break;121    case DW_FORM_ref_addr:122      assert(m_unit);123      m_value.uval = data.GetMaxU64(124          offset_ptr, m_unit->GetFormParams().getRefAddrByteSize());125      break;126    case DW_FORM_indirect:127      m_form = static_cast<dw_form_t>(data.GetULEB128(offset_ptr));128      indirect = true;129      break;130    case DW_FORM_flag_present:131      m_value.uval = 1;132      break;133    default:134      return false;135    }136  } while (indirect);137 138  if (is_block) {139    m_value.data = data.PeekData(*offset_ptr, m_value.uval);140    if (m_value.data != nullptr) {141      *offset_ptr += m_value.uval;142    }143  }144 145  return true;146}147 148struct FormSize {149  uint8_t valid:1, size:7;150};151static FormSize g_form_sizes[] = {152    {0, 0}, // 0x00 unused153    {0, 0}, // 0x01 DW_FORM_addr154    {0, 0}, // 0x02 unused155    {0, 0}, // 0x03 DW_FORM_block2156    {0, 0}, // 0x04 DW_FORM_block4157    {1, 2}, // 0x05 DW_FORM_data2158    {1, 4}, // 0x06 DW_FORM_data4159    {1, 8}, // 0x07 DW_FORM_data8160    {0, 0}, // 0x08 DW_FORM_string161    {0, 0}, // 0x09 DW_FORM_block162    {0, 0}, // 0x0a DW_FORM_block1163    {1, 1}, // 0x0b DW_FORM_data1164    {1, 1}, // 0x0c DW_FORM_flag165    {0, 0}, // 0x0d DW_FORM_sdata166    {0, 0}, // 0x0e DW_FORM_strp (4 bytes for DWARF32, 8 bytes for DWARF64)167    {0, 0}, // 0x0f DW_FORM_udata168    {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes169            // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later170    {1, 1},  // 0x11 DW_FORM_ref1171    {1, 2},  // 0x12 DW_FORM_ref2172    {1, 4},  // 0x13 DW_FORM_ref4173    {1, 8},  // 0x14 DW_FORM_ref8174    {0, 0},  // 0x15 DW_FORM_ref_udata175    {0, 0},  // 0x16 DW_FORM_indirect176    {0, 0}, // 0x17 DW_FORM_sec_offset (4 bytes for DWARF32,8 bytes for DWARF64)177    {0, 0},  // 0x18 DW_FORM_exprloc178    {1, 0},  // 0x19 DW_FORM_flag_present179    {0, 0},  // 0x1a DW_FORM_strx (ULEB128)180    {0, 0},  // 0x1b DW_FORM_addrx (ULEB128)181    {1, 4},  // 0x1c DW_FORM_ref_sup4182    {0, 0},  // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)183    {1, 16}, // 0x1e DW_FORM_data16184    {0, 0}, // 0x1f DW_FORM_line_strp (4 bytes for DWARF32, 8 bytes for DWARF64)185    {1, 8},  // 0x20 DW_FORM_ref_sig8186};187 188std::optional<uint8_t> DWARFFormValue::GetFixedSize(dw_form_t form,189                                                    const DWARFUnit *u) {190  if (form <= DW_FORM_ref_sig8 && g_form_sizes[form].valid)191    return static_cast<uint8_t>(g_form_sizes[form].size);192  if (form == DW_FORM_addr && u)193    return u->GetAddressByteSize();194  return std::nullopt;195}196 197std::optional<uint8_t> DWARFFormValue::GetFixedSize() const {198  return GetFixedSize(m_form, m_unit);199}200 201bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,202                               lldb::offset_t *offset_ptr) const {203  return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, m_unit);204}205 206bool DWARFFormValue::SkipValue(dw_form_t form,207                               const DWARFDataExtractor &debug_info_data,208                               lldb::offset_t *offset_ptr,209                               const DWARFUnit *unit) {210  switch (form) {211  // Blocks if inlined data that have a length field and the data bytes inlined212  // in the .debug_info213  case DW_FORM_exprloc:214  case DW_FORM_block: {215    uint64_t size = debug_info_data.GetULEB128(offset_ptr);216    *offset_ptr += size;217  }218    return true;219  case DW_FORM_block1: {220    uint8_t size = debug_info_data.GetU8(offset_ptr);221    *offset_ptr += size;222  }223    return true;224  case DW_FORM_block2: {225    uint16_t size = debug_info_data.GetU16(offset_ptr);226    *offset_ptr += size;227  }228    return true;229  case DW_FORM_block4: {230    uint32_t size = debug_info_data.GetU32(offset_ptr);231    *offset_ptr += size;232  }233    return true;234 235  // Inlined NULL terminated C-strings236  case DW_FORM_string:237    debug_info_data.GetCStr(offset_ptr);238    return true;239 240  // Compile unit address sized values241  case DW_FORM_addr:242    *offset_ptr += DWARFUnit::GetAddressByteSize(unit);243    return true;244 245  case DW_FORM_ref_addr:246    assert(unit); // Unit must be valid for DW_FORM_ref_addr objects or we will247                  // get this wrong248    *offset_ptr += unit->GetFormParams().getRefAddrByteSize();249    return true;250 251  // 0 bytes values (implied from DW_FORM)252  case DW_FORM_flag_present:253  case DW_FORM_implicit_const:254    return true;255 256    // 1 byte values257    case DW_FORM_addrx1:258    case DW_FORM_data1:259    case DW_FORM_flag:260    case DW_FORM_ref1:261    case DW_FORM_strx1:262      *offset_ptr += 1;263      return true;264 265    // 2 byte values266    case DW_FORM_addrx2:267    case DW_FORM_data2:268    case DW_FORM_ref2:269    case DW_FORM_strx2:270      *offset_ptr += 2;271      return true;272 273    // 3 byte values274    case DW_FORM_addrx3:275    case DW_FORM_strx3:276      *offset_ptr += 3;277      return true;278 279    // 32 bit for DWARF 32, 64 for DWARF 64280    case DW_FORM_sec_offset:281    case DW_FORM_strp:282    case DW_FORM_line_strp:283      assert(unit);284      *offset_ptr += unit->GetFormParams().getDwarfOffsetByteSize();285      return true;286 287    // 4 byte values288    case DW_FORM_addrx4:289    case DW_FORM_data4:290    case DW_FORM_ref4:291    case DW_FORM_strx4:292      *offset_ptr += 4;293      return true;294 295    // 8 byte values296    case DW_FORM_data8:297    case DW_FORM_ref8:298    case DW_FORM_ref_sig8:299      *offset_ptr += 8;300      return true;301 302    // 16 byte values303    case DW_FORM_data16:304      *offset_ptr += 16;305      return true;306 307    // signed or unsigned LEB 128 values308    case DW_FORM_addrx:309    case DW_FORM_loclistx:310    case DW_FORM_rnglistx:311    case DW_FORM_sdata:312    case DW_FORM_udata:313    case DW_FORM_ref_udata:314    case DW_FORM_GNU_addr_index:315    case DW_FORM_GNU_str_index:316    case DW_FORM_strx:317      debug_info_data.Skip_LEB128(offset_ptr);318      return true;319 320  case DW_FORM_indirect: {321      auto indirect_form =322          static_cast<dw_form_t>(debug_info_data.GetULEB128(offset_ptr));323      return DWARFFormValue::SkipValue(indirect_form, debug_info_data,324                                       offset_ptr, unit);325  }326 327  default:328    break;329  }330  return false;331}332 333void DWARFFormValue::Dump(Stream &s) const {334  uint64_t uvalue = Unsigned();335  bool unit_relative_offset = false;336 337  switch (m_form) {338  case DW_FORM_addr:339    DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));340    break;341  case DW_FORM_flag:342  case DW_FORM_data1:343    s.PutHex8(uvalue);344    break;345  case DW_FORM_data2:346    s.PutHex16(uvalue);347    break;348  case DW_FORM_sec_offset:349  case DW_FORM_data4:350    s.PutHex32(uvalue);351    break;352  case DW_FORM_ref_sig8:353  case DW_FORM_data8:354    s.PutHex64(uvalue);355    break;356  case DW_FORM_string:357    s.QuotedCString(AsCString());358    break;359  case DW_FORM_exprloc:360  case DW_FORM_block:361  case DW_FORM_block1:362  case DW_FORM_block2:363  case DW_FORM_block4:364    if (uvalue > 0) {365      switch (m_form) {366      case DW_FORM_exprloc:367      case DW_FORM_block:368        s.Printf("<0x%" PRIx64 "> ", uvalue);369        break;370      case DW_FORM_block1:371        s.Printf("<0x%2.2x> ", (uint8_t)uvalue);372        break;373      case DW_FORM_block2:374        s.Printf("<0x%4.4x> ", (uint16_t)uvalue);375        break;376      case DW_FORM_block4:377        s.Printf("<0x%8.8x> ", (uint32_t)uvalue);378        break;379      default:380        break;381      }382 383      const uint8_t *data_ptr = m_value.data;384      if (data_ptr) {385        const uint8_t *end_data_ptr =386            data_ptr + uvalue; // uvalue contains size of block387        while (data_ptr < end_data_ptr) {388          s.Printf("%2.2x ", *data_ptr);389          ++data_ptr;390        }391      } else392        s.PutCString("NULL");393    }394    break;395 396  case DW_FORM_sdata:397    s.PutSLEB128(uvalue);398    break;399  case DW_FORM_udata:400    s.PutULEB128(uvalue);401    break;402  case DW_FORM_strp:403  case DW_FORM_line_strp: {404    const char *dbg_str = AsCString();405    if (dbg_str) {406      s.QuotedCString(dbg_str);407    } else {408      s.PutHex32(uvalue);409    }410  } break;411 412  case DW_FORM_ref_addr: {413    assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we414                    // will get this wrong415    DumpAddress(s.AsRawOstream(), uvalue,416                m_unit->GetFormParams().getRefAddrByteSize());417    break;418  }419  case DW_FORM_ref1:420    unit_relative_offset = true;421    break;422  case DW_FORM_ref2:423    unit_relative_offset = true;424    break;425  case DW_FORM_ref4:426    unit_relative_offset = true;427    break;428  case DW_FORM_ref8:429    unit_relative_offset = true;430    break;431  case DW_FORM_ref_udata:432    unit_relative_offset = true;433    break;434 435  // All DW_FORM_indirect attributes should be resolved prior to calling this436  // function437  case DW_FORM_indirect:438    s.PutCString("DW_FORM_indirect");439    break;440  case DW_FORM_flag_present:441    break;442  default:443    s.Printf("DW_FORM(0x%4.4x)", m_form);444    break;445  }446 447  if (unit_relative_offset) {448    assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile449                    // unit relative or we will get this wrong450    s.Printf("{0x%8.8" PRIx64 "}", uvalue + m_unit->GetOffset());451  }452}453 454const char *DWARFFormValue::AsCString() const {455  DWARFContext &context = m_unit->GetSymbolFileDWARF().GetDWARFContext();456 457  if (m_form == DW_FORM_string)458    return m_value.cstr;459  if (m_form == DW_FORM_strp)460    return context.getOrLoadStrData().PeekCStr(m_value.uval);461 462  if (m_form == DW_FORM_GNU_str_index || m_form == DW_FORM_strx ||463      m_form == DW_FORM_strx1 || m_form == DW_FORM_strx2 ||464      m_form == DW_FORM_strx3 || m_form == DW_FORM_strx4) {465 466    std::optional<uint64_t> offset =467        m_unit->GetStringOffsetSectionItem(m_value.uval);468    if (!offset)469      return nullptr;470    return context.getOrLoadStrData().PeekCStr(*offset);471  }472 473  if (m_form == DW_FORM_line_strp)474    return context.getOrLoadLineStrData().PeekCStr(m_value.uval);475 476  return nullptr;477}478 479dw_addr_t DWARFFormValue::Address() const {480  SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();481 482  if (m_form == DW_FORM_addr)483    return Unsigned();484 485  assert(m_unit);486  assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||487         m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||488         m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);489 490  uint32_t index_size = m_unit->GetAddressByteSize();491  dw_offset_t addr_base = m_unit->GetAddrBase();492  lldb::offset_t offset = addr_base + m_value.uval * index_size;493  return symbol_file.GetDWARFContext().getOrLoadAddrData().GetMaxU64(494      &offset, index_size);495}496 497std::pair<DWARFUnit *, uint64_t>498DWARFFormValue::ReferencedUnitAndOffset() const {499  uint64_t value = m_value.uval;500  switch (m_form) {501  case DW_FORM_ref1:502  case DW_FORM_ref2:503  case DW_FORM_ref4:504  case DW_FORM_ref8:505  case DW_FORM_ref_udata:506    assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile507                    // unit relative or we will get this wrong508    value += m_unit->GetOffset();509    if (!m_unit->ContainsDIEOffset(value)) {510      m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(511          "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value);512      return {nullptr, 0};513    }514    return {const_cast<DWARFUnit *>(m_unit), value};515 516  case DW_FORM_ref_addr: {517    DWARFUnit *ref_cu =518        m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(519            DIERef::Section::DebugInfo, value);520    if (!ref_cu) {521      m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(522          "DW_FORM_ref_addr DIE reference {0:x16} has no matching CU", value);523      return {nullptr, 0};524    }525    return {ref_cu, value};526  }527 528  case DW_FORM_ref_sig8: {529    DWARFTypeUnit *tu =530        m_unit->GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(value);531    if (!tu)532      return {nullptr, 0};533    return {tu, tu->GetTypeOffset()};534  }535 536  default:537    return {nullptr, 0};538  }539}540 541DWARFDIE DWARFFormValue::Reference() const {542  auto [unit, offset] = ReferencedUnitAndOffset();543  return unit ? unit->GetDIE(offset) : DWARFDIE();544}545 546uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {547  uint64_t value = m_value.uval;548  switch (m_form) {549  case DW_FORM_ref1:550  case DW_FORM_ref2:551  case DW_FORM_ref4:552  case DW_FORM_ref8:553  case DW_FORM_ref_udata:554    return value + base_offset;555 556  case DW_FORM_ref_addr:557  case DW_FORM_ref_sig8:558  case DW_FORM_GNU_ref_alt:559    return value;560 561  default:562    return DW_INVALID_OFFSET;563  }564}565 566std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {567  if ((!IsDataForm(m_form)) || m_form == llvm::dwarf::DW_FORM_sdata)568    return std::nullopt;569  return m_value.uval;570}571 572std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {573  if ((!IsDataForm(m_form)) ||574      (m_form == llvm::dwarf::DW_FORM_udata &&575       uint64_t(std::numeric_limits<int64_t>::max()) < m_value.uval))576    return std::nullopt;577  switch (m_form) {578  case llvm::dwarf::DW_FORM_data4:579    return int32_t(m_value.uval);580  case llvm::dwarf::DW_FORM_data2:581    return int16_t(m_value.uval);582  case llvm::dwarf::DW_FORM_data1:583    return int8_t(m_value.uval);584  case llvm::dwarf::DW_FORM_sdata:585  case llvm::dwarf::DW_FORM_data8:586  default:587    return m_value.sval;588  }589}590 591const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }592 593bool DWARFFormValue::IsBlockForm(const dw_form_t form) {594  switch (form) {595  case DW_FORM_exprloc:596  case DW_FORM_block:597  case DW_FORM_block1:598  case DW_FORM_block2:599  case DW_FORM_block4:600  case DW_FORM_data16:601    return true;602  default:603    return false;604  }605  llvm_unreachable("All cases handled above!");606}607 608bool DWARFFormValue::IsDataForm(const dw_form_t form) {609  switch (form) {610  case DW_FORM_sdata:611  case DW_FORM_udata:612  case DW_FORM_data1:613  case DW_FORM_data2:614  case DW_FORM_data4:615  case DW_FORM_data8:616    return true;617  default:618    return false;619  }620  llvm_unreachable("All cases handled above!");621}622 623bool DWARFFormValue::FormIsSupported(dw_form_t form) {624  switch (form) {625    case DW_FORM_addr:626    case DW_FORM_addrx:627    case DW_FORM_loclistx:628    case DW_FORM_rnglistx:629    case DW_FORM_block2:630    case DW_FORM_block4:631    case DW_FORM_data2:632    case DW_FORM_data4:633    case DW_FORM_data8:634    case DW_FORM_data16:635    case DW_FORM_string:636    case DW_FORM_block:637    case DW_FORM_block1:638    case DW_FORM_data1:639    case DW_FORM_flag:640    case DW_FORM_sdata:641    case DW_FORM_strp:642    case DW_FORM_line_strp:643    case DW_FORM_strx:644    case DW_FORM_strx1:645    case DW_FORM_strx2:646    case DW_FORM_strx3:647    case DW_FORM_strx4:648    case DW_FORM_udata:649    case DW_FORM_ref_addr:650    case DW_FORM_ref1:651    case DW_FORM_ref2:652    case DW_FORM_ref4:653    case DW_FORM_ref8:654    case DW_FORM_ref_udata:655    case DW_FORM_indirect:656    case DW_FORM_sec_offset:657    case DW_FORM_exprloc:658    case DW_FORM_flag_present:659    case DW_FORM_ref_sig8:660    case DW_FORM_GNU_str_index:661    case DW_FORM_GNU_addr_index:662    case DW_FORM_implicit_const:663      return true;664    default:665      break;666  }667  return false;668}669