Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
35294 views
//===- DWARFFormValue.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/DebugInfo/DWARF/DWARFContext.h"13#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"14#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"15#include "llvm/DebugInfo/DWARF/DWARFObject.h"16#include "llvm/DebugInfo/DWARF/DWARFSection.h"17#include "llvm/DebugInfo/DWARF/DWARFUnit.h"18#include "llvm/Support/ErrorHandling.h"19#include "llvm/Support/Format.h"20#include "llvm/Support/WithColor.h"21#include "llvm/Support/raw_ostream.h"22#include <cinttypes>23#include <cstdint>24#include <limits>25#include <optional>2627using namespace llvm;28using namespace dwarf;2930static const DWARFFormValue::FormClass DWARF5FormClasses[] = {31DWARFFormValue::FC_Unknown, // 0x032DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr33DWARFFormValue::FC_Unknown, // 0x02 unused34DWARFFormValue::FC_Block, // 0x03 DW_FORM_block235DWARFFormValue::FC_Block, // 0x04 DW_FORM_block436DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data237// --- These can be FC_SectionOffset in DWARF3 and below:38DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data439DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data840// ---41DWARFFormValue::FC_String, // 0x08 DW_FORM_string42DWARFFormValue::FC_Block, // 0x09 DW_FORM_block43DWARFFormValue::FC_Block, // 0x0a DW_FORM_block144DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data145DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag46DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata47DWARFFormValue::FC_String, // 0x0e DW_FORM_strp48DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata49DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr50DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref151DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref252DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref453DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref854DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata55DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect56DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset57DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc58DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present59DWARFFormValue::FC_String, // 0x1a DW_FORM_strx60DWARFFormValue::FC_Address, // 0x1b DW_FORM_addrx61DWARFFormValue::FC_Reference, // 0x1c DW_FORM_ref_sup462DWARFFormValue::FC_String, // 0x1d DW_FORM_strp_sup63DWARFFormValue::FC_Constant, // 0x1e DW_FORM_data1664DWARFFormValue::FC_String, // 0x1f DW_FORM_line_strp65DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig866DWARFFormValue::FC_Constant, // 0x21 DW_FORM_implicit_const67DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx68DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx69DWARFFormValue::FC_Reference, // 0x24 DW_FORM_ref_sup870DWARFFormValue::FC_String, // 0x25 DW_FORM_strx171DWARFFormValue::FC_String, // 0x26 DW_FORM_strx272DWARFFormValue::FC_String, // 0x27 DW_FORM_strx373DWARFFormValue::FC_String, // 0x28 DW_FORM_strx474DWARFFormValue::FC_Address, // 0x29 DW_FORM_addrx175DWARFFormValue::FC_Address, // 0x2a DW_FORM_addrx276DWARFFormValue::FC_Address, // 0x2b DW_FORM_addrx377DWARFFormValue::FC_Address, // 0x2c DW_FORM_addrx478DWARFFormValue::FC_Address, // 0x2001 DW_FORM_addrx_offset79};8081DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {82return DWARFFormValue(F, ValueType(V));83}8485DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) {86return DWARFFormValue(F, ValueType(V));87}8889DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) {90return DWARFFormValue(F, ValueType(V));91}9293DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,94ArrayRef<uint8_t> D) {95ValueType V;96V.uval = D.size();97V.data = D.data();98return DWARFFormValue(F, V);99}100101DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,102uint64_t *OffsetPtr) {103DWARFFormValue FormValue(F);104FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,105U->getFormParams(), U);106return FormValue;107}108109bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,110uint64_t *OffsetPtr,111const dwarf::FormParams Params) {112bool Indirect = false;113do {114switch (Form) {115// Blocks of inlined data that have a length field and the data bytes116// inlined in the .debug_info.117case DW_FORM_exprloc:118case DW_FORM_block: {119uint64_t size = DebugInfoData.getULEB128(OffsetPtr);120*OffsetPtr += size;121return true;122}123case DW_FORM_block1: {124uint8_t size = DebugInfoData.getU8(OffsetPtr);125*OffsetPtr += size;126return true;127}128case DW_FORM_block2: {129uint16_t size = DebugInfoData.getU16(OffsetPtr);130*OffsetPtr += size;131return true;132}133case DW_FORM_block4: {134uint32_t size = DebugInfoData.getU32(OffsetPtr);135*OffsetPtr += size;136return true;137}138139// Inlined NULL terminated C-strings.140case DW_FORM_string:141DebugInfoData.getCStr(OffsetPtr);142return true;143144case DW_FORM_addr:145case DW_FORM_ref_addr:146case DW_FORM_flag_present:147case DW_FORM_data1:148case DW_FORM_data2:149case DW_FORM_data4:150case DW_FORM_data8:151case DW_FORM_data16:152case DW_FORM_flag:153case DW_FORM_ref1:154case DW_FORM_ref2:155case DW_FORM_ref4:156case DW_FORM_ref8:157case DW_FORM_ref_sig8:158case DW_FORM_ref_sup4:159case DW_FORM_ref_sup8:160case DW_FORM_strx1:161case DW_FORM_strx2:162case DW_FORM_strx3:163case DW_FORM_strx4:164case DW_FORM_addrx1:165case DW_FORM_addrx2:166case DW_FORM_addrx3:167case DW_FORM_addrx4:168case DW_FORM_sec_offset:169case DW_FORM_strp:170case DW_FORM_strp_sup:171case DW_FORM_line_strp:172case DW_FORM_GNU_ref_alt:173case DW_FORM_GNU_strp_alt:174case DW_FORM_implicit_const:175if (std::optional<uint8_t> FixedSize =176dwarf::getFixedFormByteSize(Form, Params)) {177*OffsetPtr += *FixedSize;178return true;179}180return false;181182// signed or unsigned LEB 128 values.183case DW_FORM_sdata:184DebugInfoData.getSLEB128(OffsetPtr);185return true;186187case DW_FORM_udata:188case DW_FORM_ref_udata:189case DW_FORM_strx:190case DW_FORM_addrx:191case DW_FORM_loclistx:192case DW_FORM_rnglistx:193case DW_FORM_GNU_addr_index:194case DW_FORM_GNU_str_index:195DebugInfoData.getULEB128(OffsetPtr);196return true;197198case DW_FORM_LLVM_addrx_offset:199DebugInfoData.getULEB128(OffsetPtr);200*OffsetPtr += 4;201return true;202203case DW_FORM_indirect:204Indirect = true;205Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));206break;207208default:209return false;210}211} while (Indirect);212return true;213}214215bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {216return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3);217}218219bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,220uint64_t *OffsetPtr, dwarf::FormParams FP,221const DWARFContext *Ctx,222const DWARFUnit *CU) {223if (!Ctx && CU)224Ctx = &CU->getContext();225C = Ctx;226U = CU;227Format = FP.Format;228bool Indirect = false;229bool IsBlock = false;230Value.data = nullptr;231// Read the value for the form into value and follow and DW_FORM_indirect232// instances we run into233Error Err = Error::success();234do {235Indirect = false;236switch (Form) {237case DW_FORM_addr:238case DW_FORM_ref_addr: {239uint16_t Size =240(Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();241Value.uval =242Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err);243break;244}245case DW_FORM_exprloc:246case DW_FORM_block:247Value.uval = Data.getULEB128(OffsetPtr, &Err);248IsBlock = true;249break;250case DW_FORM_block1:251Value.uval = Data.getU8(OffsetPtr, &Err);252IsBlock = true;253break;254case DW_FORM_block2:255Value.uval = Data.getU16(OffsetPtr, &Err);256IsBlock = true;257break;258case DW_FORM_block4:259Value.uval = Data.getU32(OffsetPtr, &Err);260IsBlock = true;261break;262case DW_FORM_data1:263case DW_FORM_ref1:264case DW_FORM_flag:265case DW_FORM_strx1:266case DW_FORM_addrx1:267Value.uval = Data.getU8(OffsetPtr, &Err);268break;269case DW_FORM_data2:270case DW_FORM_ref2:271case DW_FORM_strx2:272case DW_FORM_addrx2:273Value.uval = Data.getU16(OffsetPtr, &Err);274break;275case DW_FORM_strx3:276case DW_FORM_addrx3:277Value.uval = Data.getU24(OffsetPtr, &Err);278break;279case DW_FORM_data4:280case DW_FORM_ref4:281case DW_FORM_ref_sup4:282case DW_FORM_strx4:283case DW_FORM_addrx4:284Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err);285break;286case DW_FORM_data8:287case DW_FORM_ref8:288case DW_FORM_ref_sup8:289Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err);290break;291case DW_FORM_data16:292// Treat this like a 16-byte block.293Value.uval = 16;294IsBlock = true;295break;296case DW_FORM_sdata:297Value.sval = Data.getSLEB128(OffsetPtr, &Err);298break;299case DW_FORM_udata:300case DW_FORM_ref_udata:301case DW_FORM_rnglistx:302case DW_FORM_loclistx:303case DW_FORM_GNU_addr_index:304case DW_FORM_GNU_str_index:305case DW_FORM_addrx:306case DW_FORM_strx:307Value.uval = Data.getULEB128(OffsetPtr, &Err);308break;309case DW_FORM_LLVM_addrx_offset:310Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;311Value.uval |= Data.getU32(OffsetPtr, &Err);312break;313case DW_FORM_string:314Value.cstr = Data.getCStr(OffsetPtr, &Err);315break;316case DW_FORM_indirect:317Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err));318Indirect = true;319break;320case DW_FORM_strp:321case DW_FORM_sec_offset:322case DW_FORM_GNU_ref_alt:323case DW_FORM_GNU_strp_alt:324case DW_FORM_line_strp:325case DW_FORM_strp_sup: {326Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(),327OffsetPtr, nullptr, &Err);328break;329}330case DW_FORM_flag_present:331Value.uval = 1;332break;333case DW_FORM_ref_sig8:334Value.uval = Data.getU64(OffsetPtr, &Err);335break;336case DW_FORM_implicit_const:337// Value has been already set by DWARFFormValue::createFromSValue.338break;339default:340// DWARFFormValue::skipValue() will have caught this and caused all341// DWARF DIEs to fail to be parsed, so this code is not be reachable.342llvm_unreachable("unsupported form");343}344} while (Indirect && !Err);345346if (IsBlock)347Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin();348349return !errorToBool(std::move(Err));350}351352void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize,353uint64_t Address) {354uint8_t HexDigits = AddressSize * 2;355OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address);356}357358void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,359DIDumpOptions DumpOpts,360object::SectionedAddress SA) const {361dumpAddress(OS, U->getAddressByteSize(), SA.Address);362dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,363SA.SectionIndex);364}365366void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,367DIDumpOptions DumpOpts,368uint64_t SectionIndex) {369if (!DumpOpts.Verbose || SectionIndex == -1ULL)370return;371ArrayRef<SectionName> SectionNames = Obj.getSectionNames();372const auto &SecRef = SectionNames[SectionIndex];373374OS << " \"" << SecRef.Name << '\"';375376// Print section index if name is not unique.377if (!SecRef.IsNameUnique)378OS << format(" [%" PRIu64 "]", SectionIndex);379}380381void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {382uint64_t UValue = Value.uval;383bool CURelativeOffset = false;384raw_ostream &AddrOS = DumpOpts.ShowAddresses385? WithColor(OS, HighlightColor::Address).get()386: nulls();387int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);388switch (Form) {389case DW_FORM_addr:390dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});391break;392case DW_FORM_addrx:393case DW_FORM_addrx1:394case DW_FORM_addrx2:395case DW_FORM_addrx3:396case DW_FORM_addrx4:397case DW_FORM_GNU_addr_index:398case DW_FORM_LLVM_addrx_offset: {399if (U == nullptr) {400OS << "<invalid dwarf unit>";401break;402}403std::optional<object::SectionedAddress> A = getAsSectionedAddress();404if (!A || DumpOpts.Verbose) {405if (Form == DW_FORM_LLVM_addrx_offset) {406uint32_t Index = UValue >> 32;407uint32_t Offset = UValue & 0xffffffff;408AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);409} else410AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);411}412if (A)413dumpSectionedAddress(AddrOS, DumpOpts, *A);414else415OS << "<unresolved>";416break;417}418case DW_FORM_flag_present:419OS << "true";420break;421case DW_FORM_flag:422case DW_FORM_data1:423OS << format("0x%02x", (uint8_t)UValue);424break;425case DW_FORM_data2:426OS << format("0x%04x", (uint16_t)UValue);427break;428case DW_FORM_data4:429OS << format("0x%08x", (uint32_t)UValue);430break;431case DW_FORM_ref_sig8:432AddrOS << format("0x%016" PRIx64, UValue);433break;434case DW_FORM_data8:435OS << format("0x%016" PRIx64, UValue);436break;437case DW_FORM_data16:438OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16);439break;440case DW_FORM_string:441OS << '"';442OS.write_escaped(Value.cstr);443OS << '"';444break;445case DW_FORM_exprloc:446case DW_FORM_block:447case DW_FORM_block1:448case DW_FORM_block2:449case DW_FORM_block4:450if (UValue > 0) {451switch (Form) {452case DW_FORM_exprloc:453case DW_FORM_block:454AddrOS << format("<0x%" PRIx64 "> ", UValue);455break;456case DW_FORM_block1:457AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);458break;459case DW_FORM_block2:460AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);461break;462case DW_FORM_block4:463AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);464break;465default:466break;467}468469const uint8_t *DataPtr = Value.data;470if (DataPtr) {471// UValue contains size of block472const uint8_t *EndDataPtr = DataPtr + UValue;473while (DataPtr < EndDataPtr) {474AddrOS << format("%2.2x ", *DataPtr);475++DataPtr;476}477} else478OS << "NULL";479}480break;481482case DW_FORM_sdata:483case DW_FORM_implicit_const:484OS << Value.sval;485break;486case DW_FORM_udata:487OS << Value.uval;488break;489case DW_FORM_strp:490if (DumpOpts.Verbose)491OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue);492dumpString(OS);493break;494case DW_FORM_line_strp:495if (DumpOpts.Verbose)496OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth,497UValue);498dumpString(OS);499break;500case DW_FORM_strx:501case DW_FORM_strx1:502case DW_FORM_strx2:503case DW_FORM_strx3:504case DW_FORM_strx4:505case DW_FORM_GNU_str_index:506if (DumpOpts.Verbose)507OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);508dumpString(OS);509break;510case DW_FORM_GNU_strp_alt:511if (DumpOpts.Verbose)512OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);513dumpString(OS);514break;515case DW_FORM_ref_addr:516AddrOS << format("0x%016" PRIx64, UValue);517break;518case DW_FORM_ref1:519CURelativeOffset = true;520if (DumpOpts.Verbose)521AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);522break;523case DW_FORM_ref2:524CURelativeOffset = true;525if (DumpOpts.Verbose)526AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);527break;528case DW_FORM_ref4:529CURelativeOffset = true;530if (DumpOpts.Verbose)531AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);532break;533case DW_FORM_ref8:534CURelativeOffset = true;535if (DumpOpts.Verbose)536AddrOS << format("cu + 0x%8.8" PRIx64, UValue);537break;538case DW_FORM_ref_udata:539CURelativeOffset = true;540if (DumpOpts.Verbose)541AddrOS << format("cu + 0x%" PRIx64, UValue);542break;543case DW_FORM_GNU_ref_alt:544AddrOS << format("<alt 0x%" PRIx64 ">", UValue);545break;546547// All DW_FORM_indirect attributes should be resolved prior to calling548// this function549case DW_FORM_indirect:550OS << "DW_FORM_indirect";551break;552553case DW_FORM_rnglistx:554OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);555break;556557case DW_FORM_loclistx:558OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue);559break;560561case DW_FORM_sec_offset:562AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue);563break;564565default:566OS << format("DW_FORM(0x%4.4x)", Form);567break;568}569570if (CURelativeOffset) {571if (DumpOpts.Verbose)572OS << " => {";573if (DumpOpts.ShowAddresses)574WithColor(OS, HighlightColor::Address).get()575<< format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));576if (DumpOpts.Verbose)577OS << "}";578}579}580581void DWARFFormValue::dumpString(raw_ostream &OS) const {582if (auto DbgStr = dwarf::toString(*this)) {583auto COS = WithColor(OS, HighlightColor::String);584COS.get() << '"';585COS.get().write_escaped(*DbgStr);586COS.get() << '"';587}588}589590Expected<const char *> DWARFFormValue::getAsCString() const {591if (!isFormClass(FC_String))592return make_error<StringError>("Invalid form for string attribute",593inconvertibleErrorCode());594if (Form == DW_FORM_string)595return Value.cstr;596// FIXME: Add support for DW_FORM_GNU_strp_alt597if (Form == DW_FORM_GNU_strp_alt || C == nullptr)598return make_error<StringError>("Unsupported form for string attribute",599inconvertibleErrorCode());600uint64_t Offset = Value.uval;601std::optional<uint32_t> Index;602if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||603Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||604Form == DW_FORM_strx4) {605if (!U)606return make_error<StringError>("API limitation - string extraction not "607"available without a DWARFUnit",608inconvertibleErrorCode());609Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);610Index = Offset;611if (!StrOffset)612return StrOffset.takeError();613Offset = *StrOffset;614}615// Prefer the Unit's string extractor, because for .dwo it will point to616// .debug_str.dwo, while the Context's extractor always uses .debug_str.617bool IsDebugLineString = Form == DW_FORM_line_strp;618DataExtractor StrData =619IsDebugLineString ? C->getLineStringExtractor()620: U ? U->getStringExtractor() : C->getStringExtractor();621if (const char *Str = StrData.getCStr(&Offset))622return Str;623std::string Msg = FormEncodingString(Form).str();624if (Index)625Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str();626Msg += (" offset " + Twine(Offset) + " is beyond " +627(IsDebugLineString ? ".debug_line_str" : ".debug_str") + " bounds")628.str();629return make_error<StringError>(Msg,630inconvertibleErrorCode());631}632633std::optional<uint64_t> DWARFFormValue::getAsAddress() const {634if (auto SA = getAsSectionedAddress())635return SA->Address;636return std::nullopt;637}638639std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(640const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {641if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))642return std::nullopt;643bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;644if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||645Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||646Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {647648uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;649if (!U)650return std::nullopt;651std::optional<object::SectionedAddress> SA =652U->getAddrOffsetSectionItem(Index);653if (!SA)654return std::nullopt;655if (AddrOffset)656SA->Address += (Value.uval & 0xffffffff);657return SA;658}659return {{Value.uval, Value.SectionIndex}};660}661662std::optional<object::SectionedAddress>663DWARFFormValue::getAsSectionedAddress() const {664return getAsSectionedAddress(Value, Form, U);665}666667std::optional<uint64_t> DWARFFormValue::getAsRelativeReference() const {668switch (Form) {669case DW_FORM_ref1:670case DW_FORM_ref2:671case DW_FORM_ref4:672case DW_FORM_ref8:673case DW_FORM_ref_udata:674if (!U)675return std::nullopt;676return Value.uval;677default:678return std::nullopt;679}680}681682std::optional<uint64_t> DWARFFormValue::getAsDebugInfoReference() const {683if (Form == DW_FORM_ref_addr)684return Value.uval;685return std::nullopt;686}687688std::optional<uint64_t> DWARFFormValue::getAsSignatureReference() const {689if (Form == DW_FORM_ref_sig8)690return Value.uval;691return std::nullopt;692}693694std::optional<uint64_t> DWARFFormValue::getAsSupplementaryReference() const {695switch (Form) {696case DW_FORM_GNU_ref_alt:697case DW_FORM_ref_sup4:698case DW_FORM_ref_sup8:699return Value.uval;700default:701return std::nullopt;702}703}704705std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {706if (!isFormClass(FC_SectionOffset))707return std::nullopt;708return Value.uval;709}710711std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {712if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||713Form == DW_FORM_sdata)714return std::nullopt;715return Value.uval;716}717718std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {719if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||720(Form == DW_FORM_udata &&721uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))722return std::nullopt;723switch (Form) {724case DW_FORM_data4:725return int32_t(Value.uval);726case DW_FORM_data2:727return int16_t(Value.uval);728case DW_FORM_data1:729return int8_t(Value.uval);730case DW_FORM_sdata:731case DW_FORM_data8:732default:733return Value.sval;734}735}736737std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {738if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&739Form != DW_FORM_data16)740return std::nullopt;741return ArrayRef(Value.data, Value.uval);742}743744std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {745if (!isFormClass(FC_String) && Form == DW_FORM_string)746return std::nullopt;747return Value.uval;748}749750std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {751if (!isFormClass(FC_Reference))752return std::nullopt;753return Value.uval;754}755756std::optional<std::string>757DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {758if (U == nullptr || !isFormClass(FC_Constant))759return std::nullopt;760DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit();761if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) {762std::string FileName;763if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind,764FileName))765return FileName;766}767return std::nullopt;768}769770bool llvm::dwarf::doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC,771uint16_t DwarfVersion) {772// First, check DWARF5 form classes.773if (Form < std::size(DWARF5FormClasses) && DWARF5FormClasses[Form] == FC)774return true;775// Check more forms from extensions and proposals.776switch (Form) {777case DW_FORM_GNU_ref_alt:778return (FC == DWARFFormValue::FC_Reference);779case DW_FORM_GNU_addr_index:780return (FC == DWARFFormValue::FC_Address);781case DW_FORM_GNU_str_index:782case DW_FORM_GNU_strp_alt:783return (FC == DWARFFormValue::FC_String);784case DW_FORM_LLVM_addrx_offset:785return (FC == DWARFFormValue::FC_Address);786case DW_FORM_strp:787case DW_FORM_line_strp:788return (FC == DWARFFormValue::FC_SectionOffset);789case DW_FORM_data4:790case DW_FORM_data8:791// In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section792// offset.793return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3);794default:795return false;796}797}798799800