diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index eaaccfb4f33..ad6f71d664e 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -20,7 +20,7 @@ class raw_ostream; class DWARFFormValue { public: struct ValueType { - ValueType() : data(NULL) { + ValueType() : data(NULL), IsDWOIndex(false) { uval = 0; } @@ -30,6 +30,7 @@ public: const char* cstr; }; const uint8_t* data; + bool IsDWOIndex; }; enum { @@ -63,11 +64,8 @@ public: bool resolveCompileUnitReferences(const DWARFCompileUnit* cu); uint64_t getUnsigned() const { return Value.uval; } int64_t getSigned() const { return Value.sval; } - const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; - const char *getIndirectCString(const DataExtractor *, - const DataExtractor *) const; - uint64_t getIndirectAddress(const DataExtractor *, - const DWARFCompileUnit *) const; + const char *getAsCString(const DWARFCompileUnit *CU) const; + uint64_t getAsAddress(const DWARFCompileUnit *CU) const; bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFCompileUnit *cu) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp index 93b1622e807..4b6aa272f7d 100644 --- a/lib/DebugInfo/DWARFCompileUnit.cpp +++ b/lib/DebugInfo/DWARFCompileUnit.cpp @@ -12,12 +12,31 @@ #include "llvm/DebugInfo/DWARFFormValue.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace dwarf; -DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const { - return DataExtractor(InfoSection, isLittleEndian, AddrSize); +bool DWARFCompileUnit::getAddrOffsetSectionItem(uint32_t Index, + uint64_t &Result) const { + uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; + if (AddrOffsetSection.size() < Offset + AddrSize) + return false; + DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); + Result = DA.getAddress(&Offset); + return true; +} + +bool DWARFCompileUnit::getStringOffsetSectionItem(uint32_t Index, + uint32_t &Result) const { + // FIXME: string offset section entries are 8-byte for DWARF64. + const uint32_t ItemSize = 4; + uint32_t Offset = Index * ItemSize; + if (StringOffsetSection.size() < Offset + ItemSize) + return false; + DataExtractor DA(StringOffsetSection, isLittleEndian, 0); + Result = DA.getU32(&Offset); + return true; } bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { @@ -78,7 +97,8 @@ bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset, // Require that compile unit is extracted. assert(DieArray.size() > 0); DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); - return RangeList.extract(RangesData, &RangeListOffset); + uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; + return RangeList.extract(RangesData, &ActualRangeListOffset); } void DWARFCompileUnit::clear() { @@ -88,7 +108,10 @@ void DWARFCompileUnit::clear() { Abbrevs = 0; AddrSize = 0; BaseAddr = 0; + RangeSectionBase = 0; + AddrOffsetSectionBase = 0; clearDIEs(false); + DWO.reset(); } void DWARFCompileUnit::dump(raw_ostream &OS) { @@ -112,6 +135,15 @@ const char *DWARFCompileUnit::getCompilationDir() { return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); } +uint64_t DWARFCompileUnit::getDWOId() { + extractDIEsIfNeeded(true); + const uint64_t FailValue = -1ULL; + if (DieArray.empty()) + return FailValue; + return DieArray[0] + .getAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, FailValue); +} + void DWARFCompileUnit::setDIERelations() { if (DieArray.empty()) return; @@ -207,21 +239,72 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool CUDieOnly) { DieArray.size() > 1) return 0; // Already parsed. - extractDIEsToVector(DieArray.empty(), !CUDieOnly, DieArray); + bool HasCUDie = DieArray.size() > 0; + extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); - // Set the base address of current compile unit. - if (!DieArray.empty()) { + if (DieArray.empty()) + return 0; + + // If CU DIE was just parsed, copy several attribute values from it. + if (!HasCUDie) { uint64_t BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U); if (BaseAddr == -1U) BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0); setBaseAddress(BaseAddr); + AddrOffsetSectionBase = + DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_addr_base, 0); + RangeSectionBase = + DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_ranges_base, 0); } setDIERelations(); return DieArray.size(); } +DWARFCompileUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile) + : DWOFile(DWOFile), + DWOContext(cast(DIContext::getDWARFContext(DWOFile))), + DWOCU(0) { + if (DWOContext->getNumDWOCompileUnits() > 0) + DWOCU = DWOContext->getDWOCompileUnitAtIndex(0); +} + +bool DWARFCompileUnit::parseDWO() { + if (DWO.get() != 0) + return false; + extractDIEsIfNeeded(true); + if (DieArray.empty()) + return false; + const char *DWOFileName = + DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0); + if (DWOFileName == 0) + return false; + const char *CompilationDir = + DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); + SmallString<16> AbsolutePath; + if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) { + sys::path::append(AbsolutePath, CompilationDir); + } + sys::path::append(AbsolutePath, DWOFileName); + object::ObjectFile *DWOFile = + object::ObjectFile::createObjectFile(AbsolutePath); + if (!DWOFile) + return false; + // Reset DWOHolder. + DWO.reset(new DWOHolder(DWOFile)); + DWARFCompileUnit *DWOCU = DWO->getCU(); + // Verify that compile unit in .dwo file is valid. + if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) { + DWO.reset(); + return false; + } + // Share .debug_addr and .debug_ranges section with compile unit in .dwo + DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); + DWOCU->setRangesSection(RangeSection, RangeSectionBase); + return true; +} + void DWARFCompileUnit::clearDIEs(bool KeepCUDie) { if (DieArray.size() > (unsigned)KeepCUDie) { // std::vectors never get any smaller when resized to a smaller size, @@ -241,7 +324,8 @@ void DWARFCompileUnit::clearDIEs(bool KeepCUDie) { void DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed){ + bool clear_dies_if_already_not_parsed, + uint32_t CUOffsetInAranges) { // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. If the DIEs weren't parsed, then we don't want all dies for @@ -250,7 +334,17 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, // down. const bool clear_dies = extractDIEsIfNeeded(false) > 1 && clear_dies_if_already_not_parsed; - DieArray[0].buildAddressRangeTable(this, debug_aranges); + DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges); + bool DWOCreated = parseDWO(); + if (DWO.get()) { + // If there is a .dwo file for this compile unit, then skeleton CU DIE + // doesn't have children, and we should instead build address range table + // from DIEs in the .debug_info.dwo section of .dwo file. + DWO->getCU()->buildAddressRangeTable( + debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges); + } + if (DWOCreated && clear_dies_if_already_not_parsed) + DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. @@ -258,21 +352,38 @@ DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, clearDIEs(true); } +const DWARFDebugInfoEntryMinimal * +DWARFCompileUnit::getSubprogramForAddress(uint64_t Address) { + extractDIEsIfNeeded(false); + for (size_t i = 0, n = DieArray.size(); i != n; i++) + if (DieArray[i].isSubprogramDIE() && + DieArray[i].addressRangeContainsAddress(this, Address)) { + return &DieArray[i]; + } + return 0; +} + DWARFDebugInfoEntryInlinedChain DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) { // First, find a subprogram that contains the given address (the root // of inlined chain). - extractDIEsIfNeeded(false); - const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0; - for (size_t i = 0, n = DieArray.size(); i != n; i++) { - if (DieArray[i].isSubprogramDIE() && - DieArray[i].addressRangeContainsAddress(this, Address)) { - SubprogramDIE = &DieArray[i]; - break; + const DWARFCompileUnit *ChainCU = 0; + const DWARFDebugInfoEntryMinimal *SubprogramDIE = + getSubprogramForAddress(Address); + if (SubprogramDIE) { + ChainCU = this; + } else { + // Try to look for subprogram DIEs in the DWO file. + parseDWO(); + if (DWO.get()) { + SubprogramDIE = DWO->getCU()->getSubprogramForAddress(Address); + if (SubprogramDIE) + ChainCU = DWO->getCU(); } } + // Get inlined chain rooted at this subprogram DIE. if (!SubprogramDIE) return DWARFDebugInfoEntryInlinedChain(); - return SubprogramDIE->getInlinedChainForAddress(this, Address); -} + return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); + } diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h index 97f847962e2..09167d128f5 100644 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ b/lib/DebugInfo/DWARFCompileUnit.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H #define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H +#include "llvm/ADT/OwningPtr.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugInfoEntry.h" #include "DWARFDebugRangeList.h" @@ -18,6 +19,10 @@ namespace llvm { +namespace object { +class ObjectFile; +} + class DWARFDebugAbbrev; class StringRef; class raw_ostream; @@ -30,9 +35,11 @@ class DWARFCompileUnit { StringRef InfoSection; StringRef AbbrevSection; StringRef RangeSection; + uint32_t RangeSectionBase; StringRef StringSection; StringRef StringOffsetSection; StringRef AddrOffsetSection; + uint32_t AddrOffsetSectionBase; const RelocAddrMap *RelocMap; bool isLittleEndian; @@ -44,6 +51,17 @@ class DWARFCompileUnit { uint64_t BaseAddr; // The compile unit debug information entry items. std::vector DieArray; + + class DWOHolder { + OwningPtr DWOFile; + OwningPtr DWOContext; + DWARFCompileUnit *DWOCU; + public: + DWOHolder(object::ObjectFile *DWOFile); + DWARFCompileUnit *getCU() const { return DWOCU; } + }; + OwningPtr DWO; + public: DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, @@ -57,9 +75,27 @@ public: StringRef getStringSection() const { return StringSection; } StringRef getStringOffsetSection() const { return StringOffsetSection; } - StringRef getAddrOffsetSection() const { return AddrOffsetSection; } + void setAddrOffsetSection(StringRef AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + void setRangesSection(StringRef RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + // FIXME: Result should be uint64_t in DWARF64. + bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; + + DataExtractor getDebugInfoExtractor() const { + return DataExtractor(InfoSection, isLittleEndian, AddrSize); + } + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + const RelocAddrMap *getRelocMap() const { return RelocMap; } - DataExtractor getDebugInfoExtractor() const; bool extract(DataExtractor debug_info, uint32_t* offset_ptr); uint32_t extract(uint32_t offset, DataExtractor debug_info_data, @@ -105,6 +141,7 @@ public: } const char *getCompilationDir(); + uint64_t getDWOId(); /// setDIERelations - We read in all of the DIE entries into our flat list /// of DIE entries and now we need to go back through all of them and set the @@ -112,7 +149,8 @@ public: void setDIERelations(); void buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed); + bool clear_dies_if_already_not_parsed, + uint32_t CUOffsetInAranges); /// getInlinedChainForAddress - fetches inlined chain for a given address. /// Returns empty chain if there is no subprogram containing address. The @@ -125,6 +163,15 @@ private: std::vector &DIEs) const; /// clearDIEs - Clear parsed DIEs to keep memory usage low. void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); + + /// getSubprogramForAddress - Returns subprogram DIE with address range + /// encompassing the provided address. The pointer is alive as long as parsed + /// compile unit DIEs are not cleared. + const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); }; } diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp index f79862d606f..56de5ea28de 100644 --- a/lib/DebugInfo/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARFDebugAranges.cpp @@ -95,7 +95,7 @@ bool DWARFDebugAranges::generate(DWARFContext *ctx) { if (DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx)) { uint32_t CUOffset = cu->getOffset(); if (ParsedCUOffsets.insert(CUOffset).second) - cu->buildAddressRangeTable(this, true); + cu->buildAddressRangeTable(this, true, CUOffset); } } } diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index 9abf8dd2623..775e68fa23f 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -222,29 +222,30 @@ DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu, return 0; } -const char* -DWARFDebugInfoEntryMinimal::getAttributeValueAsString( - const DWARFCompileUnit* cu, - const uint16_t attr, - const char* fail_value) - const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) { - DataExtractor stringExtractor(cu->getStringSection(), false, 0); - return form_value.getAsCString(&stringExtractor); - } - return fail_value; +const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( + const DWARFCompileUnit *CU, const uint16_t Attr, + const char *FailValue) const { + DWARFFormValue FormValue; + if (getAttributeValue(CU, Attr, FormValue)) + return FormValue.getAsCString(CU); + return FailValue; } -uint64_t -DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned( - const DWARFCompileUnit* cu, - const uint16_t attr, - uint64_t fail_value) const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) - return form_value.getUnsigned(); - return fail_value; +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( + const DWARFCompileUnit *CU, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (getAttributeValue(CU, Attr, FormValue)) + return FormValue.getAsAddress(CU); + return FailValue; +} + +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned( + const DWARFCompileUnit *CU, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (getAttributeValue(CU, Attr, FormValue)) { + return FormValue.getUnsigned(); + } + return FailValue; } int64_t @@ -274,29 +275,29 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFCompileUnit *CU, uint64_t &LowPC, uint64_t &HighPC) const { HighPC = -1ULL; - LowPC = getAttributeValueAsUnsigned(CU, DW_AT_low_pc, -1ULL); + LowPC = getAttributeValueAsAddress(CU, DW_AT_low_pc, -1ULL); if (LowPC != -1ULL) - HighPC = getAttributeValueAsUnsigned(CU, DW_AT_high_pc, -1ULL); + HighPC = getAttributeValueAsAddress(CU, DW_AT_high_pc, -1ULL); return (HighPC != -1ULL); } void DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *CU, - DWARFDebugAranges *DebugAranges) + DWARFDebugAranges *DebugAranges, + uint32_t CUOffsetInAranges) const { if (AbbrevDecl) { if (isSubprogramDIE()) { uint64_t LowPC, HighPC; - if (getLowAndHighPC(CU, LowPC, HighPC)) { - DebugAranges->appendRange(CU->getOffset(), LowPC, HighPC); - } + if (getLowAndHighPC(CU, LowPC, HighPC)) + DebugAranges->appendRange(CUOffsetInAranges, LowPC, HighPC); // FIXME: try to append ranges from .debug_ranges section. } - const DWARFDebugInfoEntryMinimal *child = getFirstChild(); - while (child) { - child->buildAddressRangeTable(CU, DebugAranges); - child = child->getSibling(); + const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); + while (Child) { + Child->buildAddressRangeTable(CU, DebugAranges, CUOffsetInAranges); + Child = Child->getSibling(); } } } diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h index a69911f5618..2feea36b919 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.h +++ b/lib/DebugInfo/DWARFDebugInfoEntry.h @@ -128,6 +128,10 @@ public: const uint16_t attr, const char *fail_value) const; + uint64_t getAttributeValueAsAddress(const DWARFCompileUnit *CU, + const uint16_t Attr, + uint64_t FailValue) const; + uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu, const uint16_t attr, uint64_t fail_value) const; @@ -146,7 +150,8 @@ public: uint64_t &LowPC, uint64_t &HighPC) const; void buildAddressRangeTable(const DWARFCompileUnit *CU, - DWARFDebugAranges *DebugAranges) const; + DWARFDebugAranges *DebugAranges, + uint32_t CUOffsetInAranges) const; bool addressRangeContainsAddress(const DWARFCompileUnit *CU, const uint64_t Address) const; diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index 1a1cf2452cd..48e0d209080 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -183,10 +183,9 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, Value.uval = data.getU64(offset_ptr); break; case DW_FORM_GNU_addr_index: - Value.uval = data.getULEB128(offset_ptr); - break; case DW_FORM_GNU_str_index: Value.uval = data.getULEB128(offset_ptr); + Value.IsDWOIndex = true; break; default: return false; @@ -322,12 +321,11 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { switch (Form) { case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; case DW_FORM_GNU_addr_index: { - StringRef AddrOffsetSec = cu->getAddrOffsetSection(); OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); - if (AddrOffsetSec.size() != 0) { - DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize()); - OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu)); - } else + uint64_t Address; + if (cu->getAddrOffsetSectionItem(uvalue, Address)) + OS << format("0x%016" PRIx64, Address); + else OS << ""; break; } @@ -376,7 +374,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { case DW_FORM_udata: OS << getUnsigned(); break; case DW_FORM_strp: { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); - const char* dbg_str = getAsCString(&debug_str_data); + const char* dbg_str = getAsCString(cu); if (dbg_str) { OS << '"'; OS.write_escaped(dbg_str); @@ -386,8 +384,7 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { } case DW_FORM_GNU_str_index: { OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); - const char *dbg_str = getIndirectCString(&debug_str_data, - &debug_str_offset_data); + const char *dbg_str = getAsCString(cu); if (dbg_str) { OS << '"'; OS.write_escaped(dbg_str); @@ -440,33 +437,33 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { } const char* -DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const { - if (isInlinedCStr()) { +DWARFFormValue::getAsCString(const DWARFCompileUnit *CU) const { + if (isInlinedCStr()) return Value.cstr; - } else if (debug_str_data_ptr) { - uint32_t offset = Value.uval; - return debug_str_data_ptr->getCStr(&offset); + if (!CU) + return NULL; + uint32_t Offset = Value.uval; + if (Value.IsDWOIndex) { + uint32_t StrOffset; + if (!CU->getStringOffsetSectionItem(Offset, StrOffset)) + return NULL; + Offset = StrOffset; } - return NULL; -} - -const char* -DWARFFormValue::getIndirectCString(const DataExtractor *DS, - const DataExtractor *DSO) const { - if (!DS || !DSO) return NULL; - - uint32_t offset = Value.uval * 4; - uint32_t soffset = DSO->getU32(&offset); - return DS->getCStr(&soffset); + return CU->getStringExtractor().getCStr(&Offset); } uint64_t -DWARFFormValue::getIndirectAddress(const DataExtractor *DA, - const DWARFCompileUnit *cu) const { - if (!DA) return 0; - - uint32_t offset = Value.uval * cu->getAddressByteSize(); - return DA->getAddress(&offset); +DWARFFormValue::getAsAddress(const DWARFCompileUnit *CU) const { + if (!CU) + return 0; + if (Value.IsDWOIndex) { + uint32_t Index = Value.uval; + uint64_t Address; + if (!CU->getAddrOffsetSectionItem(Index, Address)) + return 0; + return Address; + } + return Value.uval; } uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {