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 967d4aa7a0
commit c398e67fed
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/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
@ -45,10 +46,14 @@ class DataExtractor;
class MemoryBuffer;
class raw_ostream;
/// Used as a return value for a error callback passed to DWARF context.
/// Callback should return Halt if client application wants to stop
/// object parsing, or should return Continue otherwise.
enum class ErrorPolicy { Halt, Continue };
/// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug
/// information parsing. The actual data is supplied through pure virtual
/// methods that a concrete implementation provides.
/// information parsing. The actual data is supplied through DWARFObj.
class DWARFContext : public DIContext {
DWARFUnitSection<DWARFCompileUnit> CUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
@ -95,11 +100,17 @@ class DWARFContext : public DIContext {
/// and store them in DWOTUs.
void parseDWOTypeUnits();
protected:
std::unique_ptr<const DWARFObject> DObj;
public:
DWARFContext() : DIContext(CK_DWARF) {}
DWARFContext(std::unique_ptr<const DWARFObject> DObj)
: DIContext(CK_DWARF), DObj(std::move(DObj)) {}
DWARFContext(DWARFContext &) = delete;
DWARFContext &operator=(DWARFContext &) = delete;
const DWARFObject &getDWARFObj() const { return *DObj; }
static bool classof(const DIContext *DICtx) {
return DICtx->getKind() == CK_DWARF;
}
@ -222,55 +233,24 @@ public:
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
virtual StringRef getFileName() const = 0;
virtual bool isLittleEndian() const = 0;
virtual uint8_t getAddressSize() const = 0;
virtual const DWARFSection &getInfoSection() = 0;
virtual void forEachTypesSections(function_ref<void(DWARFSection &)> F) = 0;
virtual StringRef getAbbrevSection() = 0;
virtual const DWARFSection &getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getDebugFrameSection() = 0;
virtual StringRef getEHFrameSection() = 0;
virtual const DWARFSection &getLineSection() = 0;
virtual StringRef getStringSection() = 0;
virtual const DWARFSection& getRangeSection() = 0;
virtual StringRef getMacinfoSection() = 0;
virtual StringRef getPubNamesSection() = 0;
virtual StringRef getPubTypesSection() = 0;
virtual StringRef getGnuPubNamesSection() = 0;
virtual StringRef getGnuPubTypesSection() = 0;
/// DWARF v5
/// @{
virtual const DWARFSection &getStringOffsetSection() = 0;
/// @}
// Sections for DWARF5 split dwarf proposal.
virtual const DWARFSection &getInfoDWOSection() = 0;
virtual void
forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) = 0;
virtual StringRef getAbbrevDWOSection() = 0;
virtual const DWARFSection &getLineDWOSection() = 0;
virtual const DWARFSection &getLocDWOSection() = 0;
virtual StringRef getStringDWOSection() = 0;
virtual const DWARFSection &getStringOffsetDWOSection() = 0;
virtual const DWARFSection &getRangeDWOSection() = 0;
virtual const DWARFSection &getAddrSection() = 0;
virtual const DWARFSection& getAppleNamesSection() = 0;
virtual const DWARFSection& getAppleTypesSection() = 0;
virtual const DWARFSection& getAppleNamespacesSection() = 0;
virtual const DWARFSection& getAppleObjCSection() = 0;
virtual StringRef getCUIndexSection() = 0;
virtual StringRef getGdbIndexSection() = 0;
virtual StringRef getTUIndexSection() = 0;
bool isLittleEndian() const { return DObj->isLittleEndian(); }
static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3 || version == 4 || version == 5;
}
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
/// Function used to handle default error reporting policy. Prints a error
/// message and returns Continue, so DWARF context ignores the error.
static ErrorPolicy defaultErrorHandler(Error E);
static std::unique_ptr<DWARFContext>
create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
static std::unique_ptr<DWARFContext>
create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
private:
/// Return the compile unit that includes an offset (relative to .debug_info).
DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
@ -280,142 +260,6 @@ private:
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};
/// Used as a return value for a error callback passed to DWARF context.
/// Callback should return Halt if client application wants to stop
/// object parsing, or should return Continue otherwise.
enum class ErrorPolicy { Halt, Continue };
/// DWARFContextInMemory is the simplest possible implementation of a
/// DWARFContext. It assumes all content is available in memory and stores
/// pointers to it.
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
std::map<object::SectionRef, unsigned>>;
StringRef FileName;
bool IsLittleEndian;
uint8_t AddressSize;
DWARFSection InfoSection;
TypeSectionMap TypesSections;
StringRef AbbrevSection;
DWARFSection LocSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
StringRef EHFrameSection;
DWARFSection LineSection;
StringRef StringSection;
DWARFSection RangeSection;
StringRef MacinfoSection;
StringRef PubNamesSection;
StringRef PubTypesSection;
StringRef GnuPubNamesSection;
StringRef GnuPubTypesSection;
/// DWARF v5
/// @{
DWARFSection StringOffsetSection;
/// @}
// Sections for DWARF5 split dwarf proposal.
DWARFSection InfoDWOSection;
TypeSectionMap TypesDWOSections;
StringRef AbbrevDWOSection;
DWARFSection LineDWOSection;
DWARFSection LocDWOSection;
StringRef StringDWOSection;
DWARFSection StringOffsetDWOSection;
DWARFSection RangeDWOSection;
DWARFSection AddrSection;
DWARFSection AppleNamesSection;
DWARFSection AppleTypesSection;
DWARFSection AppleNamespacesSection;
DWARFSection AppleObjCSection;
StringRef CUIndexSection;
StringRef GdbIndexSection;
StringRef TUIndexSection;
SmallVector<SmallString<32>, 4> UncompressedSections;
DWARFSection *mapNameToDWARFSection(StringRef Name);
StringRef *mapSectionToMember(StringRef Name);
/// If Sec is compressed section, decompresses and updates its contents
/// provided by Data. Otherwise leaves it unchanged.
Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
StringRef &Data);
/// Function used to handle default error reporting policy. Prints a error
/// message and returns Continue, so DWARF context ignores the error.
static ErrorPolicy defaultErrorHandler(Error E);
public:
DWARFContextInMemory(
const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
uint8_t AddrSize,
bool isLittleEndian = sys::IsLittleEndianHost);
StringRef getFileName() const override { return FileName; }
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }
void forEachTypesSections(function_ref<void(DWARFSection &)> F) override {
for (auto &P : TypesSections)
F(P.second);
}
StringRef getAbbrevSection() override { return AbbrevSection; }
const DWARFSection &getLocSection() override { return LocSection; }
StringRef getARangeSection() override { return ARangeSection; }
StringRef getDebugFrameSection() override { return DebugFrameSection; }
StringRef getEHFrameSection() override { return EHFrameSection; }
const DWARFSection &getLineSection() override { return LineSection; }
StringRef getStringSection() override { return StringSection; }
const DWARFSection &getRangeSection() override { return RangeSection; }
StringRef getMacinfoSection() override { return MacinfoSection; }
StringRef getPubNamesSection() override { return PubNamesSection; }
StringRef getPubTypesSection() override { return PubTypesSection; }
StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; }
StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; }
const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; }
const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; }
const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; }
const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; }
// DWARF v5
const DWARFSection &getStringOffsetSection() override {
return StringOffsetSection;
}
// Sections for DWARF5 split dwarf proposal.
const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
void forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) override {
for (auto &P : TypesDWOSections)
F(P.second);
}
StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }
const DWARFSection &getLineDWOSection() override { return LineDWOSection; }
const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
StringRef getStringDWOSection() override { return StringDWOSection; }
const DWARFSection &getStringOffsetDWOSection() override {
return StringOffsetDWOSection;
}
const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; }
const DWARFSection &getAddrSection() override { return AddrSection; }
StringRef getCUIndexSection() override { return CUIndexSection; }
StringRef getGdbIndexSection() override { return GdbIndexSection; }
StringRef getTUIndexSection() override { return TUIndexSection; }
};
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H

View File

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

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 {
StringRef Data;
};
struct DWARFSectionMap final : public DWARFSection {
RelocAddrMap Relocs;
};

View File

@ -197,19 +197,12 @@ public:
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
DWARFDataExtractor getDebugInfoExtractor() const {
return DWARFDataExtractor(InfoSection, isLittleEndian,
getAddressByteSize());
}
DWARFDataExtractor getDebugInfoExtractor() const;
DataExtractor getStringExtractor() const {
return DataExtractor(StringSection, false, 0);
}
const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
const RelocAddrMap &getStringOffsetsRelocMap() const {
return StringOffsetSection.Relocs;
}
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -94,7 +94,7 @@ static void error(StringRef Filename, std::error_code EC) {
}
static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
std::unique_ptr<DIContext> DICtx = DWARFContext::create(Obj);
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
@ -131,8 +131,8 @@ static void DumpInput(StringRef 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
// fails.
raw_ostream &stream = Quiet ? nulls() : outs();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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