summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2018-02-20 17:34:29 +0000
committerJonas Devlieghere <jonas@devlieghere.com>2018-02-20 17:34:29 +0000
commit563c901bac5ea12b8364c2c38c2264c4c1d027ec (patch)
treefd5209d847a502509da30ac9ace0857f862b9c70
parent581a7f0bef5a46960be3f2f65807ea60fe2ce8be (diff)
downloadbcm5719-llvm-563c901bac5ea12b8364c2c38c2264c4c1d027ec.tar.gz
bcm5719-llvm-563c901bac5ea12b8364c2c38c2264c4c1d027ec.zip
[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
-rw-r--r--llvm/test/tools/dsymutil/Inputs/label.obin0 -> 1088 bytes
-rw-r--r--llvm/test/tools/dsymutil/X86/label.test16
-rw-r--r--llvm/tools/dsymutil/DwarfLinker.cpp29
3 files changed, 44 insertions, 1 deletions
diff --git a/llvm/test/tools/dsymutil/Inputs/label.o b/llvm/test/tools/dsymutil/Inputs/label.o
new file mode 100644
index 00000000000..cd70eb57e05
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/label.o
Binary files differ
diff --git a/llvm/test/tools/dsymutil/X86/label.test b/llvm/test/tools/dsymutil/X86/label.test
new file mode 100644
index 00000000000..be4bc3c83b4
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/label.test
@@ -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 }
+...
+
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
index 4064cd0a6a4..4a34fa6e8e1 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
@@ -327,6 +327,7 @@ public:
uint64_t getLowPc() const { return LowPc; }
uint64_t getHighPc() const { return HighPc; }
+ bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
Optional<PatchLocation> getUnitRangesAttribute() const {
return UnitRangeAttribute;
@@ -366,6 +367,10 @@ public:
/// Apply all fixups recored by noteForwardReference().
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
/// offset \p 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.
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
/// 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,
int64_t PcOffset) {
Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
@@ -2453,7 +2465,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
return Flags;
uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
- const DWARFUnit &OrigUnit = Unit.getOrigUnit();
+ DWARFUnit &OrigUnit = Unit.getOrigUnit();
uint32_t LowPcOffset, LowPcEndOffset;
std::tie(LowPcOffset, LowPcEndOffset) =
getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit);
@@ -2471,6 +2483,20 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
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;
Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc);
@@ -2498,6 +2524,7 @@ unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
case dwarf::DW_TAG_variable:
return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
case dwarf::DW_TAG_subprogram:
+ case dwarf::DW_TAG_label:
return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
case dwarf::DW_TAG_imported_module:
case dwarf::DW_TAG_imported_declaration:
OpenPOWER on IntegriCloud