[dsymutil] Add relocation of compile_units low_pc/high_pc.

They need to be handled specifically as they could vary pretty
widely depending on how the linker moves functions around.

llvm-svn: 232192
This commit is contained in:
Frederic Riss 2015-03-13 18:35:54 +00:00
parent 111a0a8305
commit 5a62dc3793
4 changed files with 55 additions and 16 deletions

View File

@ -17,6 +17,7 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LL
CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ea0)
CHECK: DW_TAG_subprogram [2] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
@ -61,6 +62,7 @@ CHECK: DW_TAG_compile_unit [1] *
CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ed0)
CHECK: DW_TAG_base_type [4]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
CHECK: DW_TAG_variable [7]
@ -97,6 +99,7 @@ CHECK: DW_TAG_compile_unit [1] *
CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
CHECK: DW_TAG_variable [9]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000162})

View File

@ -11,6 +11,8 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "clang versio
CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000016] = "basic1.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000001f] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
CHECK: DW_AT_high_pc [DW_FORM_data4] (0x0000000b)
CHECK: DW_TAG_subprogram [2] *
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
CHECK: DW_AT_high_pc [DW_FORM_data4] (0x0000000b)
@ -40,6 +42,8 @@ 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)
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000003b] = "basic2.c")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f50)
CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000037)
CHECK: DW_TAG_base_type [7]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000044] = "int")
CHECK: DW_TAG_variable [8]
@ -74,6 +78,8 @@ 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_name [DW_FORM_strp] ( .debug_str[0x00000064] = "basic3.c")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90)
CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000024)
CHECK: DW_TAG_variable [13]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000006d] = "val")
CHECK: DW_AT_location [DW_FORM_exprloc] (<0x9> 03 04 10 00 00 01 00 00 00 )

View File

@ -11,6 +11,7 @@ CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LL
CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
CHECK: DW_TAG_subprogram [2] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
@ -52,6 +53,7 @@ CHECK: DW_TAG_compile_unit [1] *
CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f50)
CHECK: DW_TAG_variable [7]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int")
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
@ -87,6 +89,7 @@ CHECK: DW_TAG_compile_unit [1] *
CHECK: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90)
CHECK: DW_TAG_variable [12]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000176})

View File

@ -70,7 +70,8 @@ public:
};
CompileUnit(DWARFUnit &OrigUnit)
: OrigUnit(OrigUnit), RangeAlloc(), Ranges(RangeAlloc) {
: OrigUnit(OrigUnit), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
Ranges(RangeAlloc) {
Info.resize(OrigUnit.getNumDIEs());
}
@ -94,6 +95,9 @@ public:
uint64_t getStartOffset() const { return StartOffset; }
uint64_t getNextUnitOffset() const { return NextUnitOffset; }
uint64_t getLowPc() const { return LowPc; }
uint64_t getHighPc() const { return HighPc; }
void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; }
/// \brief Compute the end offset for this unit. Must be
@ -122,6 +126,9 @@ private:
uint64_t StartOffset;
uint64_t NextUnitOffset;
uint64_t LowPc;
uint64_t HighPc;
/// \brief A list of attributes to fixup with the absolute offset of
/// a DIE in the debug_info section.
///
@ -158,9 +165,11 @@ void CompileUnit::fixupForwardReferences() {
Ref.second->setValue(Ref.first->getOffset() + getStartOffset());
}
void CompileUnit::addFunctionRange(uint64_t LowPC, uint64_t HighPC,
int64_t PCOffset) {
Ranges.insert(LowPC, HighPC, PCOffset);
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
int64_t PcOffset) {
Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
}
/// \brief A string table that doesn't need relocations.
@ -603,7 +612,7 @@ private:
/// \brief Helper for cloneDIE.
unsigned cloneScalarAttribute(DIE &Die,
const DWARFDebugInfoEntryMinimal &InputDIE,
const DWARFUnit &U, AttributeSpec AttrSpec,
const CompileUnit &U, AttributeSpec AttrSpec,
const DWARFFormValue &Val, unsigned AttrSize);
/// \brief Helper for cloneDIE.
@ -1258,16 +1267,27 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
const DWARFFormValue &Val,
const CompileUnit &Unit,
AttributesInfo &Info) {
int64_t Addr = *Val.getAsAddress(&Unit.getOrigUnit());
uint64_t Addr = *Val.getAsAddress(&Unit.getOrigUnit());
if (AttrSpec.Attr == dwarf::DW_AT_low_pc) {
if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine ||
Die.getTag() == dwarf::DW_TAG_lexical_block)
Addr += Info.PCOffset;
else if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
Addr = Unit.getLowPc();
if (Addr == UINT64_MAX)
return 0;
}
} else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) {
// If we have a high_pc recorded for the input DIE, use
// it. Otherwise (when no relocations where applied) just use the
// one we just decoded.
Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset;
if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
if (uint64_t HighPc = Unit.getHighPc())
Addr = HighPc;
else
return 0;
} else
// If we have a high_pc recorded for the input DIE, use
// it. Otherwise (when no relocations where applied) just use the
// one we just decoded.
Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset;
}
Die.addValue(static_cast<dwarf::Attribute>(AttrSpec.Attr),
@ -1279,18 +1299,25 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
/// \brief Clone a scalar attribute and add it to \p Die.
/// \returns the size of the new attribute.
unsigned DwarfLinker::cloneScalarAttribute(
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, const DWARFUnit &U,
AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize) {
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
const CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
unsigned AttrSize) {
uint64_t Value;
if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
Die.getTag() == dwarf::DW_TAG_compile_unit) {
if (Unit.getLowPc() == -1ULL)
return 0;
// Dwarf >= 4 high_pc is an size, not an address.
Value = Unit.getHighPc() - Unit.getLowPc();
} else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
Value = *Val.getAsSectionOffset();
else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
Value = *Val.getAsSignedConstant();
else if (auto OptionalValue = Val.getAsUnsignedConstant())
Value = *OptionalValue;
else {
reportWarning("Unsupported scalar attribute form. Dropping attribute.", &U,
&InputDIE);
reportWarning("Unsupported scalar attribute form. Dropping attribute.",
&Unit.getOrigUnit(), &InputDIE);
return 0;
}
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
@ -1337,7 +1364,7 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die,
case dwarf::DW_FORM_sec_offset:
case dwarf::DW_FORM_flag:
case dwarf::DW_FORM_flag_present:
return cloneScalarAttribute(Die, InputDIE, U, AttrSpec, Val, AttrSize);
return cloneScalarAttribute(Die, InputDIE, Unit, AttrSpec, Val, AttrSize);
default:
reportWarning("Unsupported attribute form in cloneAttribute. Dropping.", &U,
&InputDIE);