forked from OSchip/llvm-project
[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: debug_info contents
|
||||||
|
|
||||||
CHECK: Compile Unit: {{.*}} version = 0x0004
|
CHECK: Compile Unit: {{.*}} version = 0x0004
|
||||||
|
|
||||||
CHECK: DW_TAG_compile_unit [1] *
|
CHECK: DW_TAG_compile_unit [1] *
|
||||||
CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang version 3.7.0 ")
|
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)
|
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_frame_base [DW_FORM_exprloc] (<0x1> 56 )
|
||||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000027] = "main")
|
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000027] = "main")
|
||||||
CHECK: DW_AT_prototyped [DW_FORM_flag_present] (true)
|
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_AT_external [DW_FORM_flag_present] (true)
|
||||||
CHECK: DW_TAG_formal_parameter [3]
|
CHECK: DW_TAG_formal_parameter [3]
|
||||||
CHECK: DW_AT_location [DW_FORM_exprloc] (<0x3> 55 93 04 )
|
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_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_TAG_formal_parameter [4]
|
||||||
CHECK: DW_AT_location [DW_FORM_exprloc] (<0x1> 54 )
|
CHECK: DW_AT_location [DW_FORM_exprloc] (<0x1> 54 )
|
||||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000031] = "argv")
|
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000031] = "argv")
|
||||||
|
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0060 => {0x00000060})
|
||||||
CHECK: NULL
|
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_pointer_type [5]
|
||||||
CHECK: DW_TAG_const_type [6]
|
CHECK: DW_TAG_const_type [6]
|
||||||
CHECK: DW_TAG_base_type [7]
|
CHECK: DW_TAG_base_type [7]
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace dsymutil {
|
namespace dsymutil {
|
||||||
|
@ -70,8 +71,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
CompileUnit(DWARFUnit &OrigUnit)
|
CompileUnit(DWARFUnit &OrigUnit)
|
||||||
: OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
|
: OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
|
||||||
Ranges(RangeAlloc) {
|
Ranges(RangeAlloc) {
|
||||||
Info.resize(OrigUnit.getNumDIEs());
|
Info.resize(OrigUnit.getNumDIEs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +107,11 @@ public:
|
||||||
/// debug_info section size).
|
/// debug_info section size).
|
||||||
uint64_t computeNextUnitOffset();
|
uint64_t computeNextUnitOffset();
|
||||||
|
|
||||||
/// \brief Keep track of a forward reference to DIE \p Die by
|
/// \brief Keep track of a forward reference to DIE \p Die in \p
|
||||||
/// \p Attr. The attribute should be fixed up later to point to the
|
/// RefUnit by \p Attr. The attribute should be fixed up later to
|
||||||
/// absolute offset of \p Die in the debug_info section.
|
/// point to the absolute offset of \p Die in the debug_info section.
|
||||||
void noteForwardReference(DIE *Die, DIEInteger *Attr);
|
void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
|
||||||
|
DIEInteger *Attr);
|
||||||
|
|
||||||
/// \brief Apply all fixups recored by noteForwardReference().
|
/// \brief Apply all fixups recored by noteForwardReference().
|
||||||
void fixupForwardReferences();
|
void fixupForwardReferences();
|
||||||
|
@ -133,9 +135,10 @@ private:
|
||||||
/// a DIE in the debug_info section.
|
/// a DIE in the debug_info section.
|
||||||
///
|
///
|
||||||
/// The offsets for the attributes in this array couldn't be set while
|
/// 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
|
/// cloning because for cross-cu forward refences the target DIE's
|
||||||
/// known you emit the reference attribute.
|
/// offset isn't known you emit the reference attribute.
|
||||||
std::vector<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences;
|
std::vector<std::tuple<DIE *, const CompileUnit *, DIEInteger *>>
|
||||||
|
ForwardDIEReferences;
|
||||||
|
|
||||||
HalfOpenIntervalMap<uint64_t, int64_t>::Allocator RangeAlloc;
|
HalfOpenIntervalMap<uint64_t, int64_t>::Allocator RangeAlloc;
|
||||||
/// \brief The ranges in that interval map are the PC ranges for
|
/// \brief The ranges in that interval map are the PC ranges for
|
||||||
|
@ -154,15 +157,22 @@ uint64_t CompileUnit::computeNextUnitOffset() {
|
||||||
return NextUnitOffset;
|
return NextUnitOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Keep track of a forward reference to \p Die.
|
/// \brief Keep track of a forward cross-cu reference from this unit
|
||||||
void CompileUnit::noteForwardReference(DIE *Die, DIEInteger *Attr) {
|
/// to \p Die that lives in \p RefUnit.
|
||||||
ForwardDIEReferences.emplace_back(Die, Attr);
|
void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
|
||||||
|
DIEInteger *Attr) {
|
||||||
|
ForwardDIEReferences.emplace_back(Die, RefUnit, Attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Apply all fixups recorded by noteForwardReference().
|
/// \brief Apply all fixups recorded by noteForwardReference().
|
||||||
void CompileUnit::fixupForwardReferences() {
|
void CompileUnit::fixupForwardReferences() {
|
||||||
for (const auto &Ref : ForwardDIEReferences)
|
for (const auto &Ref : ForwardDIEReferences) {
|
||||||
Ref.second->setValue(Ref.first->getOffset() + getStartOffset());
|
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,
|
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
|
||||||
|
@ -598,7 +608,7 @@ private:
|
||||||
cloneDieReferenceAttribute(DIE &Die,
|
cloneDieReferenceAttribute(DIE &Die,
|
||||||
const DWARFDebugInfoEntryMinimal &InputDIE,
|
const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||||
AttributeSpec AttrSpec, unsigned AttrSize,
|
AttributeSpec AttrSpec, unsigned AttrSize,
|
||||||
const DWARFFormValue &Val, const DWARFUnit &U);
|
const DWARFFormValue &Val, CompileUnit &Unit);
|
||||||
|
|
||||||
/// \brief Helper for cloneDIE.
|
/// \brief Helper for cloneDIE.
|
||||||
unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
|
unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||||
|
@ -1169,8 +1179,8 @@ unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||||
unsigned DwarfLinker::cloneDieReferenceAttribute(
|
unsigned DwarfLinker::cloneDieReferenceAttribute(
|
||||||
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
|
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||||
AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val,
|
AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val,
|
||||||
const DWARFUnit &U) {
|
CompileUnit &Unit) {
|
||||||
uint32_t Ref = *Val.getAsReference(&U);
|
uint32_t Ref = *Val.getAsReference(&Unit.getOrigUnit());
|
||||||
DIE *NewRefDie = nullptr;
|
DIE *NewRefDie = nullptr;
|
||||||
CompileUnit *RefUnit = nullptr;
|
CompileUnit *RefUnit = nullptr;
|
||||||
const DWARFDebugInfoEntryMinimal *RefDie = nullptr;
|
const DWARFDebugInfoEntryMinimal *RefDie = nullptr;
|
||||||
|
@ -1182,7 +1192,7 @@ unsigned DwarfLinker::cloneDieReferenceAttribute(
|
||||||
AttributeString = "DW_AT_???";
|
AttributeString = "DW_AT_???";
|
||||||
reportWarning(Twine("Missing DIE for ref in attribute ") + AttributeString +
|
reportWarning(Twine("Missing DIE for ref in attribute ") + AttributeString +
|
||||||
". Dropping.",
|
". Dropping.",
|
||||||
&U, &InputDIE);
|
&Unit.getOrigUnit(), &InputDIE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1211,7 +1221,7 @@ unsigned DwarfLinker::cloneDieReferenceAttribute(
|
||||||
} else {
|
} else {
|
||||||
// A forward reference. Note and fixup later.
|
// A forward reference. Note and fixup later.
|
||||||
Attr = new (DIEAlloc) DIEInteger(0xBADDEF);
|
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,
|
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr,
|
||||||
Attr);
|
Attr);
|
||||||
|
@ -1346,7 +1356,7 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die,
|
||||||
case dwarf::DW_FORM_ref4:
|
case dwarf::DW_FORM_ref4:
|
||||||
case dwarf::DW_FORM_ref8:
|
case dwarf::DW_FORM_ref8:
|
||||||
return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
|
return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
|
||||||
U);
|
Unit);
|
||||||
case dwarf::DW_FORM_block:
|
case dwarf::DW_FORM_block:
|
||||||
case dwarf::DW_FORM_block1:
|
case dwarf::DW_FORM_block1:
|
||||||
case dwarf::DW_FORM_block2:
|
case dwarf::DW_FORM_block2:
|
||||||
|
|
Loading…
Reference in New Issue