[lld] 6ab89c3 - [ELF] Allow R_PLT_PC (R_PC) to a hidden undefined weak symbol

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 17 13:06:54 PST 2020


Author: Fangrui Song
Date: 2020-01-17T13:06:42-08:00
New Revision: 6ab89c3c5df8b679e6ee240a13356309c048fc71

URL: https://github.com/llvm/llvm-project/commit/6ab89c3c5df8b679e6ee240a13356309c048fc71
DIFF: https://github.com/llvm/llvm-project/commit/6ab89c3c5df8b679e6ee240a13356309c048fc71.diff

LOG: [ELF] Allow R_PLT_PC (R_PC) to a hidden undefined weak symbol

This essentially reverts b841e119d77ed0502e3a2e710f26a899bef28b3c.

Such code construct can be used in the following way:

  // glibc/stdlib/exit.c
  // clang -fuse-ld=lld => succeeded
  // clang -fuse-ld=lld -fpie -pie => relocation R_PLT_PC cannot refer to absolute symbol
  __attribute__((weak, visibility("hidden"))) extern void __call_tls_dtors();
  void __run_exit_handlers() {
    if (__call_tls_dtors)
        __call_tls_dtors();
  }

Since we allow R_PLT_PC in -no-pie mode, it makes sense to allow it in
-pie mode as well.

Reviewed By: pcc

Differential Revision: https://reviews.llvm.org/D72943

Added: 
    

Modified: 
    lld/ELF/Relocations.cpp
    lld/test/ELF/weak-undef-hidden.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 510d515ad9a9..790b24d4a0c7 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -408,6 +408,14 @@ static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
 
   assert(absVal && relE);
 
+  // Allow R_PLT_PC (optimized to R_PC here) to a hidden undefined weak symbol
+  // in PIC mode. This is a little strange, but it allows us to link function
+  // calls to such symbols (e.g. glibc/stdlib/exit.c:__run_exit_handlers).
+  // Normally such a call will be guarded with a comparison, which will load a
+  // zero from the GOT.
+  if (sym.isUndefWeak())
+    return true;
+
   // We set the final symbols values for linker script defined symbols later.
   // They always can be computed as a link time constant.
   if (sym.scriptDefined)

diff  --git a/lld/test/ELF/weak-undef-hidden.s b/lld/test/ELF/weak-undef-hidden.s
index 632e051ffdc1..2baad5738c36 100644
--- a/lld/test/ELF/weak-undef-hidden.s
+++ b/lld/test/ELF/weak-undef-hidden.s
@@ -2,6 +2,11 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 // RUN: ld.lld %t.o -o %t.so -shared
 // RUN: llvm-readobj -r -S --section-data %t.so | FileCheck %s
+// RUN: ld.lld %t.o -o %t -pie
+// RUN: llvm-readobj -r -S --section-data %t | FileCheck %s
+
+/// This is usually guarded with a comparison. Don't report an error.
+call g
 
 .data
 .weak g


        


More information about the llvm-commits mailing list