[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. llvm-svn: 232193
This commit is contained in:
		
							parent
							
								
									5a62dc3793
								
							
						
					
					
						commit
						6afcfce2d9
					
				| 
						 | 
				
			
			@ -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_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]  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue