#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
namespace llvm {
class AsmPrinter;
+class DIE;
+class DIEUnit;
class MCExpr;
+class MCSection;
class MCSymbol;
class raw_ostream;
};
//===--------------------------------------------------------------------===//
-/// DIE - A structured debug information entry. Has an abbreviation which
+/// A structured debug information entry. Has an abbreviation which
/// describes its organization.
class DIE : IntrusiveBackListNode, public DIEValueList {
friend class IntrusiveBackList<DIE>;
+ friend class DIEUnit;
- /// Offset - Offset in debug info section.
+ /// Offset - Dwarf unit relative offset.
///
unsigned Offset;
/// Children DIEs.
IntrusiveBackList<DIE> Children;
- DIE *Parent = nullptr;
+ /// The owner is either the parent DIE for children of other DIEs, or a
+ /// DIEUnit which contains this DIE as its unit DIE.
+ PointerUnion<DIE *, DIEUnit *> Owner;
DIE() = delete;
explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag) {}
+protected:
+ void setUnit(DIEUnit *U) {
+ Owner = U;
+ }
public:
static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) {
return new (Alloc) DIE(Tag);
}
+ DIE(const DIE &RHS) = delete;
+ DIE(DIE &&RHS) = delete;
+ void operator=(const DIE &RHS) = delete;
+ void operator=(const DIE &&RHS) = delete;
+
// Accessors.
unsigned getAbbrevNumber() const { return AbbrevNumber; }
dwarf::Tag getTag() const { return Tag; }
+ /// Get the compile/type unit relative offset of this DIE.
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
bool hasChildren() const { return !Children.empty(); }
return make_range(Children.begin(), Children.end());
}
- DIE *getParent() const { return Parent; }
+ DIE *getParent() const;
/// Generate the abbreviation for this DIE.
///
/// Set the abbreviation number for this DIE.
void setAbbrevNumber(unsigned I) { AbbrevNumber = I; }
- /// Climb up the parent chain to get the compile or type unit DIE this DIE
- /// belongs to.
- const DIE *getUnit() const;
- /// Similar to getUnit, returns null when DIE is not added to an
- /// owner yet.
- const DIE *getUnitOrNull() const;
+ /// Get the absolute offset within the .debug_info or .debug_types section
+ /// for this DIE.
+ unsigned getDebugSectionOffset() const;
+
+ /// Climb up the parent chain to get the compile unit or type unit DIE that
+ /// this DIE belongs to.
+ ///
+ /// \returns the compile or type unit DIE that owns this DIE, or NULL if
+ /// this DIE hasn't been added to a unit DIE.
+ const DIE *getUnitDie() const;
+
+ /// Climb up the parent chain to get the compile unit or type unit that this
+ /// DIE belongs to.
+ ///
+ /// \returns the DIEUnit that represents the compile or type unit that owns
+ /// this DIE, or NULL if this DIE hasn't been added to a unit DIE.
+ const DIEUnit *getUnit() const;
+
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
/// Add a child to the DIE.
DIE &addChild(DIE *Child) {
assert(!Child->getParent() && "Child should be orphaned");
- Child->Parent = this;
+ Child->Owner = this;
Children.push_back(*Child);
return Children.back();
}
void dump();
};
+//===--------------------------------------------------------------------===//
+/// Represents a compile or type unit.
+class DIEUnit {
+protected:
+ /// The compile unit or type unit DIE. This variable must be an instance of
+ /// DIE so that we can calculate the DIEUnit from any DIE by traversing the
+ /// parent backchain and getting the Unit DIE, and then casting itself to a
+ /// DIEUnit. This allows us to be able to find the DIEUnit for any DIE without
+ /// having to store a pointer to the DIEUnit in each DIE instance.
+ DIE Die;
+ /// The section this unit will be emitted in. This may or may not be set to
+ /// a valid section depending on the client that is emitting DWARF.
+ MCSection *Section;
+ uint64_t Offset; /// .debug_info or .debug_types absolute section offset.
+ uint32_t Length; /// The length in bytes of all of the DIEs in this unit.
+ const uint16_t Version; /// The Dwarf version number for this unit.
+ const uint8_t AddrSize; /// The size in bytes of an address for this unit.
+public:
+ DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag);
+ DIEUnit(const DIEUnit &RHS) = delete;
+ DIEUnit(DIEUnit &&RHS) = delete;
+ void operator=(const DIEUnit &RHS) = delete;
+ void operator=(const DIEUnit &&RHS) = delete;
+ /// Set the section that this DIEUnit will be emitted into.
+ ///
+ /// This function is used by some clients to set the section. Not all clients
+ /// that emit DWARF use this section variable.
+ void setSection(MCSection *Section) {
+ assert(!this->Section);
+ this->Section = Section;
+ }
+
+ /// Return the section that this DIEUnit will be emitted into.
+ ///
+ /// \returns Section pointer which can be NULL.
+ MCSection *getSection() const { return Section; }
+ void setDebugSectionOffset(unsigned O) { Offset = O; }
+ unsigned getDebugSectionOffset() const { return Offset; }
+ void setLength(uint64_t L) { Length = L; }
+ uint64_t getLength() const { return Length; }
+ uint16_t getDwarfVersion() const { return Version; }
+ uint16_t getAddressSize() const { return AddrSize; }
+ DIE &getUnitDie() { return Die; }
+ const DIE &getUnitDie() const { return Die; }
+};
+
+
//===--------------------------------------------------------------------===//
/// DIELoc - Represents an expression location.
//
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Dwarf.h"
namespace llvm {
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
const DataExtractor &DebugInfoData, uint32_t UEndOffset);
- uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
+ dwarf::Tag getTag() const {
+ return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null;
+ }
+
bool isNULL() const { return AbbrevDecl == nullptr; }
/// Returns true if DIE represents a subprogram (not inlined).
LLVM_DUMP_METHOD
void DIEAbbrev::dump() { print(dbgs()); }
+DIE *DIE::getParent() const {
+ return Owner.dyn_cast<DIE*>();
+}
+
DIEAbbrev DIE::generateAbbrev() const {
DIEAbbrev Abbrev(Tag, hasChildren());
for (const DIEValue &V : values())
return Abbrev;
}
-/// Climb up the parent chain to get the unit DIE to which this DIE
-/// belongs.
-const DIE *DIE::getUnit() const {
- const DIE *Cu = getUnitOrNull();
- assert(Cu && "We should not have orphaned DIEs.");
- return Cu;
+unsigned DIE::getDebugSectionOffset() const {
+ const DIEUnit *Unit = getUnit();
+ assert(Unit && "DIE must be owned by a DIEUnit to get its absolute offset");
+ return getUnit()->getDebugSectionOffset() + getOffset();
}
-/// Climb up the parent chain to get the unit DIE this DIE belongs
-/// to. Return NULL if DIE is not added to an owner yet.
-const DIE *DIE::getUnitOrNull() const {
+const DIE *DIE::getUnitDie() const {
const DIE *p = this;
while (p) {
if (p->getTag() == dwarf::DW_TAG_compile_unit ||
return nullptr;
}
+const DIEUnit *DIE::getUnit() const {
+ const DIE *UnitDie = getUnitDie();
+ if (UnitDie)
+ return UnitDie->Owner.dyn_cast<DIEUnit*>();
+ return nullptr;
+}
+
DIEValue DIE::findAttribute(dwarf::Attribute Attribute) const {
// Iterate through all the attributes until we find the one we're
// looking for, if we can't find it return NULL.
print(dbgs());
}
+DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag)
+ : Die(UnitTag), Section(nullptr), Offset(0), Length(0), Version(V),
+ AddrSize(A)
+{
+ Die.setUnit(this);
+ assert((UnitTag == dwarf::DW_TAG_compile_unit ||
+ UnitTag == dwarf::DW_TAG_type_unit ||
+ UnitTag == dwarf::DW_TAG_partial_unit) && "expected a unit TAG");
+}
+
void DIEValue::EmitValue(const AsmPrinter *AP) const {
switch (Ty) {
case isNone:
void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_ref_addr) {
- const DwarfDebug *DD = AP->getDwarfDebug();
- unsigned Addr = Entry->getOffset();
- assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
- // For DW_FORM_ref_addr, output the offset from beginning of debug info
- // section. Entry->getOffset() returns the offset from start of the
- // compile unit.
- DwarfCompileUnit *CU = DD->lookupUnit(Entry->getUnit());
- assert(CU && "CUDie should belong to a CU.");
- Addr += CU->getDebugInfoOffset();
- if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
- AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr,
- DIEEntry::getRefAddrSize(AP));
- else
+ // Get the absolute offset for this DIE within the debug info/types section.
+ unsigned Addr = Entry->getDebugSectionOffset();
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
+ const DwarfDebug *DD = AP->getDwarfDebug();
+ if (DD)
+ assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
+ const DIEUnit *Unit = Entry->getUnit();
+ assert(Unit && "CUDie should belong to a CU.");
+ MCSection *Section = Unit->getSection();
+ assert(Section && "Must have a section if we are doing relocations");
+ const MCSymbol *SectionSym = Section->getBeginSymbol();
+ AP->EmitLabelPlusOffset(SectionSym, Addr, DIEEntry::getRefAddrSize(AP));
+ } else
AP->OutStreamer->EmitIntValue(Addr, DIEEntry::getRefAddrSize(AP));
} else
AP->EmitInt32(Entry->getOffset());
Asm->EmitInt32((*HI)->Data.Values.size());
for (HashDataContents *HD : (*HI)->Data.Values) {
// Emit the DIE offset
- DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit());
- assert(CU && "Accelerated DIE should belong to a CU.");
- Asm->EmitInt32(HD->Die->getOffset() + CU->getDebugInfoOffset());
+ Asm->EmitInt32(HD->Die->getDebugSectionOffset());
// If we have multiple Atoms emit that info too.
// FIXME: A bit of a hack, we either emit only one atom or all info.
if (HeaderData.Atoms.size() > 1) {
// is not okay to use line_table_start here.
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
StmtListValue =
- addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym,
+ addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,
TLOF.getDwarfLineSection()->getBeginSymbol());
}
/// A numeric ID unique among all CUs in the module
unsigned UniqueID;
- /// Offset of the UnitDie from beginning of debug info section.
- unsigned DebugInfoOffset = 0;
-
/// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
/// the need to search for it in applyStmtList.
DIE::value_iterator StmtListValue;
DwarfDebug *DW, DwarfFile *DWU);
unsigned getUniqueID() const { return UniqueID; }
- unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
- void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
DwarfCompileUnit *getSkeleton() const {
return Skeleton;
/// Set the skeleton unit associated with this unit.
void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }
- const MCSymbol *getSectionSym() const {
- assert(Section);
- return Section->getBeginSymbol();
- }
-
unsigned getLength() {
return sizeof(uint32_t) + // Length field
- getHeaderSize() + UnitDie.getSize();
+ getHeaderSize() + getUnitDie().getSize();
}
void emitHeader(bool UseOffsets) override;
}
if (useSplitDwarf())
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
else
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
if (DIUnit->getDWOId()) {
// This CU is either a clang module DWO or a skeleton CU.
// FIXME: Consider the time-space tradeoff of just storing the unit pointer
// in the ConcreteVariables list, rather than looking it up again here.
// DIE::getUnit isn't simple - it walks parent pointers, etc.
- DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit());
+ DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie());
assert(Unit);
DbgVariable *AbsVar = getExistingAbstractVariable(
InlinedVariable(Var->getVariable(), Var->getInlinedAt()));
auto OwnedUnit = make_unique<DwarfCompileUnit>(
CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
DwarfCompileUnit &NewCU = *OwnedUnit;
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
NewCU.initStmtList();
Ins.first->second = Signature;
if (useSplitDwarf())
- NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
+ NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
else {
CU.applyStmtList(UnitDie);
- NewTU.initSection(
- Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
}
NewTU.setType(NewTU.createTypeDIE(CTy));
return Ref.resolve();
}
- /// Find the DwarfCompileUnit for the given CU Die.
- DwarfCompileUnit *lookupUnit(const DIE *CU) const {
- return CUDieMap.lookup(CU);
- }
-
void addSubprogramNames(const DISubprogram *SP, DIE &Die);
AddressPool &getAddressPool() { return AddrPool; }
// Iterate over each compile unit and set the size and offsets for each
// DIE within each compile unit. All offsets are CU relative.
for (const auto &TheU : CUs) {
- TheU->setDebugInfoOffset(SecOffset);
+ TheU->setDebugSectionOffset(SecOffset);
SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
}
}
DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
- : CUNode(Node), UnitDie(*DIE::get(DIEValueAllocator, UnitTag)), Asm(A),
- DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) {
- assert(UnitTag == dwarf::DW_TAG_compile_unit ||
- UnitTag == dwarf::DW_TAG_type_unit);
+ : DIEUnit(A->getDwarfVersion(), A->getPointerSize(), UnitTag), CUNode(Node),
+ Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr) {
}
DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
: DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
SplitLineTable(SplitLineTable) {
if (SplitLineTable)
- addSectionOffset(UnitDie, dwarf::DW_AT_stmt_list, 0);
+ addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
}
DwarfUnit::~DwarfUnit() {
void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute,
DIEEntry Entry) {
- const DIE *DieCU = Die.getUnitOrNull();
- const DIE *EntryCU = Entry.getEntry().getUnitOrNull();
- if (!DieCU)
+ const DIEUnit *CU = Die.getUnit();
+ const DIEUnit *EntryCU = Entry.getEntry().getUnit();
+ if (!CU)
// We assume that Die belongs to this CU, if it is not linked to any CU yet.
- DieCU = &getUnitDie();
+ CU = getUnitDie().getUnit();
if (!EntryCU)
- EntryCU = &getUnitDie();
+ EntryCU = getUnitDie().getUnit();
Die.addValue(DIEValueAllocator, Attribute,
- EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+ EntryCU == CU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
Entry);
}
if (IndexTyDie)
return IndexTyDie;
// Construct an integer type to use for indexes.
- IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, UnitDie);
+ IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, getUnitDie());
addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype");
addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t));
addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
void DwarfUnit::emitHeader(bool UseOffsets) {
// Emit size of content not including length itself
Asm->OutStreamer->AddComment("Length of Unit");
- Asm->EmitInt32(getHeaderSize() + UnitDie.getSize());
+ Asm->EmitInt32(getHeaderSize() + getUnitDie().getSize());
Asm->OutStreamer->AddComment("DWARF version number");
Asm->EmitInt16(DD->getDwarfVersion());
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
}
-void DwarfUnit::initSection(MCSection *Section) {
- assert(!this->Section);
- this->Section = Section;
-}
-
void DwarfTypeUnit::emitHeader(bool UseOffsets) {
DwarfUnit::emitHeader(UseOffsets);
Asm->OutStreamer->AddComment("Type Signature");
//===----------------------------------------------------------------------===//
/// This dwarf writer support class manages information associated with a
/// source file.
-class DwarfUnit {
+ class DwarfUnit : public DIEUnit {
protected:
/// MDNode for the compile unit.
const DICompileUnit *CUNode;
// All DIEValues are allocated through this allocator.
BumpPtrAllocator DIEValueAllocator;
- /// Unit debug information entry.
- DIE &UnitDie;
-
/// Target of Dwarf emission.
AsmPrinter *Asm;
DwarfDebug *DD;
DwarfFile *DU;
- /// An anonymous type for index type. Owned by UnitDie.
+ /// An anonymous type for index type. Owned by DIEUnit.
DIE *IndexTyDie;
/// Tracks the mapping of unit level debug information variables to debug
/// corresponds to the MDNode mapped with the subprogram DIE.
DenseMap<DIE *, const DINode *> ContainingTypeMap;
- /// The section this unit will be emitted in.
- MCSection *Section;
-
DwarfUnit(dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A, DwarfDebug *DW,
DwarfFile *DWU);
public:
virtual ~DwarfUnit();
- void initSection(MCSection *Section);
-
- MCSection *getSection() const {
- assert(Section);
- return Section;
- }
-
// Accessors.
AsmPrinter* getAsmPrinter() const { return Asm; }
uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
const DICompileUnit *getCUNode() const { return CUNode; }
- DIE &getUnitDie() { return UnitDie; }
/// Return true if this compile unit has something to write out.
- bool hasContent() const { return UnitDie.hasChildren(); }
+ bool hasContent() const { return Die.hasChildren(); }
/// Get string containing language specific context for a global name.
///
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
+#include <memory>
#include <string>
#include <tuple>
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
StringRef ClangModuleName)
- : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
- Ranges(RangeAlloc), ClangModuleName(ClangModuleName) {
+ : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(),
+ OrigUnit.getAddressByteSize(),
+ OrigUnit.getUnitDIE()->getTag()),
+ LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc),
+ ClangModuleName(ClangModuleName) {
Info.resize(OrigUnit.getNumDIEs());
const auto *CUDie = OrigUnit.getUnitDIE(false);
Lang == dwarf::DW_LANG_ObjC_plus_plus);
}
- CompileUnit(CompileUnit &&RHS)
- : OrigUnit(RHS.OrigUnit), Info(std::move(RHS.Info)),
- CUDie(std::move(RHS.CUDie)), StartOffset(RHS.StartOffset),
- NextUnitOffset(RHS.NextUnitOffset), RangeAlloc(), Ranges(RangeAlloc) {
- // The CompileUnit container has been 'reserve()'d with the right
- // size. We cannot move the IntervalMap anyway.
- llvm_unreachable("CompileUnits should not be moved.");
- }
-
DWARFUnit &getOrigUnit() const { return OrigUnit; }
unsigned getUniqueID() const { return ID; }
- DIE *getOutputUnitDIE() const { return CUDie; }
- void setOutputUnitDIE(DIE *Die) { CUDie = Die; }
+ DIE *getOutputUnitDIE() const {
+ return &const_cast<DIEUnit &>(NewUnit).getUnitDie();
+ }
bool hasODR() const { return HasODR; }
bool isClangModule() const { return !ClangModuleName.empty(); }
DWARFUnit &OrigUnit;
unsigned ID;
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
- DIE *CUDie; ///< Root of the linked DIE tree.
+ DIEUnit NewUnit;
uint64_t StartOffset;
uint64_t NextUnitOffset;
// The root DIE might be null, meaning that the Unit had nothing to
// contribute to the linked output. In that case, we will emit the
// unit header without any actual DIE.
- if (CUDie)
- NextUnitOffset += CUDie->getSize();
+ NextUnitOffset += NewUnit.getUnitDie().getSize();
return NextUnitOffset;
}
RelocationManager &RelocMgr;
/// Allocator used for all the DIEValue objects.
BumpPtrAllocator &DIEAlloc;
- MutableArrayRef<CompileUnit> CompileUnits;
+ std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
LinkOptions Options;
public:
DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr,
BumpPtrAllocator &DIEAlloc,
- MutableArrayRef<CompileUnit> CompileUnits, LinkOptions &Options)
+ std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
+ LinkOptions &Options)
: Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
CompileUnits(CompileUnits), Options(Options) {}
/// compile unit.
/// \param PCOffset (while cloning a function scope) is the offset
/// applied to the entry point of the function to get the linked address.
- ///
+ /// \param Die the output DIE to use, pass NULL to create one.
/// \returns the root of the cloned tree or null if nothing was selected.
DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U,
- int64_t PCOffset, uint32_t OutOffset, unsigned Flags);
+ int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
+ DIE *Die = nullptr);
/// Construct the output DIE tree by cloning the DIEs we
/// chose to keep above. If there are no valid relocs, then there's
unsigned UnitID; ///< A unique ID that identifies each compile unit.
/// The units of the current debug map object.
- std::vector<CompileUnit> Units;
+ std::vector<std::unique_ptr<CompileUnit>> Units;
+
/// The debug map object currently under consideration.
DebugMapObject *CurrentDebugObject;
/// Similar to DWARFUnitSection::getUnitForOffset(), but returning our
/// CompileUnit object instead.
-static CompileUnit *getUnitForOffset(MutableArrayRef<CompileUnit> Units,
- unsigned Offset) {
+static CompileUnit *getUnitForOffset(
+ std::vector<std::unique_ptr<CompileUnit>> &Units, unsigned Offset) {
auto CU =
std::upper_bound(Units.begin(), Units.end(), Offset,
- [](uint32_t LHS, const CompileUnit &RHS) {
- return LHS < RHS.getOrigUnit().getNextUnitOffset();
+ [](uint32_t LHS, const std::unique_ptr<CompileUnit> &RHS) {
+ return LHS < RHS->getOrigUnit().getNextUnitOffset();
});
- return CU != Units.end() ? &*CU : nullptr;
+ return CU != Units.end() ? CU->get() : nullptr;
}
/// Resolve the DIE attribute reference that has been
/// CompileUnit which is stored into \p ReferencedCU.
/// \returns null if resolving fails for any reason.
static const DWARFDebugInfoEntryMinimal *resolveDIEReference(
- const DwarfLinker &Linker, MutableArrayRef<CompileUnit> Units,
+ const DwarfLinker &Linker, std::vector<std::unique_ptr<CompileUnit>> &Units,
const DWARFFormValue &RefValue, const DWARFUnit &Unit,
const DWARFDebugInfoEntryMinimal &DIE, CompileUnit *&RefCU) {
assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
}
void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject &Obj) {
- Units.reserve(Dwarf.getNumCompileUnits());
// Iterate over the debug map entries and put all the ones that are
// functions (because they have a size) into the Ranges map. This
// map is very similar to the FunctionRanges that are stored in each
case dwarf::DW_TAG_imported_unit:
// We always want to keep these.
return Flags | TF_Keep;
+ default:
+ break;
}
return Flags;
Val.extractValue(Data, &Offset, &Unit);
CompileUnit *ReferencedCU;
if (const auto *RefDIE =
- resolveDIEReference(*this, MutableArrayRef<CompileUnit>(Units), Val,
- Unit, Die, ReferencedCU)) {
+ resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) {
uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE);
CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx);
// If the referenced DIE has a DeclContext that has already been
DIE *DwarfLinker::DIECloner::cloneDIE(
const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit,
- int64_t PCOffset, uint32_t OutOffset, unsigned Flags) {
+ int64_t PCOffset, uint32_t OutOffset, unsigned Flags, DIE *Die) {
DWARFUnit &U = Unit.getOrigUnit();
unsigned Idx = U.getDIEIndex(&InputDIE);
CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
return nullptr;
uint32_t Offset = InputDIE.getOffset();
- // The DIE might have been already created by a forward reference
- // (see cloneDieReferenceAttribute()).
- DIE *Die = Info.Clone;
- if (!Die)
- Die = Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag()));
+ assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE");
+ if (!Die) {
+ // The DIE might have been already created by a forward reference
+ // (see cloneDieReferenceAttribute()).
+ if (Info.Clone)
+ Die = Info.Clone;
+ else
+ Die = Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag()));
+ }
+
assert(Die->getTag() == InputDIE.getTag());
Die->setOffset(OutOffset);
if ((Unit.hasODR() || Unit.isClangModule()) &&
outs() << "cloning .debug_info from " << Filename << "\n";
}
- DIECloner(*this, RelocMgr, DIEAlloc, MutableArrayRef<CompileUnit>(*Unit),
- Options)
+ std::vector<std::unique_ptr<CompileUnit>> CompileUnits;
+ CompileUnits.push_back(std::move(Unit));
+ DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options)
.cloneAllCompileUnits(DwarfContext);
}
return;
for (auto &CurrentUnit : CompileUnits) {
- const auto *InputDIE = CurrentUnit.getOrigUnit().getUnitDIE();
- CurrentUnit.setStartOffset(Linker.OutputDebugInfoSize);
- DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PC offset */,
- 11 /* Unit Header size */, 0);
- CurrentUnit.setOutputUnitDIE(OutputDIE);
- Linker.OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
+ const auto *InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
+ CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize);
+ // Clonse the InputDIE into your Unit DIE in our compile unit since it
+ // already has a DIE inside of it.
+ if (!cloneDIE(*InputDIE, *CurrentUnit, 0 /* PC offset */,
+ 11 /* Unit Header size */, 0,
+ CurrentUnit->getOutputUnitDIE()))
+ continue;
+ Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset();
if (Linker.Options.NoOutput)
continue;
// FIXME: for compatibility with the classic dsymutil, we emit
// an empty line table for the unit, even if the unit doesn't
// actually exist in the DIE tree.
- Linker.patchLineTableForUnit(CurrentUnit, DwarfContext);
- if (!OutputDIE)
- continue;
- Linker.patchRangesForUnit(CurrentUnit, DwarfContext);
- Linker.Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
- Linker.emitAcceleratorEntriesForUnit(CurrentUnit);
+ Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext);
+ Linker.patchRangesForUnit(*CurrentUnit, DwarfContext);
+ Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext);
+ Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
}
if (Linker.Options.NoOutput)
// Emit all the compile unit's debug information.
for (auto &CurrentUnit : CompileUnits) {
- Linker.generateUnitRanges(CurrentUnit);
- CurrentUnit.fixupForwardReferences();
- Linker.Streamer->emitCompileUnitHeader(CurrentUnit);
- if (!CurrentUnit.getOutputUnitDIE())
+ Linker.generateUnitRanges(*CurrentUnit);
+ CurrentUnit->fixupForwardReferences();
+ Linker.Streamer->emitCompileUnitHeader(*CurrentUnit);
+ if (!CurrentUnit->getOutputUnitDIE())
continue;
- Linker.Streamer->emitDIE(*CurrentUnit.getOutputUnitDIE());
+ Linker.Streamer->emitDIE(*CurrentUnit->getOutputUnitDIE());
}
}
}
if (!registerModuleReference(*CUDie, *CU, ModuleMap))
- Units.emplace_back(*CU, UnitID++, !Options.NoODR, "");
+ Units.push_back(llvm::make_unique<CompileUnit>(*CU, UnitID++,
+ !Options.NoODR, ""));
}
// Now build the DIE parent links that we will use during the next phase.
for (auto &CurrentUnit : Units)
- analyzeContextInfo(CurrentUnit.getOrigUnit().getUnitDIE(), 0, CurrentUnit,
+ analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0, *CurrentUnit,
&ODRContexts.getRoot(), StringPool, ODRContexts);
// Then mark all the DIEs that need to be present in the linked
// references require the ParentIdx to be setup for every CU in
// the object file before calling this.
for (auto &CurrentUnit : Units)
- lookForDIEsToKeep(RelocMgr, *CurrentUnit.getOrigUnit().getUnitDIE(), *Obj,
- CurrentUnit, 0);
+ lookForDIEsToKeep(RelocMgr, *CurrentUnit->getOrigUnit().getUnitDIE(), *Obj,
+ *CurrentUnit, 0);
// The calls to applyValidRelocs inside cloneDIE will walk the
// reloc array again (in the same way findValidRelocsInDebugInfo()
.cloneAllCompileUnits(DwarfContext);
if (!Options.NoOutput && !Units.empty())
patchFrameInfoForObject(*Obj, DwarfContext,
- Units[0].getOrigUnit().getAddressByteSize());
+ Units[0]->getOrigUnit().getAddressByteSize());
// Clean-up before starting working on the next object.
endDebugObject();