mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 01:12:59 +00:00
[dsymutil] Add support for debug_loc section.
There is no need to look into the location expressions to transfer them, the only modification to apply is to patch their base address to reflect the linked function address. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232267 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c0cc039a57
commit
5712ee147f
@ -129,6 +129,9 @@ CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
|
||||
CHECK: NULL
|
||||
|
||||
CHECK: .debug_loc contents
|
||||
CHECK-NOT: Location
|
||||
|
||||
CHECK:.debug_aranges contents:
|
||||
CHECK-NEXT:Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
|
||||
CHECK-NEXT:[0x0000000100000ea0 - 0x0000000100000ec4)
|
||||
|
@ -66,7 +66,8 @@ CHECK: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005c] = "foo")
|
||||
CHECK: DW_AT_prototyped [DW_FORM_flag_present] (true)
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x002a => {0x000000a1})
|
||||
CHECK: DW_TAG_formal_parameter [11]
|
||||
CHECK: DW_TAG_formal_parameter [11]
|
||||
CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000)
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "arg")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x002a => {0x000000a1})
|
||||
CHECK: DW_TAG_inlined_subroutine [12]
|
||||
@ -95,7 +96,8 @@ CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f90)
|
||||
CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000024)
|
||||
CHECK: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000071] = "bar")
|
||||
CHECK: DW_TAG_formal_parameter [16]
|
||||
CHECK: DW_TAG_formal_parameter [16]
|
||||
CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000025)
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "arg")
|
||||
CHECK: DW_TAG_inlined_subroutine [17]
|
||||
CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x0044 => {0x0000015f} "inc")
|
||||
@ -106,6 +108,20 @@ CHECK: [0x0000000100000f9f - 0x0000000100000fa7))
|
||||
CHECK: NULL
|
||||
CHECK: NULL
|
||||
|
||||
|
||||
CHECK: .debug_loc contents:
|
||||
CHECK-NEXT: 0x00000000: Beginning address offset: 0x0000000000000000
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000000c
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
CHECK-NEXT: {{^$}}
|
||||
CHECK-NEXT: 0x00000025: Beginning address offset: 0x0000000000000000
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000000f
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
CHECK-NEXT: {{^$}}
|
||||
CHECK-NEXT: Beginning address offset: 0x0000000000000019
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000001d
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
|
||||
CHECK: .debug_aranges contents:
|
||||
CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
|
||||
CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b)
|
||||
|
@ -71,6 +71,7 @@ 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_AT_location [DW_FORM_data4] (0x00000000)
|
||||
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)
|
||||
@ -105,6 +106,7 @@ 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_AT_location [DW_FORM_data4] (0x00000025)
|
||||
CHECK: DW_TAG_lexical_block [14] *
|
||||
CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000100000f94)
|
||||
CHECK DW_AT_high_pc [DW_FORM_addr] (0x0000000100000fa7)
|
||||
@ -120,6 +122,19 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: NULL
|
||||
|
||||
CHECK:.debug_loc contents:
|
||||
CHECK-NEXT: 0x00000000: Beginning address offset: 0x0000000000000000
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000000e
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
CHECK-NEXT: {{^$}}
|
||||
CHECK-NEXT: 0x00000025: Beginning address offset: 0x0000000000000000
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000000f
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
CHECK-NEXT: {{^$}}
|
||||
CHECK-NEXT: Beginning address offset: 0x0000000000000019
|
||||
CHECK-NEXT: Ending address offset: 0x000000000000001d
|
||||
CHECK-NEXT: Location description: 55 93 04
|
||||
|
||||
CHECK: .debug_aranges contents:
|
||||
CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
|
||||
CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b)
|
||||
|
@ -110,6 +110,11 @@ public:
|
||||
return RangeAttributes;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<DIEInteger *, int64_t>> &
|
||||
getLocationAttributes() const {
|
||||
return LocationAttributes;
|
||||
}
|
||||
|
||||
/// \brief Compute the end offset for this unit. Must be
|
||||
/// called after the CU's DIEs have been cloned.
|
||||
/// \returns the next unit offset (which is also the current
|
||||
@ -133,6 +138,10 @@ public:
|
||||
/// patch up later.
|
||||
void noteRangeAttribute(const DIE &Die, DIEInteger *Attr);
|
||||
|
||||
/// \brief Keep track of a location attribute pointing to a location
|
||||
/// list in the debug_loc section.
|
||||
void noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset);
|
||||
|
||||
private:
|
||||
DWARFUnit &OrigUnit;
|
||||
unsigned ID;
|
||||
@ -166,6 +175,12 @@ private:
|
||||
std::vector<DIEInteger *> RangeAttributes;
|
||||
DIEInteger *UnitRangeAttribute;
|
||||
/// @}
|
||||
|
||||
/// \brief Location attributes that need to be transfered from th
|
||||
/// original debug_loc section to the liked one. They are stored
|
||||
/// along with the PC offset that is to be applied to their
|
||||
/// function's address.
|
||||
std::vector<std::pair<DIEInteger *, int64_t>> LocationAttributes;
|
||||
};
|
||||
|
||||
uint64_t CompileUnit::computeNextUnitOffset() {
|
||||
@ -210,6 +225,10 @@ void CompileUnit::noteRangeAttribute(const DIE &Die, DIEInteger *Attr) {
|
||||
UnitRangeAttribute = Attr;
|
||||
}
|
||||
|
||||
void CompileUnit::noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset) {
|
||||
LocationAttributes.emplace_back(Attr, PcOffset);
|
||||
}
|
||||
|
||||
/// \brief A string table that doesn't need relocations.
|
||||
///
|
||||
/// We are doing a final link, no need for a string table that
|
||||
@ -319,6 +338,7 @@ class DwarfStreamer {
|
||||
std::unique_ptr<raw_fd_ostream> OutFile;
|
||||
|
||||
uint32_t RangesSectionSize;
|
||||
uint32_t LocSectionSize;
|
||||
|
||||
public:
|
||||
/// \brief Actually create the streamer and the ouptut file.
|
||||
@ -367,6 +387,11 @@ public:
|
||||
void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection);
|
||||
|
||||
uint32_t getRangesSectionSize() const { return RangesSectionSize; }
|
||||
|
||||
/// \brief Emit the debug_loc contribution for \p Unit by copying
|
||||
/// the entries from \p Dwarf and offseting them. Update the
|
||||
/// location attributes to point to the new entries.
|
||||
void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
|
||||
};
|
||||
|
||||
bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
|
||||
@ -433,6 +458,7 @@ bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
|
||||
return error("no asm printer for target " + TripleName, Context);
|
||||
|
||||
RangesSectionSize = 0;
|
||||
LocSectionSize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -617,6 +643,57 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
|
||||
RangesSectionSize += 2 * AddressSize;
|
||||
}
|
||||
|
||||
/// \brief Emit location lists for \p Unit and update attribtues to
|
||||
/// point to the new entries.
|
||||
void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
|
||||
DWARFContext &Dwarf) {
|
||||
const std::vector<std::pair<DIEInteger *, int64_t>> &Attributes =
|
||||
Unit.getLocationAttributes();
|
||||
|
||||
if (Attributes.empty())
|
||||
return;
|
||||
|
||||
MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
|
||||
|
||||
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
|
||||
const DWARFSection &InputSec = Dwarf.getLocSection();
|
||||
DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
|
||||
DWARFUnit &OrigUnit = Unit.getOrigUnit();
|
||||
const auto *OrigUnitDie = OrigUnit.getCompileUnitDIE(false);
|
||||
int64_t UnitPcOffset = 0;
|
||||
uint64_t OrigLowPc = OrigUnitDie->getAttributeValueAsAddress(
|
||||
&OrigUnit, dwarf::DW_AT_low_pc, -1ULL);
|
||||
if (OrigLowPc != -1ULL)
|
||||
UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
|
||||
|
||||
for (const auto &Attr : Attributes) {
|
||||
uint32_t Offset = Attr.first->getValue();
|
||||
Attr.first->setValue(LocSectionSize);
|
||||
// This is the quantity to add to the old location address to get
|
||||
// the correct address for the new one.
|
||||
int64_t LocPcOffset = Attr.second + UnitPcOffset;
|
||||
while (Data.isValidOffset(Offset)) {
|
||||
uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
|
||||
uint64_t High = Data.getUnsigned(&Offset, AddressSize);
|
||||
LocSectionSize += 2 * AddressSize;
|
||||
if (Low == 0 && High == 0) {
|
||||
Asm->OutStreamer.EmitIntValue(0, AddressSize);
|
||||
Asm->OutStreamer.EmitIntValue(0, AddressSize);
|
||||
break;
|
||||
}
|
||||
Asm->OutStreamer.EmitIntValue(Low + LocPcOffset, AddressSize);
|
||||
Asm->OutStreamer.EmitIntValue(High + LocPcOffset, AddressSize);
|
||||
uint64_t Length = Data.getU16(&Offset);
|
||||
Asm->OutStreamer.EmitIntValue(Length, 2);
|
||||
// Just copy the bytes over.
|
||||
Asm->OutStreamer.EmitBytes(
|
||||
StringRef(InputSec.Data.substr(Offset, Length)));
|
||||
Offset += Length;
|
||||
LocSectionSize += Length + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief The core of the Dwarf linking logic.
|
||||
///
|
||||
/// The link of the dwarf information from the object files will be
|
||||
@ -791,7 +868,8 @@ private:
|
||||
unsigned cloneScalarAttribute(DIE &Die,
|
||||
const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
CompileUnit &U, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize);
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
const AttributesInfo &Info);
|
||||
|
||||
/// \brief Helper for cloneDIE.
|
||||
bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
|
||||
@ -1486,7 +1564,8 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned DwarfLinker::cloneScalarAttribute(
|
||||
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit,
|
||||
AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize) {
|
||||
AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize,
|
||||
const AttributesInfo &Info) {
|
||||
uint64_t Value;
|
||||
if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
|
||||
Die.getTag() == dwarf::DW_TAG_compile_unit) {
|
||||
@ -1508,6 +1587,13 @@ unsigned DwarfLinker::cloneScalarAttribute(
|
||||
DIEInteger *Attr = new (DIEAlloc) DIEInteger(Value);
|
||||
if (AttrSpec.Attr == dwarf::DW_AT_ranges)
|
||||
Unit.noteRangeAttribute(Die, Attr);
|
||||
// A more generic way to check for location attributes would be
|
||||
// nice, but it's very unlikely that any other attribute needs a
|
||||
// location list.
|
||||
else if (AttrSpec.Attr == dwarf::DW_AT_location ||
|
||||
AttrSpec.Attr == dwarf::DW_AT_frame_base)
|
||||
Unit.noteLocationAttribute(Attr, Info.PCOffset);
|
||||
|
||||
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
|
||||
Attr);
|
||||
return AttrSize;
|
||||
@ -1552,7 +1638,8 @@ 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, Unit, AttrSpec, Val, AttrSize);
|
||||
return cloneScalarAttribute(Die, InputDIE, Unit, AttrSpec, Val, AttrSize,
|
||||
Info);
|
||||
default:
|
||||
reportWarning("Unsupported attribute form in cloneAttribute. Dropping.", &U,
|
||||
&InputDIE);
|
||||
@ -1843,6 +1930,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
if (!OutputDIE || Options.NoOutput)
|
||||
continue;
|
||||
patchRangesForUnit(CurrentUnit, DwarfContext);
|
||||
Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
|
||||
}
|
||||
|
||||
// Emit all the compile unit's debug information.
|
||||
|
Loading…
Reference in New Issue
Block a user