#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
class MemoryBuffer;
class raw_ostream;
+/// Used as a return value for a error callback passed to DWARF context.
+/// Callback should return Halt if client application wants to stop
+/// object parsing, or should return Continue otherwise.
+enum class ErrorPolicy { Halt, Continue };
+
/// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug
-/// information parsing. The actual data is supplied through pure virtual
-/// methods that a concrete implementation provides.
+/// information parsing. The actual data is supplied through DWARFObj.
class DWARFContext : public DIContext {
DWARFUnitSection<DWARFCompileUnit> CUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
/// and store them in DWOTUs.
void parseDWOTypeUnits();
+protected:
+ std::unique_ptr<const DWARFObject> DObj;
+
public:
- DWARFContext() : DIContext(CK_DWARF) {}
+ DWARFContext(std::unique_ptr<const DWARFObject> DObj)
+ : DIContext(CK_DWARF), DObj(std::move(DObj)) {}
DWARFContext(DWARFContext &) = delete;
DWARFContext &operator=(DWARFContext &) = delete;
+ const DWARFObject &getDWARFObj() const { return *DObj; }
+
static bool classof(const DIContext *DICtx) {
return DICtx->getKind() == CK_DWARF;
}
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- virtual StringRef getFileName() const = 0;
- virtual bool isLittleEndian() const = 0;
- virtual uint8_t getAddressSize() const = 0;
- virtual const DWARFSection &getInfoSection() = 0;
- virtual void forEachTypesSections(function_ref<void(DWARFSection &)> F) = 0;
- virtual StringRef getAbbrevSection() = 0;
- virtual const DWARFSection &getLocSection() = 0;
- virtual StringRef getARangeSection() = 0;
- virtual StringRef getDebugFrameSection() = 0;
- virtual StringRef getEHFrameSection() = 0;
- virtual const DWARFSection &getLineSection() = 0;
- virtual StringRef getStringSection() = 0;
- virtual const DWARFSection& getRangeSection() = 0;
- virtual StringRef getMacinfoSection() = 0;
- virtual StringRef getPubNamesSection() = 0;
- virtual StringRef getPubTypesSection() = 0;
- virtual StringRef getGnuPubNamesSection() = 0;
- virtual StringRef getGnuPubTypesSection() = 0;
-
- /// DWARF v5
- /// @{
- virtual const DWARFSection &getStringOffsetSection() = 0;
- /// @}
-
- // Sections for DWARF5 split dwarf proposal.
- virtual const DWARFSection &getInfoDWOSection() = 0;
- virtual void
- forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) = 0;
- virtual StringRef getAbbrevDWOSection() = 0;
- virtual const DWARFSection &getLineDWOSection() = 0;
- virtual const DWARFSection &getLocDWOSection() = 0;
- virtual StringRef getStringDWOSection() = 0;
- virtual const DWARFSection &getStringOffsetDWOSection() = 0;
- virtual const DWARFSection &getRangeDWOSection() = 0;
- virtual const DWARFSection &getAddrSection() = 0;
- virtual const DWARFSection& getAppleNamesSection() = 0;
- virtual const DWARFSection& getAppleTypesSection() = 0;
- virtual const DWARFSection& getAppleNamespacesSection() = 0;
- virtual const DWARFSection& getAppleObjCSection() = 0;
- virtual StringRef getCUIndexSection() = 0;
- virtual StringRef getGdbIndexSection() = 0;
- virtual StringRef getTUIndexSection() = 0;
-
+ bool isLittleEndian() const { return DObj->isLittleEndian(); }
static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3 || version == 4 || version == 5;
}
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
+ /// Function used to handle default error reporting policy. Prints a error
+ /// message and returns Continue, so DWARF context ignores the error.
+ static ErrorPolicy defaultErrorHandler(Error E);
+ static std::unique_ptr<DWARFContext>
+ create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
+ function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
+
+ static std::unique_ptr<DWARFContext>
+ create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
+
private:
/// Return the compile unit that includes an offset (relative to .debug_info).
DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};
-/// Used as a return value for a error callback passed to DWARF context.
-/// Callback should return Halt if client application wants to stop
-/// object parsing, or should return Continue otherwise.
-enum class ErrorPolicy { Halt, Continue };
-
-/// 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 {
- virtual void anchor();
-
- using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
- std::map<object::SectionRef, unsigned>>;
-
- StringRef FileName;
- bool IsLittleEndian;
- uint8_t AddressSize;
- DWARFSection InfoSection;
- TypeSectionMap TypesSections;
- StringRef AbbrevSection;
- DWARFSection LocSection;
- StringRef ARangeSection;
- StringRef DebugFrameSection;
- StringRef EHFrameSection;
- DWARFSection LineSection;
- StringRef StringSection;
- DWARFSection RangeSection;
- StringRef MacinfoSection;
- StringRef PubNamesSection;
- StringRef PubTypesSection;
- StringRef GnuPubNamesSection;
- StringRef GnuPubTypesSection;
-
- /// DWARF v5
- /// @{
- DWARFSection StringOffsetSection;
- /// @}
-
- // Sections for DWARF5 split dwarf proposal.
- DWARFSection InfoDWOSection;
- TypeSectionMap TypesDWOSections;
- StringRef AbbrevDWOSection;
- DWARFSection LineDWOSection;
- DWARFSection LocDWOSection;
- StringRef StringDWOSection;
- DWARFSection StringOffsetDWOSection;
- DWARFSection RangeDWOSection;
- DWARFSection AddrSection;
- DWARFSection AppleNamesSection;
- DWARFSection AppleTypesSection;
- DWARFSection AppleNamespacesSection;
- DWARFSection AppleObjCSection;
- StringRef CUIndexSection;
- StringRef GdbIndexSection;
- StringRef TUIndexSection;
-
- SmallVector<SmallString<32>, 4> UncompressedSections;
-
- DWARFSection *mapNameToDWARFSection(StringRef Name);
- StringRef *mapSectionToMember(StringRef Name);
-
- /// 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);
-
- /// Function used to handle default error reporting policy. Prints a error
- /// message and returns Continue, so DWARF context ignores the error.
- static ErrorPolicy defaultErrorHandler(Error E);
-
-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);
-
- StringRef getFileName() const override { return FileName; }
- bool isLittleEndian() const override { return IsLittleEndian; }
- uint8_t getAddressSize() const override { return AddressSize; }
- const DWARFSection &getInfoSection() override { return InfoSection; }
- void forEachTypesSections(function_ref<void(DWARFSection &)> F) override {
- for (auto &P : TypesSections)
- F(P.second);
- }
- StringRef getAbbrevSection() override { return AbbrevSection; }
- const DWARFSection &getLocSection() override { return LocSection; }
- StringRef getARangeSection() override { return ARangeSection; }
- StringRef getDebugFrameSection() override { return DebugFrameSection; }
- StringRef getEHFrameSection() override { return EHFrameSection; }
- const DWARFSection &getLineSection() override { return LineSection; }
- StringRef getStringSection() override { return StringSection; }
- const DWARFSection &getRangeSection() override { return RangeSection; }
- StringRef getMacinfoSection() override { return MacinfoSection; }
- StringRef getPubNamesSection() override { return PubNamesSection; }
- StringRef getPubTypesSection() override { return PubTypesSection; }
- StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; }
- StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; }
- const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; }
- const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; }
- const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; }
- const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; }
-
- // DWARF v5
- const DWARFSection &getStringOffsetSection() override {
- return StringOffsetSection;
- }
-
- // Sections for DWARF5 split dwarf proposal.
- const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
-
- void forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) override {
- for (auto &P : TypesDWOSections)
- F(P.second);
- }
-
- StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }
- const DWARFSection &getLineDWOSection() override { return LineDWOSection; }
- const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
- StringRef getStringDWOSection() override { return StringDWOSection; }
-
- const DWARFSection &getStringOffsetDWOSection() override {
- return StringOffsetDWOSection;
- }
-
- const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; }
-
- const DWARFSection &getAddrSection() override { return AddrSection; }
-
- StringRef getCUIndexSection() override { return CUIndexSection; }
- StringRef getGdbIndexSection() override { return GdbIndexSection; }
- StringRef getTUIndexSection() override { return TUIndexSection; }
-};
-
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
#include "llvm/Support/DataExtractor.h"
namespace llvm {
+class DWARFObject;
/// A DataExtractor (typically for an in-memory copy of an object-file section)
/// plus a relocation map for that section, if there is one.
class DWARFDataExtractor : public DataExtractor {
- const RelocAddrMap *RelocMap = nullptr;
+ const DWARFObject *Obj = nullptr;
+ const DWARFSection *Section = nullptr;
+
public:
/// Constructor for the normal case of extracting data from a DWARF section.
/// The DWARFSection's lifetime must be at least as long as the extractor's.
- DWARFDataExtractor(const DWARFSection &Section, bool IsLittleEndian,
- uint8_t AddressSize)
- : DataExtractor(Section.Data, IsLittleEndian, AddressSize),
- RelocMap(&Section.Relocs) {}
+ DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
+ bool IsLittleEndian, uint8_t AddressSize)
+ : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj),
+ Section(&Section) {}
/// Constructor for cases when there are no relocations.
DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
--- /dev/null
+//===- DWARFObject.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_DWARF_DWARFOBJECT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H
+
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+
+namespace llvm {
+// This is responsible for low level access to the object file. It
+// knows how to find the required sections and compute relocated
+// values.
+// The default implementations of the get<Section> methods return dummy values.
+// This is to allow clients that only need some of those to implement just the
+// ones they need. We can't use unreachable for as many cases because the parser
+// implementation is eager and will call some of these methods even if the
+// result is not used.
+class DWARFObject {
+ DWARFSection Dummy;
+
+public:
+ virtual ~DWARFObject() = default;
+ virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); }
+ virtual bool isLittleEndian() const = 0;
+ virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); }
+ virtual const DWARFSection &getInfoSection() const { return Dummy; }
+ virtual void
+ forEachTypesSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual StringRef getAbbrevSection() const { return ""; }
+ virtual const DWARFSection &getLocSection() const { return Dummy; }
+ virtual StringRef getARangeSection() const { return ""; }
+ virtual StringRef getDebugFrameSection() const { return ""; }
+ virtual StringRef getEHFrameSection() const { return ""; }
+ virtual const DWARFSection &getLineSection() const { return Dummy; }
+ virtual StringRef getStringSection() const { return ""; }
+ virtual const DWARFSection &getRangeSection() const { return Dummy; }
+ virtual StringRef getMacinfoSection() const { return ""; }
+ virtual StringRef getPubNamesSection() const { return ""; }
+ virtual StringRef getPubTypesSection() const { return ""; }
+ virtual StringRef getGnuPubNamesSection() const { return ""; }
+ virtual StringRef getGnuPubTypesSection() const { return ""; }
+ virtual const DWARFSection &getStringOffsetSection() const { return Dummy; }
+ virtual const DWARFSection &getInfoDWOSection() const { return Dummy; }
+ virtual void
+ forEachTypesDWOSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual StringRef getAbbrevDWOSection() const { return ""; }
+ virtual const DWARFSection &getLineDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getLocDWOSection() const { return Dummy; }
+ virtual StringRef getStringDWOSection() const { return ""; }
+ virtual const DWARFSection &getStringOffsetDWOSection() const {
+ return Dummy;
+ }
+ virtual const DWARFSection &getRangeDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getAddrSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleNamesSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleTypesSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleNamespacesSection() const {
+ return Dummy;
+ }
+ virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
+ virtual StringRef getCUIndexSection() const { return ""; }
+ virtual StringRef getGdbIndexSection() const { return ""; }
+ virtual StringRef getTUIndexSection() const { return ""; }
+ virtual Optional<RelocAddrEntry> find(const DWARFSection &Sec,
+ uint64_t Pos) const = 0;
+};
+
+} // namespace llvm
+#endif
struct DWARFSection {
StringRef Data;
+};
+
+struct DWARFSectionMap final : public DWARFSection {
RelocAddrMap Relocs;
};
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
- DWARFDataExtractor getDebugInfoExtractor() const {
- return DWARFDataExtractor(InfoSection, isLittleEndian,
- getAddressByteSize());
- }
+ DWARFDataExtractor getDebugInfoExtractor() const;
DataExtractor getStringExtractor() const {
return DataExtractor(StringSection, false, 0);
}
- const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
- const RelocAddrMap &getStringOffsetsRelocMap() const {
- return StringOffsetSection.Relocs;
- }
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
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);
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();
// 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) {
// 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);
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);
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);
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);
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)) {
}
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)) {
// 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))
}
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) {
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);
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);
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;
if (Abbrev)
return Abbrev.get();
- DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
+ DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
Abbrev.reset(new DWARFDebugAbbrev());
Abbrev->extract(abbrData);
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();
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);
}
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();
// 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();
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();
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();
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);
});
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()) {
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;
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);
return MachObj->isRelocationScattered(RelocInfo);
}
-Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
- StringRef Name, StringRef &Data) {
- if (!Decompressor::isCompressed(Sec))
- return Error::success();
+ErrorPolicy DWARFContext::defaultErrorHandler(Error E) {
+ errs() << "error: " + toString(std::move(E)) << '\n';
+ return ErrorPolicy::Continue;
+}
- Expected<Decompressor> Decompressor =
- Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
- if (!Decompressor)
- return Decompressor.takeError();
+class DWARFObjInMemory final : public DWARFObject {
+ bool IsLittleEndian;
+ uint8_t AddressSize;
+ StringRef FileName;
+
+ using TypeSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
+ std::map<object::SectionRef, unsigned>>;
+
+ 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);
+ }
- SmallString<32> Out;
- if (auto Err = Decompressor->resizeAndDecompress(Out))
- return Err;
+ 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);
+ }
- UncompressedSections.emplace_back(std::move(Out));
- Data = UncompressedSections.back();
+ /// 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();
- return Error::success();
-}
+ Expected<Decompressor> Decompressor =
+ Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
+ if (!Decompressor)
+ return Decompressor.takeError();
-ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) {
- errs() << "error: " + toString(std::move(E)) << '\n';
- return ErrorPolicy::Continue;
-}
+ SmallString<32> Out;
+ if (auto Err = Decompressor->resizeAndDecompress(Out))
+ return Err;
-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;
-
- 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);
-
- if (auto Err = maybeDecompress(Section, Name, Data)) {
- ErrorPolicy EP = HandleError(
- createError("failed to decompress '" + Name + "', ", std::move(Err)));
- if (EP == ErrorPolicy::Halt)
- return;
- continue;
- }
+ UncompressedSections.emplace_back(std::move(Out));
+ Data = UncompressedSections.back();
- // 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.
+ return Error::success();
+ }
- // Map platform specific debug section names to DWARF standard section
- // names.
- Name = Obj.mapDebugSectionName(Name);
+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()) {
+
+ 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;
- 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;
+ 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);
+
+ if (auto Err = maybeDecompress(Section, Name, Data)) {
+ ErrorPolicy EP = HandleError(createError(
+ "failed to decompress '" + Name + "', ", std::move(Err)));
+ if (EP == ErrorPolicy::Halt)
+ return;
+ continue;
+ }
+
+ // 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;
}
- } 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
+ if (RelocatedSection == Obj.section_end())
continue;
- }
- if (Section.relocation_begin() == Section.relocation_end())
- continue;
+ StringRef RelSecName;
+ StringRef RelSecData;
+ RelocatedSection->getName(RelSecName);
- // 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))
+ // 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;
- Expected<SymInfo> SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache);
- if (!SymInfoOrErr) {
- if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt)
- return;
+ // 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;
}
- 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;
+ 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});
}
- 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;
}
-}
-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);
-}
+ 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 *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);
+ 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));
}
-void DWARFContextInMemory::anchor() {}
+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));
+}
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
using namespace llvm;
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
uint64_t *SecNdx) const {
- if (!RelocMap)
+ if (!Section)
return getUnsigned(Off, Size);
- RelocAddrMap::const_iterator AI = RelocMap->find(*Off);
- if (AI == RelocMap->end())
+ Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);
+ if (!Rel)
return getUnsigned(Off, Size);
if (SecNdx)
- *SecNdx = AI->second.SectionIndex;
- return getUnsigned(Off, Size) + AI->second.Value;
+ *SecNdx = Rel->SectionIndex;
+ return getUnsigned(Off, Size) + Rel->Value;
}
return;
// Extract aranges from .debug_aranges section.
- DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
+ DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(),
+ CTX->isLittleEndian(), 0);
extract(ArangesData);
// Generate aranges from DIEs: even if .debug_aranges section is present,
using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
- parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(),
- C.getStringSection(), C.getStringOffsetSection(),
- &C.getAddrSection(), C.getLineSection(), C.isLittleEndian(), false);
+ const DWARFObject &D = C.getDWARFObj();
+ parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(),
+ D.getStringSection(), D.getStringOffsetSection(),
+ &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false);
}
void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
const DWARFSection &DWOSection,
DWARFUnitIndex *Index) {
- parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &C.getRangeDWOSection(),
- C.getStringDWOSection(), C.getStringOffsetDWOSection(),
- &C.getAddrSection(), C.getLineDWOSection(), C.isLittleEndian(),
+ const DWARFObject &D = C.getDWARFObj();
+ parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(),
+ D.getStringDWOSection(), D.getStringOffsetDWOSection(),
+ &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(),
true);
}
DWARFUnit::~DWARFUnit() = default;
+DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
+ return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian,
+ getAddressByteSize());
+}
+
bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
uint64_t &Result) const {
uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize();
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
return false;
- DWARFDataExtractor DA(*AddrOffsetSection, isLittleEndian,
- getAddressByteSize());
+ DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
+ isLittleEndian, getAddressByteSize());
Result = DA.getRelocatedAddress(&Offset);
return true;
}
uint32_t Offset = StringOffsetSectionBase + Index * ItemSize;
if (StringOffsetSection.Data.size() < Offset + ItemSize)
return false;
- DWARFDataExtractor DA(StringOffsetSection, isLittleEndian, 0);
+ DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
+ isLittleEndian, 0);
Result = DA.getRelocatedValue(ItemSize, &Offset);
return true;
}
DWARFDebugRangeList &RangeList) const {
// Require that compile unit is extracted.
assert(!DieArray.empty());
- DWARFDataExtractor RangesData(*RangeSection, isLittleEndian,
- getAddressByteSize());
+ DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
+ isLittleEndian, getAddressByteSize());
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
return RangeList.extract(RangesData, &ActualRangeListOffset);
}
bool DWARFVerifier::handleDebugInfo() {
OS << "Verifying .debug_info Unit Header Chain...\n";
- DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),
- 0);
+ const DWARFObject &DObj = DCtx.getDWARFObj();
+ DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(),
+ DCtx.isLittleEndian(), 0);
uint32_t NumDebugInfoErrors = 0;
uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
uint8_t UnitType = 0;
case dwarf::DW_UT_split_type: {
DWARFUnitSection<DWARFTypeUnit> TUSection{};
Unit.reset(new DWARFTypeUnit(
- DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
- &DCtx.getRangeSection(), DCtx.getStringSection(),
- DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
- DCtx.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
+ DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
+ &DObj.getRangeSection(), DObj.getStringSection(),
+ DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
+ DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
nullptr));
break;
}
case 0: {
DWARFUnitSection<DWARFCompileUnit> CUSection{};
Unit.reset(new DWARFCompileUnit(
- DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
- &DCtx.getRangeSection(), DCtx.getStringSection(),
- DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
- DCtx.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
+ DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
+ &DObj.getRangeSection(), DObj.getStringSection(),
+ DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
+ DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
nullptr));
break;
}
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
DWARFAttribute &AttrValue) {
+ const DWARFObject &DObj = DCtx.getDWARFObj();
unsigned NumErrors = 0;
const auto Attr = AttrValue.Attr;
switch (Attr) {
case DW_AT_ranges:
// Make sure the offset in the DW_AT_ranges attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
- if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
+ if (*SectionOffset >= DObj.getRangeSection().Data.size()) {
++NumErrors;
OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
"bounds:\n";
case DW_AT_stmt_list:
// Make sure the offset in the DW_AT_stmt_list attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
- if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
+ if (*SectionOffset >= DObj.getLineSection().Data.size()) {
++NumErrors;
OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
"bounds: "
unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
DWARFAttribute &AttrValue) {
+ const DWARFObject &DObj = DCtx.getDWARFObj();
unsigned NumErrors = 0;
const auto Form = AttrValue.Value.getForm();
switch (Form) {
Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
assert(RefVal);
if (RefVal) {
- if (*RefVal >= DCtx.getInfoSection().Data.size()) {
+ if (*RefVal >= DObj.getInfoSection().Data.size()) {
++NumErrors;
OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
"bounds:\n";
case DW_FORM_strp: {
auto SecOffset = AttrValue.Value.getAsSectionOffset();
assert(SecOffset); // DW_FORM_strp is a section offset.
- if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
+ if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
++NumErrors;
OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
Die.dump(OS, 0);
continue;
const uint32_t LineTableOffset = *StmtSectionOffset;
auto LineTable = DCtx.getLineTableForUnit(CU.get());
- if (LineTableOffset < DCtx.getLineSection().Data.size()) {
+ if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
if (!LineTable) {
++NumDebugLineErrors;
OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
bool DWARFVerifier::handleAppleNames() {
NumAppleNamesErrors = 0;
-
- DWARFDataExtractor AppleNamesSection(DCtx.getAppleNamesSection(),
+ const DWARFObject &D = DCtx.getDWARFObj();
+ DWARFDataExtractor AppleNamesSection(D, D.getAppleNamesSection(),
DCtx.isLittleEndian(), 0);
- DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0);
+ DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData);
if (!AppleNames.extract()) {
}
}
if (!Context)
- Context.reset(new DWARFContextInMemory(*Objects.second));
+ Context = DWARFContext::create(*Objects.second);
assert(Context);
auto InfoOrErr =
SymbolizableObjectFile::create(Objects.first, std::move(Context));
MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
- const DWARFSection &InputSec = Dwarf.getLocSection();
+ const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false);
/// Construct the output DIE tree by cloning the DIEs we
/// chose to keep above. If there are no valid relocs, then there's
/// nothing to clone/emit.
- void cloneAllCompileUnits(DWARFContextInMemory &DwarfContext);
+ void cloneAllCompileUnits(DWARFContext &DwarfContext);
private:
typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
DWARFDebugRangeList RangeList;
const auto &FunctionRanges = Unit.getFunctionRanges();
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
- DWARFDataExtractor RangeExtractor(OrigDwarf.getRangeSection(),
+ DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
+ OrigDwarf.getDWARFObj().getRangeSection(),
OrigDwarf.isLittleEndian(), AddressSize);
auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
DWARFUnit &OrigUnit = Unit.getOrigUnit();
// Parse the original line info for the unit.
DWARFDebugLine::LineTable LineTable;
uint32_t StmtOffset = *StmtList;
- DWARFDataExtractor LineExtractor(OrigDwarf.getLineSection(),
- OrigDwarf.isLittleEndian(),
- Unit.getOrigUnit().getAddressByteSize());
+ DWARFDataExtractor LineExtractor(
+ OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
+ OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
LineTable.parse(LineExtractor, &StmtOffset);
// This vector is the output line table.
LineTable.Prologue.OpcodeBase > 13)
reportWarning("line table parameters mismatch. Cannot emit.");
else {
- StringRef LineData = OrigDwarf.getLineSection().Data;
+ StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data;
MCDwarfLineTableParams Params;
Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
Params.DWARF2LineBase = LineTable.Prologue.LineBase;
void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
DWARFContext &OrigDwarf,
unsigned AddrSize) {
- StringRef FrameData = OrigDwarf.getDebugFrameSection();
+ StringRef FrameData = OrigDwarf.getDWARFObj().getDebugFrameSection();
if (FrameData.empty())
return;
std::unique_ptr<CompileUnit> Unit;
// Setup access to the debug info.
- DWARFContextInMemory DwarfContext(*ErrOrObj);
+ auto DwarfContext = DWARFContext::create(*ErrOrObj);
RelocationManager RelocMgr(*this);
- for (const auto &CU : DwarfContext.compile_units()) {
+ for (const auto &CU : DwarfContext->compile_units()) {
auto CUDie = CU->getUnitDIE(false);
// Recursively get all modules imported by this one.
if (!registerModuleReference(CUDie, *CU, ModuleMap, Indent)) {
std::vector<std::unique_ptr<CompileUnit>> CompileUnits;
CompileUnits.push_back(std::move(Unit));
DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options)
- .cloneAllCompileUnits(DwarfContext);
+ .cloneAllCompileUnits(*DwarfContext);
}
-void DwarfLinker::DIECloner::cloneAllCompileUnits(
- DWARFContextInMemory &DwarfContext) {
+void DwarfLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext) {
if (!Linker.Streamer)
return;
}
// Setup access to the debug info.
- DWARFContextInMemory DwarfContext(*ErrOrObj);
- startDebugObject(DwarfContext, *Obj);
+ auto DwarfContext = DWARFContext::create(*ErrOrObj);
+ startDebugObject(*DwarfContext, *Obj);
// In a first phase, just read in the debug info and load all clang modules.
- for (const auto &CU : DwarfContext.compile_units()) {
+ for (const auto &CU : DwarfContext->compile_units()) {
auto CUDie = CU->getUnitDIE(false);
if (Options.Verbose) {
outs() << "Input compilation unit:";
RelocMgr.resetValidRelocs();
if (RelocMgr.hasValidRelocs())
DIECloner(*this, RelocMgr, DIEAlloc, Units, Options)
- .cloneAllCompileUnits(DwarfContext);
+ .cloneAllCompileUnits(*DwarfContext);
if (!Options.NoOutput && !Units.empty())
- patchFrameInfoForObject(*Obj, DwarfContext,
+ patchFrameInfoForObject(*Obj, *DwarfContext,
Units[0]->getOrigUnit().getAddressByteSize());
// Clean-up before starting working on the next object.
}
static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
- std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
+ std::unique_ptr<DIContext> DICtx = DWARFContext::create(Obj);
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
}
static bool VerifyObjectFile(ObjectFile &Obj, Twine Filename) {
- std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
-
+ std::unique_ptr<DIContext> DICtx = DWARFContext::create(Obj);
+
// Verify the DWARF and exit with non-zero exit status if verification
// fails.
raw_ostream &stream = Quiet ? nulls() : outs();
printWeakBindTable(MachOOF);
if (DwarfDumpType != DIDT_Null) {
- std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF));
+ std::unique_ptr<DIContext> DICtx = DWARFContext::create(*MachOOF);
// Dump the complete DWARF structure.
DIDumpOptions DumpOpts;
DumpOpts.DumpType = DwarfDumpType;
}
// Setup the DIContext
- diContext.reset(new DWARFContextInMemory(*DbgObj));
+ diContext = DWARFContext::create(*DbgObj);
}
if (FilterSections.size() == 0)
#include <cctype>
#include <cstring>
#include <system_error>
-#include <utility>
#include <unordered_map>
+#include <utility>
using namespace llvm;
using namespace object;
if (PrintFaultMaps)
printFaultMaps(o);
if (DwarfDumpType != DIDT_Null) {
- std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*o));
+ std::unique_ptr<DIContext> DICtx = DWARFContext::create(*o);
// Dump the complete DWARF structure.
DIDumpOptions DumpOpts;
DumpOpts.DumpType = DwarfDumpType;
}
}
- std::unique_ptr<DIContext> Context(
- new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get()));
+ std::unique_ptr<DIContext> Context =
+ DWARFContext::create(*SymbolObj, LoadedObjInfo.get());
std::vector<std::pair<SymbolRef, uint64_t>> SymAddr =
object::computeSymbolSizes(*SymbolObj);
InitialLength.TotalLength64 = Data.getU64(&Offset);
}
-void dumpDebugAbbrev(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
+void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
auto AbbrevSetPtr = DCtx.getDebugAbbrev();
if (AbbrevSetPtr) {
for (auto AbbrvDeclSet : *AbbrevSetPtr) {
}
}
-void dumpDebugStrings(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
- StringRef RemainingTable = DCtx.getStringSection();
+void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+ StringRef RemainingTable = DCtx.getDWARFObj().getStringSection();
while (RemainingTable.size() > 0) {
auto SymbolPair = RemainingTable.split('\0');
RemainingTable = SymbolPair.second;
}
}
-void dumpDebugARanges(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
- DataExtractor ArangesData(DCtx.getARangeSection(), DCtx.isLittleEndian(), 0);
+void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+ DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(),
+ DCtx.isLittleEndian(), 0);
uint32_t Offset = 0;
DWARFDebugArangeSet Set;
}
}
-void dumpPubSection(DWARFContextInMemory &DCtx, DWARFYAML::PubSection &Y,
+void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
StringRef Section) {
DataExtractor PubSectionData(Section, DCtx.isLittleEndian(), 0);
uint32_t Offset = 0;
}
}
-void dumpDebugPubSections(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
+void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+ const DWARFObject &D = DCtx.getDWARFObj();
Y.PubNames.IsGNUStyle = false;
- dumpPubSection(DCtx, Y.PubNames, DCtx.getPubNamesSection());
+ dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection());
Y.PubTypes.IsGNUStyle = false;
- dumpPubSection(DCtx, Y.PubTypes, DCtx.getPubTypesSection());
+ dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection());
Y.GNUPubNames.IsGNUStyle = true;
- dumpPubSection(DCtx, Y.GNUPubNames, DCtx.getGnuPubNamesSection());
+ dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection());
Y.GNUPubTypes.IsGNUStyle = true;
- dumpPubSection(DCtx, Y.GNUPubTypes, DCtx.getGnuPubTypesSection());
+ dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection());
}
-void dumpDebugInfo(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
+void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
for (const auto &CU : DCtx.compile_units()) {
DWARFYAML::Unit NewUnit;
NewUnit.Length.setLength(CU->getLength());
return true;
}
-void dumpDebugLines(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
+void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
for (const auto &CU : DCtx.compile_units()) {
auto CUDIE = CU->getUnitDIE();
if (!CUDIE)
if (auto StmtOffset =
dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
DWARFYAML::LineTable DebugLines;
- DataExtractor LineData(DCtx.getLineSection().Data, DCtx.isLittleEndian(),
- CU->getAddressByteSize());
+ DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
+ DCtx.isLittleEndian(), CU->getAddressByteSize());
uint32_t Offset = *StmtOffset;
dumpInitialLength(LineData, Offset, DebugLines.Length);
uint64_t LineTableLength = DebugLines.Length.getLength();
}
}
-std::error_code dwarf2yaml(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
+std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
dumpDebugAbbrev(DCtx, Y);
dumpDebugStrings(DCtx, Y);
dumpDebugARanges(DCtx, Y);
ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false);
void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
void dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y);
- void dumpDebugAbbrev(DWARFContextInMemory &DCtx,
+ void dumpDebugAbbrev(DWARFContext &DCtx,
std::unique_ptr<MachOYAML::Object> &Y);
- void dumpDebugStrings(DWARFContextInMemory &DCtx,
+ void dumpDebugStrings(DWARFContext &DCtx,
std::unique_ptr<MachOYAML::Object> &Y);
public:
dumpLoadCommands(Y);
dumpLinkEdit(Y);
- DWARFContextInMemory DICtx(Obj);
- if (auto Err = dwarf2yaml(DICtx, Y->DWARF))
+ std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
+ if (auto Err = dwarf2yaml(*DICtx, Y->DWARF))
return errorCodeToError(Err);
return std::move(Y);
}
// Forward decls for dwarf2yaml
namespace llvm {
-class DWARFContextInMemory;
+class DWARFContext;
namespace DWARFYAML {
struct Data;
}
}
-std::error_code dwarf2yaml(llvm::DWARFContextInMemory &DCtx,
- llvm::DWARFYAML::Data &Y);
+std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
#endif
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/Config/llvm-config.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
#include <climits>
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
auto DieDG = U->getUnitDIE(false);
EXPECT_TRUE(DieDG.isValid());
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto DieDG = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 2u);
- DWARFCompileUnit *U1 = DwarfContext.getCompileUnitAtIndex(0);
- DWARFCompileUnit *U2 = DwarfContext.getCompileUnitAtIndex(1);
+ DWARFCompileUnit *U1 = DwarfContext->getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U2 = DwarfContext->getCompileUnitAtIndex(1);
// Get the compile unit DIE is valid.
auto Unit1DieDG = U1->getUnitDIE(false);
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto DieDG = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct.
- uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+ uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u);
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false);
MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
- DWARFContextInMemory DwarfContext(*Obj.get());
- DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
+ DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
EXPECT_TRUE((bool)U);
const auto *Abbrevs = U->getAbbreviations();
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is "
- "invalid (must be less than CU size of "
- "0x0000001a):");
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is "
+ "invalid (must be less than CU size of "
+ "0x0000001a):");
}
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) {
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext,
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext,
"error: DW_FORM_ref_addr offset beyond .debug_info bounds:");
}
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext,
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext,
"error: DW_AT_ranges offset is beyond .debug_ranges bounds:");
}
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
VerifyError(
- DwarfContext,
+ *DwarfContext,
"error: DW_AT_stmt_list offset is beyond .debug_line bounds: 0x00001000");
}
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext,
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext,
"error: DW_FORM_strp offset beyond .debug_str bounds:");
}
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
VerifyError(
- DwarfContext,
+ *DwarfContext,
"error: invalid DIE reference 0x00000011. Offset is in between DIEs:");
}
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext, "error: .debug_line[0x00000000] row[1] decreases "
- "in address from previous row:");
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext, "error: .debug_line[0x00000000] row[1] decreases "
+ "in address from previous row:");
}
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext, "error: .debug_line[0x00000000][1] has invalid "
- "file index 5 (valid values are [1,1]):");
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext, "error: .debug_line[0x00000000][1] has invalid "
+ "file index 5 (valid values are [1,1]):");
}
TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
)";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections);
- DWARFContextInMemory DwarfContext(*ErrOrSections, 8);
- VerifyError(DwarfContext, "error: two compile unit DIEs, 0x0000000b and "
- "0x0000001f, have the same DW_AT_stmt_list section "
- "offset:");
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ VerifyError(*DwarfContext,
+ "error: two compile unit DIEs, 0x0000000b and "
+ "0x0000001f, have the same DW_AT_stmt_list section "
+ "offset:");
}
TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
// DWARFContextInMemory
// to parse whole file and find both two errors we know about.
int Errors = 0;
- DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) {
- ++Errors;
- consumeError(std::move(E));
- return ErrorPolicy::Continue;
- });
+ std::unique_ptr<DWARFContext> Ctx1 =
+ DWARFContext::create(**Obj, nullptr, [&](Error E) {
+ ++Errors;
+ consumeError(std::move(E));
+ return ErrorPolicy::Continue;
+ });
EXPECT_TRUE(Errors == 2);
// Case 2: error handler stops parsing of object after first error.
Errors = 0;
- DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) {
- ++Errors;
- consumeError(std::move(E));
- return ErrorPolicy::Halt;
- });
+ std::unique_ptr<DWARFContext> Ctx2 =
+ DWARFContext::create(**Obj, nullptr, [&](Error E) {
+ ++Errors;
+ consumeError(std::move(E));
+ return ErrorPolicy::Halt;
+ });
EXPECT_TRUE(Errors == 1);
}