[ELF] Only allow the binding of SharedSymbol to change for the first undef ref
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
Loading
Please sign in to comment