Fixes PR42442
t.o has a STB_GLOBAL undef ref to f
t2.so has a STB_WEAK undef ref to f
t1.so defines f
ld.lld t.o t1.so t2.so currently sets the binding of `f` to STB_WEAK.
This is not correct because there exists a STB_GLOBAL undef ref from a
regular object. The problem is that resolveUndefined() doesn't check
if the undef ref is seen for the first time:
if (isShared() || isLazy() || (isUndefined() && Other.Binding != STB_WEAK))
Binding = Other.Binding;
The isShared() condition should be `isShared() && !Referenced`
where Referenced is set to true after an undef ref is seen.
In practice, when linking a pthread program with glibc:
// a.o
#include <pthread.h>
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
int main() { pthread_mutex_unlock(&mu); }
{clang,gcc} -fuse-ld=lld a.o -lpthread # libpthread.so is linked before libgcc_s.so.1
The weak undef pthread_mutex_unlock in libgcc_s.so.1 makes the result
weak, which diverges from GNU linkers where STB_DEFAULT is used:
23: 0000000000000000 0 FUNC WEAK DEFAULT UND pthread_mutex_lock
(Note, if -pthread is used instead, libpthread.so will be linked **after**
libgcc_s.so.1 . lld sets the binding to the expected STB_GLOBAL)
Similar linking sequences (ld.lld t.o t1.so t2.so) appear to be used by
Go, which cause a build error https://github.com/golang/go/issues/31912.
Reviewed By: grimar, ruiu
Differential Revision: https://reviews.llvm.org/D63974
llvm-svn: 364913
22 lines
756 B
ArmAsm
22 lines
756 B
ArmAsm
# REQUIRES: x86
|
|
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
|
|
# RUN: echo '.globl f; f:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
|
|
# RUN: echo '.weak f; .data; .quad f' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
|
|
# RUN: ld.lld -shared %t1.o -o %t1.so
|
|
# RUN: ld.lld -shared %t2.o -o %t2.so
|
|
|
|
## The undefined reference is STB_GLOBAL in %t.o while STB_WEAK in %t2.so.
|
|
## Check the binding of the result is STB_GLOBAL.
|
|
|
|
# RUN: ld.lld %t.o %t1.so %t2.so -o %t
|
|
# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
|
|
# RUN: ld.lld %t1.so %t.o %t2.so -o %t
|
|
# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
|
|
# RUN: ld.lld %t1.so %t2.so %t.o -o %t
|
|
# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
|
|
|
|
# CHECK: NOTYPE GLOBAL DEFAULT UND f
|
|
|
|
.data
|
|
.quad f
|