aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2013-03-14 10:51:38 +0000
committerAlexander Kornienko <alexfh@google.com>2013-03-14 10:51:38 +0000
commit647735c781c5b37061ee03d6e9e6c7dda92218e2 (patch)
tree5a5e56606d41060263048b5a5586b3d2380898ba /lib/DebugInfo
parent6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (diff)
parentf635ef401786c84df32090251a8cf45981ecca33 (diff)
Updating branches/google/stable to r176857
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@177040 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/DWARFAbbreviationDeclaration.cpp18
-rw-r--r--lib/DebugInfo/DWARFAbbreviationDeclaration.h10
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.cpp15
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h27
-rw-r--r--lib/DebugInfo/DWARFContext.cpp313
-rw-r--r--lib/DebugInfo/DWARFContext.h86
-rw-r--r--lib/DebugInfo/DWARFDebugFrame.cpp391
-rw-r--r--lib/DebugInfo/DWARFDebugFrame.h46
-rw-r--r--lib/DebugInfo/DWARFDebugInfoEntry.cpp30
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp92
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h8
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp91
-rw-r--r--lib/DebugInfo/DWARFFormValue.h4
-rw-r--r--lib/DebugInfo/DWARFRelocMap.h22
15 files changed, 1027 insertions, 127 deletions
diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt
index 1e9e509fd2..e97455abac 100644
--- a/lib/DebugInfo/CMakeLists.txt
+++ b/lib/DebugInfo/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_library(LLVMDebugInfo
DWARFDebugAbbrev.cpp
DWARFDebugArangeSet.cpp
DWARFDebugAranges.cpp
+ DWARFDebugFrame.cpp
DWARFDebugInfoEntry.cpp
DWARFDebugLine.cpp
DWARFDebugRangeList.cpp
diff --git a/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
index 0df692c3a3..2de62ab938 100644
--- a/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
+++ b/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp
@@ -23,7 +23,7 @@ bool
DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr,
uint32_t code) {
Code = code;
- Attributes.clear();
+ Attribute.clear();
if (Code) {
Tag = data.getULEB128(offset_ptr);
HasChildren = data.getU8(offset_ptr);
@@ -33,7 +33,7 @@ DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr,
uint16_t form = data.getULEB128(offset_ptr);
if (attr && form)
- Attributes.push_back(DWARFAttribute(attr, form));
+ Attribute.push_back(DWARFAttribute(attr, form));
else
break;
}
@@ -55,19 +55,19 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
else
OS << format("DW_TAG_Unknown_%x", getTag());
OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
- for (unsigned i = 0, e = Attributes.size(); i != e; ++i) {
+ for (unsigned i = 0, e = Attribute.size(); i != e; ++i) {
OS << '\t';
- const char *attrString = AttributeString(Attributes[i].getAttribute());
+ const char *attrString = AttributeString(Attribute[i].getAttribute());
if (attrString)
OS << attrString;
else
- OS << format("DW_AT_Unknown_%x", Attributes[i].getAttribute());
+ OS << format("DW_AT_Unknown_%x", Attribute[i].getAttribute());
OS << '\t';
- const char *formString = FormEncodingString(Attributes[i].getForm());
+ const char *formString = FormEncodingString(Attribute[i].getForm());
if (formString)
OS << formString;
else
- OS << format("DW_FORM_Unknown_%x", Attributes[i].getForm());
+ OS << format("DW_FORM_Unknown_%x", Attribute[i].getForm());
OS << '\n';
}
OS << '\n';
@@ -75,8 +75,8 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
uint32_t
DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
- for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) {
- if (Attributes[i].getAttribute() == attr)
+ for (uint32_t i = 0, e = Attribute.size(); i != e; ++i) {
+ if (Attribute[i].getAttribute() == attr)
return i;
}
return -1U;
diff --git a/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/lib/DebugInfo/DWARFAbbreviationDeclaration.h
index 2463a3cc04..9a3fcd8a78 100644
--- a/lib/DebugInfo/DWARFAbbreviationDeclaration.h
+++ b/lib/DebugInfo/DWARFAbbreviationDeclaration.h
@@ -22,7 +22,7 @@ class DWARFAbbreviationDeclaration {
uint32_t Code;
uint32_t Tag;
bool HasChildren;
- SmallVector<DWARFAttribute, 8> Attributes;
+ SmallVector<DWARFAttribute, 8> Attribute;
public:
enum { InvalidCode = 0 };
DWARFAbbreviationDeclaration()
@@ -31,12 +31,12 @@ public:
uint32_t getCode() const { return Code; }
uint32_t getTag() const { return Tag; }
bool hasChildren() const { return HasChildren; }
- uint32_t getNumAttributes() const { return Attributes.size(); }
+ uint32_t getNumAttributes() const { return Attribute.size(); }
uint16_t getAttrByIndex(uint32_t idx) const {
- return Attributes.size() > idx ? Attributes[idx].getAttribute() : 0;
+ return Attribute.size() > idx ? Attribute[idx].getAttribute() : 0;
}
uint16_t getFormByIndex(uint32_t idx) const {
- return Attributes.size() > idx ? Attributes[idx].getForm() : 0;
+ return Attribute.size() > idx ? Attribute[idx].getForm() : 0;
}
uint32_t findAttributeIndex(uint16_t attr) const;
@@ -45,7 +45,7 @@ public:
bool isValid() const { return Code != 0 && Tag != 0; }
void dump(raw_ostream &OS) const;
const SmallVectorImpl<DWARFAttribute> &getAttributes() const {
- return Attributes;
+ return Attribute;
}
};
diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp
index bdd65b77e4..e3e4ccd7d9 100644
--- a/lib/DebugInfo/DWARFCompileUnit.cpp
+++ b/lib/DebugInfo/DWARFCompileUnit.cpp
@@ -17,8 +17,7 @@ using namespace llvm;
using namespace dwarf;
DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const {
- return DataExtractor(Context.getInfoSection(),
- Context.isLittleEndian(), getAddressByteSize());
+ return DataExtractor(InfoSection, isLittleEndian, AddrSize);
}
bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
@@ -28,7 +27,6 @@ bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
if (debug_info.isValidOffset(*offset_ptr)) {
uint64_t abbrOffset;
- const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev();
Length = debug_info.getU32(offset_ptr);
Version = debug_info.getU16(offset_ptr);
abbrOffset = debug_info.getU32(offset_ptr);
@@ -36,11 +34,11 @@ bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1);
bool versionOK = DWARFContext::isSupportedVersion(Version);
- bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset;
+ bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
bool addrSizeOK = AddrSize == 4 || AddrSize == 8;
- if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) {
- Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset);
+ if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && Abbrev != NULL) {
+ Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
return true;
}
@@ -79,8 +77,7 @@ bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset,
DWARFDebugRangeList &RangeList) const {
// Require that compile unit is extracted.
assert(DieArray.size() > 0);
- DataExtractor RangesData(Context.getRangeSection(),
- Context.isLittleEndian(), AddrSize);
+ DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
return RangeList.extract(RangesData, &RangeListOffset);
}
@@ -211,7 +208,7 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
// should always terminate at or before the start of the next compilation
// unit header).
if (offset > next_cu_offset)
- fprintf(stderr, "warning: DWARF compile unit extends beyond its"
+ fprintf(stderr, "warning: DWARF compile unit extends beyond its "
"bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset);
setDIERelations();
diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h
index 03e28620d4..2a74605fcb 100644
--- a/lib/DebugInfo/DWARFCompileUnit.h
+++ b/lib/DebugInfo/DWARFCompileUnit.h
@@ -13,15 +13,25 @@
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugRangeList.h"
+#include "DWARFRelocMap.h"
#include <vector>
namespace llvm {
-class DWARFContext;
+class DWARFDebugAbbrev;
+class StringRef;
class raw_ostream;
class DWARFCompileUnit {
- DWARFContext &Context;
+ const DWARFDebugAbbrev *Abbrev;
+ StringRef InfoSection;
+ StringRef AbbrevSection;
+ StringRef RangeSection;
+ StringRef StringSection;
+ StringRef StringOffsetSection;
+ StringRef AddrOffsetSection;
+ const RelocAddrMap *RelocMap;
+ bool isLittleEndian;
uint32_t Offset;
uint32_t Length;
@@ -32,11 +42,20 @@ class DWARFCompileUnit {
// The compile unit debug information entry item.
std::vector<DWARFDebugInfoEntryMinimal> DieArray;
public:
- DWARFCompileUnit(DWARFContext &context) : Context(context) {
+
+ DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
+ StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
+ const RelocAddrMap *M, bool LE) :
+ Abbrev(DA), InfoSection(IS), AbbrevSection(AS),
+ RangeSection(RS), StringSection(SS), StringOffsetSection(SOS),
+ AddrOffsetSection(AOS), RelocMap(M), isLittleEndian(LE) {
clear();
}
- DWARFContext &getContext() const { return Context; }
+ StringRef getStringSection() const { return StringSection; }
+ StringRef getStringOffsetSection() const { return StringOffsetSection; }
+ StringRef getAddrOffsetSection() const { return AddrOffsetSection; }
+ const RelocAddrMap *getRelocMap() const { return RelocMap; }
DataExtractor getDebugInfoExtractor() const;
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 91ed2d22ab..9e19310a99 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -19,57 +19,124 @@ using namespace dwarf;
typedef DWARFDebugLine::LineTable DWARFLineTable;
-void DWARFContext::dump(raw_ostream &OS) {
- OS << ".debug_abbrev contents:\n";
- getDebugAbbrev()->dump(OS);
+void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
+ if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
+ OS << ".debug_abbrev contents:\n";
+ getDebugAbbrev()->dump(OS);
+ }
- OS << "\n.debug_info contents:\n";
- for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
- getCompileUnitAtIndex(i)->dump(OS);
+ if (DumpType == DIDT_All || DumpType == DIDT_Info) {
+ OS << "\n.debug_info contents:\n";
+ for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
+ getCompileUnitAtIndex(i)->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
+ OS << "\n.debug_frame contents:\n";
+ getDebugFrame()->dump(OS);
+ }
- OS << "\n.debug_aranges contents:\n";
- DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
uint32_t offset = 0;
- DWARFDebugArangeSet set;
- while (set.extract(arangesData, &offset))
- set.dump(OS);
+ if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
+ OS << "\n.debug_aranges contents:\n";
+ DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
+ DWARFDebugArangeSet set;
+ while (set.extract(arangesData, &offset))
+ set.dump(OS);
+ }
uint8_t savedAddressByteSize = 0;
- OS << "\n.debug_line contents:\n";
- for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
- DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
- savedAddressByteSize = cu->getAddressByteSize();
- unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
- -1U);
- if (stmtOffset != -1U) {
- DataExtractor lineData(getLineSection(), isLittleEndian(),
+ if (DumpType == DIDT_All || DumpType == DIDT_Line) {
+ OS << "\n.debug_line contents:\n";
+ for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
+ DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
+ savedAddressByteSize = cu->getAddressByteSize();
+ unsigned stmtOffset =
+ cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
+ -1U);
+ if (stmtOffset != -1U) {
+ DataExtractor lineData(getLineSection(), isLittleEndian(),
+ savedAddressByteSize);
+ DWARFDebugLine::DumpingState state(OS);
+ DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state);
+ }
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Str) {
+ OS << "\n.debug_str contents:\n";
+ DataExtractor strData(getStringSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint32_t strOffset = 0;
+ while (const char *s = strData.getCStr(&offset)) {
+ OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
+ strOffset = offset;
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Ranges) {
+ OS << "\n.debug_ranges contents:\n";
+ // In fact, different compile units may have different address byte
+ // sizes, but for simplicity we just use the address byte size of the last
+ // compile unit (there is no easy and fast way to associate address range
+ // list and the compile unit it describes).
+ DataExtractor rangesData(getRangeSection(), isLittleEndian(),
savedAddressByteSize);
- DWARFDebugLine::DumpingState state(OS);
- DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
+ offset = 0;
+ DWARFDebugRangeList rangeList;
+ while (rangeList.extract(rangesData, &offset))
+ rangeList.dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) {
+ OS << "\n.debug_pubnames contents:\n";
+ DataExtractor pubNames(getPubNamesSection(), isLittleEndian(), 0);
+ offset = 0;
+ OS << "Length: " << pubNames.getU32(&offset) << "\n";
+ OS << "Version: " << pubNames.getU16(&offset) << "\n";
+ OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n";
+ OS << "Size: " << pubNames.getU32(&offset) << "\n";
+ OS << "\n Offset Name\n";
+ while (offset < getPubNamesSection().size()) {
+ uint32_t n = pubNames.getU32(&offset);
+ if (n == 0)
+ break;
+ OS << format("%8x ", n);
+ OS << pubNames.getCStr(&offset) << "\n";
}
}
- OS << "\n.debug_str contents:\n";
- DataExtractor strData(getStringSection(), isLittleEndian(), 0);
- offset = 0;
- uint32_t lastOffset = 0;
- while (const char *s = strData.getCStr(&offset)) {
- OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
- lastOffset = offset;
+ if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
+ OS << "\n.debug_abbrev.dwo contents:\n";
+ getDebugAbbrevDWO()->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) {
+ OS << "\n.debug_info.dwo contents:\n";
+ for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
+ getDWOCompileUnitAtIndex(i)->dump(OS);
}
- OS << "\n.debug_ranges contents:\n";
- // In fact, different compile units may have different address byte
- // sizes, but for simplicity we just use the address byte size of the last
- // compile unit (there is no easy and fast way to associate address range
- // list and the compile unit it describes).
- DataExtractor rangesData(getRangeSection(), isLittleEndian(),
- savedAddressByteSize);
- offset = 0;
- DWARFDebugRangeList rangeList;
- while (rangeList.extract(rangesData, &offset))
- rangeList.dump(OS);
+ if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) {
+ OS << "\n.debug_str.dwo contents:\n";
+ DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint32_t strDWOOffset = 0;
+ while (const char *s = strDWOData.getCStr(&offset)) {
+ OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
+ strDWOOffset = offset;
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
+ OS << "\n.debug_str_offsets.dwo contents:\n";
+ DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
+ offset = 0;
+ while (offset < getStringOffsetDWOSection().size()) {
+ OS << format("0x%8.8x: ", offset);
+ OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
+ }
+ }
}
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@@ -83,6 +150,16 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
return Abbrev.get();
}
+const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
+ if (AbbrevDWO)
+ return AbbrevDWO.get();
+
+ DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
+ AbbrevDWO.reset(new DWARFDebugAbbrev());
+ AbbrevDWO->parse(abbrData);
+ return AbbrevDWO.get();
+}
+
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
if (Aranges)
return Aranges.get();
@@ -98,10 +175,30 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
return Aranges.get();
}
+const DWARFDebugFrame *DWARFContext::getDebugFrame() {
+ if (DebugFrame)
+ return DebugFrame.get();
+
+ // There's a "bug" in the DWARFv3 standard with respect to the target address
+ // size within debug frame sections. While DWARF is supposed to be independent
+ // of its container, FDEs have fields with size being "target address size",
+ // which isn't specified in DWARF in general. It's only specified for CUs, but
+ // .eh_frame can appear without a .debug_info section. Follow the example of
+ // other tools (libdwarf) and extract this from the container (ObjectFile
+ // provides this information). This problem is fixed in DWARFv4
+ // See this dwarf-discuss discussion for more details:
+ // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
+ DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(),
+ getAddressSize());
+ DebugFrame.reset(new DWARFDebugFrame());
+ DebugFrame->parse(debugFrameData);
+ return DebugFrame.get();
+}
+
const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
- Line.reset(new DWARFDebugLine());
+ Line.reset(new DWARFDebugLine(&lineRelocMap()));
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
@@ -124,7 +221,12 @@ void DWARFContext::parseCompileUnits() {
const DataExtractor &DIData = DataExtractor(getInfoSection(),
isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- CUs.push_back(DWARFCompileUnit(*this));
+ CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
+ getAbbrevSection(), getRangeSection(),
+ getStringSection(), StringRef(),
+ getAddrSection(),
+ &infoRelocMap(),
+ isLittleEndian()));
if (!CUs.back().extract(DIData, &offset)) {
CUs.pop_back();
break;
@@ -134,6 +236,28 @@ void DWARFContext::parseCompileUnits() {
}
}
+void DWARFContext::parseDWOCompileUnits() {
+ uint32_t offset = 0;
+ const DataExtractor &DIData = DataExtractor(getInfoDWOSection(),
+ isLittleEndian(), 0);
+ while (DIData.isValidOffset(offset)) {
+ DWOCUs.push_back(DWARFCompileUnit(getDebugAbbrevDWO(), getInfoDWOSection(),
+ getAbbrevDWOSection(),
+ getRangeDWOSection(),
+ getStringDWOSection(),
+ getStringOffsetDWOSection(),
+ getAddrSection(),
+ &infoDWORelocMap(),
+ isLittleEndian()));
+ if (!DWOCUs.back().extract(DIData, &offset)) {
+ DWOCUs.pop_back();
+ break;
+ }
+
+ offset = DWOCUs.back().getNextCompileUnitOffset();
+ }
+}
+
namespace {
struct OffsetComparator {
bool operator()(const DWARFCompileUnit &LHS,
@@ -244,6 +368,64 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
Line, Column);
}
+DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address,
+ uint64_t Size,
+ DILineInfoSpecifier Specifier) {
+ DILineInfoTable Lines;
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return Lines;
+
+ std::string FunctionName = "<invalid>";
+ if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
+ // The address may correspond to instruction in some inlined function,
+ // so we have to build the chain of inlined functions and take the
+ // name of the topmost function in it.
+ const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ FunctionName = Name;
+ }
+ }
+
+ StringRef FuncNameRef = StringRef(FunctionName);
+
+ // If the Specifier says we don't need FileLineInfo, just
+ // return the top-most function at the starting address.
+ if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
+ Lines.push_back(std::make_pair(Address,
+ DILineInfo(StringRef("<invalid>"),
+ FuncNameRef, 0, 0)));
+ return Lines;
+ }
+
+ const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
+ const bool NeedsAbsoluteFilePath =
+ Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
+
+ // Get the index of row we're looking for in the line table.
+ std::vector<uint32_t> RowVector;
+ if (!LineTable->lookupAddressRange(Address, Size, RowVector))
+ return Lines;
+
+ uint32_t NumRows = RowVector.size();
+ for (uint32_t i = 0; i < NumRows; ++i) {
+ uint32_t RowIndex = RowVector[i];
+ // Take file number and line/column from the row.
+ const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
+ std::string FileName = "<invalid>";
+ getFileNameForCompileUnit(CU, LineTable, Row.File,
+ NeedsAbsoluteFilePath, FileName);
+ Lines.push_back(std::make_pair(Row.Address,
+ DILineInfo(StringRef(FileName),
+ FuncNameRef, Row.Line, Row.Column)));
+ }
+
+ return Lines;
+}
+
DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier) {
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
@@ -301,7 +483,8 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
}
DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
- IsLittleEndian(true /* FIXME */) {
+ IsLittleEndian(Obj->isLittleEndian()),
+ AddressSize(Obj->getBytesInAddress()) {
error_code ec;
for (object::section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
@@ -311,8 +494,6 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
StringRef data;
i->getContents(data);
- if (name.startswith("__DWARF,"))
- name = name.substr(8); // Skip "__DWARF," prefix.
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
if (name == "debug_info")
InfoSection = data;
@@ -322,16 +503,41 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
LineSection = data;
else if (name == "debug_aranges")
ARangeSection = data;
+ else if (name == "debug_frame")
+ DebugFrameSection = data;
else if (name == "debug_str")
StringSection = data;
- else if (name == "debug_ranges")
+ else if (name == "debug_ranges") {
+ // FIXME: Use the other dwo range section when we emit it.
+ RangeDWOSection = data;
RangeSection = data;
+ }
+ else if (name == "debug_pubnames")
+ PubNamesSection = data;
+ else if (name == "debug_info.dwo")
+ InfoDWOSection = data;
+ else if (name == "debug_abbrev.dwo")
+ AbbrevDWOSection = data;
+ else if (name == "debug_str.dwo")
+ StringDWOSection = data;
+ else if (name == "debug_str_offsets.dwo")
+ StringOffsetDWOSection = data;
+ else if (name == "debug_addr")
+ AddrSection = data;
// Any more debug info sections go here.
else
continue;
- // TODO: For now only handle relocations for the debug_info section.
- if (name != "debug_info")
+ // TODO: Add support for relocations in other sections as needed.
+ // Record relocations for the debug_info and debug_line sections.
+ RelocAddrMap *Map;
+ if (name == "debug_info")
+ Map = &InfoRelocMap;
+ else if (name == "debug_info.dwo")
+ Map = &InfoDWORelocMap;
+ else if (name == "debug_line")
+ Map = &LineRelocMap;
+ else
continue;
if (i->begin_relocations() != i->end_relocations()) {
@@ -344,10 +550,17 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
reloc_i->getAddress(Address);
uint64_t Type;
reloc_i->getType(Type);
+ uint64_t SymAddr = 0;
+ // ELF relocations may need the symbol address
+ if (Obj->isELF()) {
+ object::SymbolRef Sym;
+ reloc_i->getSymbol(Sym);
+ Sym.getAddress(SymAddr);
+ }
object::RelocVisitor V(Obj->getFileFormatName());
// The section address is always 0 for debug sections.
- object::RelocToApply R(V.visit(Type, *reloc_i));
+ object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr));
if (V.error()) {
SmallString<32> Name;
error_code ec(reloc_i->getTypeName(Name));
@@ -374,7 +587,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
<< " at " << format("%p", Address)
<< " with width " << format("%d", R.Width)
<< "\n");
- RelocMap[Address] = std::make_pair(R.Width, R.Value);
+ Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
}
}
}
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index 24613594de..37b272993f 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -12,6 +12,7 @@
#include "DWARFCompileUnit.h"
#include "DWARFDebugAranges.h"
+#include "DWARFDebugFrame.h"
#include "DWARFDebugLine.h"
#include "DWARFDebugRangeList.h"
#include "llvm/ADT/OwningPtr.h"
@@ -29,6 +30,10 @@ class DWARFContext : public DIContext {
OwningPtr<DWARFDebugAbbrev> Abbrev;
OwningPtr<DWARFDebugAranges> Aranges;
OwningPtr<DWARFDebugLine> Line;
+ OwningPtr<DWARFDebugFrame> DebugFrame;
+
+ SmallVector<DWARFCompileUnit, 1> DWOCUs;
+ OwningPtr<DWARFDebugAbbrev> AbbrevDWO;
DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION;
DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION;
@@ -36,9 +41,13 @@ class DWARFContext : public DIContext {
/// Read compile units from the debug_info section and store them in CUs.
void parseCompileUnits();
+ /// Read compile units from the debug_info.dwo section and store them in
+ /// DWOCUs.
+ void parseDWOCompileUnits();
+
public:
DWARFContext() {}
- virtual void dump(raw_ostream &OS);
+ virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All);
/// Get the number of compile units in this context.
unsigned getNumCompileUnits() {
@@ -46,6 +55,14 @@ public:
parseCompileUnits();
return CUs.size();
}
+
+ /// Get the number of compile units in the DWO context.
+ unsigned getNumDWOCompileUnits() {
+ if (DWOCUs.empty())
+ parseDWOCompileUnits();
+ return DWOCUs.size();
+ }
+
/// Get the compile unit at the specified index for this compile unit.
DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
if (CUs.empty())
@@ -53,29 +70,57 @@ public:
return &CUs[index];
}
+ /// Get the compile unit at the specified index for the DWO compile units.
+ DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) {
+ if (DWOCUs.empty())
+ parseDWOCompileUnits();
+ return &DWOCUs[index];
+ }
+
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
+ /// Get a pointer to the parsed dwo abbreviations object.
+ const DWARFDebugAbbrev *getDebugAbbrevDWO();
+
/// Get a pointer to the parsed DebugAranges object.
const DWARFDebugAranges *getDebugAranges();
+ /// Get a pointer to the parsed frame information object.
+ const DWARFDebugFrame *getDebugFrame();
+
/// Get a pointer to a parsed line table corresponding to a compile unit.
const DWARFDebugLine::LineTable *
getLineTableForCompileUnit(DWARFCompileUnit *cu);
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier());
+ virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
+ uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier());
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier());
virtual bool isLittleEndian() const = 0;
- virtual const RelocAddrMap &relocMap() const = 0;
+ virtual uint8_t getAddressSize() const = 0;
+ virtual const RelocAddrMap &infoRelocMap() const = 0;
+ virtual const RelocAddrMap &lineRelocMap() const = 0;
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
virtual StringRef getARangeSection() = 0;
+ virtual StringRef getDebugFrameSection() = 0;
virtual StringRef getLineSection() = 0;
virtual StringRef getStringSection() = 0;
virtual StringRef getRangeSection() = 0;
+ virtual StringRef getPubNamesSection() = 0;
+
+ // Sections for DWARF5 split dwarf proposal.
+ virtual StringRef getInfoDWOSection() = 0;
+ virtual StringRef getAbbrevDWOSection() = 0;
+ virtual StringRef getStringDWOSection() = 0;
+ virtual StringRef getStringOffsetDWOSection() = 0;
+ virtual StringRef getRangeDWOSection() = 0;
+ virtual StringRef getAddrSection() = 0;
+ virtual const RelocAddrMap &infoDWORelocMap() const = 0;
static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3;
@@ -95,23 +140,56 @@ private:
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
bool IsLittleEndian;
- RelocAddrMap RelocMap;
+ uint8_t AddressSize;
+ RelocAddrMap InfoRelocMap;
+ RelocAddrMap LineRelocMap;
StringRef InfoSection;
StringRef AbbrevSection;
StringRef ARangeSection;
+ StringRef DebugFrameSection;
StringRef LineSection;
StringRef StringSection;
StringRef RangeSection;
+ StringRef PubNamesSection;
+
+ // Sections for DWARF5 split dwarf proposal.
+ RelocAddrMap InfoDWORelocMap;
+ StringRef InfoDWOSection;
+ StringRef AbbrevDWOSection;
+ StringRef StringDWOSection;
+ StringRef StringOffsetDWOSection;
+ StringRef RangeDWOSection;
+ StringRef AddrSection;
+
public:
DWARFContextInMemory(object::ObjectFile *);
virtual bool isLittleEndian() const { return IsLittleEndian; }
- virtual const RelocAddrMap &relocMap() const { return RelocMap; }
+ virtual uint8_t getAddressSize() const { return AddressSize; }
+ virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
+ virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
virtual StringRef getInfoSection() { return InfoSection; }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
virtual StringRef getARangeSection() { return ARangeSection; }
+ virtual StringRef getDebugFrameSection() { return DebugFrameSection; }
virtual StringRef getLineSection() { return LineSection; }
virtual StringRef getStringSection() { return StringSection; }
virtual StringRef getRangeSection() { return RangeSection; }
+ virtual StringRef getPubNamesSection() { return PubNamesSection; }
+
+ // Sections for DWARF5 split dwarf proposal.
+ virtual StringRef getInfoDWOSection() { return InfoDWOSection; }
+ virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; }
+ virtual StringRef getStringDWOSection() { return StringDWOSection; }
+ virtual StringRef getStringOffsetDWOSection() {
+ return StringOffsetDWOSection;
+ }
+ virtual StringRef getRangeDWOSection() { return RangeDWOSection; }
+ virtual StringRef getAddrSection() {
+ return AddrSection;
+ }
+ virtual const RelocAddrMap &infoDWORelocMap() const {
+ return InfoDWORelocMap;
+ }
};
}
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp
new file mode 100644
index 0000000000..3efe6a1ebd
--- /dev/null
+++ b/lib/DebugInfo/DWARFDebugFrame.cpp
@@ -0,0 +1,391 @@
+//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugFrame.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+
+/// \brief Abstract frame entry defining the common interface concrete
+/// entries implement.
+class llvm::FrameEntry {
+public:
+ enum FrameKind {FK_CIE, FK_FDE};
+ FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
+ : Kind(K), Data(D), Offset(Offset), Length(Length) {}
+
+ virtual ~FrameEntry() {
+ }
+
+ FrameKind getKind() const { return Kind; }
+ virtual uint64_t getOffset() const { return Offset; }
+
+ /// \brief Parse and store a sequence of CFI instructions from our data
+ /// stream, starting at *Offset and ending at EndOffset. If everything
+ /// goes well, *Offset should be equal to EndOffset when this method
+ /// returns. Otherwise, an error occurred.
+ virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset);
+
+ /// \brief Dump the entry header to the given output stream.
+ virtual void dumpHeader(raw_ostream &OS) const = 0;
+
+ /// \brief Dump the entry's instructions to the given output stream.
+ virtual void dumpInstructions(raw_ostream &OS) const;
+
+protected:
+ const FrameKind Kind;
+
+ /// \brief The data stream holding the section from which the entry was
+ /// parsed.
+ DataExtractor Data;
+
+ /// \brief Offset of this entry in the section.
+ uint64_t Offset;
+
+ /// \brief Entry length as specified in DWARF.
+ uint64_t Length;
+
+ /// An entry may contain CFI instructions. An instruction consists of an
+ /// opcode and an optional sequence of operands.
+ typedef std::vector<uint64_t> Operands;
+ struct Instruction {
+ Instruction(uint8_t Opcode)
+ : Opcode(Opcode)
+ {}
+
+ uint8_t Opcode;
+ Operands Ops;
+ };
+
+ std::vector<Instruction> Instructions;
+
+ /// Convenience methods to add a new instruction with the given opcode and
+ /// operands to the Instructions vector.
+ void addInstruction(uint8_t Opcode) {
+ Instructions.push_back(Instruction(Opcode));
+ }
+
+ void addInstruction(uint8_t Opcode, uint64_t Operand1) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ }
+
+ void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ Instructions.back().Ops.push_back(Operand2);
+ }
+};
+
+
+// See DWARF standard v3, section 7.23
+const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
+const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
+
+
+void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) {
+ while (*Offset < EndOffset) {
+ uint8_t Opcode = Data.getU8(Offset);
+ // Some instructions have a primary opcode encoded in the top bits.
+ uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
+
+ if (Primary) {
+ // If it's a primary opcode, the first operand is encoded in the bottom
+ // bits of the opcode itself.
+ uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
+ switch (Primary) {
+ default: llvm_unreachable("Impossible primary CFI opcode");
+ case DW_CFA_advance_loc:
+ case DW_CFA_restore:
+ addInstruction(Primary, Op1);
+ break;
+ case DW_CFA_offset:
+ addInstruction(Primary, Op1, Data.getULEB128(Offset));
+ break;
+ }
+ } else {
+ // Extended opcode - its value is Opcode itself.
+ switch (Opcode) {
+ default: llvm_unreachable("Invalid extended CFI opcode");
+ case DW_CFA_nop:
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
+ // No operands
+ addInstruction(Opcode);
+ break;
+ case DW_CFA_set_loc:
+ // Operands: Address
+ addInstruction(Opcode, Data.getAddress(Offset));
+ break;
+ case DW_CFA_advance_loc1:
+ // Operands: 1-byte delta
+ addInstruction(Opcode, Data.getU8(Offset));
+ break;
+ case DW_CFA_advance_loc2:
+ // Operands: 2-byte delta
+ addInstruction(Opcode, Data.getU16(Offset));
+ break;
+ case DW_CFA_advance_loc4:
+ // Operands: 4-byte delta
+ addInstruction(Opcode, Data.getU32(Offset));
+ break;
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_def_cfa_offset:
+ // Operands: ULEB128
+ addInstruction(Opcode, Data.getULEB128(Offset));
+ break;
+ case DW_CFA_def_cfa_offset_sf:
+ // Operands: SLEB128
+ addInstruction(Opcode, Data.getSLEB128(Offset));
+ break;
+ case DW_CFA_offset_extended:
+ case DW_CFA_register:
+ case DW_CFA_def_cfa:
+ case DW_CFA_val_offset:
+ // Operands: ULEB128, ULEB128
+ addInstruction(Opcode, Data.getULEB128(Offset),
+ Data.getULEB128(Offset));
+ break;
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_val_offset_sf:
+ // Operands: ULEB128, SLEB128
+ addInstruction(Opcode, Data.getULEB128(Offset),
+ Data.getSLEB128(Offset));
+ break;
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
+ case DW_CFA_val_expression:
+ // TODO: implement this
+ report_fatal_error("Values with expressions not implemented yet!");
+ }
+ }
+ }
+}
+
+
+void FrameEntry::dumpInstructions(raw_ostream &OS) const {
+ // TODO: at the moment only instruction names are dumped. Expand this to
+ // dump operands as well.
+ for (std::vector<Instruction>::const_iterator I = Instructions.begin(),
+ E = Instructions.end();
+ I != E; ++I) {
+ uint8_t Opcode = I->Opcode;
+ if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
+ Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
+ OS << " " << CallFrameString(Opcode) << ":\n";
+ }
+}
+
+
+namespace {
+/// \brief DWARF Common Information Entry (CIE)
+class CIE : public FrameEntry {
+public:
+ // CIEs (and FDEs) are simply container classes, so the only sensible way to
+ // create them is by providing the full parsed contents in the constructor.
+ CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
+ SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
+ : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
+ Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister) {}
+
+ ~CIE() {
+ }
+
+ void dumpHeader(raw_ostream &OS) const {
+ OS << format("%08x %08x %08x CIE",
+ (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
+ << "\n";
+ OS << format(" Version: %d\n", Version);
+ OS << " Augmentation: \"" << Augmentation << "\"\n";
+ OS << format(" Code alignment factor: %u\n",
+ (uint32_t)CodeAlignmentFactor);
+ OS << format(" Data alignment factor: %d\n",
+ (int32_t)DataAlignmentFactor);
+ OS << format(" Return address column: %d\n",
+ (int32_t)ReturnAddressRegister);
+ OS << "\n";
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_CIE;
+ }
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v3
+ uint8_t Version;
+ SmallString<8> Augmentation;
+ uint64_t CodeAlignmentFactor;
+ int64_t DataAlignmentFactor;
+ uint64_t ReturnAddressRegister;
+};
+
+
+/// \brief DWARF Frame Description Entry (FDE)
+class FDE : public FrameEntry {
+public:
+ // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
+ // an offset to the CIE (provided by parsing the FDE header). The CIE itself
+ // is obtained lazily once it's actually required.
+ FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
+ int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
+ : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
+ InitialLocation(InitialLocation), AddressRange(AddressRange),
+ LinkedCIE(NULL) {}
+
+ ~FDE() {
+ }
+
+ void dumpHeader(raw_ostream &OS) const {
+ OS << format("%08x %08x %08x FDE ",
+ (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
+ OS << format("cie=%08x pc=%08x...%08x\n",
+ (int32_t)LinkedCIEOffset,
+ (uint32_t)InitialLocation,
+ (uint32_t)InitialLocation + (uint32_t)AddressRange);
+ if (LinkedCIE) {
+ OS << format("%p\n", LinkedCIE);
+ }
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_FDE;
+ }
+private:
+
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v3
+ uint64_t LinkedCIEOffset;
+ uint64_t InitialLocation;
+ uint64_t AddressRange;
+ CIE *LinkedCIE;
+};
+} // end anonymous namespace
+
+
+DWARFDebugFrame::DWARFDebugFrame() {
+}
+
+
+DWARFDebugFrame::~DWARFDebugFrame() {
+ for (EntryVector::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ delete *I;
+ }
+}
+
+
+static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
+ uint32_t Offset, int Length) {
+ errs() << "DUMP: ";
+ for (int i = 0; i < Length; ++i) {
+ uint8_t c = Data.getU8(&Offset);
+ errs().write_hex(c); errs() << " ";
+ }
+ errs() << "\n";
+}
+
+
+void DWARFDebugFrame::parse(DataExtractor Data) {
+ uint32_t Offset = 0;
+
+ while (Data.isValidOffset(Offset)) {
+ uint32_t StartOffset = Offset;
+
+ bool IsDWARF64 = false;
+ uint64_t Length = Data.getU32(&Offset);
+ uint64_t Id;
+
+ if (Length == UINT32_MAX) {
+ // DWARF-64 is distinguished by the first 32 bits of the initial length
+ // field being 0xffffffff. Then, the next 64 bits are the actual entry
+ // length.
+ IsDWARF64 = true;
+ Length = Data.getU64(&Offset);
+ }
+
+ // At this point, Offset points to the next field after Length.
+ // Length is the structure size excluding itself. Compute an offset one
+ // past the end of the structure (needed to know how many instructions to
+ // read).
+ // TODO: For honest DWARF64 support, DataExtractor will have to treat
+ // offset_ptr as uint64_t*
+ uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
+
+ // The Id field's size depends on the DWARF format
+ Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
+ bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
+
+ FrameEntry *Entry = 0;
+ if (IsCIE) {
+ // Note: this is specifically DWARFv3 CIE header structure. It was
+ // changed in DWARFv4. We currently don't support reading DWARFv4
+ // here because LLVM itself does not emit it (and LLDB doesn't
+ // support it either).
+ uint8_t Version = Data.getU8(&Offset);
+ const char *Augmentation = Data.getCStr(&Offset);
+ uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
+ int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
+ uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
+
+ Entry = new CIE(Data, StartOffset, Length, Version,
+ StringRef(Augmentation), CodeAlignmentFactor,
+ DataAlignmentFactor, ReturnAddressRegister);
+ } else {
+ // FDE
+ uint64_t CIEPointer = Id;
+ uint64_t InitialLocation = Data.getAddress(&Offset);
+ uint64_t AddressRange = Data.getAddress(&Offset);
+
+ Entry = new FDE(Data, StartOffset, Length, CIEPointer,
+ InitialLocation, AddressRange);
+ }
+
+ assert(Entry && "Expected Entry to be populated with CIE or FDE");
+ Entry->parseInstructions(&Offset, EndStructureOffset);
+
+ if (Offset == EndStructureOffset) {
+ // Entry instrucitons parsed successfully.
+ Entries.push_back(Entry);
+ } else {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << format("Parsing entry instructions at %lx failed",
+ Entry->getOffset());
+ report_fatal_error(Str);
+ }
+ }
+}
+
+
+void DWARFDebugFrame::dump(raw_ostream &OS) const {
+ OS << "\n";
+ for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ FrameEntry *Entry = *I;
+ Entry->dumpHeader(OS);
+ Entry->dumpInstructions(OS);
+ OS << "\n";
+ }
+}
+
diff --git a/lib/DebugInfo/DWARFDebugFrame.h b/lib/DebugInfo/DWARFDebugFrame.h
new file mode 100644
index 0000000000..48b8d63a5a
--- /dev/null
+++ b/lib/DebugInfo/DWARFDebugFrame.h
@@ -0,0 +1,46 @@
+//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGFRAME_H
+#define LLVM_DEBUGINFO_DWARFDEBUGFRAME_H
+
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+
+namespace llvm {
+
+class FrameEntry;
+
+
+/// \brief A parsed .debug_frame section
+///
+class DWARFDebugFrame {
+public:
+ DWARFDebugFrame();
+ ~DWARFDebugFrame();
+
+ /// \brief Dump the section data into the given stream.
+ void dump(raw_ostream &OS) const;
+
+ /// \brief Parse the section from raw data.
+ /// data is assumed to be pointing to the beginning of the section.
+ void parse(DataExtractor Data);
+
+private:
+ typedef std::vector<FrameEntry *> EntryVector;
+ EntryVector Entries;
+};
+
+
+} // namespace llvm
+
+#endif
+
diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
index ab67464453..02b15d6904 100644
--- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp
+++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp
@@ -12,6 +12,7 @@
#include "DWARFContext.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFFormValue.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -39,7 +40,7 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS,
OS << format(" [%u] %c\n", abbrCode,
AbbrevDecl->hasChildren() ? '*' : ' ');
- // Dump all data in the .debug_info for the attributes
+ // Dump all data in the DIE for the attributes.
const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
for (uint32_t i = 0; i != numAttributes; ++i) {
uint16_t attr = AbbrevDecl->getAttrByIndex(i);
@@ -113,9 +114,14 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
uint32_t i;
uint16_t form;
for (i=0; i<numAttributes; ++i) {
+
form = AbbrevDecl->getFormByIndex(i);
- const uint8_t fixed_skip_size = fixed_form_sizes[form];
+ // FIXME: Currently we're checking if this is less than the last
+ // entry in the fixed_form_sizes table, but this should be changed
+ // to use dynamic dispatch.
+ const uint8_t fixed_skip_size = (form < DW_FORM_ref_sig8) ?
+ fixed_form_sizes[form] : 0;
if (fixed_skip_size)
offset += fixed_skip_size;
else {
@@ -187,6 +193,8 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
debug_info_data.getULEB128(&offset);
break;
@@ -195,11 +203,9 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
form = debug_info_data.getULEB128(&offset);
break;
+ // FIXME: 64-bit for DWARF64
case DW_FORM_sec_offset:
- if (cu->getAddressByteSize() == 4)
- debug_info_data.getU32(offset_ptr);
- else
- debug_info_data.getU64(offset_ptr);
+ debug_info_data.getU32(offset_ptr);
break;
default:
@@ -207,7 +213,6 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu,
return false;
}
offset += form_size;
-
} while (form_is_indirect);
}
}
@@ -327,6 +332,8 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
debug_info_data.getULEB128(&offset);
break;
@@ -335,11 +342,9 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu,
form_is_indirect = true;
break;
+ // FIXME: 64-bit for DWARF64.
case DW_FORM_sec_offset:
- if (cu->getAddressByteSize() == 4)
- debug_info_data.getU32(offset_ptr);
- else
- debug_info_data.getU64(offset_ptr);
+ debug_info_data.getU32(offset_ptr);
break;
default:
@@ -417,8 +422,7 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
const {
DWARFFormValue form_value;
if (getAttributeValue(cu, attr, form_value)) {
- DataExtractor stringExtractor(cu->getContext().getStringSection(),
- false, 0);
+ DataExtractor stringExtractor(cu->getStringSection(), false, 0);
return form_value.getAsCString(&stringExtractor);
}
return fail_value;
diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index 267364adfa..192381c6f7 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/lib/DebugInfo/DWARFDebugLine.cpp
@@ -155,7 +155,7 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
if (pos.second) {
// Parse and cache the line table for at this offset.
State state;
- if (!parseStatementTable(debug_line_data, &offset, state))
+ if (!parseStatementTable(debug_line_data, RelocMap, &offset, state))
return 0;
pos.first->second = state;
}
@@ -219,7 +219,8 @@ DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
}
bool
-DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
+DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
uint32_t *offset_ptr, State &state) {
const uint32_t debug_line_offset = *offset_ptr;
@@ -268,7 +269,15 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// relocatable address. All of the other statement program opcodes
// that affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
- state.Address = debug_line_data.getAddress(offset_ptr);
+ {
+ // If this address is in our relocation map, apply the relocation.
+ RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr);
+ if (AI != RMap->end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ state.Address = debug_line_data.getAddress(offset_ptr) + R.second;
+ } else
+ state.Address = debug_line_data.getAddress(offset_ptr);
+ }
break;
case DW_LNE_define_file:
@@ -516,6 +525,83 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
}
bool
+DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address,
+ uint64_t size,
+ std::vector<uint32_t>& result) const {
+ if (Sequences.empty())
+ return false;
+ uint64_t end_addr = address + size;
+ // First, find an instruction sequence containing the given address.
+ DWARFDebugLine::Sequence sequence;
+ sequence.LowPC = address;
+ SequenceIter first_seq = Sequences.begin();
+ SequenceIter last_seq = Sequences.end();
+ SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
+ DWARFDebugLine::Sequence::orderByLowPC);
+ if (seq_pos == last_seq || seq_pos->LowPC != address) {
+ if (seq_pos == first_seq)
+ return false;
+ seq_pos--;
+ }
+ if (!seq_pos->containsPC(address))
+ return false;
+
+ SequenceIter start_pos = seq_pos;
+
+ // Add the rows from the first sequence to the vector, starting with the
+ // index we just calculated
+
+ while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
+ DWARFDebugLine::Sequence cur_seq = *seq_pos;
+ uint32_t first_row_index;
+ uint32_t last_row_index;
+ if (seq_pos == start_pos) {
+ // For the first sequence, we need to find which row in the sequence is the
+ // first in our range. Rows are stored in a vector, so we may use
+ // arithmetical operations with iterators.
+ DWARFDebugLine::Row row;
+ row.Address = address;
+ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
+ RowIter row_pos = std::upper_bound(first_row, last_row, row,
+ DWARFDebugLine::Row::orderByAddress);
+ // The 'row_pos' iterator references the first row that is greater than
+ // our start address. Unless that's the first row, we want to start at
+ // the row before that.
+ first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row);
+ if (row_pos != first_row)
+ --first_row_index;
+ } else
+ first_row_index = cur_seq.FirstRowIndex;
+
+ // For the last sequence in our range, we need to figure out the last row in
+ // range. For all other sequences we can go to the end of the sequence.
+ if (cur_seq.HighPC > end_addr) {
+ DWARFDebugLine::Row row;
+ row.Address = end_addr;
+ RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + cur_seq.LastRowIndex;
+ RowIter row_pos = std::upper_bound(first_row, last_row, row,
+ DWARFDebugLine::Row::orderByAddress);
+ // The 'row_pos' iterator references the first row that is greater than
+ // our end address. The row before that is the last row we want.
+ last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1;
+ } else
+ // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex
+ // isn't a valid index within the current sequence. It's that plus one.
+ last_row_index = cur_seq.LastRowIndex - 1;
+
+ for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
+ result.push_back(i);
+ }
+
+ ++seq_pos;
+ }
+
+ return true;
+}
+
+bool
DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
bool NeedsAbsoluteFilePath,
std::string &Result) const {
diff --git a/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
index 586dd7e878..2990756bd7 100644
--- a/lib/DebugInfo/DWARFDebugLine.h
+++ b/lib/DebugInfo/DWARFDebugLine.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
+#include "DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
#include <map>
#include <string>
@@ -21,6 +22,7 @@ class raw_ostream;
class DWARFDebugLine {
public:
+ DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
struct FileNameEntry {
FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {}
@@ -176,6 +178,10 @@ public:
// or -1 if there is no such row.
uint32_t lookupAddress(uint64_t address) const;
+ bool lookupAddressRange(uint64_t address,
+ uint64_t size,
+ std::vector<uint32_t>& result) const;
+
// Extracts filename by its index in filename table in prologue.
// Returns true on success.
bool getFileNameByIndex(uint64_t FileIndex,
@@ -227,6 +233,7 @@ public:
Prologue *prologue);
/// Parse a single line table (prologue and all rows).
static bool parseStatementTable(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
uint32_t *offset_ptr, State &state);
const LineTable *getLineTable(uint32_t offset) const;
@@ -238,6 +245,7 @@ private:
typedef LineTableMapTy::iterator LineTableIter;
typedef LineTableMapTy::const_iterator LineTableConstIter;
+ const RelocAddrMap *RelocMap;
LineTableMapTy LineTableMap;
};
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index 1d8ea01110..9f807aac5f 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -46,8 +46,6 @@ static const uint8_t form_sizes_addr4[] = {
0, // 0x18 DW_FORM_exprloc
0, // 0x19 DW_FORM_flag_present
8, // 0x20 DW_FORM_ref_sig8
- 4, // 0x1f01 DW_FORM_GNU_addr_index
- 4, // 0x1f02 DW_FORM_GNU_str_index
};
static const uint8_t form_sizes_addr8[] = {
@@ -74,12 +72,10 @@ static const uint8_t form_sizes_addr8[] = {
8, // 0x14 DW_FORM_ref8
0, // 0x15 DW_FORM_ref_udata
0, // 0x16 DW_FORM_indirect
- 8, // 0x17 DW_FORM_sec_offset
+ 4, // 0x17 DW_FORM_sec_offset
0, // 0x18 DW_FORM_exprloc
0, // 0x19 DW_FORM_flag_present
8, // 0x20 DW_FORM_ref_sig8
- 8, // 0x1f01 DW_FORM_GNU_addr_index
- 8, // 0x1f01 DW_FORM_GNU_str_index
};
const uint8_t *
@@ -105,11 +101,11 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
case DW_FORM_addr:
case DW_FORM_ref_addr: {
RelocAddrMap::const_iterator AI
- = cu->getContext().relocMap().find(*offset_ptr);
- if (AI != cu->getContext().relocMap().end()) {
+ = cu->getRelocMap()->find(*offset_ptr);
+ if (AI != cu->getRelocMap()->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
- Value.uval = R.second;
- *offset_ptr += R.first;
+ Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()) +
+ R.second;
} else
Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
break;
@@ -153,11 +149,10 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
break;
case DW_FORM_strp: {
RelocAddrMap::const_iterator AI
- = cu->getContext().relocMap().find(*offset_ptr);
- if (AI != cu->getContext().relocMap().end()) {
+ = cu->getRelocMap()->find(*offset_ptr);
+ if (AI != cu->getRelocMap()->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
- Value.uval = R.second;
- *offset_ptr += R.first;
+ Value.uval = data.getU32(offset_ptr) + R.second;
} else
Value.uval = data.getU32(offset_ptr);
break;
@@ -178,10 +173,8 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
indirect = true;
break;
case DW_FORM_sec_offset:
- if (cu->getAddressByteSize() == 4)
- Value.uval = data.getU32(offset_ptr);
- else
- Value.uval = data.getU64(offset_ptr);
+ // FIXME: This is 64-bit for DWARF64.
+ Value.uval = data.getU32(offset_ptr);
break;
case DW_FORM_flag_present:
Value.uval = 1;
@@ -263,7 +256,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
// 0 byte values - implied from the form.
case DW_FORM_flag_present:
return true;
-
+
// 1 byte values
case DW_FORM_data1:
case DW_FORM_flag:
@@ -296,6 +289,8 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
debug_info_data.getULEB128(offset_ptr);
return true;
@@ -304,14 +299,11 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
form = debug_info_data.getULEB128(offset_ptr);
break;
- // 4 for DWARF32, 8 for DWARF64.
+ // FIXME: 4 for DWARF32, 8 for DWARF64.
case DW_FORM_sec_offset:
- if (cu->getAddressByteSize() == 4)
- *offset_ptr += 4;
- else
- *offset_ptr += 8;
+ *offset_ptr += 4;
return true;
-
+
default:
return false;
}
@@ -321,12 +313,23 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
void
DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
- DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0);
+ DataExtractor debug_str_data(cu->getStringSection(), true, 0);
+ DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
uint64_t uvalue = getUnsigned();
bool cu_relative_offset = false;
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
+ OS << "<no .debug_addr section>";
+ break;
+ }
case DW_FORM_flag_present: OS << "true"; break;
case DW_FORM_flag:
case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break;
@@ -380,6 +383,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
}
break;
}
+ 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);
+ if (dbg_str) {
+ OS << '"';
+ OS.write_escaped(dbg_str);
+ OS << '"';
+ }
+ break;
+ }
case DW_FORM_ref_addr:
OS << format("0x%016" PRIx64, uvalue);
break;
@@ -410,13 +424,11 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
OS << "DW_FORM_indirect";
break;
+ // Should be formatted to 64-bit for DWARF64.
case DW_FORM_sec_offset:
- if (cu->getAddressByteSize() == 4)
- OS << format("0x%08x", (uint32_t)uvalue);
- else
- OS << format("0x%016" PRIx64, uvalue);
+ OS << format("0x%08x", (uint32_t)uvalue);
break;
-
+
default:
OS << format("DW_FORM(0x%4.4x)", Form);
break;
@@ -437,6 +449,25 @@ DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
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);
+}
+
+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);
+}
+
uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
uint64_t die_offset = Value.uval;
switch (Form) {
diff --git a/lib/DebugInfo/DWARFFormValue.h b/lib/DebugInfo/DWARFFormValue.h
index c5b590db95..b863001e4a 100644
--- a/lib/DebugInfo/DWARFFormValue.h
+++ b/lib/DebugInfo/DWARFFormValue.h
@@ -64,6 +64,10 @@ public:
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;
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/DWARFRelocMap.h b/lib/DebugInfo/DWARFRelocMap.h
new file mode 100644
index 0000000000..6929e367b8
--- /dev/null
+++ b/lib/DebugInfo/DWARFRelocMap.h
@@ -0,0 +1,22 @@
+//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFRELOCMAP_H
+#define LLVM_DEBUGINFO_DWARFRELOCMAP_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFRELOCMAP_H
+