Use delegation instead of inheritance.
This changes DwarfContext to delegate to DwarfObject instead of having
pure virtual methods.
With this DwarfContextInMemory is replaced with an implementation of
DwarfObject that is local to a .cpp file.
llvm-svn: 308543
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 495e09f..c91bd27 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -60,9 +60,10 @@
using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
static void dumpAccelSection(raw_ostream &OS, StringRef Name,
- const DWARFSection& Section, StringRef StringSection,
- bool LittleEndian) {
- DWARFDataExtractor AccelSection(Section, LittleEndian, 0);
+ const DWARFObject &Obj,
+ const DWARFSection &Section,
+ StringRef StringSection, bool LittleEndian) {
+ DWARFDataExtractor AccelSection(Obj, Section, LittleEndian, 0);
DataExtractor StrData(StringSection, LittleEndian, 0);
OS << "\n." << Name << " contents:\n";
DWARFAcceleratorTable Accel(AccelSection, StrData);
@@ -73,9 +74,10 @@
static void
dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
+ const DWARFObject &Obj,
const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian) {
- DWARFDataExtractor StrOffsetExt(StringOffsetsSection, LittleEndian, 0);
+ DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
uint32_t Offset = 0;
uint64_t SectionSize = StringOffsetsSection.Data.size();
@@ -153,6 +155,7 @@
// monolithic series of string offsets, as generated by the pre-DWARF v5
// implementation of split DWARF.
static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
+ const DWARFObject &Obj,
const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian,
unsigned MaxVersion) {
@@ -163,7 +166,7 @@
// we assume that the section is formatted like a DWARF v5 string offsets
// section.
if (MaxVersion >= 5)
- dumpDWARFv5StringOffsetsSection(OS, SectionName, StringOffsetsSection,
+ dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection,
StringSection, LittleEndian);
else {
DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
@@ -259,7 +262,7 @@
uint32_t offset = 0;
if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
OS << "\n.debug_aranges contents:\n";
- DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
+ DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0);
DWARFDebugArangeSet set;
while (set.extract(arangesData, &offset))
set.dump(OS);
@@ -274,8 +277,8 @@
if (!CUDIE)
continue;
if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) {
- DWARFDataExtractor lineData(getLineSection(), isLittleEndian(),
- savedAddressByteSize);
+ DWARFDataExtractor lineData(*DObj, DObj->getLineSection(),
+ isLittleEndian(), savedAddressByteSize);
DWARFDebugLine::LineTable LineTable;
uint32_t Offset = *StmtOffset;
LineTable.parse(lineData, &Offset);
@@ -297,8 +300,8 @@
if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
OS << "\n.debug_line.dwo contents:\n";
unsigned stmtOffset = 0;
- DWARFDataExtractor lineData(getLineDWOSection(), isLittleEndian(),
- savedAddressByteSize);
+ DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(),
+ isLittleEndian(), savedAddressByteSize);
DWARFDebugLine::LineTable LineTable;
while (LineTable.Prologue.parse(lineData, &stmtOffset)) {
LineTable.dump(OS);
@@ -308,7 +311,7 @@
if (DumpType == DIDT_All || DumpType == DIDT_Str) {
OS << "\n.debug_str contents:\n";
- DataExtractor strData(getStringSection(), isLittleEndian(), 0);
+ DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) {
@@ -318,9 +321,9 @@
}
if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) &&
- !getStringDWOSection().empty()) {
+ !DObj->getStringDWOSection().empty()) {
OS << "\n.debug_str.dwo contents:\n";
- DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
+ DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0);
offset = 0;
uint32_t strDWOOffset = 0;
while (const char *s = strDWOData.getCStr(&offset)) {
@@ -335,8 +338,8 @@
// 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).
- DWARFDataExtractor rangesData(getRangeSection(), isLittleEndian(),
- savedAddressByteSize);
+ DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
+ isLittleEndian(), savedAddressByteSize);
offset = 0;
DWARFDebugRangeList rangeList;
while (rangeList.extract(rangesData, &offset))
@@ -344,55 +347,56 @@
}
if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
- DWARFDebugPubTable(getPubNamesSection(), isLittleEndian(), false)
+ DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false)
.dump("debug_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
- DWARFDebugPubTable(getPubTypesSection(), isLittleEndian(), false)
+ DWARFDebugPubTable(DObj->getPubTypesSection(), isLittleEndian(), false)
.dump("debug_pubtypes", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
- DWARFDebugPubTable(getGnuPubNamesSection(), isLittleEndian(),
+ DWARFDebugPubTable(DObj->getGnuPubNamesSection(), isLittleEndian(),
true /* GnuStyle */)
.dump("debug_gnu_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
- DWARFDebugPubTable(getGnuPubTypesSection(), isLittleEndian(),
+ DWARFDebugPubTable(DObj->getGnuPubTypesSection(), isLittleEndian(),
true /* GnuStyle */)
.dump("debug_gnu_pubtypes", OS);
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets)
- dumpStringOffsetsSection(OS, "debug_str_offsets", getStringOffsetSection(),
- getStringSection(), isLittleEndian(),
- getMaxVersion());
+ dumpStringOffsetsSection(
+ OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(),
+ DObj->getStringSection(), isLittleEndian(), getMaxVersion());
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
- dumpStringOffsetsSection(OS, "debug_str_offsets.dwo",
- getStringOffsetDWOSection(), getStringDWOSection(),
- isLittleEndian(), getMaxVersion());
+ dumpStringOffsetsSection(
+ OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(),
+ DObj->getStringDWOSection(), isLittleEndian(), getMaxVersion());
}
if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) &&
- !getGdbIndexSection().empty()) {
+ !DObj->getGdbIndexSection().empty()) {
OS << "\n.gnu_index contents:\n";
getGdbIndex().dump(OS);
}
if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
- dumpAccelSection(OS, "apple_names", getAppleNamesSection(),
- getStringSection(), isLittleEndian());
+ dumpAccelSection(OS, "apple_names", *DObj, DObj->getAppleNamesSection(),
+ DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes)
- dumpAccelSection(OS, "apple_types", getAppleTypesSection(),
- getStringSection(), isLittleEndian());
+ dumpAccelSection(OS, "apple_types", *DObj, DObj->getAppleTypesSection(),
+ DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces)
- dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(),
- getStringSection(), isLittleEndian());
+ dumpAccelSection(OS, "apple_namespaces", *DObj,
+ DObj->getAppleNamespacesSection(),
+ DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC)
- dumpAccelSection(OS, "apple_objc", getAppleObjCSection(),
- getStringSection(), isLittleEndian());
+ dumpAccelSection(OS, "apple_objc", *DObj, DObj->getAppleObjCSection(),
+ DObj->getStringSection(), isLittleEndian());
}
DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
@@ -433,7 +437,7 @@
if (CUIndex)
return *CUIndex;
- DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0);
+ DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
CUIndex->parse(CUIndexData);
@@ -444,7 +448,7 @@
if (TUIndex)
return *TUIndex;
- DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0);
+ DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0);
TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES);
TUIndex->parse(TUIndexData);
@@ -455,7 +459,7 @@
if (GdbIndex)
return *GdbIndex;
- DataExtractor GdbIndexData(getGdbIndexSection(), true /*LE*/, 0);
+ DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0);
GdbIndex = llvm::make_unique<DWARFGdbIndex>();
GdbIndex->parse(GdbIndexData);
return *GdbIndex;
@@ -465,7 +469,7 @@
if (Abbrev)
return Abbrev.get();
- DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
+ DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
Abbrev.reset(new DWARFDebugAbbrev());
Abbrev->extract(abbrData);
@@ -476,7 +480,7 @@
if (AbbrevDWO)
return AbbrevDWO.get();
- DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
+ DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0);
AbbrevDWO.reset(new DWARFDebugAbbrev());
AbbrevDWO->extract(abbrData);
return AbbrevDWO.get();
@@ -489,7 +493,7 @@
Loc.reset(new DWARFDebugLoc);
// assume all compile units have the same address byte size
if (getNumCompileUnits()) {
- DWARFDataExtractor LocData(getLocSection(), isLittleEndian(),
+ DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(),
getCompileUnitAtIndex(0)->getAddressByteSize());
Loc->parse(LocData);
}
@@ -500,7 +504,7 @@
if (LocDWO)
return LocDWO.get();
- DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0);
+ DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 0);
LocDWO.reset(new DWARFDebugLocDWO());
LocDWO->parse(LocData);
return LocDWO.get();
@@ -528,8 +532,8 @@
// 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());
+ DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(),
+ DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */));
DebugFrame->parse(debugFrameData);
return DebugFrame.get();
@@ -539,8 +543,8 @@
if (EHFrame)
return EHFrame.get();
- DataExtractor debugFrameData(getEHFrameSection(), isLittleEndian(),
- getAddressSize());
+ DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
+ DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
DebugFrame->parse(debugFrameData);
return DebugFrame.get();
@@ -550,7 +554,7 @@
if (Macro)
return Macro.get();
- DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0);
+ DataExtractor MacinfoData(DObj->getMacinfoSection(), isLittleEndian(), 0);
Macro.reset(new DWARFDebugMacro());
Macro->parse(MacinfoData);
return Macro.get();
@@ -579,32 +583,32 @@
return nullptr;
// We have to parse it first.
- DWARFDataExtractor lineData(U->getLineSection(), isLittleEndian(),
+ DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
U->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset);
}
void DWARFContext::parseCompileUnits() {
- CUs.parse(*this, getInfoSection());
+ CUs.parse(*this, DObj->getInfoSection());
}
void DWARFContext::parseTypeUnits() {
if (!TUs.empty())
return;
- forEachTypesSections([&](const DWARFSection &S) {
+ DObj->forEachTypesSections([&](const DWARFSection &S) {
TUs.emplace_back();
TUs.back().parse(*this, S);
});
}
void DWARFContext::parseDWOCompileUnits() {
- DWOCUs.parseDWO(*this, getInfoDWOSection());
+ DWOCUs.parseDWO(*this, DObj->getInfoDWOSection());
}
void DWARFContext::parseDWOTypeUnits() {
if (!DWOTUs.empty())
return;
- forEachTypesDWOSections([&](const DWARFSection &S) {
+ DObj->forEachTypesDWOSections([&](const DWARFSection &S) {
DWOTUs.emplace_back();
DWOTUs.back().parseDWO(*this, S);
});
@@ -779,6 +783,20 @@
return InliningInfo;
}
+/// DWARFContextInMemory is the simplest possible implementation of a
+/// DWARFContext. It assumes all content is available in memory and stores
+/// pointers to it.
+class DWARFContextInMemory : public DWARFContext {
+public:
+ DWARFContextInMemory(
+ const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
+ function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
+
+ DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize,
+ bool isLittleEndian = sys::IsLittleEndianHost);
+};
+
std::shared_ptr<DWARFContext>
DWARFContext::getDWOContext(StringRef AbsolutePath) {
if (auto S = DWP.lock()) {
@@ -796,7 +814,7 @@
SmallString<128> DWPName;
Expected<OwningBinary<ObjectFile>> Obj = [&] {
if (!CheckedForDWP) {
- (getFileName() + ".dwp").toVector(DWPName);
+ (DObj->getFileName() + ".dwp").toVector(DWPName);
auto Obj = object::ObjectFile::createObjectFile(DWPName);
if (Obj) {
Entry = &DWP;
@@ -820,7 +838,7 @@
auto S = std::make_shared<DWOFile>();
S->File = std::move(Obj.get());
- S->Context = llvm::make_unique<DWARFContextInMemory>(*S->File.getBinary());
+ S->Context = DWARFContext::create(*S->File.getBinary());
*Entry = S;
auto *Ctxt = S->Context.get();
return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
@@ -906,208 +924,355 @@
return MachObj->isRelocationScattered(RelocInfo);
}
-Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
- StringRef Name, StringRef &Data) {
- if (!Decompressor::isCompressed(Sec))
- return Error::success();
-
- Expected<Decompressor> Decompressor =
- Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
- if (!Decompressor)
- return Decompressor.takeError();
-
- SmallString<32> Out;
- if (auto Err = Decompressor->resizeAndDecompress(Out))
- return Err;
-
- UncompressedSections.emplace_back(std::move(Out));
- Data = UncompressedSections.back();
-
- return Error::success();
-}
-
-ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) {
+ErrorPolicy DWARFContext::defaultErrorHandler(Error E) {
errs() << "error: " + toString(std::move(E)) << '\n';
return ErrorPolicy::Continue;
}
-DWARFContextInMemory::DWARFContextInMemory(
- const object::ObjectFile &Obj, const LoadedObjectInfo *L,
- function_ref<ErrorPolicy(Error)> HandleError)
- : FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
- AddressSize(Obj.getBytesInAddress()) {
- for (const SectionRef &Section : Obj.sections()) {
- StringRef Name;
- Section.getName(Name);
- // Skip BSS and Virtual sections, they aren't interesting.
- if (Section.isBSS() || Section.isVirtual())
- continue;
+class DWARFObjInMemory final : public DWARFObject {
+ bool IsLittleEndian;
+ uint8_t AddressSize;
+ StringRef FileName;
- StringRef Data;
- section_iterator RelocatedSection = Section.getRelocatedSection();
- // Try to obtain an already relocated version of this section.
- // Else use the unrelocated section from the object file. We'll have to
- // apply relocations ourselves later.
- if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data))
- Section.getContents(Data);
+ using TypeSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
+ std::map<object::SectionRef, unsigned>>;
- if (auto Err = maybeDecompress(Section, Name, Data)) {
- ErrorPolicy EP = HandleError(
- createError("failed to decompress '" + Name + "', ", std::move(Err)));
- if (EP == ErrorPolicy::Halt)
- return;
- continue;
+ TypeSectionMap TypesSections;
+ TypeSectionMap TypesDWOSections;
+
+ DWARFSectionMap InfoSection;
+ DWARFSectionMap LocSection;
+ DWARFSectionMap LineSection;
+ DWARFSectionMap RangeSection;
+ DWARFSectionMap StringOffsetSection;
+ DWARFSectionMap InfoDWOSection;
+ DWARFSectionMap LineDWOSection;
+ DWARFSectionMap LocDWOSection;
+ DWARFSectionMap StringOffsetDWOSection;
+ DWARFSectionMap RangeDWOSection;
+ DWARFSectionMap AddrSection;
+ DWARFSectionMap AppleNamesSection;
+ DWARFSectionMap AppleTypesSection;
+ DWARFSectionMap AppleNamespacesSection;
+ DWARFSectionMap AppleObjCSection;
+
+ DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
+ return StringSwitch<DWARFSectionMap *>(Name)
+ .Case("debug_info", &InfoSection)
+ .Case("debug_loc", &LocSection)
+ .Case("debug_line", &LineSection)
+ .Case("debug_str_offsets", &StringOffsetSection)
+ .Case("debug_ranges", &RangeSection)
+ .Case("debug_info.dwo", &InfoDWOSection)
+ .Case("debug_loc.dwo", &LocDWOSection)
+ .Case("debug_line.dwo", &LineDWOSection)
+ .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+ .Case("debug_addr", &AddrSection)
+ .Case("apple_names", &AppleNamesSection)
+ .Case("apple_types", &AppleTypesSection)
+ .Case("apple_namespaces", &AppleNamespacesSection)
+ .Case("apple_namespac", &AppleNamespacesSection)
+ .Case("apple_objc", &AppleObjCSection)
+ .Default(nullptr);
+ }
+
+ StringRef AbbrevSection;
+ StringRef ARangeSection;
+ StringRef DebugFrameSection;
+ StringRef EHFrameSection;
+ StringRef StringSection;
+ StringRef MacinfoSection;
+ StringRef PubNamesSection;
+ StringRef PubTypesSection;
+ StringRef GnuPubNamesSection;
+ StringRef AbbrevDWOSection;
+ StringRef StringDWOSection;
+ StringRef GnuPubTypesSection;
+ StringRef CUIndexSection;
+ StringRef GdbIndexSection;
+ StringRef TUIndexSection;
+
+ SmallVector<SmallString<32>, 4> UncompressedSections;
+
+ StringRef *mapSectionToMember(StringRef Name) {
+ if (DWARFSection *Sec = mapNameToDWARFSection(Name))
+ return &Sec->Data;
+ return StringSwitch<StringRef *>(Name)
+ .Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_aranges", &ARangeSection)
+ .Case("debug_frame", &DebugFrameSection)
+ .Case("eh_frame", &EHFrameSection)
+ .Case("debug_str", &StringSection)
+ .Case("debug_macinfo", &MacinfoSection)
+ .Case("debug_pubnames", &PubNamesSection)
+ .Case("debug_pubtypes", &PubTypesSection)
+ .Case("debug_gnu_pubnames", &GnuPubNamesSection)
+ .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
+ .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+ .Case("debug_str.dwo", &StringDWOSection)
+ .Case("debug_cu_index", &CUIndexSection)
+ .Case("debug_tu_index", &TUIndexSection)
+ .Case("gdb_index", &GdbIndexSection)
+ // Any more debug info sections go here.
+ .Default(nullptr);
+ }
+
+ /// If Sec is compressed section, decompresses and updates its contents
+ /// provided by Data. Otherwise leaves it unchanged.
+ Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
+ StringRef &Data) {
+ if (!Decompressor::isCompressed(Sec))
+ return Error::success();
+
+ Expected<Decompressor> Decompressor =
+ Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
+ if (!Decompressor)
+ return Decompressor.takeError();
+
+ SmallString<32> Out;
+ if (auto Err = Decompressor->resizeAndDecompress(Out))
+ return Err;
+
+ UncompressedSections.emplace_back(std::move(Out));
+ Data = UncompressedSections.back();
+
+ return Error::success();
+ }
+
+public:
+ DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize, bool IsLittleEndian)
+ : IsLittleEndian(IsLittleEndian) {
+ for (const auto &SecIt : Sections) {
+ if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
+ *SectionData = SecIt.second->getBuffer();
}
+ }
+ DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
+ function_ref<ErrorPolicy(Error)> HandleError)
+ : IsLittleEndian(Obj.isLittleEndian()),
+ AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()) {
- // Compressed sections names in GNU style starts from ".z",
- // at this point section is decompressed and we drop compression prefix.
- Name = Name.substr(
- Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
-
- // Map platform specific debug section names to DWARF standard section
- // names.
- Name = Obj.mapDebugSectionName(Name);
-
- if (StringRef *SectionData = mapSectionToMember(Name)) {
- *SectionData = Data;
- if (Name == "debug_ranges") {
- // FIXME: Use the other dwo range section when we emit it.
- RangeDWOSection.Data = Data;
- }
- } else if (Name == "debug_types") {
- // Find debug_types data by section rather than name as there are
- // multiple, comdat grouped, debug_types sections.
- TypesSections[Section].Data = Data;
- } else if (Name == "debug_types.dwo") {
- TypesDWOSections[Section].Data = Data;
- }
-
- if (RelocatedSection == Obj.section_end())
- continue;
-
- StringRef RelSecName;
- StringRef RelSecData;
- RelocatedSection->getName(RelSecName);
-
- // If the section we're relocating was relocated already by the JIT,
- // then we used the relocated version above, so we do not need to process
- // relocations for it now.
- if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
- continue;
-
- // In Mach-o files, the relocations do not need to be applied if
- // there is no load offset to apply. The value read at the
- // relocation point already factors in the section address
- // (actually applying the relocations will produce wrong results
- // as the section address will be added twice).
- if (!L && isa<MachOObjectFile>(&Obj))
- continue;
-
- RelSecName = RelSecName.substr(
- RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
-
- // TODO: Add support for relocations in other sections as needed.
- // Record relocations for the debug_info and debug_line sections.
- DWARFSection *Sec = mapNameToDWARFSection(RelSecName);
- RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
- if (!Map) {
- // Find debug_types relocs by section rather than name as there are
- // multiple, comdat grouped, debug_types sections.
- if (RelSecName == "debug_types")
- Map = &TypesSections[*RelocatedSection].Relocs;
- else if (RelSecName == "debug_types.dwo")
- Map = &TypesDWOSections[*RelocatedSection].Relocs;
- else
- continue;
- }
-
- if (Section.relocation_begin() == Section.relocation_end())
- continue;
-
- // Symbol to [address, section index] cache mapping.
- std::map<SymbolRef, SymInfo> AddrCache;
- for (const RelocationRef &Reloc : Section.relocations()) {
- // FIXME: it's not clear how to correctly handle scattered
- // relocations.
- if (isRelocScattered(Obj, Reloc))
+ for (const SectionRef &Section : Obj.sections()) {
+ StringRef Name;
+ Section.getName(Name);
+ // Skip BSS and Virtual sections, they aren't interesting.
+ if (Section.isBSS() || Section.isVirtual())
continue;
- Expected<SymInfo> SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache);
- if (!SymInfoOrErr) {
- if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
- return;
- continue;
- }
+ StringRef Data;
+ section_iterator RelocatedSection = Section.getRelocatedSection();
+ // Try to obtain an already relocated version of this section.
+ // Else use the unrelocated section from the object file. We'll have to
+ // apply relocations ourselves later.
+ if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data))
+ Section.getContents(Data);
- object::RelocVisitor V(Obj);
- uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address);
- if (V.error()) {
- SmallString<32> Type;
- Reloc.getTypeName(Type);
- ErrorPolicy EP = HandleError(
- createError("failed to compute relocation: " + Type + ", ",
- errorCodeToError(object_error::parse_failed)));
+ if (auto Err = maybeDecompress(Section, Name, Data)) {
+ ErrorPolicy EP = HandleError(createError(
+ "failed to decompress '" + Name + "', ", std::move(Err)));
if (EP == ErrorPolicy::Halt)
return;
continue;
}
- RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
- Map->insert({Reloc.getOffset(), Rel});
+
+ // Compressed sections names in GNU style starts from ".z",
+ // at this point section is decompressed and we drop compression prefix.
+ Name = Name.substr(
+ Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
+
+ // Map platform specific debug section names to DWARF standard section
+ // names.
+ Name = Obj.mapDebugSectionName(Name);
+
+ if (StringRef *SectionData = mapSectionToMember(Name)) {
+ *SectionData = Data;
+ if (Name == "debug_ranges") {
+ // FIXME: Use the other dwo range section when we emit it.
+ RangeDWOSection.Data = Data;
+ }
+ } else if (Name == "debug_types") {
+ // Find debug_types data by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ TypesSections[Section].Data = Data;
+ } else if (Name == "debug_types.dwo") {
+ TypesDWOSections[Section].Data = Data;
+ }
+
+ if (RelocatedSection == Obj.section_end())
+ continue;
+
+ StringRef RelSecName;
+ StringRef RelSecData;
+ RelocatedSection->getName(RelSecName);
+
+ // If the section we're relocating was relocated already by the JIT,
+ // then we used the relocated version above, so we do not need to process
+ // relocations for it now.
+ if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
+ continue;
+
+ // In Mach-o files, the relocations do not need to be applied if
+ // there is no load offset to apply. The value read at the
+ // relocation point already factors in the section address
+ // (actually applying the relocations will produce wrong results
+ // as the section address will be added twice).
+ if (!L && isa<MachOObjectFile>(&Obj))
+ continue;
+
+ RelSecName = RelSecName.substr(
+ RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
+
+ // TODO: Add support for relocations in other sections as needed.
+ // Record relocations for the debug_info and debug_line sections.
+ DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
+ RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
+ if (!Map) {
+ // Find debug_types relocs by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ if (RelSecName == "debug_types")
+ Map =
+ &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
+ .Relocs;
+ else if (RelSecName == "debug_types.dwo")
+ Map = &static_cast<DWARFSectionMap &>(
+ TypesDWOSections[*RelocatedSection])
+ .Relocs;
+ else
+ continue;
+ }
+
+ if (Section.relocation_begin() == Section.relocation_end())
+ continue;
+
+ // Symbol to [address, section index] cache mapping.
+ std::map<SymbolRef, SymInfo> AddrCache;
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ // FIXME: it's not clear how to correctly handle scattered
+ // relocations.
+ if (isRelocScattered(Obj, Reloc))
+ continue;
+
+ Expected<SymInfo> SymInfoOrErr =
+ getSymbolInfo(Obj, Reloc, L, AddrCache);
+ if (!SymInfoOrErr) {
+ if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
+ return;
+ continue;
+ }
+
+ object::RelocVisitor V(Obj);
+ uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address);
+ if (V.error()) {
+ SmallString<32> Type;
+ Reloc.getTypeName(Type);
+ ErrorPolicy EP = HandleError(
+ createError("failed to compute relocation: " + Type + ", ",
+ errorCodeToError(object_error::parse_failed)));
+ if (EP == ErrorPolicy::Halt)
+ return;
+ continue;
+ }
+ RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
+ Map->insert({Reloc.getOffset(), Rel});
+ }
}
}
-}
-DWARFContextInMemory::DWARFContextInMemory(
- const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize,
- bool isLittleEndian)
- : IsLittleEndian(isLittleEndian), AddressSize(AddrSize) {
- for (const auto &SecIt : Sections) {
- if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
- *SectionData = SecIt.second->getBuffer();
+ Optional<RelocAddrEntry> find(const DWARFSection &S,
+ uint64_t Pos) const override {
+ auto &Sec = static_cast<const DWARFSectionMap &>(S);
+ RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
+ if (AI == Sec.Relocs.end())
+ return None;
+ return AI->second;
}
+
+ bool isLittleEndian() const override { return IsLittleEndian; }
+ StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
+ const DWARFSection &getLineDWOSection() const override {
+ return LineDWOSection;
+ }
+ const DWARFSection &getLocDWOSection() const override {
+ return LocDWOSection;
+ }
+ StringRef getStringDWOSection() const override { return StringDWOSection; }
+ const DWARFSection &getStringOffsetDWOSection() const override {
+ return StringOffsetDWOSection;
+ }
+ const DWARFSection &getRangeDWOSection() const override {
+ return RangeDWOSection;
+ }
+ const DWARFSection &getAddrSection() const override { return AddrSection; }
+ StringRef getCUIndexSection() const override { return CUIndexSection; }
+ StringRef getGdbIndexSection() const override { return GdbIndexSection; }
+ StringRef getTUIndexSection() const override { return TUIndexSection; }
+
+ // DWARF v5
+ const DWARFSection &getStringOffsetSection() const override {
+ return StringOffsetSection;
+ }
+
+ // Sections for DWARF5 split dwarf proposal.
+ const DWARFSection &getInfoDWOSection() const override {
+ return InfoDWOSection;
+ }
+ void forEachTypesDWOSections(
+ function_ref<void(const DWARFSection &)> F) const override {
+ for (auto &P : TypesDWOSections)
+ F(P.second);
+ }
+
+ StringRef getAbbrevSection() const override { return AbbrevSection; }
+ const DWARFSection &getLocSection() const override { return LocSection; }
+ StringRef getARangeSection() const override { return ARangeSection; }
+ StringRef getDebugFrameSection() const override { return DebugFrameSection; }
+ StringRef getEHFrameSection() const override { return EHFrameSection; }
+ const DWARFSection &getLineSection() const override { return LineSection; }
+ StringRef getStringSection() const override { return StringSection; }
+ const DWARFSection &getRangeSection() const override { return RangeSection; }
+ StringRef getMacinfoSection() const override { return MacinfoSection; }
+ StringRef getPubNamesSection() const override { return PubNamesSection; }
+ StringRef getPubTypesSection() const override { return PubTypesSection; }
+ StringRef getGnuPubNamesSection() const override {
+ return GnuPubNamesSection;
+ }
+ StringRef getGnuPubTypesSection() const override {
+ return GnuPubTypesSection;
+ }
+ const DWARFSection &getAppleNamesSection() const override {
+ return AppleNamesSection;
+ }
+ const DWARFSection &getAppleTypesSection() const override {
+ return AppleTypesSection;
+ }
+ const DWARFSection &getAppleNamespacesSection() const override {
+ return AppleNamespacesSection;
+ }
+ const DWARFSection &getAppleObjCSection() const override {
+ return AppleObjCSection;
+ }
+
+ StringRef getFileName() const override { return FileName; }
+ uint8_t getAddressSize() const override { return AddressSize; }
+ const DWARFSection &getInfoSection() const override { return InfoSection; }
+ void forEachTypesSections(
+ function_ref<void(const DWARFSection &)> F) const override {
+ for (auto &P : TypesSections)
+ F(P.second);
+ }
+};
+
+std::unique_ptr<DWARFContext>
+DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
+ function_ref<ErrorPolicy(Error)> HandleError) {
+ auto DObj = make_unique<DWARFObjInMemory>(Obj, L, HandleError);
+ return make_unique<DWARFContext>(std::move(DObj));
}
-DWARFSection *DWARFContextInMemory::mapNameToDWARFSection(StringRef Name) {
- return StringSwitch<DWARFSection *>(Name)
- .Case("debug_info", &InfoSection)
- .Case("debug_loc", &LocSection)
- .Case("debug_line", &LineSection)
- .Case("debug_str_offsets", &StringOffsetSection)
- .Case("debug_ranges", &RangeSection)
- .Case("debug_info.dwo", &InfoDWOSection)
- .Case("debug_loc.dwo", &LocDWOSection)
- .Case("debug_line.dwo", &LineDWOSection)
- .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
- .Case("debug_addr", &AddrSection)
- .Case("apple_names", &AppleNamesSection)
- .Case("apple_types", &AppleTypesSection)
- .Case("apple_namespaces", &AppleNamespacesSection)
- .Case("apple_namespac", &AppleNamespacesSection)
- .Case("apple_objc", &AppleObjCSection)
- .Default(nullptr);
+std::unique_ptr<DWARFContext>
+DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize, bool isLittleEndian) {
+ auto DObj = make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
+ return make_unique<DWARFContext>(std::move(DObj));
}
-
-StringRef *DWARFContextInMemory::mapSectionToMember(StringRef Name) {
- if (DWARFSection *Sec = mapNameToDWARFSection(Name))
- return &Sec->Data;
- return StringSwitch<StringRef *>(Name)
- .Case("debug_abbrev", &AbbrevSection)
- .Case("debug_aranges", &ARangeSection)
- .Case("debug_frame", &DebugFrameSection)
- .Case("eh_frame", &EHFrameSection)
- .Case("debug_str", &StringSection)
- .Case("debug_macinfo", &MacinfoSection)
- .Case("debug_pubnames", &PubNamesSection)
- .Case("debug_pubtypes", &PubTypesSection)
- .Case("debug_gnu_pubnames", &GnuPubNamesSection)
- .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
- .Case("debug_abbrev.dwo", &AbbrevDWOSection)
- .Case("debug_str.dwo", &StringDWOSection)
- .Case("debug_cu_index", &CUIndexSection)
- .Case("debug_tu_index", &TUIndexSection)
- .Case("gdb_index", &GdbIndexSection)
- // Any more debug info sections go here.
- .Default(nullptr);
-}
-
-void DWARFContextInMemory::anchor() {}