[dsymutil] Correctly handle DW_TAG_label
This patch contains logic for handling DW_TAG_label that's present in darwin's dsymutil implementation, but not yet upstream. Differential revision: https://reviews.llvm.org/D43438 llvm-svn: 325600
This commit is contained in:
parent
581a7f0bef
commit
563c901bac
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
# RUN: llvm-dsymutil -oso-prepend-path %p/../Inputs -y %s -f -o - | llvm-dwarfdump - --debug-info | FileCheck %s
|
||||||
|
|
||||||
|
# Compile with:
|
||||||
|
# echo -e ".global _foo;\nfoo:\nnop" | clang -x assembler -g - -c -o /tmp/label.o
|
||||||
|
|
||||||
|
# CHECK: DW_TAG_label
|
||||||
|
# CHECK-NEXT: DW_AT_name ("foo")
|
||||||
|
|
||||||
|
---
|
||||||
|
triple: 'x86_64-apple-darwin'
|
||||||
|
objects:
|
||||||
|
- filename: label.o
|
||||||
|
symbols:
|
||||||
|
- { sym: _foo, objAddr: 0x0, binAddr: 0x1000, size: 0x1 }
|
||||||
|
...
|
||||||
|
|
|
@ -327,6 +327,7 @@ public:
|
||||||
|
|
||||||
uint64_t getLowPc() const { return LowPc; }
|
uint64_t getLowPc() const { return LowPc; }
|
||||||
uint64_t getHighPc() const { return HighPc; }
|
uint64_t getHighPc() const { return HighPc; }
|
||||||
|
bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
|
||||||
|
|
||||||
Optional<PatchLocation> getUnitRangesAttribute() const {
|
Optional<PatchLocation> getUnitRangesAttribute() const {
|
||||||
return UnitRangeAttribute;
|
return UnitRangeAttribute;
|
||||||
|
@ -366,6 +367,10 @@ public:
|
||||||
/// Apply all fixups recored by noteForwardReference().
|
/// Apply all fixups recored by noteForwardReference().
|
||||||
void fixupForwardReferences();
|
void fixupForwardReferences();
|
||||||
|
|
||||||
|
/// Add the low_pc of a label that is relocatad by applying
|
||||||
|
/// offset \p PCOffset.
|
||||||
|
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
|
||||||
|
|
||||||
/// Add a function range [\p LowPC, \p HighPC) that is relocatad by applying
|
/// Add a function range [\p LowPC, \p HighPC) that is relocatad by applying
|
||||||
/// offset \p PCOffset.
|
/// offset \p PCOffset.
|
||||||
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
|
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
|
||||||
|
@ -471,6 +476,9 @@ private:
|
||||||
/// to the addresses to get the linked address.
|
/// to the addresses to get the linked address.
|
||||||
FunctionIntervals Ranges;
|
FunctionIntervals Ranges;
|
||||||
|
|
||||||
|
/// The DW_AT_low_pc of each DW_TAG_label.
|
||||||
|
SmallDenseMap<uint64_t, uint64_t, 1> Labels;
|
||||||
|
|
||||||
/// DW_AT_ranges attributes to patch after we have gathered
|
/// DW_AT_ranges attributes to patch after we have gathered
|
||||||
/// all the unit's function addresses.
|
/// all the unit's function addresses.
|
||||||
/// @{
|
/// @{
|
||||||
|
@ -585,6 +593,10 @@ void CompileUnit::fixupForwardReferences() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
|
||||||
|
Labels.insert({LabelLowPc, PcOffset});
|
||||||
|
}
|
||||||
|
|
||||||
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
|
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
|
||||||
int64_t PcOffset) {
|
int64_t PcOffset) {
|
||||||
Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
|
Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
|
||||||
|
@ -2453,7 +2465,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||||
return Flags;
|
return Flags;
|
||||||
|
|
||||||
uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
|
uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
|
||||||
const DWARFUnit &OrigUnit = Unit.getOrigUnit();
|
DWARFUnit &OrigUnit = Unit.getOrigUnit();
|
||||||
uint32_t LowPcOffset, LowPcEndOffset;
|
uint32_t LowPcOffset, LowPcEndOffset;
|
||||||
std::tie(LowPcOffset, LowPcEndOffset) =
|
std::tie(LowPcOffset, LowPcEndOffset) =
|
||||||
getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit);
|
getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit);
|
||||||
|
@ -2471,6 +2483,20 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||||
DIE.dump(outs(), 8 /* Indent */, DumpOpts);
|
DIE.dump(outs(), 8 /* Indent */, DumpOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DIE.getTag() == dwarf::DW_TAG_label) {
|
||||||
|
if (Unit.hasLabelAt(*LowPc))
|
||||||
|
return Flags;
|
||||||
|
// FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider labels
|
||||||
|
// that don't fall into the CU's aranges. This is wrong IMO. Debug info
|
||||||
|
// generation bugs aside, this is really wrong in the case of labels, where
|
||||||
|
// a label marking the end of a function will have a PC == CU's high_pc.
|
||||||
|
if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc))
|
||||||
|
.getValueOr(UINT64_MAX) <= LowPc)
|
||||||
|
return Flags;
|
||||||
|
Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust);
|
||||||
|
return Flags | TF_Keep;
|
||||||
|
}
|
||||||
|
|
||||||
Flags |= TF_Keep;
|
Flags |= TF_Keep;
|
||||||
|
|
||||||
Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
|
Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
|
||||||
|
@ -2498,6 +2524,7 @@ unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
|
||||||
case dwarf::DW_TAG_variable:
|
case dwarf::DW_TAG_variable:
|
||||||
return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
||||||
case dwarf::DW_TAG_subprogram:
|
case dwarf::DW_TAG_subprogram:
|
||||||
|
case dwarf::DW_TAG_label:
|
||||||
return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
||||||
case dwarf::DW_TAG_imported_module:
|
case dwarf::DW_TAG_imported_module:
|
||||||
case dwarf::DW_TAG_imported_declaration:
|
case dwarf::DW_TAG_imported_declaration:
|
||||||
|
|
Loading…
Reference in New Issue