Index: llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h =================================================================== --- llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h +++ llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h @@ -77,6 +77,9 @@ /// Is ODR marking done? bool ODRMarkingDone : 1; + + /// Is this a reference to a DIE that hasn't been cloned yet? + bool Reference : 1; }; CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, @@ -160,15 +163,15 @@ /// current debug_info section size). uint64_t computeNextUnitOffset(uint16_t DwarfVersion); - /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p - /// Attr. The attribute should be fixed up later to point to the absolute - /// offset of \p Die in the debug_info section or to the canonical offset of - /// \p Ctxt if it is non-null. - void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DeclContext *Ctxt, PatchLocation Attr); + /// Keep track of a forward or backward reference to DIE \p Die in \p RefUnit + /// by \p Attr. The attribute should be fixed up later to point to the + /// absolute offset of \p Die in the debug_info section or to the canonical + /// offset of \p Ctxt if it is non-null. + void noteReference(DIE *Die, const CompileUnit *RefUnit, DeclContext *Ctxt, + PatchLocation Attr); - /// Apply all fixups recorded by noteForwardReference(). - void fixupForwardReferences(); + /// Apply all fixups recorded by noteReference(). + void fixupReferences(); /// Add the low_pc of a label that is relocated by applying /// offset \p PCOffset. @@ -260,7 +263,7 @@ /// isn't known you emit the reference attribute. std::vector< std::tuple> - ForwardDIEReferences; + DIEReferences; /// The ranges in that map are the PC ranges for functions in this unit, /// associated with the PC offset to apply to the addresses to get Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -934,9 +934,9 @@ } if (!RefInfo.Clone) { - assert(Ref > InputDIE.getOffset()); // We haven't cloned this DIE yet. Just create an empty one and // store it. It'll get really cloned when we process it. + RefInfo.Reference = true; RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); } NewRefDie = RefInfo.Clone; @@ -949,7 +949,7 @@ // FIXME: we should be able to design DIEEntry reliance on // DwarfDebug away. uint64_t Attr; - if (Ref < InputDIE.getOffset()) { + if (Ref < InputDIE.getOffset() && !RefInfo.Reference) { // We must have already cloned that DIE. uint32_t NewRefOffset = RefUnit->getStartOffset() + NewRefDie->getOffset(); @@ -957,12 +957,12 @@ Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr, DIEInteger(Attr)); } else { - // A forward reference. Note and fixup later. + // A forward or backward reference. Note and fixup later. Attr = 0xBADDEF; - Unit.noteForwardReference( - NewRefDie, RefUnit, RefInfo.Ctxt, - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::DW_FORM_ref_addr, DIEInteger(Attr))); + Unit.noteReference(NewRefDie, RefUnit, RefInfo.Ctxt, + Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), + dwarf::DW_FORM_ref_addr, + DIEInteger(Attr))); } return U.getRefAddrByteSize(); } @@ -2237,7 +2237,7 @@ if (LLVM_LIKELY(!Linker.Options.Update)) Linker.generateUnitRanges(*CurrentUnit); - CurrentUnit->fixupForwardReferences(); + CurrentUnit->fixupReferences(); if (!CurrentUnit->getOutputUnitDIE()) continue; Index: llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp +++ llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp @@ -78,13 +78,13 @@ /// Keep track of a forward cross-cu reference from this unit /// to \p Die that lives in \p RefUnit. -void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit, - DeclContext *Ctxt, PatchLocation Attr) { - ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); +void CompileUnit::noteReference(DIE *Die, const CompileUnit *RefUnit, + DeclContext *Ctxt, PatchLocation Attr) { + DIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr); } -void CompileUnit::fixupForwardReferences() { - for (const auto &Ref : ForwardDIEReferences) { +void CompileUnit::fixupReferences() { + for (const auto &Ref : DIEReferences) { DIE *RefDie; const CompileUnit *RefUnit; PatchLocation Attr;