[llvm] r231955 - [dsymutil] Correctly clone address attributes.
Frederic Riss
friss at apple.com
Wed Mar 11 11:45:52 PDT 2015
Author: friss
Date: Wed Mar 11 13:45:52 2015
New Revision: 231955
URL: http://llvm.org/viewvc/llvm-project?rev=231955&view=rev
Log:
[dsymutil] Correctly clone address attributes.
DW_AT_low_pc on functions is taken care of by the relocation processing, but
DW_AT_high_pc and DW_AT_low_pc on other lexical scopes need special handling.
Modified:
llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
llvm/trunk/tools/dsymutil/DwarfLinker.cpp
Modified: llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test?rev=231955&r1=231954&r2=231955&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Wed Mar 11 13:45:52 2015
@@ -25,6 +25,7 @@ CHECK: DW_AT_type [DW_FORM_ref4]
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ea0)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000ec4)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
@@ -75,6 +76,7 @@ CHECK: DW_TAG_subprogram [2] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000ed0)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f19)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
@@ -85,6 +87,7 @@ CHECK: DW_TAG_subprogram [8]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f20)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f37)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: NULL
@@ -107,6 +110,7 @@ CHECK: DW_TAG_subprogram [2] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f84)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
@@ -117,6 +121,7 @@ CHECK: DW_TAG_subprogram [8]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000fa9)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: NULL
Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test?rev=231955&r1=231954&r2=231955&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test Wed Mar 11 13:45:52 2015
@@ -19,6 +19,7 @@ CHECK: DW_AT_type [DW_FORM_ref4]
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f40)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f4b)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [3]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
@@ -63,12 +64,15 @@ CHECK: DW_TAG_subprogram [8] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f50)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f89)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [9]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
CHECK: DW_TAG_inlined_subroutine [10]
CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x00a7 => {0x00000128} "inc")
+CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f63)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000f72)
CHECK: DW_AT_call_line [DW_FORM_data1] (20)
CHECK: NULL
CHECK: DW_TAG_subprogram [11]
@@ -93,11 +97,14 @@ CHECK: DW_TAG_subprogram [8] *
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90)
+CHECK: DW_AT_high_pc [DW_FORM_addr] (0x0000000100000fb4)
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
CHECK: DW_TAG_formal_parameter [9]
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
CHECK: DW_TAG_lexical_block [14] *
+CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f94)
+CHECK DW_AT_high_pc [DW_FORM_addr] (0x0000000100000fa7)
CHECK: DW_TAG_inlined_subroutine [15]
CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x009a => {0x000001d4} "inc")
Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=231955&r1=231954&r2=231955&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Wed Mar 11 13:45:52 2015
@@ -54,7 +54,7 @@ class CompileUnit {
public:
/// \brief Information gathered about a DIE in the object file.
struct DIEInfo {
- uint64_t Address; ///< Linked address of the described entity.
+ int64_t AddrAdjust; ///< Address offset to apply to the described entity.
DIE *Clone; ///< Cloned version of that DIE.
uint32_t ParentIdx; ///< The index of this DIE's parent.
bool Keep; ///< Is the DIE part of the linked output?
@@ -529,17 +529,29 @@ private:
///
/// \param OutOffset is the offset the cloned DIE in the output
/// compile unit.
+ /// \param PCOffset (while cloning a function scope) is the offset
+ /// applied to the entry point of the function to get the linked address.
///
/// \returns the root of the cloned tree.
DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U,
- uint32_t OutOffset);
+ int64_t PCOffset, uint32_t OutOffset);
typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
+ /// \brief Information gathered and exchanged between the various
+ /// clone*Attributes helpers about the attributes of a particular DIE.
+ struct AttributesInfo {
+ uint64_t OrigHighPc; ///< Value of AT_high_pc in the input DIE
+ int64_t PCOffset; ///< Offset to apply to PC addresses inside a function.
+
+ AttributesInfo() : OrigHighPc(0), PCOffset(0) {}
+ };
+
/// \brief Helper for cloneDIE.
unsigned cloneAttribute(DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
CompileUnit &U, const DWARFFormValue &Val,
- const AttributeSpec AttrSpec, unsigned AttrSize);
+ const AttributeSpec AttrSpec, unsigned AttrSize,
+ AttributesInfo &AttrInfo);
/// \brief Helper for cloneDIE.
unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
@@ -557,6 +569,11 @@ private:
const DWARFFormValue &Val, unsigned AttrSize);
/// \brief Helper for cloneDIE.
+ unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
+ const DWARFFormValue &Val,
+ const CompileUnit &Unit, AttributesInfo &Info);
+
+ /// \brief Helper for cloneDIE.
unsigned cloneScalarAttribute(DIE &Die,
const DWARFDebugInfoEntryMinimal &InputDIE,
const DWARFUnit &U, AttributeSpec AttrSpec,
@@ -831,8 +848,9 @@ bool DwarfLinker::hasValidRelocation(uin
ValidReloc.Mapping->getValue().ObjectAddress,
ValidReloc.Mapping->getValue().BinaryAddress);
- Info.Address =
- ValidReloc.Mapping->getValue().BinaryAddress + ValidReloc.Addend;
+ Info.AddrAdjust = int64_t(ValidReloc.Mapping->getValue().BinaryAddress) +
+ ValidReloc.Addend -
+ ValidReloc.Mapping->getValue().ObjectAddress;
Info.InDebugMap = true;
return true;
}
@@ -1189,6 +1207,30 @@ unsigned DwarfLinker::cloneBlockAttribut
return AttrSize;
}
+/// \brief Clone an address attribute and add it to \p Die.
+/// \returns the size of the new attribute.
+unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
+ const DWARFFormValue &Val,
+ const CompileUnit &Unit,
+ AttributesInfo &Info) {
+ int64_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 (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;
+ }
+
+ Die.addValue(static_cast<dwarf::Attribute>(AttrSpec.Attr),
+ static_cast<dwarf::Form>(AttrSpec.Form),
+ new (DIEAlloc) DIEInteger(Addr));
+ return Unit.getOrigUnit().getAddressByteSize();
+}
+
/// \brief Clone a scalar attribute and add it to \p Die.
/// \returns the size of the new attribute.
unsigned DwarfLinker::cloneScalarAttribute(
@@ -1199,8 +1241,6 @@ unsigned DwarfLinker::cloneScalarAttribu
Value = *Val.getAsSectionOffset();
else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
Value = *Val.getAsSignedConstant();
- else if (AttrSpec.Form == dwarf::DW_FORM_addr)
- Value = *Val.getAsAddress(&U);
else if (auto OptionalValue = Val.getAsUnsignedConstant())
Value = *OptionalValue;
else {
@@ -1221,7 +1261,7 @@ unsigned DwarfLinker::cloneAttribute(DIE
CompileUnit &Unit,
const DWARFFormValue &Val,
const AttributeSpec AttrSpec,
- unsigned AttrSize) {
+ unsigned AttrSize, AttributesInfo &Info) {
const DWARFUnit &U = Unit.getOrigUnit();
switch (AttrSpec.Form) {
@@ -1242,6 +1282,7 @@ unsigned DwarfLinker::cloneAttribute(DIE
case dwarf::DW_FORM_exprloc:
return cloneBlockAttribute(Die, AttrSpec, Val, AttrSize);
case dwarf::DW_FORM_addr:
+ return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info);
case dwarf::DW_FORM_data1:
case dwarf::DW_FORM_data2:
case dwarf::DW_FORM_data4:
@@ -1312,7 +1353,8 @@ bool DwarfLinker::applyValidRelocs(Mutab
///
/// \returns the cloned DIE object or null if nothing was selected.
DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
- CompileUnit &Unit, uint32_t OutOffset) {
+ CompileUnit &Unit, int64_t PCOffset,
+ uint32_t OutOffset) {
DWARFUnit &U = Unit.getOrigUnit();
unsigned Idx = U.getDIEIndex(&InputDIE);
CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
@@ -1333,6 +1375,7 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
// Extract and clone every attribute.
DataExtractor Data = U.getDebugInfoExtractor();
uint32_t NextOffset = U.getDIEAtIndex(Idx + 1)->getOffset();
+ AttributesInfo AttrInfo;
// We could copy the data only if we need to aply a relocation to
// it. After testing, it seems there is no performance downside to
@@ -1340,7 +1383,17 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
Data = DataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
// Modify the copy with relocated addresses.
- applyValidRelocs(DIECopy, Offset, Data.isLittleEndian());
+ if (applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
+ // If we applied relocations, we store the value of high_pc that was
+ // potentially stored in the input DIE. If high_pc is an address
+ // (Dwarf version == 2), then it might have been relocated to a
+ // totally unrelated value (because the end address in the object
+ // file might be start address of another function which got moved
+ // independantly by the linker). The computation of the actual
+ // high_pc value is done in cloneAddressAttribute().
+ AttrInfo.OrigHighPc =
+ InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_high_pc, 0);
+ }
// Reset the Offset to 0 as we will be working on the local copy of
// the data.
@@ -1349,13 +1402,19 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
Offset += getULEB128Size(Abbrev->getCode());
+ // We are entering a subprogram. Get and propagate the PCOffset.
+ if (Die->getTag() == dwarf::DW_TAG_subprogram)
+ PCOffset = Info.AddrAdjust;
+ AttrInfo.PCOffset = PCOffset;
+
for (const auto &AttrSpec : Abbrev->attributes()) {
DWARFFormValue Val(AttrSpec.Form);
uint32_t AttrSize = Offset;
Val.extractValue(Data, &Offset, &U);
AttrSize = Offset - AttrSize;
- OutOffset += cloneAttribute(*Die, InputDIE, Unit, Val, AttrSpec, AttrSize);
+ OutOffset +=
+ cloneAttribute(*Die, InputDIE, Unit, Val, AttrSpec, AttrSize, AttrInfo);
}
DIEAbbrev &NewAbbrev = Die->getAbbrev();
@@ -1379,7 +1438,7 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
// Recursively clone children.
for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL();
Child = Child->getSibling()) {
- if (DIE *Clone = cloneDIE(*Child, Unit, OutOffset)) {
+ if (DIE *Clone = cloneDIE(*Child, Unit, PCOffset, OutOffset)) {
Die->addChild(std::unique_ptr<DIE>(Clone));
OutOffset = Clone->getOffset() + Clone->getSize();
}
@@ -1460,8 +1519,8 @@ bool DwarfLinker::link(const DebugMap &M
for (auto &CurrentUnit : Units) {
const auto *InputDIE = CurrentUnit.getOrigUnit().getCompileUnitDIE();
CurrentUnit.setStartOffset(OutputDebugInfoSize);
- DIE *OutputDIE =
- cloneDIE(*InputDIE, CurrentUnit, 11 /* Unit Header size */);
+ DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PCOffset */,
+ 11 /* Unit Header size */);
CurrentUnit.setOutputUnitDIE(OutputDIE);
OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
}
More information about the llvm-commits
mailing list