aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
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