-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/link: Go tip fails to build with lld linker #31912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CC @aclements It's hard to understand why changing to lld would cause this error to appear. This error comes from the Go linker before the C linker is ever invoked. |
To be really sure, I tried again with ld.lld-8, ld.bfd, and again ld.lld-8. The error persists, and only when ld points to ld.lld. |
It works fine with ld.lld-6. The command executed during
|
I can reproduce this on my linux/amd64 Debian testing-ish machine by changing I think the problem occurs when the cgo tool invokes the linker when building the cgo object for To demonstrate: ./make.bash
go install cmd/buildid cmd/pack
strace -f -e execve -s 256 go build -a -x -o /dev/null cmd/go >& /tmp/st Search /tmp/st for /usr/bin/ld. The surrounding context shows it being invoked by cgo. |
@cherrymui pointed out that
This appears to be because the
The cgo tool uses Ping @ianlancetaylor @cherrymui for thoughts. |
The functions Unfortunately, It seems to me that lld is acting incorrectly here. Since we link against libc.so.6, and the symbols are In the meantime I think we need to change cgo to call |
I just built LLD tip from source and it still generates weak symbols for pthread_mutex_lock/unlock. |
I have a fix for the bootstrap, though it appears this isn't the only problem with lld 8:
(This happens with or without my fix, as long as I apply my fix to get past bootstrap.) |
@ianlancetaylor, are there going to be other consequences of importing weak symbols in the cgo tool? I don't really understand the semantics here. Is the cgo tool just wrong to omit these right now? |
The error you show above suggests that somehow the version of gccgo you are using is not passing |
It definitely doesn't have anything to do with my change to cgo because it happens if I revert my change. |
Change https://golang.org/cl/184100 mentions this issue: |
Change https://golang.org/cl/184099 mentions this issue: |
What version of gccgo do you have installed? What is |
$ gccgo -v
Using built-in specs.
COLLECT_GCC=gccgo
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 7.3.0-18' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.3.0 (Debian 7.3.0-18) $ go env GCCGO
/usr/bin/gccgo |
Ian, I believe that your "what the linker should do" analysis in the previous comment is a bit erroneous by being overcomplicated. The STB_GLOBAL symbols in libc.so.6 are a red herring. If I have an object file with a STB_GLOBAL reference to "foo", and link it against a shared library that exposes a definition of foo, I should get a STB_GLOBAL reference in the resulting file -- regardless of whether the definition of foo is weak or strong. The weakness of the reference and the weakness of the definition are distinct things, and there's no reason they need to match. Testing this with various linkers:
Looks like in this simple case, LLD (via Clang) is doing the right thing. So it must be something other than simply the presence of weak definitions in FWIW, I also repeated this analysis adding an |
Addendum: I checked things with a somewhat older build of LLD, to rule out the "this was fixed between @cherrymui's tip-of-trunk version and my slightly-newer one", and this still works the same way with the older LLD versions. |
I just build tip LLD and it is the same.
The line above is how we invoke the linker. The linker output contains weak references.
The input to the linker seems normal.
|
Interestingly, if we don't pass
Note that gcc will still pass
(there is |
@brooksmoses What you say makes perfect sense. That said, here is how to recreate the problem.
I tested this using an lld built at Google, not one I built myself. |
@aclements I have no explanation for what you are seeing with gccgo. It does work for me. I guess it's unrelated to this issue, though, so should probably be dealt with elsewhere if at all. It might help to see the |
Thanks, @ianlancetaylor -- having a nice minimal reproducer like that is very helpful, and I'll dig into that tomorrow and see if I can boil this down to a clean easily-fixable LLD bug report. The difference in symbol-versioning there is also weird (and perhaps significant). I wonder if that's also related to getting the symbols from different places -- iirc, they're versioned in one library and not the other. |
Quick confirmation: @ianlancetaylor, I can reproduce what you're seeing with my Clang-based setup -- including the fact that, without -lpthread, the LLD link gets strong symbols. |
Some more reduction, using @ianlancetaylor's
(Both produce a warning about |
And, as one might start to expect from this data,
|
A complete, simple reproducer:
First, to confirm
If we link without
However, if we append
That seems to pretty clearly be an LLD bug. The program still has code that was written to require a strong reference to Interestingly, if we invert the order, making it I'll go file this in the LLVM bugtracker. |
This is now filed as https://bugs.llvm.org/show_bug.cgi?id=42442. |
Thanks @brooksmoses |
…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 resolves f to STB_WEAK. This is not correct because there exists a STB_GLOBAL undef ref from a regular object. This behavior is 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; When an undef ref is seen for a shared definition, the rule should check: `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. 23: 0000000000000000 0 FUNC WEAK DEFAULT UND pthread_mutex_lock {clang,gcc} a.o -pthread # libpthread.so is linked after libgcc_s.so.1 Similar linking sequence (ld.lld t.o t1.so t2.so) appears to be used by Go and causes it to fail to build golang/go#31912. Reviewers: brooksmoses, grimar, ruiu, espindola Subscribers: emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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 resolves f to STB_WEAK. This is not correct because there exists a STB_GLOBAL undef ref from a regular object. This behavior is 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; When an undef ref is seen for a shared definition, the rule should check: `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. 23: 0000000000000000 0 FUNC WEAK DEFAULT UND pthread_mutex_lock {clang,gcc} a.o -pthread # libpthread.so is linked after libgcc_s.so.1 Similar linking sequence (ld.lld t.o t1.so t2.so) appears to be used by Go and causes it to fail to build golang/go#31912. Reviewers: brooksmoses, grimar, ruiu, espindola Subscribers: emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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. This behavior is 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; When an undef ref is seen for a shared definition, the rule should check: `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. 23: 0000000000000000 0 FUNC WEAK DEFAULT UND pthread_mutex_lock {clang,gcc} a.o -pthread # libpthread.so is linked after libgcc_s.so.1 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: emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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
Thanks to Ian and Brooks for analysis. I am really sad to see pthread weak undef in libgcc_s.so.1... Anyway, proposed fix of the bug: https://reviews.llvm.org/D63974
At runtime, setting the binding of a symbol from STB_GLOBAL to STB_WEAK dosn't cause issues. |
…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, peter.smith, ruiu, espindola Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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() && !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 golang/go#31912. Reviewers: brooksmoses, grimar, peter.smith, ruiu, espindola Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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() && !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 golang/go#31912. Reviewers: brooksmoses, grimar, peter.smith, ruiu, espindola Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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() && !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 golang/go#31912. Reviewers: brooksmoses, grimar, peter.smith, ruiu, espindola Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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() && !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 golang/go#31912. Reviewers: brooksmoses, grimar, ruiu, espindola, peter.smith Reviewed By: grimar Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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() && !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 golang/go#31912. Reviewers: brooksmoses, grimar, ruiu, espindola, peter.smith Reviewed By: grimar Subscribers: jfb, emaste, arichardson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63974
…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 golang/go#31912. Reviewed By: grimar, ruiu Differential Revision: https://reviews.llvm.org/D63974
…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 golang/go#31912. Reviewed By: grimar, ruiu Differential Revision: https://reviews.llvm.org/D63974 llvm-svn: 364913
…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 golang/go#31912. Reviewed By: grimar, ruiu Differential Revision: https://reviews.llvm.org/D63974 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@364913 91177308-0d34-0410-b5e6-96231b3b80d8
Timed out in state WaitingForInfo. Closing. (I am just a bot, though. Please speak up if this is a mistake or you have the requested information.) |
Whoops, we have the info we need, but forgot to remove the label. Reopening. |
Currently, File.ImportedSymbols is the only API that exposes the GNU symbol version information for dynamic symbols. Unfortunately, it also filters to specific types of symbols, and only returns symbol names. The cgo tool is going to need symbol version information for more symbols. In order to support this and make the API more orthogonal, this CL adds version information to the Symbol type and updates File.DynamicSymbols to fill this in. This has the downside of increasing the size of Symbol, but seems to be the most natural API for exposing this. I also explored 1) adding a method to get the version information for the i'th dynamic symbol, but we don't use symbol indexes anywhere else in the API, and it's not clear if this index would be 0-based or 1-based, and 2) adding a DynamicSymbolVersions method that returns a slice of version information that parallels the DynamicSymbols slice, but that's less efficient to implement and harder to use. For #31912. Change-Id: I69052ac3894f7af2aa9561f7085275130e0cf717 Reviewed-on: https://go-review.googlesource.com/c/go/+/184099 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Change https://golang.org/cl/189458 mentions this issue: |
These will need auditing per #32813 like a few others in go1.13.txt, but in the meantime they break the API check for beta/RC releases. Updates #32813 Updates #31912 Change-Id: I3b0501b46324ee6fc0985f84971b99b772c7e4a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/189458 Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
While building go tip (at commit 3403ee5), I got the following error:
This is because I use the lld linker from LLVM:
When I change the symlink to point to
ld.gold
orld.bfd
, compiling Go works as expected. I don't know what the error exactly means (pthread_mutex_* is both defined and not defined for ABI0?) but would expect Go to compile just fine with lld as the system linker.My system is Debian stretch with LLVM 8 installed from here: http://apt.llvm.org/
What version of Go are you using (
go version
)?What operating system and processor architecture are you using (
go env
)?go env
OutputThe text was updated successfully, but these errors were encountered: