From e83badb7d5f3d7a8881f6a1e9092dc2028f9422d Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Fri, 13 Mar 2015 18:35:57 +0000 Subject: [PATCH] [dsymutil] Fix handling of cross-cu forward references. We recorded the forward references in the CU that holds the referenced DIE, but this is wrong as those will get resoled *after* the CU that holds the reference. Record the references in their originating CU along with a pointer to the remote CU to be able to compute the fixed up offset at the right time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232193 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/basic-lto-dw4-linking-x86.test | 7 ++- tools/dsymutil/DwarfLinker.cpp | 50 +++++++++++-------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test b/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test index 83f35f43903..d2881933135 100644 --- a/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test +++ b/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test @@ -5,7 +5,6 @@ CHECK: file format Mach-O 64-bit x86-64 CHECK: debug_info contents CHECK: Compile Unit: {{.*}} version = 0x0004 - CHECK: DW_TAG_compile_unit [1] * CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang version 3.7.0 ") CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99) @@ -19,15 +18,19 @@ CHECK: DW_AT_high_pc [DW_FORM_data4] (0x0000000b) CHECK: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 ) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000027] = "main") CHECK: DW_AT_prototyped [DW_FORM_flag_present] (true) +CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000000000a1) CHECK: DW_AT_external [DW_FORM_flag_present] (true) CHECK: DW_TAG_formal_parameter [3] CHECK: DW_AT_location [DW_FORM_exprloc] (<0x3> 55 93 04 ) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000002c] = "argc") +CHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000000000a1) CHECK: DW_TAG_formal_parameter [4] CHECK: DW_AT_location [DW_FORM_exprloc] (<0x1> 54 ) CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000031] = "argv") +CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0060 => {0x00000060}) CHECK: NULL -CHECK: DW_TAG_pointer_type [5] +CHECK: DW_TAG_pointer_type [5] +CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0065 => {0x00000065}) CHECK: DW_TAG_pointer_type [5] CHECK: DW_TAG_const_type [6] CHECK: DW_TAG_base_type [7] diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index d8d8fc1ee55..8a4a8935ce5 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -33,6 +33,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include +#include namespace llvm { namespace dsymutil { @@ -70,8 +71,8 @@ public: }; CompileUnit(DWARFUnit &OrigUnit) - : OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), - Ranges(RangeAlloc) { + : OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), + Ranges(RangeAlloc) { Info.resize(OrigUnit.getNumDIEs()); } @@ -106,10 +107,11 @@ public: /// debug_info section size). uint64_t computeNextUnitOffset(); - /// \brief Keep track of a forward reference to DIE \p Die by - /// \p Attr. The attribute should be fixed up later to point to the - /// absolute offset of \p Die in the debug_info section. - void noteForwardReference(DIE *Die, DIEInteger *Attr); + /// \brief 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. + void noteForwardReference(DIE *Die, const CompileUnit *RefUnit, + DIEInteger *Attr); /// \brief Apply all fixups recored by noteForwardReference(). void fixupForwardReferences(); @@ -133,9 +135,10 @@ private: /// a DIE in the debug_info section. /// /// The offsets for the attributes in this array couldn't be set while - /// cloning because for forward refences the target DIE's offset isn't - /// known you emit the reference attribute. - std::vector> ForwardDIEReferences; + /// cloning because for cross-cu forward refences the target DIE's + /// offset isn't known you emit the reference attribute. + std::vector> + ForwardDIEReferences; HalfOpenIntervalMap::Allocator RangeAlloc; /// \brief The ranges in that interval map are the PC ranges for @@ -154,15 +157,22 @@ uint64_t CompileUnit::computeNextUnitOffset() { return NextUnitOffset; } -/// \brief Keep track of a forward reference to \p Die. -void CompileUnit::noteForwardReference(DIE *Die, DIEInteger *Attr) { - ForwardDIEReferences.emplace_back(Die, Attr); +/// \brief 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, + DIEInteger *Attr) { + ForwardDIEReferences.emplace_back(Die, RefUnit, Attr); } /// \brief Apply all fixups recorded by noteForwardReference(). void CompileUnit::fixupForwardReferences() { - for (const auto &Ref : ForwardDIEReferences) - Ref.second->setValue(Ref.first->getOffset() + getStartOffset()); + for (const auto &Ref : ForwardDIEReferences) { + DIE *RefDie; + const CompileUnit *RefUnit; + DIEInteger *Attr; + std::tie(RefDie, RefUnit, Attr) = Ref; + Attr->setValue(RefDie->getOffset() + RefUnit->getStartOffset()); + } } void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, @@ -598,7 +608,7 @@ private: cloneDieReferenceAttribute(DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, AttributeSpec AttrSpec, unsigned AttrSize, - const DWARFFormValue &Val, const DWARFUnit &U); + const DWARFFormValue &Val, CompileUnit &Unit); /// \brief Helper for cloneDIE. unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec, @@ -1169,8 +1179,8 @@ unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec, unsigned DwarfLinker::cloneDieReferenceAttribute( DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val, - const DWARFUnit &U) { - uint32_t Ref = *Val.getAsReference(&U); + CompileUnit &Unit) { + uint32_t Ref = *Val.getAsReference(&Unit.getOrigUnit()); DIE *NewRefDie = nullptr; CompileUnit *RefUnit = nullptr; const DWARFDebugInfoEntryMinimal *RefDie = nullptr; @@ -1182,7 +1192,7 @@ unsigned DwarfLinker::cloneDieReferenceAttribute( AttributeString = "DW_AT_???"; reportWarning(Twine("Missing DIE for ref in attribute ") + AttributeString + ". Dropping.", - &U, &InputDIE); + &Unit.getOrigUnit(), &InputDIE); return 0; } @@ -1211,7 +1221,7 @@ unsigned DwarfLinker::cloneDieReferenceAttribute( } else { // A forward reference. Note and fixup later. Attr = new (DIEAlloc) DIEInteger(0xBADDEF); - RefUnit->noteForwardReference(NewRefDie, Attr); + Unit.noteForwardReference(NewRefDie, RefUnit, Attr); } Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr, Attr); @@ -1346,7 +1356,7 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die, case dwarf::DW_FORM_ref4: case dwarf::DW_FORM_ref8: return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, - U); + Unit); case dwarf::DW_FORM_block: case dwarf::DW_FORM_block1: case dwarf::DW_FORM_block2: -- 2.34.1