+++ This bug was initially created as a clone of Bug #56353 +++
libjava.jni/invocation/PR16923.c behaves differently, depending
on linking with gold or ld. _Jv_RegisterClasses is weak reference
and libgcj.so isn't on the linker command line. Since libgcj.so isn't
on the linker command line, gold resolves _Jv_RegisterClasses to 0 and
ld silently resolves it to _Jv_RegisterClasses in libgcj.so:
[hjl@gnu-13 testsuite]$ readelf -sWr /tmp/PR16923.gold | grep _Jv_RegisterClasses
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
37: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
[hjl@gnu-13 testsuite]$ readelf -sWr /tmp/PR16923.bfd | grep _Jv_RegisterClasses
0000000000600cd0 0000000900000007 R_X86_64_JUMP_SLOT 00000000004005e0 _Jv_RegisterClasses + 0
9: 00000000004005e0 0 FUNC WEAK DEFAULT UND _Jv_RegisterClasses
59: 00000000004005e0 0 FUNC WEAK DEFAULT UND _Jv_RegisterClasses
-lgo has the same issue. With the bfd linker, I got
[hjl@gnu-mic-2 go]$ ld --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /lib/../lib/crt1.o /lib/../lib/crti.o /export/build/gnu/gcc-asan/build-x86_64-linux/gcc/testsuite/go/../../32/crtbegin.o -L/export/build/gnu/gcc-asan/build-x86_64-linux/x86_64-unknown-linux-gnu/32/libgo -L/export/build/gnu/gcc-asan/build-x86_64-linux/x86_64-unknown-linux-gnu/32/libgo/.libs -L/export/build/gnu/gcc-asan/build-x86_64-linux/gcc/testsuite/go/../../32 -L/lib/../lib -L/usr/lib/../lib -L/export/build/gnu/gcc-asan/build-x86_64-linux/gcc/testsuite/go/../.. array-1.o -lgobegin -lgo -lm --wrap=pthread_create -lgcc_s -lgcc -lc -lgcc_s -lgcc /export/build/gnu/gcc-asan/build-x86_64-linux/gcc/testsuite/go/../../32/crtend.o /lib/../lib/crtn.o
ld: /export/build/gnu/gcc-asan/build-x86_64-linux/gcc/testsuite/go/../../32/libgcc.a(generic-morestack.o): undefined reference to symbol 'pthread_sigmask@@GLIBC_2.0'
ld: note: 'pthread_sigmask@@GLIBC_2.0' is defined in DSO /lib/libpthread.so.0 so try adding it to the linker command line
/lib/libpthread.so.0: could not read symbols: Invalid operation
gold links, but it generates
51: 00000000 0 NOTYPE WEAK DEFAULT UND pthread_sigmask
It means that go executables generated by bfd ld and gold may behave
differently. Go driver should add -lpthread to -lgo if libgo.so is
linked against libpthread.so.
The reference to pthread_sigmask in generic-morestack.c is weak, and the code handles the weak reference correctly. It looks like gold is doing the right thing by emitting a weak reference.
I don't understand why GNU ld is complaining about an undefined weak reference. As far as I can see, this is a GNU ld bug; it should be testing h->ref_regular_nonweak in the code that issues this "is defined in DSO" warning.
The new GNU ld is complaining about an undefined weak reference because
it sees libpthread.so from DT_NEEDED in libgo.so. The old GNU ld just
silently adds libpthread.so from DT_NEEDED in libgo.so. When creating
executables, GNU ld checks DT_NEEDED in DSOes on command line. Since
libpthread.so is included from libgo.so for creating executables, it expects
libpthread.so will be used and pthread_sigmask is defined at run-time
Object OBJ has a weak reference to SYM.
OBJ is linked against shared library S1. S1 does not define SYM.
S1 happens to be linked against shared library S2. S2 does define SYM.
That will work fine: at runtime OBJ will see that SYM is defined, because S1 brings in S2.
Suppose that, later on, S1 is not linked against S2. That will also work fine: at runtime OBJ will see that SYM is not defined.
Right now GNU ld is issuing a warning because it sees that the weak reference from OBJ will be defined at runtime by S2, brought in at runtime because S1 is linked against S2. GNU ld is suggesting that OBJ should be linked against S2 directly. But nothing will go wrong if S1 is changed such that it does not link against S2.
Therefore, GNU ld's warning is inappropriate. There is no reason to link OBJ against S2 in this case.
(In reply to comment #3)
> Object OBJ has a weak reference to SYM.
> OBJ is linked against shared library S1. S1 does not define SYM.
> S1 happens to be linked against shared library S2. S2 does define SYM.
> That will work fine: at runtime OBJ will see that SYM is defined, because S1
> brings in S2.
This isn't what happens. Since gold doesn't check S2 at link-time, it
resolves SYM to 0:
[hjl@gnu-6 pr15149]$ cat foo.c
extern int xxx () __attribute__((weak));
return xxx ();
printf ("xxx: %d\n", foo ());
[hjl@gnu-6 pr15149]$ cat xxx.c
[hjl@gnu-6 pr15149]$ cat yyy.c
/* Dummy */
[hjl@gnu-6 pr15149]$ make y
gcc -Wl,--no-copy-dt-needed-entries -c -o foo.o foo.c
gcc -Wl,--no-copy-dt-needed-entries -shared -fPIC -o libxxx.so xxx.c
gcc -Wl,--no-copy-dt-needed-entries -shared -fPIC -o libyyy.so yyy.c libxxx.so -Wl,-rpath,.
gcc -Wl,--no-copy-dt-needed-entries -fuse-ld=gold -B./ -Wl,--no-as-needed -o y foo.o libyyy.so -Wl,-rpath,.
[hjl@gnu-6 pr15149]$ ./y
38: 0000000000000000 0 NOTYPE WEAK DEFAULT UND xxx
If gold sees SYM defined in S2, it will create a R_X86_64_JUMP_SLO relocation, set xxx value to the PLT entry and resolve xxx to the PLT entry.
000000401ad0 000700000007 R_X86_64_JUMP_SLO 0000000000400570 xxx + 0
7: 0000000000400570 0 FUNC WEAK DEFAULT UND xxx
That is the difference between seeing SYM in S2 or not.
I see. Interesting. I wonder if that is a bug in gold. I wonder what other ELF linkers do.
(In reply to comment #5)
> I see. Interesting. I wonder if that is a bug in gold. I wonder what other
I think this is related to the gold bug:
> ELF linkers do.
On Linux, ld and gold set the standard.
I'm seeing the same link error on Linux/x86_64 on mainline when configured with
/vol/gcc/bin/gld-2.31: /var/gcc/regression/trunk/4.17.3-gcc-gas-gld/build/./gcc/libgcc.a(generic-morestack.o): in function `__morestack_block_signals':
/vol/gcc/src/hg/trunk/local/libgcc/generic-morestack.c:661: undefined reference to `pthread_sigmask'
linking e.g. test2json.
The workaround for this is probably to change gcc/go/gospec.c to remove the need_thread variable. That would have the effect of changing the only use of need_thread to only test library > 0, which would mean that gccgo would add -lpthread every time it adds -lgo. (I don't plan to try implementing and testing this myself.)