1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

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
This commit is contained in:
Rafael Espindola 2017-07-19 22:27:28 +00:00
parent 2d8fc4864f
commit d66fd5d54c
20 changed files with 696 additions and 586 deletions

View File

@ -26,6 +26,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
@ -45,10 +46,14 @@ class DataExtractor;
class MemoryBuffer; class MemoryBuffer;
class raw_ostream; 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 /// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug /// This data structure is the top level entity that deals with dwarf debug
/// information parsing. The actual data is supplied through pure virtual /// information parsing. The actual data is supplied through DWARFObj.
/// methods that a concrete implementation provides.
class DWARFContext : public DIContext { class DWARFContext : public DIContext {
DWARFUnitSection<DWARFCompileUnit> CUs; DWARFUnitSection<DWARFCompileUnit> CUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs; std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
@ -95,11 +100,17 @@ class DWARFContext : public DIContext {
/// and store them in DWOTUs. /// and store them in DWOTUs.
void parseDWOTypeUnits(); void parseDWOTypeUnits();
protected:
std::unique_ptr<const DWARFObject> DObj;
public: public:
DWARFContext() : DIContext(CK_DWARF) {} DWARFContext(std::unique_ptr<const DWARFObject> DObj)
: DIContext(CK_DWARF), DObj(std::move(DObj)) {}
DWARFContext(DWARFContext &) = delete; DWARFContext(DWARFContext &) = delete;
DWARFContext &operator=(DWARFContext &) = delete; DWARFContext &operator=(DWARFContext &) = delete;
const DWARFObject &getDWARFObj() const { return *DObj; }
static bool classof(const DIContext *DICtx) { static bool classof(const DIContext *DICtx) {
return DICtx->getKind() == CK_DWARF; return DICtx->getKind() == CK_DWARF;
} }
@ -222,55 +233,24 @@ public:
DIInliningInfo getInliningInfoForAddress(uint64_t Address, DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
virtual StringRef getFileName() const = 0; bool isLittleEndian() const { return DObj->isLittleEndian(); }
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;
static bool isSupportedVersion(unsigned version) { static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3 || version == 4 || version == 5; return version == 2 || version == 3 || version == 4 || version == 5;
} }
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath); 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: private:
/// Return the compile unit that includes an offset (relative to .debug_info). /// Return the compile unit that includes an offset (relative to .debug_info).
DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
@ -280,142 +260,6 @@ private:
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); 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 } // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H

View File

