summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2020-01-17 11:50:00 -0800
committerFangrui Song <maskray@google.com>2020-01-17 18:54:52 -0800
commit9aacec8331d9bc1f80046e5954be1f5e0e0acd42 (patch)
tree5f810e17c815538599c93bb87ca955462644a287 /lld
parentb28326516ca3ad9d51688532e944f491ce8b7908 (diff)
downloadbcm5719-llvm-9aacec8331d9bc1f80046e5954be1f5e0e0acd42.tar.gz
bcm5719-llvm-9aacec8331d9bc1f80046e5954be1f5e0e0acd42.zip
[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 (cherry picked from commit 6ab89c3c5df8b679e6ee240a13356309c048fc71)
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Relocations.cpp8
-rw-r--r--lld/test/ELF/weak-undef-hidden.s5
2 files changed, 13 insertions, 0 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 4731554e0c0..ced9991f200 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 632e051ffdc..2baad5738c3 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
OpenPOWER on IntegriCloud