aboutsummaryrefslogtreecommitdiffstats
path: root/lib/DebugInfo/DWARFContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/DWARFContext.cpp')
-rw-r--r--lib/DebugInfo/DWARFContext.cpp198
1 files changed, 175 insertions, 23 deletions
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 241f55e..d6d9fcf 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -17,6 +17,8 @@
using namespace llvm;
using namespace dwarf;
+typedef DWARFDebugLine::LineTable DWARFLineTable;
+
void DWARFContext::dump(raw_ostream &OS) {
OS << ".debug_abbrev contents:\n";
getDebugAbbrev()->dump(OS);
@@ -33,7 +35,7 @@ void DWARFContext::dump(raw_ostream &OS) {
set.dump(OS);
uint8_t savedAddressByteSize = 0;
- OS << "\n.debug_lines contents:\n";
+ OS << "\n.debug_line contents:\n";
for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
savedAddressByteSize = cu->getAddressByteSize();
@@ -51,10 +53,10 @@ void DWARFContext::dump(raw_ostream &OS) {
OS << "\n.debug_str contents:\n";
DataExtractor strData(getStringSection(), isLittleEndian(), 0);
offset = 0;
- uint32_t lastOffset = 0;
+ uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) {
- OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
- lastOffset = offset;
+ OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
+ strOffset = offset;
}
OS << "\n.debug_ranges contents:\n";
@@ -68,6 +70,22 @@ void DWARFContext::dump(raw_ostream &OS) {
DWARFDebugRangeList rangeList;
while (rangeList.extract(rangesData, &offset))
rangeList.dump(OS);
+
+ OS << "\n.debug_abbrev.dwo contents:\n";
+ getDebugAbbrevDWO()->dump(OS);
+
+ OS << "\n.debug_info.dwo contents:\n";
+ for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
+ getDWOCompileUnitAtIndex(i)->dump(OS);
+
+ 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;
+ }
}
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@@ -81,6 +99,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();
@@ -89,12 +117,14 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
Aranges.reset(new DWARFDebugAranges());
Aranges->extract(arangesData);
- if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
- Aranges->generate(this);
+ // Generate aranges from DIEs: even if .debug_aranges section is present,
+ // it may describe only a small subset of compilation units, so we need to
+ // manually build aranges for the rest of them.
+ Aranges->generate(this);
return Aranges.get();
}
-const DWARFDebugLine::LineTable *
+const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
Line.reset(new DWARFDebugLine());
@@ -106,7 +136,7 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
return 0; // No line table for this compile unit.
// See if the line table is cached.
- if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset))
+ if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
return lt;
// We have to parse it first.
@@ -117,11 +147,15 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
void DWARFContext::parseCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
- isLittleEndian(), 0);
- while (debug_info_data.isValidOffset(offset)) {
- CUs.push_back(DWARFCompileUnit(*this));
- if (!CUs.back().extract(debug_info_data, &offset)) {
+ const DataExtractor &DIData = DataExtractor(getInfoSection(),
+ isLittleEndian(), 0);
+ while (DIData.isValidOffset(offset)) {
+ CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
+ getAbbrevSection(), getRangeSection(),
+ getStringSection(), "",
+ &infoRelocMap(),
+ isLittleEndian()));
+ if (!CUs.back().extract(DIData, &offset)) {
CUs.pop_back();
break;
}
@@ -130,6 +164,27 @@ 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(),
+ &infoDWORelocMap(),
+ isLittleEndian()));
+ if (!DWOCUs.back().extract(DIData, &offset)) {
+ DWOCUs.pop_back();
+ break;
+ }
+
+ offset = DWOCUs.back().getNextCompileUnitOffset();
+ }
+}
+
namespace {
struct OffsetComparator {
bool operator()(const DWARFCompileUnit &LHS,
@@ -163,9 +218,11 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
return getCompileUnitForOffset(CUOffset);
}
-static bool getFileNameForCompileUnit(
- DWARFCompileUnit *CU, const DWARFDebugLine::LineTable *LineTable,
- uint64_t FileIndex, bool NeedsAbsoluteFilePath, std::string &FileName) {
+static bool getFileNameForCompileUnit(DWARFCompileUnit *CU,
+ const DWARFLineTable *LineTable,
+ uint64_t FileIndex,
+ bool NeedsAbsoluteFilePath,
+ std::string &FileName) {
if (CU == 0 ||
LineTable == 0 ||
!LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath,
@@ -183,10 +240,12 @@ static bool getFileNameForCompileUnit(
return true;
}
-static bool getFileLineInfoForCompileUnit(
- DWARFCompileUnit *CU, const DWARFDebugLine::LineTable *LineTable,
- uint64_t Address, bool NeedsAbsoluteFilePath, std::string &FileName,
- uint32_t &Line, uint32_t &Column) {
+static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU,
+ const DWARFLineTable *LineTable,
+ uint64_t Address,
+ bool NeedsAbsoluteFilePath,
+ std::string &FileName,
+ uint32_t &Line, uint32_t &Column) {
if (CU == 0 || LineTable == 0)
return false;
// Get the index of row we're looking for in the line table.
@@ -225,8 +284,7 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
}
}
if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- const DWARFDebugLine::LineTable *LineTable =
- getLineTableForCompileUnit(CU);
+ const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU);
const bool NeedsAbsoluteFilePath =
Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath);
getFileLineInfoForCompileUnit(CU, LineTable, Address,
@@ -250,7 +308,7 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
DIInliningInfo InliningInfo;
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
- const DWARFDebugLine::LineTable *LineTable = 0;
+ const DWARFLineTable *LineTable = 0;
for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
std::string FileName = "<invalid>";
@@ -293,4 +351,98 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
+DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
+ IsLittleEndian(true /* FIXME */) {
+ error_code ec;
+ for (object::section_iterator i = Obj->begin_sections(),
+ e = Obj->end_sections();
+ i != e; i.increment(ec)) {
+ StringRef name;
+ i->getName(name);
+ StringRef data;
+ i->getContents(data);
+
+ name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
+ if (name == "debug_info")
+ InfoSection = data;
+ else if (name == "debug_abbrev")
+ AbbrevSection = data;
+ else if (name == "debug_line")
+ LineSection = data;
+ else if (name == "debug_aranges")
+ ARangeSection = data;
+ else if (name == "debug_str")
+ StringSection = data;
+ else if (name == "debug_ranges") {
+ // FIXME: Use the other dwo range section when we emit it.
+ RangeDWOSection = data;
+ RangeSection = 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;
+ // Any more debug info sections go here.
+ else
+ continue;
+
+ // TODO: For now only handle relocations for the debug_info section.
+ RelocAddrMap *Map;
+ if (name == "debug_info")
+ Map = &InfoRelocMap;
+ else if (name == "debug_info.dwo")
+ Map = &InfoDWORelocMap;
+ else
+ continue;
+
+ if (i->begin_relocations() != i->end_relocations()) {
+ uint64_t SectionSize;
+ i->getSize(SectionSize);
+ for (object::relocation_iterator reloc_i = i->begin_relocations(),
+ reloc_e = i->end_relocations();
+ reloc_i != reloc_e; reloc_i.increment(ec)) {
+ uint64_t Address;
+ reloc_i->getAddress(Address);
+ uint64_t Type;
+ reloc_i->getType(Type);
+
+ object::RelocVisitor V(Obj->getFileFormatName());
+ // The section address is always 0 for debug sections.
+ object::RelocToApply R(V.visit(Type, *reloc_i));
+ if (V.error()) {
+ SmallString<32> Name;
+ error_code ec(reloc_i->getTypeName(Name));
+ if (ec) {
+ errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
+ }
+ errs() << "error: failed to compute relocation: "
+ << Name << "\n";
+ continue;
+ }
+
+ if (Address + R.Width > SectionSize) {
+ errs() << "error: " << R.Width << "-byte relocation starting "
+ << Address << " bytes into section " << name << " which is "
+ << SectionSize << " bytes long.\n";
+ continue;
+ }
+ if (R.Width > 8) {
+ errs() << "error: can't handle a relocation of more than 8 bytes at "
+ "a time.\n";
+ continue;
+ }
+ DEBUG(dbgs() << "Writing " << format("%p", R.Value)
+ << " at " << format("%p", Address)
+ << " with width " << format("%d", R.Width)
+ << "\n");
+ Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
+ }
+ }
+ }
+}
+
void DWARFContextInMemory::anchor() { }