diff options
Diffstat (limited to 'lib/DebugInfo/DWARFContext.cpp')
| -rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 198 |
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() { } |
