[dsymutil] Fix handling of cross-cu forward references.
authorFrederic Riss <friss@apple.com>
Fri, 13 Mar 2015 18:35:57 +0000 (18:35 +0000)
committerFrederic Riss <friss@apple.com>
Fri, 13 Mar 2015 18:35:57 +0000 (18:35 +0000)
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

test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test
tools/dsymutil/DwarfLinker.cpp

index 83f35f43903bdc5242e5cf0a183a6f53fc4f6229..d2881933135defb844edce210a0e0bff03adce0c 100644 (file)
@@ -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]  
index d8d8fc1ee5561efdf15d45fbf1894818204570ab..8a4a8935ce5684959f25466fea389dd4c8edcca5 100644 (file)
@@ -33,6 +33,7 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include <string>
+#include <tuple>
 
 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<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences;
+  /// cloning because for cross-cu forward refences the target DIE's
+  /// offset isn't known you emit the reference attribute.
+  std::vector<std::tuple<DIE *, const CompileUnit *, DIEInteger *>>
+      ForwardDIEReferences;
 
   HalfOpenIntervalMap<uint64_t, int64_t>::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: