summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-08-27 09:20:22 +0000
committerAlexey Samsonov <samsonov@google.com>2013-08-27 09:20:22 +0000
commit63fd2af3892a81026f40374d08b5124e72ccff4e (patch)
tree8587e5f891d29f8cf006b2d3e39adebe47fa7a7b
parent1567abe74f519e542786bdb82664f68b10afda0b (diff)
downloadllvm-63fd2af3892a81026f40374d08b5124e72ccff4e.tar.gz
llvm-63fd2af3892a81026f40374d08b5124e72ccff4e.tar.bz2
llvm-63fd2af3892a81026f40374d08b5124e72ccff4e.tar.xz
Add support for DebugFission to DWARF parser
Summary: 1) Make llvm-symbolizer properly symbolize files with split debug info (by using stanalone .dwo files). 2) Make DWARFCompileUnit parse and store corresponding .dwo file, if necessary. 3) Make bits of DWARF parsing more CompileUnit-oriented. Reviewers: echristo Reviewed By: echristo CC: bkramer, llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1164 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189329 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/DebugInfo/DWARFFormValue.h10
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.cpp145
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h53
-rw-r--r--lib/DebugInfo/DWARFDebugAranges.cpp2
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp63
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.h7
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp61
7 files changed, 250 insertions, 91 deletions
diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h
index eaaccfb4f3..ad6f71d664 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 93b1622e80..4b6aa272f7 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<DWARFContext>(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 97f847962e..09167d128f 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<DWARFDebugInfoEntryMinimal> DieArray;
+
+ class DWOHolder {
+ OwningPtr<object::ObjectFile> DWOFile;
+ OwningPtr<DWARFContext> DWOContext;
+ DWARFCompileUnit *DWOCU;
+ public:
+ DWOHolder(object::ObjectFile *DWOFile);
+ DWARFCompileUnit *getCU() const { return DWOCU; }
+ };
+ OwningPtr<DWOHolder> 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<DWARFDebugInfoEntryMinimal> &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 f79862d606..56de5ea28d 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 9abf8dd262..775e68fa23 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 a69911f561..2feea36b91 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 1a1cf2452c..48e0d20908 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 << "<no .debug_addr section>";
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 {