mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-12 14:17:59 +00:00
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231955 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ca75f1df99
commit
89393bbba6
@ -25,6 +25,7 @@ CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
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
|
||||
|
@ -19,6 +19,7 @@ CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
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")
|
||||
|
||||
|
@ -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,
|
||||
@ -556,6 +568,11 @@ private:
|
||||
unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
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,
|
||||
@ -831,8 +848,9 @@ bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
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::cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
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::cloneScalarAttribute(
|
||||
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 &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 &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(MutableArrayRef<char> Data,
|
||||
///
|
||||
/// \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 DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
// 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 DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
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 DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
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 DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
// 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 &Map) {
|
||||
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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user