summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Riss <friss@apple.com>2015-08-31 01:43:14 +0000
committerFrederic Riss <friss@apple.com>2015-08-31 01:43:14 +0000
commit7b5563aa5c4bd5cb304c58e33a0230a05fd1debf (patch)
tree9e22740d9df85d36116a579f18b8872cd41e17ad
parentdaa92a61932380f84a22a4bfce20445fec57efbe (diff)
downloadbcm5719-llvm-7b5563aa5c4bd5cb304c58e33a0230a05fd1debf.tar.gz
bcm5719-llvm-7b5563aa5c4bd5cb304c58e33a0230a05fd1debf.zip
[dsymutil] Fix handling of inlined_subprogram low_pcs
The value of an inlined subprogram low_pc attribute should not get relocated, but it can happen that it matches the enclosing function's start address and thus gets the generic treatment. Special case it to avoid applying the PC offset twice. llvm-svn: 246406
-rw-r--r--llvm/test/tools/dsymutil/ARM/dummy-debug-map-amr64.map15
-rw-r--r--llvm/test/tools/dsymutil/ARM/inlined-low_pc.c15
-rw-r--r--llvm/test/tools/dsymutil/ARM/lit.local.cfg3
-rw-r--r--llvm/test/tools/dsymutil/Inputs/inlined-low_pc/1.obin0 -> 1960 bytes
-rw-r--r--llvm/tools/dsymutil/DwarfLinker.cpp17
5 files changed, 47 insertions, 3 deletions
diff --git a/llvm/test/tools/dsymutil/ARM/dummy-debug-map-amr64.map b/llvm/test/tools/dsymutil/ARM/dummy-debug-map-amr64.map
new file mode 100644
index 00000000000..a23e0c34c3f
--- /dev/null
+++ b/llvm/test/tools/dsymutil/ARM/dummy-debug-map-amr64.map
@@ -0,0 +1,15 @@
+# This is a dummy debug map used for some tests where the contents of the
+# map are just an implementation detail. The tests wanting to use that file
+# should put all there object files in an explicitely named sub-directory
+# of Inputs, and they should be named 1.o, 2.o, ...
+# As not finding an object file or symbols isn't a fatal error for dsymutil,
+# you can extend this file with as much object files and symbols as needed.
+
+---
+triple: 'arm64-apple-darwin'
+objects:
+ - filename: 1.o
+ symbols:
+ - { sym: _bar, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }
+...
+
diff --git a/llvm/test/tools/dsymutil/ARM/inlined-low_pc.c b/llvm/test/tools/dsymutil/ARM/inlined-low_pc.c
new file mode 100644
index 00000000000..7ade33e3e44
--- /dev/null
+++ b/llvm/test/tools/dsymutil/ARM/inlined-low_pc.c
@@ -0,0 +1,15 @@
+/* Compiled with: clang -arch=arm64 -O2 -g -c inlined_low_pc.c */
+
+static int foo(int i) { return 42 + i; }
+int bar(int a) { return foo(a); }
+
+// RUN: llvm-dsymutil -f -y %p/dummy-debug-map-amr64.map -oso-prepend-path %p/../Inputs/inlined-low_pc -o - | llvm-dwarfdump - | FileCheck %s
+
+// CHECK: DW_TAG_subprogram
+// CHECK: DW_AT_low_pc{{.*}}0x0000000000010000
+// CHECK: DW_AT_name{{.*}}"bar"
+// CHECK-NOT: NULL
+// CHECK: DW_TAG_inlined_subroutine
+// CHECK-NEXT: DW_AT_abstract_origin{{.*}}"foo"
+// CHECK-NEXT: DW_AT_low_pc{{.*}}0x0000000000010000
+
diff --git a/llvm/test/tools/dsymutil/ARM/lit.local.cfg b/llvm/test/tools/dsymutil/ARM/lit.local.cfg
index b704ac4031f..442cd554bfe 100644
--- a/llvm/test/tools/dsymutil/ARM/lit.local.cfg
+++ b/llvm/test/tools/dsymutil/ARM/lit.local.cfg
@@ -2,3 +2,6 @@ if not 'ARM' in config.root.targets:
config.unsupported = True
if not 'AArch64' in config.root.targets:
config.unsupported = True
+
+config.suffixes = ['.test', '.cpp', '.c']
+
diff --git a/llvm/test/tools/dsymutil/Inputs/inlined-low_pc/1.o b/llvm/test/tools/dsymutil/Inputs/inlined-low_pc/1.o
new file mode 100644
index 00000000000..7ab4e9205bb
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/inlined-low_pc/1.o
Binary files differ
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
index 0be12375b26..1e171db44c4 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
@@ -1206,6 +1206,7 @@ private:
const char *Name, *MangledName; ///< Names.
uint32_t NameOffset, MangledNameOffset; ///< Offsets in the string pool.
+ uint64_t OrigLowPc; ///< Value of AT_low_pc in the input DIE
uint64_t OrigHighPc; ///< Value of AT_high_pc in the input DIE
int64_t PCOffset; ///< Offset to apply to PC addresses inside a function.
@@ -1214,8 +1215,8 @@ private:
AttributesInfo()
: Name(nullptr), MangledName(nullptr), NameOffset(0),
- MangledNameOffset(0), OrigHighPc(0), PCOffset(0), HasLowPc(false),
- IsDeclaration(false) {}
+ MangledNameOffset(0), OrigLowPc(UINT64_MAX), OrigHighPc(0),
+ PCOffset(0), HasLowPc(false), IsDeclaration(false) {}
};
/// \brief Helper for cloneDIE.
@@ -2274,7 +2275,12 @@ unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
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;
+ // The low_pc of a block or inline subroutine might get
+ // relocated because it happens to match the low_pc of the
+ // enclosing subprogram. To prevent issues with that, always use
+ // the low_pc from the input DIE if relocations have been applied.
+ Addr = (Info.OrigLowPc != UINT64_MAX ? Info.OrigLowPc : Addr) +
+ Info.PCOffset;
else if (Die.getTag() == dwarf::DW_TAG_compile_unit) {
Addr = Unit.getLowPc();
if (Addr == UINT64_MAX)
@@ -2522,6 +2528,11 @@ DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
// high_pc value is done in cloneAddressAttribute().
AttrInfo.OrigHighPc =
InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_high_pc, 0);
+ // Also store the low_pc. It might get relocated in an
+ // inline_subprogram that happens at the beginning of its
+ // inlining function.
+ AttrInfo.OrigLowPc =
+ InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_low_pc, UINT64_MAX);
}
// Reset the Offset to 0 as we will be working on the local copy of
OpenPOWER on IntegriCloud