diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index f9bf8b98a60..334c1083161 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -112,6 +112,18 @@ DIE::~DIE() { delete Children[i]; } +/// Climb up the parent chain to get the compile unit DIE to which this DIE +/// belongs. +const DIE *DIE::getCompileUnit() const { + const DIE *p = this; + while (p) { + if (p->getTag() == dwarf::DW_TAG_compile_unit) + return p; + p = p->getParent(); + } + llvm_unreachable("We should not have orphaned DIEs."); +} + DIEValue *DIE::findAttribute(uint16_t Attribute) { const SmallVectorImpl &Values = getValues(); const DIEAbbrev &Abbrevs = getAbbrev(); diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 6d4f305c840..96a01327f76 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -146,6 +146,9 @@ namespace llvm { const std::vector &getChildren() const { return Children; } const SmallVectorImpl &getValues() const { return Values; } DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile unit DIE this DIE belongs + /// to. + const DIE *getCompileUnit() const; void setOffset(unsigned O) { Offset = O; } void setSize(unsigned S) { Size = S; } diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index db8558cfeca..27ba19a8964 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -33,7 +33,8 @@ using namespace llvm; /// CompileUnit - Compile unit constructor. CompileUnit::CompileUnit(unsigned UID, DIE *D, const MDNode *N, AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU) - : UniqueID(UID), Node(N), CUDie(D), Asm(A), DD(DW), DU(DWU), IndexTyDie(0) { + : UniqueID(UID), Node(N), CUDie(D), Asm(A), DD(DW), DU(DWU), IndexTyDie(0), + DebugInfoOffset(0) { DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); insertDIE(N, D); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 1759ac4bdaa..4a59ec544de 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -120,6 +120,9 @@ public: return AccelTypes; } + unsigned getDebugInfoOffset() const { return DebugInfoOffset; } + void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; } + /// hasContent - Return true if this compile unit has something to write out. /// bool hasContent() const { return !CUDie->getChildren().empty(); } @@ -347,6 +350,9 @@ private: /// getOrCreateStaticMemberDIE - Create new static data member DIE. DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); + /// Offset of the CUDie from beginning of debug info section. + unsigned DebugInfoOffset; + /// getLowerBoundDefault - Return the default lower bound for an array. If the /// DWARF version doesn't handle the language, return -1. int64_t getDefaultLowerBound() const; diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f491d01876c..722dd32d7ed 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -821,6 +821,7 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { InfoHolder.addUnit(NewCU); CUMap.insert(std::make_pair(N, NewCU)); + CUDieMap.insert(std::make_pair(Die, NewCU)); return NewCU; } @@ -1915,7 +1916,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Emit Methods //===----------------------------------------------------------------------===// -// Compute the size and offset of a DIE. +// Compute the size and offset of a DIE. The offset is relative to start of the +// CU. It returns the offset after laying out the DIE. unsigned DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Get the children. @@ -1960,16 +1962,26 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Compute the size and offset for each DIE. void DwarfUnits::computeSizeAndOffsets() { + // Offset from the first CU in the debug info section is 0 initially. + unsigned SecOffset = 0; + // Iterate over each compile unit and set the size and offsets for each // DIE within each compile unit. All offsets are CU relative. for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); I != E; ++I) { + (*I)->setDebugInfoOffset(SecOffset); + + // CU-relative offset is reset to 0 here. unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) - computeSizeAndOffset((*I)->getCUDie(), Offset); + + // EndOffset here is CU-relative, after laying out + // all of the CU DIE. + unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset); + SecOffset += EndOffset; } } @@ -2049,6 +2061,33 @@ void DwarfDebug::emitDIE(DIE *Die, std::vector *Abbrevs) { Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { + case dwarf::DW_AT_abstract_origin: + case dwarf::DW_AT_type: + case dwarf::DW_AT_friend: + case dwarf::DW_AT_specification: + case dwarf::DW_AT_import: + case dwarf::DW_AT_containing_type: { + DIEEntry *E = cast(Values[i]); + DIE *Origin = E->getEntry(); + unsigned Addr = Origin->getOffset(); + if (Form == dwarf::DW_FORM_ref_addr) { + assert(!useSplitDwarf() && "TODO: dwo files can't have relocations."); + // For DW_FORM_ref_addr, output the offset from beginning of debug info + // section. Origin->getOffset() returns the offset from start of the + // compile unit. + CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit()); + assert(CU && "CUDie should belong to a CU."); + Addr += CU->getDebugInfoOffset(); + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr, + DIEEntry::getRefAddrSize(Asm)); + else + Asm->OutStreamer.EmitIntValue(Addr, DIEEntry::getRefAddrSize(Asm)); + } else { + Asm->EmitInt32(Addr); + } + break; + } case dwarf::DW_AT_ranges: { // DW_AT_range Value encodes offset in debug_range section. DIEInteger *V = cast(Values[i]); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 83ea0cc967a..d3ce12c67a9 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -329,6 +329,9 @@ class DwarfDebug { // Maps subprogram MDNode with its corresponding CompileUnit. DenseMap SPMap; + // Maps a CU DIE with its corresponding CompileUnit. + DenseMap CUDieMap; + // Used to uniquely define abbreviations. FoldingSet AbbreviationsSet;