brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.1 KiB · bc4badc Raw
799 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 "llvm/DebugInfo/DWARF/DWARFFormValue.h"10#include "llvm/ADT/ArrayRef.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/BinaryFormat/Dwarf.h"13#include "llvm/DebugInfo/DWARF/DWARFContext.h"14#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"15#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"16#include "llvm/DebugInfo/DWARF/DWARFObject.h"17#include "llvm/DebugInfo/DWARF/DWARFSection.h"18#include "llvm/DebugInfo/DWARF/DWARFUnit.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Support/Format.h"21#include "llvm/Support/WithColor.h"22#include "llvm/Support/raw_ostream.h"23#include <cinttypes>24#include <cstdint>25#include <limits>26#include <optional>27 28using namespace llvm;29using namespace dwarf;30 31static const DWARFFormValue::FormClass DWARF5FormClasses[] = {32    DWARFFormValue::FC_Unknown,  // 0x033    DWARFFormValue::FC_Address,  // 0x01 DW_FORM_addr34    DWARFFormValue::FC_Unknown,  // 0x02 unused35    DWARFFormValue::FC_Block,    // 0x03 DW_FORM_block236    DWARFFormValue::FC_Block,    // 0x04 DW_FORM_block437    DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data238    // --- These can be FC_SectionOffset in DWARF3 and below:39    DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data440    DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data841    // ---42    DWARFFormValue::FC_String,        // 0x08 DW_FORM_string43    DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block44    DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block145    DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data146    DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag47    DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata48    DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp49    DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata50    DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr51    DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref152    DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref253    DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref454    DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref855    DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata56    DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect57    DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset58    DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc59    DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present60    DWARFFormValue::FC_String,        // 0x1a DW_FORM_strx61    DWARFFormValue::FC_Address,       // 0x1b DW_FORM_addrx62    DWARFFormValue::FC_Reference,     // 0x1c DW_FORM_ref_sup463    DWARFFormValue::FC_String,        // 0x1d DW_FORM_strp_sup64    DWARFFormValue::FC_Constant,      // 0x1e DW_FORM_data1665    DWARFFormValue::FC_String,        // 0x1f DW_FORM_line_strp66    DWARFFormValue::FC_Reference,     // 0x20 DW_FORM_ref_sig867    DWARFFormValue::FC_Constant,      // 0x21 DW_FORM_implicit_const68    DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx69    DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx70    DWARFFormValue::FC_Reference,     // 0x24 DW_FORM_ref_sup871    DWARFFormValue::FC_String,        // 0x25 DW_FORM_strx172    DWARFFormValue::FC_String,        // 0x26 DW_FORM_strx273    DWARFFormValue::FC_String,        // 0x27 DW_FORM_strx374    DWARFFormValue::FC_String,        // 0x28 DW_FORM_strx475    DWARFFormValue::FC_Address,       // 0x29 DW_FORM_addrx176    DWARFFormValue::FC_Address,       // 0x2a DW_FORM_addrx277    DWARFFormValue::FC_Address,       // 0x2b DW_FORM_addrx378    DWARFFormValue::FC_Address,       // 0x2c DW_FORM_addrx479    DWARFFormValue::FC_Address,       // 0x2001 DW_FORM_addrx_offset80};81 82DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {83  return DWARFFormValue(F, ValueType(V));84}85 86DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) {87  return DWARFFormValue(F, ValueType(V));88}89 90DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) {91  return DWARFFormValue(F, ValueType(V));92}93 94DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,95                                                    ArrayRef<uint8_t> D) {96  ValueType V;97  V.uval = D.size();98  V.data = D.data();99  return DWARFFormValue(F, V);100}101 102DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,103                                              uint64_t *OffsetPtr) {104  DWARFFormValue FormValue(F);105  FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,106                         U->getFormParams(), U);107  return FormValue;108}109 110bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,111                               uint64_t *OffsetPtr,112                               const dwarf::FormParams Params) {113  bool Indirect = false;114  do {115    switch (Form) {116    // Blocks of inlined data that have a length field and the data bytes117    // inlined in the .debug_info.118    case DW_FORM_exprloc:119    case DW_FORM_block: {120      uint64_t size = DebugInfoData.getULEB128(OffsetPtr);121      *OffsetPtr += size;122      return true;123    }124    case DW_FORM_block1: {125      uint8_t size = DebugInfoData.getU8(OffsetPtr);126      *OffsetPtr += size;127      return true;128    }129    case DW_FORM_block2: {130      uint16_t size = DebugInfoData.getU16(OffsetPtr);131      *OffsetPtr += size;132      return true;133    }134    case DW_FORM_block4: {135      uint32_t size = DebugInfoData.getU32(OffsetPtr);136      *OffsetPtr += size;137      return true;138    }139 140    // Inlined NULL terminated C-strings.141    case DW_FORM_string:142      DebugInfoData.getCStr(OffsetPtr);143      return true;144 145    case DW_FORM_addr:146    case DW_FORM_ref_addr:147    case DW_FORM_flag_present:148    case DW_FORM_data1:149    case DW_FORM_data2:150    case DW_FORM_data4:151    case DW_FORM_data8:152    case DW_FORM_data16:153    case DW_FORM_flag:154    case DW_FORM_ref1:155    case DW_FORM_ref2:156    case DW_FORM_ref4:157    case DW_FORM_ref8:158    case DW_FORM_ref_sig8:159    case DW_FORM_ref_sup4:160    case DW_FORM_ref_sup8:161    case DW_FORM_strx1:162    case DW_FORM_strx2:163    case DW_FORM_strx3:164    case DW_FORM_strx4:165    case DW_FORM_addrx1:166    case DW_FORM_addrx2:167    case DW_FORM_addrx3:168    case DW_FORM_addrx4:169    case DW_FORM_sec_offset:170    case DW_FORM_strp:171    case DW_FORM_strp_sup:172    case DW_FORM_line_strp:173    case DW_FORM_GNU_ref_alt:174    case DW_FORM_GNU_strp_alt:175    case DW_FORM_implicit_const:176      if (std::optional<uint8_t> FixedSize =177              dwarf::getFixedFormByteSize(Form, Params)) {178        *OffsetPtr += *FixedSize;179        return true;180      }181      return false;182 183    // signed or unsigned LEB 128 values.184    case DW_FORM_sdata:185      DebugInfoData.getSLEB128(OffsetPtr);186      return true;187 188    case DW_FORM_udata:189    case DW_FORM_ref_udata:190    case DW_FORM_strx:191    case DW_FORM_addrx:192    case DW_FORM_loclistx:193    case DW_FORM_rnglistx:194    case DW_FORM_GNU_addr_index:195    case DW_FORM_GNU_str_index:196      DebugInfoData.getULEB128(OffsetPtr);197      return true;198 199    case DW_FORM_LLVM_addrx_offset:200      DebugInfoData.getULEB128(OffsetPtr);201      *OffsetPtr += 4;202      return true;203 204    case DW_FORM_indirect:205      Indirect = true;206      Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));207      break;208 209    default:210      return false;211    }212  } while (Indirect);213  return true;214}215 216bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {217  return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3);218}219 220bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,221                                  uint64_t *OffsetPtr, dwarf::FormParams FP,222                                  const DWARFContext *Ctx,223                                  const DWARFUnit *CU) {224  if (!Ctx && CU)225    Ctx = &CU->getContext();226  C = Ctx;227  U = CU;228  Format = FP.Format;229  bool Indirect = false;230  bool IsBlock = false;231  Value.data = nullptr;232  // Read the value for the form into value and follow and DW_FORM_indirect233  // instances we run into234  Error Err = Error::success();235  do {236    Indirect = false;237    switch (Form) {238    case DW_FORM_addr:239    case DW_FORM_ref_addr: {240      uint16_t Size =241          (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();242      Value.uval =243          Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err);244      break;245    }246    case DW_FORM_exprloc:247    case DW_FORM_block:248      Value.uval = Data.getULEB128(OffsetPtr, &Err);249      IsBlock = true;250      break;251    case DW_FORM_block1:252      Value.uval = Data.getU8(OffsetPtr, &Err);253      IsBlock = true;254      break;255    case DW_FORM_block2:256      Value.uval = Data.getU16(OffsetPtr, &Err);257      IsBlock = true;258      break;259    case DW_FORM_block4:260      Value.uval = Data.getU32(OffsetPtr, &Err);261      IsBlock = true;262      break;263    case DW_FORM_data1:264    case DW_FORM_ref1:265    case DW_FORM_flag:266    case DW_FORM_strx1:267    case DW_FORM_addrx1:268      Value.uval = Data.getU8(OffsetPtr, &Err);269      break;270    case DW_FORM_data2:271    case DW_FORM_ref2:272    case DW_FORM_strx2:273    case DW_FORM_addrx2:274      Value.uval = Data.getU16(OffsetPtr, &Err);275      break;276    case DW_FORM_strx3:277    case DW_FORM_addrx3:278      Value.uval = Data.getU24(OffsetPtr, &Err);279      break;280    case DW_FORM_data4:281    case DW_FORM_ref4:282    case DW_FORM_ref_sup4:283    case DW_FORM_strx4:284    case DW_FORM_addrx4:285      Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err);286      break;287    case DW_FORM_data8:288    case DW_FORM_ref8:289    case DW_FORM_ref_sup8:290      Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err);291      break;292    case DW_FORM_data16:293      // Treat this like a 16-byte block.294      Value.uval = 16;295      IsBlock = true;296      break;297    case DW_FORM_sdata:298      Value.sval = Data.getSLEB128(OffsetPtr, &Err);299      break;300    case DW_FORM_udata:301    case DW_FORM_ref_udata:302    case DW_FORM_rnglistx:303    case DW_FORM_loclistx:304    case DW_FORM_GNU_addr_index:305    case DW_FORM_GNU_str_index:306    case DW_FORM_addrx:307    case DW_FORM_strx:308      Value.uval = Data.getULEB128(OffsetPtr, &Err);309      break;310    case DW_FORM_LLVM_addrx_offset:311      Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;312      Value.uval |= Data.getU32(OffsetPtr, &Err);313      break;314    case DW_FORM_string:315      Value.cstr = Data.getCStr(OffsetPtr, &Err);316      break;317    case DW_FORM_indirect:318      Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err));319      Indirect = true;320      break;321    case DW_FORM_strp:322    case DW_FORM_sec_offset:323    case DW_FORM_GNU_ref_alt:324    case DW_FORM_GNU_strp_alt:325    case DW_FORM_line_strp:326    case DW_FORM_strp_sup: {327      Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(),328                                          OffsetPtr, nullptr, &Err);329      break;330    }331    case DW_FORM_flag_present:332      Value.uval = 1;333      break;334    case DW_FORM_ref_sig8:335      Value.uval = Data.getU64(OffsetPtr, &Err);336      break;337    case DW_FORM_implicit_const:338      // Value has been already set by DWARFFormValue::createFromSValue.339      break;340    default:341      // DWARFFormValue::skipValue() will have caught this and caused all342      // DWARF DIEs to fail to be parsed, so this code is not be reachable.343      llvm_unreachable("unsupported form");344    }345  } while (Indirect && !Err);346 347  if (IsBlock)348    Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin();349 350  return !errorToBool(std::move(Err));351}352 353void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize,354                                 uint64_t Address) {355  uint8_t HexDigits = AddressSize * 2;356  OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address);357}358 359void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,360                                          DIDumpOptions DumpOpts,361                                          object::SectionedAddress SA) const {362  dumpAddress(OS, U->getAddressByteSize(), SA.Address);363  dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,364                     SA.SectionIndex);365}366 367void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,368                                        DIDumpOptions DumpOpts,369                                        uint64_t SectionIndex) {370  if (!DumpOpts.Verbose || SectionIndex == -1ULL)371    return;372  ArrayRef<SectionName> SectionNames = Obj.getSectionNames();373  const auto &SecRef = SectionNames[SectionIndex];374 375  OS << " \"" << SecRef.Name << '\"';376 377  // Print section index if name is not unique.378  if (!SecRef.IsNameUnique)379    OS << format(" [%" PRIu64 "]", SectionIndex);380}381 382void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {383  uint64_t UValue = Value.uval;384  bool CURelativeOffset = false;385  raw_ostream &AddrOS = DumpOpts.ShowAddresses386                            ? WithColor(OS, HighlightColor::Address).get()387                            : nulls();388  int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);389  switch (Form) {390  case DW_FORM_addr:391    dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});392    break;393  case DW_FORM_addrx:394  case DW_FORM_addrx1:395  case DW_FORM_addrx2:396  case DW_FORM_addrx3:397  case DW_FORM_addrx4:398  case DW_FORM_GNU_addr_index:399  case DW_FORM_LLVM_addrx_offset: {400    if (U == nullptr) {401      OS << "<invalid dwarf unit>";402      break;403    }404    std::optional<object::SectionedAddress> A = getAsSectionedAddress();405    if (!A || DumpOpts.Verbose) {406      if (Form == DW_FORM_LLVM_addrx_offset) {407        uint32_t Index = UValue >> 32;408        uint32_t Offset = UValue & 0xffffffff;409        AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);410      } else411        AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);412    }413    if (A)414      dumpSectionedAddress(AddrOS, DumpOpts, *A);415    else416      OS << "<unresolved>";417    break;418  }419  case DW_FORM_flag_present:420    OS << "true";421    break;422  case DW_FORM_flag:423  case DW_FORM_data1:424    OS << format("0x%02x", (uint8_t)UValue);425    break;426  case DW_FORM_data2:427    OS << format("0x%04x", (uint16_t)UValue);428    break;429  case DW_FORM_data4:430    OS << format("0x%08x", (uint32_t)UValue);431    break;432  case DW_FORM_ref_sig8:433    AddrOS << format("0x%016" PRIx64, UValue);434    break;435  case DW_FORM_data8:436    OS << format("0x%016" PRIx64, UValue);437    break;438  case DW_FORM_data16:439    OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16);440    break;441  case DW_FORM_string:442    OS << '"';443    OS.write_escaped(Value.cstr);444    OS << '"';445    break;446  case DW_FORM_exprloc:447  case DW_FORM_block:448  case DW_FORM_block1:449  case DW_FORM_block2:450  case DW_FORM_block4:451    if (UValue > 0) {452      switch (Form) {453      case DW_FORM_exprloc:454      case DW_FORM_block:455        AddrOS << format("<0x%" PRIx64 "> ", UValue);456        break;457      case DW_FORM_block1:458        AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);459        break;460      case DW_FORM_block2:461        AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);462        break;463      case DW_FORM_block4:464        AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);465        break;466      default:467        break;468      }469 470      const uint8_t *DataPtr = Value.data;471      if (DataPtr) {472        // UValue contains size of block473        const uint8_t *EndDataPtr = DataPtr + UValue;474        while (DataPtr < EndDataPtr) {475          AddrOS << format("%2.2x ", *DataPtr);476          ++DataPtr;477        }478      } else479        OS << "NULL";480    }481    break;482 483  case DW_FORM_sdata:484  case DW_FORM_implicit_const:485    OS << Value.sval;486    break;487  case DW_FORM_udata:488    OS << Value.uval;489    break;490  case DW_FORM_strp:491    if (DumpOpts.Verbose)492      OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue);493    dumpString(OS);494    break;495  case DW_FORM_line_strp:496    if (DumpOpts.Verbose)497      OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth,498                   UValue);499    dumpString(OS);500    break;501  case DW_FORM_strx:502  case DW_FORM_strx1:503  case DW_FORM_strx2:504  case DW_FORM_strx3:505  case DW_FORM_strx4:506  case DW_FORM_GNU_str_index:507    if (DumpOpts.Verbose)508      OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);509    dumpString(OS);510    break;511  case DW_FORM_GNU_strp_alt:512    if (DumpOpts.Verbose)513      OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);514    dumpString(OS);515    break;516  case DW_FORM_ref_addr:517    AddrOS << format("0x%016" PRIx64, UValue);518    break;519  case DW_FORM_ref1:520    CURelativeOffset = true;521    if (DumpOpts.Verbose)522      AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);523    break;524  case DW_FORM_ref2:525    CURelativeOffset = true;526    if (DumpOpts.Verbose)527      AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);528    break;529  case DW_FORM_ref4:530    CURelativeOffset = true;531    if (DumpOpts.Verbose)532      AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);533    break;534  case DW_FORM_ref8:535    CURelativeOffset = true;536    if (DumpOpts.Verbose)537      AddrOS << format("cu + 0x%8.8" PRIx64, UValue);538    break;539  case DW_FORM_ref_udata:540    CURelativeOffset = true;541    if (DumpOpts.Verbose)542      AddrOS << format("cu + 0x%" PRIx64, UValue);543    break;544  case DW_FORM_GNU_ref_alt:545    AddrOS << format("<alt 0x%" PRIx64 ">", UValue);546    break;547 548  // All DW_FORM_indirect attributes should be resolved prior to calling549  // this function550  case DW_FORM_indirect:551    OS << "DW_FORM_indirect";552    break;553 554  case DW_FORM_rnglistx:555    OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);556    break;557 558  case DW_FORM_loclistx:559    OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue);560    break;561 562  case DW_FORM_sec_offset:563    AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue);564    break;565 566  default:567    OS << format("DW_FORM(0x%4.4x)", Form);568    break;569  }570 571  if (CURelativeOffset) {572    if (DumpOpts.Verbose)573      OS << " => {";574    if (DumpOpts.ShowAddresses)575      WithColor(OS, HighlightColor::Address).get()576          << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));577    if (DumpOpts.Verbose)578      OS << "}";579  }580}581 582void DWARFFormValue::dumpString(raw_ostream &OS) const {583  if (auto DbgStr = dwarf::toString(*this)) {584    auto COS = WithColor(OS, HighlightColor::String);585    COS.get() << '"';586    COS.get().write_escaped(*DbgStr);587    COS.get() << '"';588  }589}590 591Expected<const char *> DWARFFormValue::getAsCString() const {592  if (!isFormClass(FC_String))593    return make_error<StringError>("Invalid form for string attribute",594                                   inconvertibleErrorCode());595  if (Form == DW_FORM_string)596    return Value.cstr;597  // FIXME: Add support for DW_FORM_GNU_strp_alt598  if (Form == DW_FORM_GNU_strp_alt || C == nullptr)599    return make_error<StringError>("Unsupported form for string attribute",600                                   inconvertibleErrorCode());601  uint64_t Offset = Value.uval;602  std::optional<uint32_t> Index;603  if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||604      Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||605      Form == DW_FORM_strx4) {606    if (!U)607      return make_error<StringError>("API limitation - string extraction not "608                                     "available without a DWARFUnit",609                                     inconvertibleErrorCode());610    Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);611    Index = Offset;612    if (!StrOffset)613      return StrOffset.takeError();614    Offset = *StrOffset;615  }616  // Prefer the Unit's string extractor, because for .dwo it will point to617  // .debug_str.dwo, while the Context's extractor always uses .debug_str.618  bool IsDebugLineString = Form == DW_FORM_line_strp;619  DataExtractor StrData =620      IsDebugLineString ? C->getLineStringExtractor()621                        : U ? U->getStringExtractor() : C->getStringExtractor();622  if (const char *Str = StrData.getCStr(&Offset))623    return Str;624  std::string Msg = FormEncodingString(Form).str();625  if (Index)626    Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str();627  Msg += (" offset " + Twine(Offset) + " is beyond " +628          (IsDebugLineString ? ".debug_line_str" : ".debug_str") + " bounds")629             .str();630  return make_error<StringError>(Msg,631      inconvertibleErrorCode());632}633 634std::optional<uint64_t> DWARFFormValue::getAsAddress() const {635  if (auto SA = getAsSectionedAddress())636    return SA->Address;637  return std::nullopt;638}639 640std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(641    const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {642  if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))643    return std::nullopt;644  bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;645  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||646      Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||647      Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {648 649    uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;650    if (!U)651      return std::nullopt;652    std::optional<object::SectionedAddress> SA =653        U->getAddrOffsetSectionItem(Index);654    if (!SA)655      return std::nullopt;656    if (AddrOffset)657      SA->Address += (Value.uval & 0xffffffff);658    return SA;659  }660  return {{Value.uval, Value.SectionIndex}};661}662 663std::optional<object::SectionedAddress>664DWARFFormValue::getAsSectionedAddress() const {665  return getAsSectionedAddress(Value, Form, U);666}667 668std::optional<uint64_t> DWARFFormValue::getAsRelativeReference() const {669  switch (Form) {670  case DW_FORM_ref1:671  case DW_FORM_ref2:672  case DW_FORM_ref4:673  case DW_FORM_ref8:674  case DW_FORM_ref_udata:675    if (!U)676      return std::nullopt;677    return Value.uval;678  default:679    return std::nullopt;680  }681}682 683std::optional<uint64_t> DWARFFormValue::getAsDebugInfoReference() const {684  if (Form == DW_FORM_ref_addr)685    return Value.uval;686  return std::nullopt;687}688 689std::optional<uint64_t> DWARFFormValue::getAsSignatureReference() const {690  if (Form == DW_FORM_ref_sig8)691    return Value.uval;692  return std::nullopt;693}694 695std::optional<uint64_t> DWARFFormValue::getAsSupplementaryReference() const {696  switch (Form) {697  case DW_FORM_GNU_ref_alt:698  case DW_FORM_ref_sup4:699  case DW_FORM_ref_sup8:700    return Value.uval;701  default:702    return std::nullopt;703  }704}705 706std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {707  if (!isFormClass(FC_SectionOffset))708    return std::nullopt;709  return Value.uval;710}711 712std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {713  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||714      Form == DW_FORM_sdata)715    return std::nullopt;716  return Value.uval;717}718 719std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {720  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||721      (Form == DW_FORM_udata &&722       uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))723    return std::nullopt;724  switch (Form) {725  case DW_FORM_data4:726    return int32_t(Value.uval);727  case DW_FORM_data2:728    return int16_t(Value.uval);729  case DW_FORM_data1:730    return int8_t(Value.uval);731  case DW_FORM_sdata:732  case DW_FORM_data8:733  default:734    return Value.sval;735  }736}737 738std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {739  if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&740      Form != DW_FORM_data16)741    return std::nullopt;742  return ArrayRef(Value.data, Value.uval);743}744 745std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {746  if (!isFormClass(FC_String) && Form == DW_FORM_string)747    return std::nullopt;748  return Value.uval;749}750 751std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {752  if (!isFormClass(FC_Reference))753    return std::nullopt;754  return Value.uval;755}756 757std::optional<std::string>758DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {759  if (U == nullptr || !isFormClass(FC_Constant))760    return std::nullopt;761  DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit();762  if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) {763    std::string FileName;764    if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind,765                               FileName))766      return FileName;767  }768  return std::nullopt;769}770 771bool llvm::dwarf::doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC,772                           uint16_t DwarfVersion) {773  // First, check DWARF5 form classes.774  if (Form < std::size(DWARF5FormClasses) && DWARF5FormClasses[Form] == FC)775    return true;776  // Check more forms from extensions and proposals.777  switch (Form) {778  case DW_FORM_GNU_ref_alt:779    return (FC == DWARFFormValue::FC_Reference);780  case DW_FORM_GNU_addr_index:781    return (FC == DWARFFormValue::FC_Address);782  case DW_FORM_GNU_str_index:783  case DW_FORM_GNU_strp_alt:784    return (FC == DWARFFormValue::FC_String);785  case DW_FORM_LLVM_addrx_offset:786    return (FC == DWARFFormValue::FC_Address);787  case DW_FORM_strp:788  case DW_FORM_line_strp:789    return (FC == DWARFFormValue::FC_SectionOffset);790  case DW_FORM_data4:791  case DW_FORM_data8:792    // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section793    // offset.794    return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3);795  default:796    return false;797  }798}799