@ -14,18 +14,21 @@
#include "llvm/Support/DataExtractor.h" #include "llvm/Support/DataExtractor.h"
namespace llvm { namespace llvm {
class DWARFObject;
/// A DataExtractor (typically for an in-memory copy of an object-file section) /// A DataExtractor (typically for an in-memory copy of an object-file section)
/// plus a relocation map for that section, if there is one. /// plus a relocation map for that section, if there is one.
class DWARFDataExtractor : public DataExtractor { class DWARFDataExtractor : public DataExtractor {
const RelocAddrMap *RelocMap = nullptr; const DWARFObject *Obj = nullptr;
const DWARFSection *Section = nullptr;
public: public:
/// Constructor for the normal case of extracting data from a DWARF section. /// 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. /// The DWARFSection's lifetime must be at least as long as the extractor's.
DWARFDataExtractor(const DWARFSection &Section, bool IsLittleEndian, DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
uint8_t AddressSize) bool IsLittleEndian, uint8_t AddressSize)
: DataExtractor(Section.Data, IsLittleEndian, AddressSize), : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj),
RelocMap(&Section.Relocs) {} Section(&Section) {}
/// Constructor for cases when there are no relocations. /// Constructor for cases when there are no relocations.
DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)

View File

@ -0,0 +1,75 @@
//===- 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

View File

@ -17,6 +17,9 @@ namespace llvm {
struct DWARFSection { struct DWARFSection {
StringRef Data; StringRef Data;
};
struct DWARFSectionMap final : public DWARFSection {
RelocAddrMap Relocs; RelocAddrMap Relocs;
}; };

View File

@ -197,19 +197,12 @@ public:
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const; bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
DWARFDataExtractor getDebugInfoExtractor() const { DWARFDataExtractor getDebugInfoExtractor() const;
return DWARFDataExtractor(InfoSection, isLittleEndian,
getAddressByteSize());
}
DataExtractor getStringExtractor() const { DataExtractor getStringExtractor() const {
return DataExtractor(StringSection, false, 0); 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); bool extract(DataExtractor debug_info, uint32_t* offset_ptr);

View File

@ -60,9 +60,10 @@ using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
static void dumpAccelSection(raw_ostream &OS, StringRef Name, static void dumpAccelSection(raw_ostream &OS, StringRef Name,
const DWARFSection& Section, StringRef StringSection, const DWARFObject &Obj,
bool LittleEndian) { const DWARFSection &Section,
DWARFDataExtractor AccelSection(Section, LittleEndian, 0); StringRef StringSection, bool LittleEndian) {
DWARFDataExtractor AccelSection(Obj, Section, LittleEndian, 0);
DataExtractor StrData(StringSection, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0);
OS << "\n." << Name << " contents:\n"; OS << "\n." << Name << " contents:\n";
DWARFAcceleratorTable Accel(AccelSection, StrData); DWARFAcceleratorTable Accel(AccelSection, StrData);
@ -73,9 +74,10 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name,
static void static void
dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName, dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
const DWARFObject &Obj,
const DWARFSection &StringOffsetsSection, const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian) { StringRef StringSection, bool LittleEndian) {
DWARFDataExtractor StrOffsetExt(StringOffsetsSection, LittleEndian, 0); DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
uint32_t Offset = 0; uint32_t Offset = 0;
uint64_t SectionSize = StringOffsetsSection.Data.size(); uint64_t SectionSize = StringOffsetsSection.Data.size();
@ -153,6 +155,7 @@ dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName,
// monolithic series of string offsets, as generated by the pre-DWARF v5 // monolithic series of string offsets, as generated by the pre-DWARF v5
// implementation of split DWARF. // implementation of split DWARF.
static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
const DWARFObject &Obj,
const DWARFSection &StringOffsetsSection, const DWARFSection &StringOffsetsSection,
StringRef StringSection, bool LittleEndian, StringRef StringSection, bool LittleEndian,
unsigned MaxVersion) { unsigned MaxVersion) {
@ -163,7 +166,7 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,
// we assume that the section is formatted like a DWARF v5 string offsets // we assume that the section is formatted like a DWARF v5 string offsets
// section. // section.
if (MaxVersion >= 5) if (MaxVersion >= 5)
dumpDWARFv5StringOffsetsSection(OS, SectionName, StringOffsetsSection, dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection,
StringSection, LittleEndian); StringSection, LittleEndian);
else { else {
DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0);
@ -259,7 +262,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
uint32_t offset = 0; uint32_t offset = 0;
if (DumpType == DIDT_All || DumpType == DIDT_Aranges) { if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
OS << "\n.debug_aranges contents:\n"; OS << "\n.debug_aranges contents:\n";
DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); DataExtractor arangesData(DObj->getARangeSection(), isLittleEndian(), 0);
DWARFDebugArangeSet set; DWARFDebugArangeSet set;
while (set.extract(arangesData, &offset)) while (set.extract(arangesData, &offset))
set.dump(OS); set.dump(OS);
@ -274,8 +277,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
if (!CUDIE) if (!CUDIE)
continue; continue;
if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) { if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) {
DWARFDataExtractor lineData(getLineSection(), isLittleEndian(), DWARFDataExtractor lineData(*DObj, DObj->getLineSection(),
savedAddressByteSize); isLittleEndian(), savedAddressByteSize);
DWARFDebugLine::LineTable LineTable; DWARFDebugLine::LineTable LineTable;
uint32_t Offset = *StmtOffset; uint32_t Offset = *StmtOffset;
LineTable.parse(lineData, &Offset); LineTable.parse(lineData, &Offset);
@ -297,8 +300,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
OS << "\n.debug_line.dwo contents:\n"; OS << "\n.debug_line.dwo contents:\n";
unsigned stmtOffset = 0; unsigned stmtOffset = 0;
DWARFDataExtractor lineData(getLineDWOSection(), isLittleEndian(), DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(),
savedAddressByteSize); isLittleEndian(), savedAddressByteSize);
DWARFDebugLine::LineTable LineTable; DWARFDebugLine::LineTable LineTable;
while (LineTable.Prologue.parse(lineData, &stmtOffset)) { while (LineTable.Prologue.parse(lineData, &stmtOffset)) {
LineTable.dump(OS); LineTable.dump(OS);
@ -308,7 +311,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
if (DumpType == DIDT_All || DumpType == DIDT_Str) { if (DumpType == DIDT_All || DumpType == DIDT_Str) {
OS << "\n.debug_str contents:\n"; OS << "\n.debug_str contents:\n";
DataExtractor strData(getStringSection(), isLittleEndian(), 0); DataExtractor strData(DObj->getStringSection(), isLittleEndian(), 0);
offset = 0; offset = 0;
uint32_t strOffset = 0; uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) { while (const char *s = strData.getCStr(&offset)) {
@ -318,9 +321,9 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
} }
if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) && if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) &&
!getStringDWOSection().empty()) { !DObj->getStringDWOSection().empty()) {
OS << "\n.debug_str.dwo contents:\n"; OS << "\n.debug_str.dwo contents:\n";
DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); DataExtractor strDWOData(DObj->getStringDWOSection(), isLittleEndian(), 0);
offset = 0; offset = 0;
uint32_t strDWOOffset = 0; uint32_t strDWOOffset = 0;
while (const char *s = strDWOData.getCStr(&offset)) { while (const char *s = strDWOData.getCStr(&offset)) {
@ -335,8 +338,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
// sizes, but for simplicity we just use the address byte size of the last // 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 // compile unit (there is no easy and fast way to associate address range
// list and the compile unit it describes). // list and the compile unit it describes).
DWARFDataExtractor rangesData(getRangeSection(), isLittleEndian(), DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(),
savedAddressByteSize); isLittleEndian(), savedAddressByteSize);
offset = 0; offset = 0;
DWARFDebugRangeList rangeList; DWARFDebugRangeList rangeList;
while (rangeList.extract(rangesData, &offset)) while (rangeList.extract(rangesData, &offset))
@ -344,55 +347,56 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
} }
if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
DWARFDebugPubTable(getPubNamesSection(), isLittleEndian(), false) DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false)
.dump("debug_pubnames", OS); .dump("debug_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes) if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
DWARFDebugPubTable(getPubTypesSection(), isLittleEndian(), false) DWARFDebugPubTable(DObj->getPubTypesSection(), isLittleEndian(), false)
.dump("debug_pubtypes", OS); .dump("debug_pubtypes", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames) if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
DWARFDebugPubTable(getGnuPubNamesSection(), isLittleEndian(), DWARFDebugPubTable(DObj->getGnuPubNamesSection(), isLittleEndian(),
true /* GnuStyle */) true /* GnuStyle */)
.dump("debug_gnu_pubnames", OS); .dump("debug_gnu_pubnames", OS);
if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes) if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
DWARFDebugPubTable(getGnuPubTypesSection(), isLittleEndian(), DWARFDebugPubTable(DObj->getGnuPubTypesSection(), isLittleEndian(),
true /* GnuStyle */) true /* GnuStyle */)
.dump("debug_gnu_pubtypes", OS); .dump("debug_gnu_pubtypes", OS);
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets) if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets)
dumpStringOffsetsSection(OS, "debug_str_offsets", getStringOffsetSection(), dumpStringOffsetsSection(
getStringSection(), isLittleEndian(), OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(),
getMaxVersion()); DObj->getStringSection(), isLittleEndian(), getMaxVersion());
if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) { if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) {
dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", dumpStringOffsetsSection(
getStringOffsetDWOSection(), getStringDWOSection(), OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(),
isLittleEndian(), getMaxVersion()); DObj->getStringDWOSection(), isLittleEndian(), getMaxVersion());
} }
if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) && if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) &&
!getGdbIndexSection().empty()) { !DObj->getGdbIndexSection().empty()) {
OS << "\n.gnu_index contents:\n"; OS << "\n.gnu_index contents:\n";
getGdbIndex().dump(OS); getGdbIndex().dump(OS);
} }
if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
dumpAccelSection(OS, "apple_names", getAppleNamesSection(), dumpAccelSection(OS, "apple_names", *DObj, DObj->getAppleNamesSection(),
getStringSection(), isLittleEndian()); DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes) if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes)
dumpAccelSection(OS, "apple_types", getAppleTypesSection(), dumpAccelSection(OS, "apple_types", *DObj, DObj->getAppleTypesSection(),
getStringSection(), isLittleEndian()); DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces) if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces)
dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(), dumpAccelSection(OS, "apple_namespaces", *DObj,
getStringSection(), isLittleEndian()); DObj->getAppleNamespacesSection(),
DObj->getStringSection(), isLittleEndian());
if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC) if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC)
dumpAccelSection(OS, "apple_objc", getAppleObjCSection(), dumpAccelSection(OS, "apple_objc", *DObj, DObj->getAppleObjCSection(),
getStringSection(), isLittleEndian()); DObj->getStringSection(), isLittleEndian());
} }
DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
@ -433,7 +437,7 @@ const DWARFUnitIndex &DWARFContext::getCUIndex() {
if (CUIndex) if (CUIndex)
return *CUIndex; return *CUIndex;
DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0); DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO); CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
CUIndex->parse(CUIndexData); CUIndex->parse(CUIndexData);
@ -444,7 +448,7 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() {
if (TUIndex) if (TUIndex)
return *TUIndex; return *TUIndex;
DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0); DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0);
TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES); TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES);
TUIndex->parse(TUIndexData); TUIndex->parse(TUIndexData);
@ -455,7 +459,7 @@ DWARFGdbIndex &DWARFContext::getGdbIndex() {
if (GdbIndex) if (GdbIndex)
return *GdbIndex; return *GdbIndex;
DataExtractor GdbIndexData(getGdbIndexSection(), true /*LE*/, 0); DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0);
GdbIndex = llvm::make_unique<DWARFGdbIndex>(); GdbIndex = llvm::make_unique<DWARFGdbIndex>();
GdbIndex->parse(GdbIndexData); GdbIndex->parse(GdbIndexData);
return *GdbIndex; return *GdbIndex;
@ -465,7 +469,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
if (Abbrev) if (Abbrev)
return Abbrev.get(); return Abbrev.get();
DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
Abbrev.reset(new DWARFDebugAbbrev()); Abbrev.reset(new DWARFDebugAbbrev());
Abbrev->extract(abbrData); Abbrev->extract(abbrData);
@ -476,7 +480,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
if (AbbrevDWO) if (AbbrevDWO)
return AbbrevDWO.get(); return AbbrevDWO.get();
DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0);
AbbrevDWO.reset(new DWARFDebugAbbrev()); AbbrevDWO.reset(new DWARFDebugAbbrev());
AbbrevDWO->extract(abbrData); AbbrevDWO->extract(abbrData);
return AbbrevDWO.get(); return AbbrevDWO.get();
@ -489,7 +493,7 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() {
Loc.reset(new DWARFDebugLoc); Loc.reset(new DWARFDebugLoc);
// assume all compile units have the same address byte size // assume all compile units have the same address byte size
if (getNumCompileUnits()) { if (getNumCompileUnits()) {
DWARFDataExtractor LocData(getLocSection(), isLittleEndian(), DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(),
getCompileUnitAtIndex(0)->getAddressByteSize()); getCompileUnitAtIndex(0)->getAddressByteSize());
Loc->parse(LocData); Loc->parse(LocData);
} }
@ -500,7 +504,7 @@ const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
if (LocDWO) if (LocDWO)
return LocDWO.get(); return LocDWO.get();
DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0); DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 0);
LocDWO.reset(new DWARFDebugLocDWO()); LocDWO.reset(new DWARFDebugLocDWO());
LocDWO->parse(LocData); LocDWO->parse(LocData);
return LocDWO.get(); return LocDWO.get();
@ -528,8 +532,8 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() {
// provides this information). This problem is fixed in DWARFv4 // provides this information). This problem is fixed in DWARFv4
// See this dwarf-discuss discussion for more details: // See this dwarf-discuss discussion for more details:
// http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(), DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(),
getAddressSize()); DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */)); DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */));
DebugFrame->parse(debugFrameData); DebugFrame->parse(debugFrameData);
return DebugFrame.get(); return DebugFrame.get();
@ -539,8 +543,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() {
if (EHFrame) if (EHFrame)
return EHFrame.get(); return EHFrame.get();
DataExtractor debugFrameData(getEHFrameSection(), isLittleEndian(), DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
getAddressSize()); DObj->getAddressSize());
DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */)); DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
DebugFrame->parse(debugFrameData); DebugFrame->parse(debugFrameData);
return DebugFrame.get(); return DebugFrame.get();
@ -550,7 +554,7 @@ const DWARFDebugMacro *DWARFContext::getDebugMacro() {
if (Macro) if (Macro)
return Macro.get(); return Macro.get();
DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0); DataExtractor MacinfoData(DObj->getMacinfoSection(), isLittleEndian(), 0);
Macro.reset(new DWARFDebugMacro()); Macro.reset(new DWARFDebugMacro());
Macro->parse(MacinfoData); Macro->parse(MacinfoData);
return Macro.get(); return Macro.get();
@ -579,32 +583,32 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
return nullptr; return nullptr;
// We have to parse it first. // We have to parse it first.
DWARFDataExtractor lineData(U->getLineSection(), isLittleEndian(), DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
U->getAddressByteSize()); U->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset); return Line->getOrParseLineTable(lineData, stmtOffset);
} }
void DWARFContext::parseCompileUnits() { void DWARFContext::parseCompileUnits() {
CUs.parse(*this, getInfoSection()); CUs.parse(*this, DObj->getInfoSection());
} }
void DWARFContext::parseTypeUnits() { void DWARFContext::parseTypeUnits() {
if (!TUs.empty()) if (!TUs.empty())
return; return;
forEachTypesSections([&](const DWARFSection &S) { DObj->forEachTypesSections([&](const DWARFSection &S) {
TUs.emplace_back(); TUs.emplace_back();
TUs.back().parse(*this, S); TUs.back().parse(*this, S);
}); });
} }
void DWARFContext::parseDWOCompileUnits() { void DWARFContext::parseDWOCompileUnits() {
DWOCUs.parseDWO(*this, getInfoDWOSection()); DWOCUs.parseDWO(*this, DObj->getInfoDWOSection());
} }
void DWARFContext::parseDWOTypeUnits() { void DWARFContext::parseDWOTypeUnits() {
if (!DWOTUs.empty()) if (!DWOTUs.empty())
return; return;
forEachTypesDWOSections([&](const DWARFSection &S) { DObj->forEachTypesDWOSections([&](const DWARFSection &S) {
DWOTUs.emplace_back(); DWOTUs.emplace_back();
DWOTUs.back().parseDWO(*this, S); DWOTUs.back().parseDWO(*this, S);
}); });
@ -779,6 +783,20 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo; 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> std::shared_ptr<DWARFContext>
DWARFContext::getDWOContext(StringRef AbsolutePath) { DWARFContext::getDWOContext(StringRef AbsolutePath) {
if (auto S = DWP.lock()) { if (auto S = DWP.lock()) {
@ -796,7 +814,7 @@ DWARFContext::getDWOContext(StringRef AbsolutePath) {
SmallString<128> DWPName; SmallString<128> DWPName;
Expected<OwningBinary<ObjectFile>> Obj = [&] { Expected<OwningBinary<ObjectFile>> Obj = [&] {
if (!CheckedForDWP) { if (!CheckedForDWP) {
(getFileName() + ".dwp").toVector(DWPName); (DObj->getFileName() + ".dwp").toVector(DWPName);
auto Obj = object::ObjectFile::createObjectFile(DWPName); auto Obj = object::ObjectFile::createObjectFile(DWPName);
if (Obj) { if (Obj) {
Entry = &DWP; Entry = &DWP;
@ -820,7 +838,7 @@ DWARFContext::getDWOContext(StringRef AbsolutePath) {
auto S = std::make_shared<DWOFile>(); auto S = std::make_shared<DWOFile>();
S->File = std::move(Obj.get()); S->File = std::move(Obj.get());
S->Context = llvm::make_unique<DWARFContextInMemory>(*S->File.getBinary()); S->Context = DWARFContext::create(*S->File.getBinary());
*Entry = S; *Entry = S;
auto *Ctxt = S->Context.get(); auto *Ctxt = S->Context.get();
return std::shared_ptr<DWARFContext>(std::move(S), Ctxt); return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
@ -906,208 +924,355 @@ static bool isRelocScattered(const object::ObjectFile &Obj,
return MachObj->isRelocationScattered(RelocInfo); return MachObj->isRelocationScattered(RelocInfo);
} }
Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec, ErrorPolicy DWARFContext::defaultErrorHandler(Error E) {
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) {
errs() << "error: " + toString(std::move(E)) << '\n'; errs() << "error: " + toString(std::move(E)) << '\n';
return ErrorPolicy::Continue; return ErrorPolicy::Continue;
} }
DWARFContextInMemory::DWARFContextInMemory( class DWARFObjInMemory final : public DWARFObject {
const object::ObjectFile &Obj, const LoadedObjectInfo *L, bool IsLittleEndian;
function_ref<ErrorPolicy(Error)> HandleError) uint8_t AddressSize;
: FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()), StringRef FileName;
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; using TypeSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
section_iterator RelocatedSection = Section.getRelocatedSection(); std::map<object::SectionRef, unsigned>>;
// 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)) { TypeSectionMap TypesSections;
ErrorPolicy EP = HandleError( TypeSectionMap TypesDWOSections;
createError("failed to decompress '" + Name + "', ", std::move(Err)));
if (EP == ErrorPolicy::Halt) DWARFSectionMap InfoSection;
return; DWARFSectionMap LocSection;
continue; 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", for (const SectionRef &Section : Obj.sections()) {
// at this point section is decompressed and we drop compression prefix. StringRef Name;
Name = Name.substr( Section.getName(Name);
Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. // Skip BSS and Virtual sections, they aren't interesting.
if (Section.isBSS() || Section.isVirtual())
// 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))
continue; continue;
Expected<SymInfo> SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache); StringRef Data;
if (!SymInfoOrErr) { section_iterator RelocatedSection = Section.getRelocatedSection();
if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt) // Try to obtain an already relocated version of this section.
return; // Else use the unrelocated section from the object file. We'll have to
continue; // apply relocations ourselves later.
} if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data))
Section.getContents(Data);
object::RelocVisitor V(Obj); if (auto Err = maybeDecompress(Section, Name, Data)) {
uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); ErrorPolicy EP = HandleError(createError(
if (V.error()) { "failed to decompress '" + Name + "', ", std::move(Err)));
SmallString<32> Type;
Reloc.getTypeName(Type);
ErrorPolicy EP = HandleError(
createError("failed to compute relocation: " + Type + ", ",
errorCodeToError(object_error::parse_failed)));
if (EP == ErrorPolicy::Halt) if (EP == ErrorPolicy::Halt)
return; return;
continue; 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( Optional<RelocAddrEntry> find(const DWARFSection &S,
const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize, uint64_t Pos) const override {
bool isLittleEndian) auto &Sec = static_cast<const DWARFSectionMap &>(S);
: IsLittleEndian(isLittleEndian), AddressSize(AddrSize) { RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
for (const auto &SecIt : Sections) { if (AI == Sec.Relocs.end())
if (StringRef *SectionData = mapSectionToMember(SecIt.first())) return None;
*SectionData = SecIt.second->getBuffer(); 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) { std::unique_ptr<DWARFContext>
return StringSwitch<DWARFSection *>(Name) DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
.Case("debug_info", &InfoSection) uint8_t AddrSize, bool isLittleEndian) {
.Case("debug_loc", &LocSection) auto DObj = make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
.Case("debug_line", &LineSection) return make_unique<DWARFContext>(std::move(DObj));
.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 *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() {}

View File

@ -8,17 +8,18 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
using namespace llvm; using namespace llvm;
uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
uint64_t *SecNdx) const { uint64_t *SecNdx) const {
if (!RelocMap) if (!Section)
return getUnsigned(Off, Size); return getUnsigned(Off, Size);
RelocAddrMap::const_iterator AI = RelocMap->find(*Off); Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);
if (AI == RelocMap->end()) if (!Rel)
return getUnsigned(Off, Size); return getUnsigned(Off, Size);
if (SecNdx) if (SecNdx)
*SecNdx = AI->second.SectionIndex; *SecNdx = Rel->SectionIndex;
return getUnsigned(Off, Size) + AI->second.Value; return getUnsigned(Off, Size) + Rel->Value;
} }

View File

@ -43,7 +43,8 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) {
return; return;
// Extract aranges from .debug_aranges section. // Extract aranges from .debug_aranges section.
DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0); DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(),
CTX->isLittleEndian(), 0);
extract(ArangesData); extract(ArangesData);
// Generate aranges from DIEs: even if .debug_aranges section is present, // Generate aranges from DIEs: even if .debug_aranges section is present,

View File

@ -30,17 +30,19 @@ using namespace llvm;
using namespace dwarf; using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
parseImpl(C, Section, C.getDebugAbbrev(), &C.getRangeSection(), const DWARFObject &D = C.getDWARFObj();
C.getStringSection(), C.getStringOffsetSection(), parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(),
&C.getAddrSection(), C.getLineSection(), C.isLittleEndian(), false); D.getStringSection(), D.getStringOffsetSection(),
&D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false);
} }
void DWARFUnitSectionBase::parseDWO(DWARFContext &C, void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
const DWARFSection &DWOSection, const DWARFSection &DWOSection,
DWARFUnitIndex *Index) { DWARFUnitIndex *Index) {
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &C.getRangeDWOSection(), const DWARFObject &D = C.getDWARFObj();
C.getStringDWOSection(), C.getStringOffsetDWOSection(), parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(),
&C.getAddrSection(), C.getLineDWOSection(), C.isLittleEndian(), D.getStringDWOSection(), D.getStringOffsetDWOSection(),
&D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(),
true); true);
} }
@ -59,13 +61,18 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
DWARFUnit::~DWARFUnit() = default; DWARFUnit::~DWARFUnit() = default;
DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian,
getAddressByteSize());
}
bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
uint64_t &Result) const { uint64_t &Result) const {
uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize();
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
return false; return false;
DWARFDataExtractor DA(*AddrOffsetSection, isLittleEndian, DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
getAddressByteSize()); isLittleEndian, getAddressByteSize());
Result = DA.getRelocatedAddress(&Offset); Result = DA.getRelocatedAddress(&Offset);
return true; return true;
} }
@ -76,7 +83,8 @@ bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
uint32_t Offset = StringOffsetSectionBase + Index * ItemSize; uint32_t Offset = StringOffsetSectionBase + Index * ItemSize;
if (StringOffsetSection.Data.size() < Offset + ItemSize) if (StringOffsetSection.Data.size() < Offset + ItemSize)
return false; return false;
DWARFDataExtractor DA(StringOffsetSection, isLittleEndian, 0); DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
isLittleEndian, 0);
Result = DA.getRelocatedValue(ItemSize, &Offset); Result = DA.getRelocatedValue(ItemSize, &Offset);
return true; return true;
} }
@ -141,8 +149,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
DWARFDebugRangeList &RangeList) const { DWARFDebugRangeList &RangeList) const {
// Require that compile unit is extracted. // Require that compile unit is extracted.
assert(!DieArray.empty()); assert(!DieArray.empty());
DWARFDataExtractor RangesData(*RangeSection, isLittleEndian, DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
getAddressByteSize()); isLittleEndian, getAddressByteSize());
uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
return RangeList.extract(RangesData, &ActualRangeListOffset); return RangeList.extract(RangesData, &ActualRangeListOffset);
} }

