[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