[llvm] 5feb80e - [dsymutil] Fix double relocation of DW_AT_call_return_pc

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 13 17:46:10 PST 2020


Author: Jonas Devlieghere
Date: 2020-02-13T17:42:48-08:00
New Revision: 5feb80e748924606531ba28c97fe65145c65372e

URL: https://github.com/llvm/llvm-project/commit/5feb80e748924606531ba28c97fe65145c65372e
DIFF: https://github.com/llvm/llvm-project/commit/5feb80e748924606531ba28c97fe65145c65372e.diff

LOG: [dsymutil] Fix double relocation of DW_AT_call_return_pc

When the DW_AT_call_return_pc matches a relocation, the call return pc
would get relocated twice, once because of the relocation in the object
file and once because of dsymutil. The same problem exists for the low
and high PC and the fix is the same. We remember the low, high and
return pc of the original DIE and relocate that, rather than the
potentially already relocated value.

Reviewed offline by Fred Riss.

Added: 
    llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call
    llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o
    llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test

Modified: 
    llvm/include/llvm/DWARFLinker/DWARFLinker.h
    llvm/lib/DWARFLinker/DWARFLinker.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 5a8d08148091..31e8bccbf408 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -582,6 +582,9 @@ class DWARFLinker {
       /// Value of AT_high_pc in the input DIE
       uint64_t OrigHighPc = 0;
 
+      /// Value of DW_AT_call_return_pc in the input DIE
+      uint64_t OrigCallReturnPc = 0;
+
       /// Offset to apply to PC addresses inside a function.
       int64_t PCOffset = 0;
 

diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index adcbebfc7c77..03919c805130 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1017,7 +1017,8 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
   } else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) {
     // Relocate a return PC address within a call site entry.
     if (Die.getTag() == dwarf::DW_TAG_call_site)
-      Addr += Info.PCOffset;
+      Addr = (Info.OrigCallReturnPc ? Info.OrigCallReturnPc : Addr) +
+             Info.PCOffset;
   }
 
   Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
@@ -1280,6 +1281,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE(
     // inlining function.
     AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc),
                                           std::numeric_limits<uint64_t>::max());
+    AttrInfo.OrigCallReturnPc =
+        dwarf::toAddress(InputDIE.find(dwarf::DW_AT_call_return_pc), 0);
   }
 
   // Reset the Offset to 0 as we will be working on the local copy of

diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call
new file mode 100755
index 000000000000..d7587f944e9f
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call 
diff er

diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o
new file mode 100644
index 000000000000..df698e8a3284
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o 
diff er

diff  --git a/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test b/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test
new file mode 100644
index 000000000000..46e947044ffc
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test
@@ -0,0 +1,26 @@
+Test binaries created with the following commands:
+
+$ cat call.c
+__attribute__((noinline, noreturn)) void foo() {
+    asm volatile("" ::: "memory");
+      __builtin_unreachable();
+}
+__attribute__((noinline)) void bar() {
+    asm volatile("nop" :::);
+      foo();
+}
+
+int main() { bar(); }
+
+$ clang -g call.c -fomit-frame-pointer -c -Os -o call.o
+$ clang -g call.o -o call
+
+The test requires the return PC to match a relocation (in this case the
+DW_AT_high_pc of main). Without this change the value would get relocated
+twice.
+
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/call_return_pc/call -o %t.dSYM
+RUN: llvm-dwarfdump %t.dSYM | FileCheck %s -implicit-check-not=DW_AT_call_return_pc
+
+CHECK: DW_AT_call_return_pc  (0x0000000100000f72)
+CHECK: DW_AT_call_return_pc  (0x0000000100000f78)


        


More information about the llvm-commits mailing list