View File

@ -105,8 +105,9 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit) {
bool DWARFVerifier::handleDebugInfo() { bool DWARFVerifier::handleDebugInfo() {
OS << "Verifying .debug_info Unit Header Chain...\n"; OS << "Verifying .debug_info Unit Header Chain...\n";
DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(), const DWARFObject &DObj = DCtx.getDWARFObj();
0); DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(),
DCtx.isLittleEndian(), 0);
uint32_t NumDebugInfoErrors = 0; uint32_t NumDebugInfoErrors = 0;
uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0; uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
uint8_t UnitType = 0; uint8_t UnitType = 0;
@ -127,10 +128,10 @@ bool DWARFVerifier::handleDebugInfo() {
case dwarf::DW_UT_split_type: { case dwarf::DW_UT_split_type: {
DWARFUnitSection<DWARFTypeUnit> TUSection{}; DWARFUnitSection<DWARFTypeUnit> TUSection{};
Unit.reset(new DWARFTypeUnit( Unit.reset(new DWARFTypeUnit(
DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(), DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
&DCtx.getRangeSection(), DCtx.getStringSection(), &DObj.getRangeSection(), DObj.getStringSection(),
DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
DCtx.getLineSection(), DCtx.isLittleEndian(), false, TUSection, DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
nullptr)); nullptr));
break; break;
} }
@ -143,10 +144,10 @@ bool DWARFVerifier::handleDebugInfo() {
case 0: { case 0: {
DWARFUnitSection<DWARFCompileUnit> CUSection{}; DWARFUnitSection<DWARFCompileUnit> CUSection{};
Unit.reset(new DWARFCompileUnit( Unit.reset(new DWARFCompileUnit(
DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(), DCtx, DObj.getInfoSection(), DCtx.getDebugAbbrev(),
&DCtx.getRangeSection(), DCtx.getStringSection(), &DObj.getRangeSection(), DObj.getStringSection(),
DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
DCtx.getLineSection(), DCtx.isLittleEndian(), false, CUSection, DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
nullptr)); nullptr));
break; break;
} }
@ -169,13 +170,14 @@ bool DWARFVerifier::handleDebugInfo() {
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
DWARFAttribute &AttrValue) { DWARFAttribute &AttrValue) {
const DWARFObject &DObj = DCtx.getDWARFObj();
unsigned NumErrors = 0; unsigned NumErrors = 0;
const auto Attr = AttrValue.Attr; const auto Attr = AttrValue.Attr;
switch (Attr) { switch (Attr) {
case DW_AT_ranges: case DW_AT_ranges:
// Make sure the offset in the DW_AT_ranges attribute is valid. // Make sure the offset in the DW_AT_ranges attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
if (*SectionOffset >= DCtx.getRangeSection().Data.size()) { if (*SectionOffset >= DObj.getRangeSection().Data.size()) {
++NumErrors; ++NumErrors;
OS << "error: DW_AT_ranges offset is beyond .debug_ranges " OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
"bounds:\n"; "bounds:\n";
@ -192,7 +194,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
case DW_AT_stmt_list: case DW_AT_stmt_list:
// Make sure the offset in the DW_AT_stmt_list attribute is valid. // Make sure the offset in the DW_AT_stmt_list attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
if (*SectionOffset >= DCtx.getLineSection().Data.size()) { if (*SectionOffset >= DObj.getLineSection().Data.size()) {
++NumErrors; ++NumErrors;
OS << "error: DW_AT_stmt_list offset is beyond .debug_line " OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
"bounds: " "bounds: "
@ -216,6 +218,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
DWARFAttribute &AttrValue) { DWARFAttribute &AttrValue) {
const DWARFObject &DObj = DCtx.getDWARFObj();
unsigned NumErrors = 0; unsigned NumErrors = 0;
const auto Form = AttrValue.Value.getForm(); const auto Form = AttrValue.Value.getForm();
switch (Form) { switch (Form) {
@ -253,7 +256,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
Optional<uint64_t> RefVal = AttrValue.Value.getAsReference(); Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
assert(RefVal); assert(RefVal);
if (RefVal) { if (RefVal) {
if (*RefVal >= DCtx.getInfoSection().Data.size()) { if (*RefVal >= DObj.getInfoSection().Data.size()) {
++NumErrors; ++NumErrors;
OS << "error: DW_FORM_ref_addr offset beyond .debug_info " OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
"bounds:\n"; "bounds:\n";
@ -270,7 +273,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
case DW_FORM_strp: { case DW_FORM_strp: {
auto SecOffset = AttrValue.Value.getAsSectionOffset(); auto SecOffset = AttrValue.Value.getAsSectionOffset();
assert(SecOffset); // DW_FORM_strp is a section offset. assert(SecOffset); // DW_FORM_strp is a section offset.
if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) { if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
++NumErrors; ++NumErrors;
OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n"; OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
Die.dump(OS, 0); Die.dump(OS, 0);
@ -318,7 +321,7 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() {
continue; continue;
const uint32_t LineTableOffset = *StmtSectionOffset; const uint32_t LineTableOffset = *StmtSectionOffset;
auto LineTable = DCtx.getLineTableForUnit(CU.get()); auto LineTable = DCtx.getLineTableForUnit(CU.get());
if (LineTableOffset < DCtx.getLineSection().Data.size()) { if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
if (!LineTable) { if (!LineTable) {
++NumDebugLineErrors; ++NumDebugLineErrors;
OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
@ -408,10 +411,10 @@ bool DWARFVerifier::handleDebugLine() {
bool DWARFVerifier::handleAppleNames() { bool DWARFVerifier::handleAppleNames() {
NumAppleNamesErrors = 0; NumAppleNamesErrors = 0;
const DWARFObject &D = DCtx.getDWARFObj();
DWARFDataExtractor AppleNamesSection(DCtx.getAppleNamesSection(), DWARFDataExtractor AppleNamesSection(D, D.getAppleNamesSection(),
DCtx.isLittleEndian(), 0); DCtx.isLittleEndian(), 0);
DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0); DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData); DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData);
if (!AppleNames.extract()) { if (!AppleNames.extract()) {

View File

@ -409,7 +409,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
} }
} }
if (!Context) if (!Context)
Context.reset(new DWARFContextInMemory(*Objects.second)); Context = DWARFContext::create(*Objects.second);
assert(Context); assert(Context);
auto InfoOrErr = auto InfoOrErr =
SymbolizableObjectFile::create(Objects.first, std::move(Context)); SymbolizableObjectFile::create(Objects.first, std::move(Context));

View File

@ -845,7 +845,7 @@ void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection()); MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
const DWARFSection &InputSec = Dwarf.getLocSection(); const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize); DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
DWARFUnit &OrigUnit = Unit.getOrigUnit(); DWARFUnit &OrigUnit = Unit.getOrigUnit();
auto OrigUnitDie = OrigUnit.getUnitDIE(false); auto OrigUnitDie = OrigUnit.getUnitDIE(false);
@ -1301,7 +1301,7 @@ private:
/// Construct the output DIE tree by cloning the DIEs we /// Construct the output DIE tree by cloning the DIEs we
/// chose to keep above. If there are no valid relocs, then there's /// chose to keep above. If there are no valid relocs, then there's
/// nothing to clone/emit. /// nothing to clone/emit.
void cloneAllCompileUnits(DWARFContextInMemory &DwarfContext); void cloneAllCompileUnits(DWARFContext &DwarfContext);
private: private:
typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec; typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
@ -2873,7 +2873,8 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
DWARFDebugRangeList RangeList; DWARFDebugRangeList RangeList;
const auto &FunctionRanges = Unit.getFunctionRanges(); const auto &FunctionRanges = Unit.getFunctionRanges();
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
DWARFDataExtractor RangeExtractor(OrigDwarf.getRangeSection(), DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(),
OrigDwarf.getDWARFObj().getRangeSection(),
OrigDwarf.isLittleEndian(), AddressSize); OrigDwarf.isLittleEndian(), AddressSize);
auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
DWARFUnit &OrigUnit = Unit.getOrigUnit(); DWARFUnit &OrigUnit = Unit.getOrigUnit();
@ -2984,9 +2985,9 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
// Parse the original line info for the unit. // Parse the original line info for the unit.
DWARFDebugLine::LineTable LineTable; DWARFDebugLine::LineTable LineTable;
uint32_t StmtOffset = *StmtList; uint32_t StmtOffset = *StmtList;
DWARFDataExtractor LineExtractor(OrigDwarf.getLineSection(), DWARFDataExtractor LineExtractor(
OrigDwarf.isLittleEndian(), OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(),
Unit.getOrigUnit().getAddressByteSize()); OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize());
LineTable.parse(LineExtractor, &StmtOffset); LineTable.parse(LineExtractor, &StmtOffset);
// This vector is the output line table. // This vector is the output line table.
@ -3086,7 +3087,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
LineTable.Prologue.OpcodeBase > 13) LineTable.Prologue.OpcodeBase > 13)
reportWarning("line table parameters mismatch. Cannot emit."); reportWarning("line table parameters mismatch. Cannot emit.");
else { else {
StringRef LineData = OrigDwarf.getLineSection().Data; StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data;
MCDwarfLineTableParams Params; MCDwarfLineTableParams Params;
Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
Params.DWARF2LineBase = LineTable.Prologue.LineBase; Params.DWARF2LineBase = LineTable.Prologue.LineBase;
@ -3112,7 +3113,7 @@ void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
DWARFContext &OrigDwarf, DWARFContext &OrigDwarf,
unsigned AddrSize) { unsigned AddrSize) {
StringRef FrameData = OrigDwarf.getDebugFrameSection(); StringRef FrameData = OrigDwarf.getDWARFObj().getDebugFrameSection();
if (FrameData.empty()) if (FrameData.empty())
return; return;
@ -3323,9 +3324,9 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
std::unique_ptr<CompileUnit> Unit; std::unique_ptr<CompileUnit> Unit;
// Setup access to the debug info. // Setup access to the debug info.
DWARFContextInMemory DwarfContext(*ErrOrObj); auto DwarfContext = DWARFContext::create(*ErrOrObj);
RelocationManager RelocMgr(*this); RelocationManager RelocMgr(*this);
for (const auto &CU : DwarfContext.compile_units()) { for (const auto &CU : DwarfContext->compile_units()) {
auto CUDie = CU->getUnitDIE(false); auto CUDie = CU->getUnitDIE(false);
// Recursively get all modules imported by this one. // Recursively get all modules imported by this one.
if (!registerModuleReference(CUDie, *CU, ModuleMap, Indent)) { if (!registerModuleReference(CUDie, *CU, ModuleMap, Indent)) {
@ -3365,11 +3366,10 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
std::vector<std::unique_ptr<CompileUnit>> CompileUnits; std::vector<std::unique_ptr<CompileUnit>> CompileUnits;
CompileUnits.push_back(std::move(Unit)); CompileUnits.push_back(std::move(Unit));
DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options) DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options)
.cloneAllCompileUnits(DwarfContext); .cloneAllCompileUnits(*DwarfContext);
} }
void DwarfLinker::DIECloner::cloneAllCompileUnits( void DwarfLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext) {
DWARFContextInMemory &DwarfContext) {
if (!Linker.Streamer) if (!Linker.Streamer)
return; return;
@ -3438,11 +3438,11 @@ bool DwarfLinker::link(const DebugMap &Map) {
} }
// Setup access to the debug info. // Setup access to the debug info.
DWARFContextInMemory DwarfContext(*ErrOrObj); auto DwarfContext = DWARFContext::create(*ErrOrObj);
startDebugObject(DwarfContext, *Obj); startDebugObject(*DwarfContext, *Obj);
// In a first phase, just read in the debug info and load all clang modules. // 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); auto CUDie = CU->getUnitDIE(false);
if (Options.Verbose) { if (Options.Verbose) {
outs() << "Input compilation unit:"; outs() << "Input compilation unit:";
@ -3476,9 +3476,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
RelocMgr.resetValidRelocs(); RelocMgr.resetValidRelocs();
if (RelocMgr.hasValidRelocs()) if (RelocMgr.hasValidRelocs())
DIECloner(*this, RelocMgr, DIEAlloc, Units, Options) DIECloner(*this, RelocMgr, DIEAlloc, Units, Options)
.cloneAllCompileUnits(DwarfContext); .cloneAllCompileUnits(*DwarfContext);
if (!Options.NoOutput && !Units.empty()) if (!Options.NoOutput && !Units.empty())
patchFrameInfoForObject(*Obj, DwarfContext, patchFrameInfoForObject(*Obj, *DwarfContext,
Units[0]->getOrigUnit().getAddressByteSize()); Units[0]->getOrigUnit().getAddressByteSize());
// Clean-up before starting working on the next object. // Clean-up before starting working on the next object.

View File

@ -94,7 +94,7 @@ static void error(StringRef Filename, std::error_code EC) {
} }
static void DumpObjectFile(ObjectFile &Obj, Twine Filename) { 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() outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n"; << "\n\n";
@ -131,8 +131,8 @@ static void DumpInput(StringRef Filename) {
} }
static bool VerifyObjectFile(ObjectFile &Obj, Twine Filename) { 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 // Verify the DWARF and exit with non-zero exit status if verification
// fails. // fails.
raw_ostream &stream = Quiet ? nulls() : outs(); raw_ostream &stream = Quiet ? nulls() : outs();

View File

@ -1275,7 +1275,7 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
printWeakBindTable(MachOOF); printWeakBindTable(MachOOF);
if (DwarfDumpType != DIDT_Null) { 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. // Dump the complete DWARF structure.
DIDumpOptions DumpOpts; DIDumpOptions DumpOpts;
DumpOpts.DumpType = DwarfDumpType; DumpOpts.DumpType = DwarfDumpType;
@ -6594,7 +6594,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
} }
// Setup the DIContext // Setup the DIContext
diContext.reset(new DWARFContextInMemory(*DbgObj)); diContext = DWARFContext::create(*DbgObj);
} }
if (FilterSections.size() == 0) if (FilterSections.size() == 0)

View File

@ -62,8 +62,8 @@
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
#include <system_error> #include <system_error>
#include <utility>
#include <unordered_map> #include <unordered_map>
#include <utility>
using namespace llvm; using namespace llvm;
using namespace object; using namespace object;
@ -2081,7 +2081,7 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
if (PrintFaultMaps) if (PrintFaultMaps)
printFaultMaps(o); printFaultMaps(o);
if (DwarfDumpType != DIDT_Null) { 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. // Dump the complete DWARF structure.
DIDumpOptions DumpOpts; DIDumpOptions DumpOpts;
DumpOpts.DumpType = DwarfDumpType; DumpOpts.DumpType = DwarfDumpType;

View File

@ -324,8 +324,8 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
} }
} }
std::unique_ptr<DIContext> Context( std::unique_ptr<DIContext> Context =
new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); DWARFContext::create(*SymbolObj, LoadedObjInfo.get());
std::vector<std::pair<SymbolRef, uint64_t>> SymAddr = std::vector<std::pair<SymbolRef, uint64_t>> SymAddr =
object::computeSymbolSizes(*SymbolObj); object::computeSymbolSizes(*SymbolObj);

View File

@ -24,7 +24,7 @@ void dumpInitialLength(DataExtractor &Data, uint32_t &Offset,
InitialLength.TotalLength64 = Data.getU64(&Offset); InitialLength.TotalLength64 = Data.getU64(&Offset);
} }
void dumpDebugAbbrev(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
auto AbbrevSetPtr = DCtx.getDebugAbbrev(); auto AbbrevSetPtr = DCtx.getDebugAbbrev();
if (AbbrevSetPtr) { if (AbbrevSetPtr) {
for (auto AbbrvDeclSet : *AbbrevSetPtr) { for (auto AbbrvDeclSet : *AbbrevSetPtr) {
@ -48,8 +48,8 @@ void dumpDebugAbbrev(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
} }
} }
void dumpDebugStrings(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
StringRef RemainingTable = DCtx.getStringSection(); StringRef RemainingTable = DCtx.getDWARFObj().getStringSection();
while (RemainingTable.size() > 0) { while (RemainingTable.size() > 0) {
auto SymbolPair = RemainingTable.split('\0'); auto SymbolPair = RemainingTable.split('\0');
RemainingTable = SymbolPair.second; RemainingTable = SymbolPair.second;
@ -57,8 +57,9 @@ void dumpDebugStrings(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
} }
} }
void dumpDebugARanges(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
DataExtractor ArangesData(DCtx.getARangeSection(), DCtx.isLittleEndian(), 0); DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(),
DCtx.isLittleEndian(), 0);
uint32_t Offset = 0; uint32_t Offset = 0;
DWARFDebugArangeSet Set; DWARFDebugArangeSet Set;
@ -79,7 +80,7 @@ void dumpDebugARanges(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
} }
} }
void dumpPubSection(DWARFContextInMemory &DCtx, DWARFYAML::PubSection &Y, void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
StringRef Section) { StringRef Section) {
DataExtractor PubSectionData(Section, DCtx.isLittleEndian(), 0); DataExtractor PubSectionData(Section, DCtx.isLittleEndian(), 0);
uint32_t Offset = 0; uint32_t Offset = 0;
@ -97,21 +98,22 @@ void dumpPubSection(DWARFContextInMemory &DCtx, DWARFYAML::PubSection &Y,
} }
} }
void dumpDebugPubSections(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
const DWARFObject &D = DCtx.getDWARFObj();
Y.PubNames.IsGNUStyle = false; Y.PubNames.IsGNUStyle = false;
dumpPubSection(DCtx, Y.PubNames, DCtx.getPubNamesSection()); dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection());
Y.PubTypes.IsGNUStyle = false; Y.PubTypes.IsGNUStyle = false;
dumpPubSection(DCtx, Y.PubTypes, DCtx.getPubTypesSection()); dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection());
Y.GNUPubNames.IsGNUStyle = true; Y.GNUPubNames.IsGNUStyle = true;
dumpPubSection(DCtx, Y.GNUPubNames, DCtx.getGnuPubNamesSection()); dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection());
Y.GNUPubTypes.IsGNUStyle = true; 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()) { for (const auto &CU : DCtx.compile_units()) {
DWARFYAML::Unit NewUnit; DWARFYAML::Unit NewUnit;
NewUnit.Length.setLength(CU->getLength()); NewUnit.Length.setLength(CU->getLength());
@ -235,7 +237,7 @@ bool dumpFileEntry(DataExtractor &Data, uint32_t &Offset,
return true; return true;
} }
void dumpDebugLines(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
for (const auto &CU : DCtx.compile_units()) { for (const auto &CU : DCtx.compile_units()) {
auto CUDIE = CU->getUnitDIE(); auto CUDIE = CU->getUnitDIE();
if (!CUDIE) if (!CUDIE)
@ -243,8 +245,8 @@ void dumpDebugLines(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
if (auto StmtOffset = if (auto StmtOffset =
dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) { dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
DWARFYAML::LineTable DebugLines; DWARFYAML::LineTable DebugLines;
DataExtractor LineData(DCtx.getLineSection().Data, DCtx.isLittleEndian(), DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
CU->getAddressByteSize()); DCtx.isLittleEndian(), CU->getAddressByteSize());
uint32_t Offset = *StmtOffset; uint32_t Offset = *StmtOffset;
dumpInitialLength(LineData, Offset, DebugLines.Length); dumpInitialLength(LineData, Offset, DebugLines.Length);
uint64_t LineTableLength = DebugLines.Length.getLength(); uint64_t LineTableLength = DebugLines.Length.getLength();
@ -344,7 +346,7 @@ void dumpDebugLines(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) {
} }
} }
std::error_code dwarf2yaml(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
dumpDebugAbbrev(DCtx, Y); dumpDebugAbbrev(DCtx, Y);
dumpDebugStrings(DCtx, Y); dumpDebugStrings(DCtx, Y);
dumpDebugARanges(DCtx, Y); dumpDebugARanges(DCtx, Y);

View File

@ -35,9 +35,9 @@ class MachODumper {
ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false); ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false);
void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y); void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
void dumpSymbols(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); std::unique_ptr<MachOYAML::Object> &Y);
void dumpDebugStrings(DWARFContextInMemory &DCtx, void dumpDebugStrings(DWARFContext &DCtx,
std::unique_ptr<MachOYAML::Object> &Y); std::unique_ptr<MachOYAML::Object> &Y);
public: public:
@ -187,8 +187,8 @@ Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
dumpLoadCommands(Y); dumpLoadCommands(Y);
dumpLinkEdit(Y); dumpLinkEdit(Y);
DWARFContextInMemory DICtx(Obj); std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
if (auto Err = dwarf2yaml(DICtx, Y->DWARF)) if (auto Err = dwarf2yaml(*DICtx, Y->DWARF))
return errorCodeToError(Err); return errorCodeToError(Err);
return std::move(Y); return std::move(Y);
} }

View File

@ -29,13 +29,12 @@ std::error_code wasm2yaml(llvm::raw_ostream &Out,
// Forward decls for dwarf2yaml // Forward decls for dwarf2yaml
namespace llvm { namespace llvm {
class DWARFContextInMemory; class DWARFContext;
namespace DWARFYAML { namespace DWARFYAML {
struct Data; struct Data;
} }
} }
std::error_code dwarf2yaml(llvm::DWARFContextInMemory &DCtx, std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
llvm::DWARFYAML::Data &Y);
#endif #endif

View File

@ -14,8 +14,8 @@
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h"
@ -28,8 +28,8 @@
#include "llvm/ObjectYAML/DWARFYAML.h" #include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Testing/Support/Error.h" #include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <climits> #include <climits>
@ -228,10 +228,10 @@ void TestAllForms() {
MemoryBufferRef FileBuffer(FileBytes, "dwarf"); MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
auto DieDG = U->getUnitDIE(false); auto DieDG = U->getUnitDIE(false);
EXPECT_TRUE(DieDG.isValid()); EXPECT_TRUE(DieDG.isValid());
@ -458,12 +458,12 @@ template <uint16_t Version, class AddrType> void TestChildren() {
MemoryBufferRef FileBuffer(FileBytes, "dwarf"); MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto DieDG = U->getUnitDIE(false); auto DieDG = U->getUnitDIE(false);
@ -629,13 +629,13 @@ template <uint16_t Version, class AddrType> void TestReferences() {
MemoryBufferRef FileBuffer(FileBytes, "dwarf"); MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 2u); EXPECT_EQ(NumCUs, 2u);
DWARFCompileUnit *U1 = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U1 = DwarfContext->getCompileUnitAtIndex(0);
DWARFCompileUnit *U2 = DwarfContext.getCompileUnitAtIndex(1); DWARFCompileUnit *U2 = DwarfContext->getCompileUnitAtIndex(1);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto Unit1DieDG = U1->getUnitDIE(false); auto Unit1DieDG = U1->getUnitDIE(false);
@ -837,12 +837,12 @@ template <uint16_t Version, class AddrType> void TestAddresses() {
MemoryBufferRef FileBuffer(FileBytes, "dwarf"); MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto DieDG = U->getUnitDIE(false); auto DieDG = U->getUnitDIE(false);
@ -1012,12 +1012,12 @@ TEST(DWARFDebugInfo, TestRelations) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1127,12 +1127,12 @@ TEST(DWARFDebugInfo, TestChildIterators) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1188,12 +1188,13 @@ TEST(DWARFDebugInfo, TestEmptyChildren) {
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); 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. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1235,12 +1236,12 @@ TEST(DWARFDebugInfo, TestAttributeIterators) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1299,12 +1300,12 @@ TEST(DWARFDebugInfo, TestFindRecurse) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1505,12 +1506,12 @@ TEST(DWARFDebugInfo, TestFindAttrs) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
// Verify the number of compile units is correct. // Verify the number of compile units is correct.
uint32_t NumCUs = DwarfContext.getNumCompileUnits(); uint32_t NumCUs = DwarfContext->getNumCompileUnits();
EXPECT_EQ(NumCUs, 1u); EXPECT_EQ(NumCUs, 1u);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
// Get the compile unit DIE is valid. // Get the compile unit DIE is valid.
auto CUDie = U->getUnitDIE(false); auto CUDie = U->getUnitDIE(false);
@ -1568,8 +1569,8 @@ TEST(DWARFDebugInfo, TestImplicitConstAbbrevs) {
MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer); auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj); EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get()); std::unique_ptr<DWARFContext> DwarfContext = DWARFContext::create(**Obj);
DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); DWARFCompileUnit *U = DwarfContext->getCompileUnitAtIndex(0);
EXPECT_TRUE((bool)U); EXPECT_TRUE((bool)U);
const auto *Abbrevs = U->getAbbreviations(); const auto *Abbrevs = U->getAbbreviations();
@ -1708,10 +1709,11 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidCURef) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is " DWARFContext::create(*ErrOrSections, 8);
"invalid (must be less than CU size of " VerifyError(*DwarfContext, "error: DW_FORM_ref4 CU offset 0x00001234 is "
"0x0000001a):"); "invalid (must be less than CU size of "
"0x0000001a):");
} }
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) { TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) {
@ -1756,8 +1758,9 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddr) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, DWARFContext::create(*ErrOrSections, 8);
VerifyError(*DwarfContext,
"error: DW_FORM_ref_addr offset beyond .debug_info bounds:"); "error: DW_FORM_ref_addr offset beyond .debug_info bounds:");
} }
@ -1792,8 +1795,9 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRanges) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, DWARFContext::create(*ErrOrSections, 8);
VerifyError(*DwarfContext,
"error: DW_AT_ranges offset is beyond .debug_ranges bounds:"); "error: DW_AT_ranges offset is beyond .debug_ranges bounds:");
} }
@ -1828,9 +1832,10 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidStmtList) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
DWARFContext::create(*ErrOrSections, 8);
VerifyError( VerifyError(
DwarfContext, *DwarfContext,
"error: DW_AT_stmt_list offset is beyond .debug_line bounds: 0x00001000"); "error: DW_AT_stmt_list offset is beyond .debug_line bounds: 0x00001000");
} }
@ -1860,8 +1865,9 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidStrp) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, DWARFContext::create(*ErrOrSections, 8);
VerifyError(*DwarfContext,
"error: DW_FORM_strp offset beyond .debug_str bounds:"); "error: DW_FORM_strp offset beyond .debug_str bounds:");
} }
@ -1907,9 +1913,10 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidRefAddrBetween) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata)); auto ErrOrSections = DWARFYAML::EmitDebugSections(StringRef(yamldata));
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
DWARFContext::create(*ErrOrSections, 8);
VerifyError( VerifyError(
DwarfContext, *DwarfContext,
"error: invalid DIE reference 0x00000011. Offset is in between DIEs:"); "error: invalid DIE reference 0x00000011. Offset is in between DIEs:");
} }
@ -1977,9 +1984,10 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineSequence) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, "error: .debug_line[0x00000000] row[1] decreases " DWARFContext::create(*ErrOrSections, 8);
"in address from previous row:"); VerifyError(*DwarfContext, "error: .debug_line[0x00000000] row[1] decreases "
"in address from previous row:");
} }
TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) { TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
@ -2048,9 +2056,10 @@ TEST(DWARFDebugInfo, TestDwarfVerifyInvalidLineFileIndex) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, "error: .debug_line[0x00000000][1] has invalid " DWARFContext::create(*ErrOrSections, 8);
"file index 5 (valid values are [1,1]):"); VerifyError(*DwarfContext, "error: .debug_line[0x00000000][1] has invalid "
"file index 5 (valid values are [1,1]):");
} }
TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) { TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
@ -2128,10 +2137,12 @@ TEST(DWARFDebugInfo, TestDwarfVerifyCUDontShareLineTable) {
)"; )";
auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata); auto ErrOrSections = DWARFYAML::EmitDebugSections(yamldata);
ASSERT_TRUE((bool)ErrOrSections); ASSERT_TRUE((bool)ErrOrSections);
DWARFContextInMemory DwarfContext(*ErrOrSections, 8); std::unique_ptr<DWARFContext> DwarfContext =
VerifyError(DwarfContext, "error: two compile unit DIEs, 0x0000000b and " DWARFContext::create(*ErrOrSections, 8);
"0x0000001f, have the same DW_AT_stmt_list section " VerifyError(*DwarfContext,
"offset:"); "error: two compile unit DIEs, 0x0000000b and "
"0x0000001f, have the same DW_AT_stmt_list section "
"offset:");
} }
TEST(DWARFDebugInfo, TestErrorReportingPolicy) { TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
@ -2161,20 +2172,22 @@ TEST(DWARFDebugInfo, TestErrorReportingPolicy) {
// DWARFContextInMemory // DWARFContextInMemory
// to parse whole file and find both two errors we know about. // to parse whole file and find both two errors we know about.
int Errors = 0; int Errors = 0;
DWARFContextInMemory Ctx1(*Obj.get(), nullptr, [&](Error E) { std::unique_ptr<DWARFContext> Ctx1 =
++Errors; DWARFContext::create(**Obj, nullptr, [&](Error E) {
consumeError(std::move(E)); ++Errors;
return ErrorPolicy::Continue; consumeError(std::move(E));
}); return ErrorPolicy::Continue;
});
EXPECT_TRUE(Errors == 2); EXPECT_TRUE(Errors == 2);
// Case 2: error handler stops parsing of object after first error. // Case 2: error handler stops parsing of object after first error.
Errors = 0; Errors = 0;
DWARFContextInMemory Ctx2(*Obj.get(), nullptr, [&](Error E) { std::unique_ptr<DWARFContext> Ctx2 =
++Errors; DWARFContext::create(**Obj, nullptr, [&](Error E) {
consumeError(std::move(E)); ++Errors;
return ErrorPolicy::Halt; consumeError(std::move(E));
}); return ErrorPolicy::Halt;
});
EXPECT_TRUE(Errors == 1); EXPECT_TRUE(Errors == 1);
} }