forked from llvm-mirror/lld
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ELF] Only allow the binding of SharedSymbol to change for the first …
…undef ref Summary: 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() && !BindingFinalized` where BindingFinalized 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 golang/go#31912. Reviewers: brooksmoses, grimar, ruiu, espindola Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
- Loading branch information
Showing
4 changed files
with
61 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,31 @@ | ||
// REQUIRES: x86 | ||
// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux | ||
// RUN: llvm-mc %p/Inputs/shared.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux | ||
// RUN: ld.lld %t2.o -o %t2.so -shared | ||
// RUN: ld.lld %t.o %t2.so -o %t.exe | ||
// RUN: llvm-readobj --symbols %t.exe | FileCheck %s | ||
# REQUIRES: x86 | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o | ||
# RUN: ld.lld -shared %t.o -o %t.so | ||
|
||
// CHECK: Name: bar | ||
// CHECK-NEXT: Value: 0x201020 | ||
// CHECK-NEXT: Size: 0 | ||
// CHECK-NEXT: Binding: Weak | ||
// CHECK-NEXT: Type: Function | ||
// CHECK-NEXT: Other: 0 | ||
// CHECK-NEXT: Section: Undefined | ||
# RUN: echo '.data; .weak foo; .quad foo' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o | ||
# RUN: echo '.data; .quad foo' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o | ||
|
||
.global _start | ||
_start: | ||
.weak bar | ||
.quad bar | ||
## If the first undefined reference is weak, the binding changes to | ||
## STB_WEAK. | ||
# RUN: ld.lld %t1.o %t.so -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s | ||
# RUN: ld.lld %t.so %t1.o -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s | ||
|
||
## The binding remains STB_WEAK if there is no STB_GLOBAL undefined reference. | ||
# RUN: ld.lld %t1.o %t.so %t1.o -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s | ||
# RUN: ld.lld %t.so %t1.o %t1.o -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s | ||
|
||
## The binding changes back to STB_GLOBAL if there is a STB_GLOBAL undefined reference. | ||
# RUN: ld.lld %t1.o %t.so %t2.o -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=GLOBAL %s | ||
# RUN: ld.lld %t2.o %t.so %t1.o -o %t | ||
# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=GLOBAL %s | ||
|
||
# WEAK: NOTYPE WEAK DEFAULT UND foo | ||
# GLOBAL: NOTYPE GLOBAL DEFAULT UND foo | ||
|
||
.globl foo | ||
foo: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# 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 |