Skip to content
This repository has been archived by the owner on Aug 17, 2022. It is now read-only.

linker can not load libraries metioned in DT_NEEDED section of another library #108

Closed
kraj opened this issue Oct 5, 2017 · 6 comments
Closed

Comments

@kraj
Copy link

kraj commented Oct 5, 2017

Test case

https://uclibc.org/~kraj/riscv-linker-test.tar.bz2

Fails to link

$ /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc nss.c -lnss3 -L. -Wl,-rpath-link .
/opt/riscv/lib/gcc/riscv64-unknown-linux-gnu/7.1.1/../../../../riscv64-unknown-linux-gnu/bin/ld: /opt/riscv/sysroot/usr/lib64/lp64d/crt1.o: undefined reference to symbol '__global_pointer$'
./libplc4.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

This example works ok on other architectures. Adding -lplc4 to cmdline then link succeeds. Issue is observed in multiple packages.

Here is DT_NEEDED entries for libnss3.so

Dynamic section at offset 0xaddc0 contains 32 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libnssutil3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libplc4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libplds4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnspr4.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-riscv64-lp64d.so.1]
 0x000000000000000e (SONAME)             Library soname: [libnss3.so]
@jim-wilson
Copy link
Collaborator

hidden-gp.patch.gz
Hi Khem. The issue here is that most every program and shared library uses __global_pointer$, which is equivalent to the MIPS gp symbol. libnss3.so oddly does not. I'm not sure how that can happen, but it doesn't matter. libnss3 has a DT_NEEDED pointing at libplc4.so. libplc4.so has a __global_pointer$ symbol, and it is being exported. So when you link, the linker thinks that you have a direct symbol reference to a library not on the linker command line, and that requires an error on all targets. The real problem here is that __global_pointer$ should not be exported by shared libraries. This is easy to fix. See the attached patch.

Unfortunately, I don't have an easy way to prove that this patch works. It requires relinking libplc4.so. I don't have a full riscv linux environment, just a simple busybox based one, and this bug does not show up on that system. I have not yet been able to write a simple testcase that reproduces the problem.

@jim-wilson
Copy link
Collaborator

Fix committed to the FSF Binutils tree. Let me know if you need the patch on one of the riscv-binutils-gdb branches.

@jim-wilson
Copy link
Collaborator

Palmer just brought all upstream fixes into riscv-binutils-2.29 branch a day or two ago.

rwmjones added a commit to rwmjones/fedora-riscv-bootstrap that referenced this issue Jan 6, 2018
@rwmjones
Copy link

rwmjones commented Jan 6, 2018

I didn't try the riscv-binutils-2.29 branch (why isn't riscv-tools using that branch?)

However I can confirm that the two patches above fix the issue for me.

@jim-wilson
Copy link
Collaborator

riscv-tools does use the riscv-binutlis-2.29 branch of the riscv-binutils-gdb tree. However, the use of git submodules means that you don't automatically get updates from that branch. And the fact that binutils is actually two suibmodule levels down makes it more complicated.

In general, there is a lack of documentation for what the various riscv projects are used for, who maintains them, how they are maintained, etc. I use riscv-gnu-toolchain myself, because it is used by the sifive freedom-u-sdk and freedom-e-sdk. I don't know what riscv-tools is for, and haven't used it myself. I'd prefer that everyone just move to the upstream trees which are better documented.

Anyways, you can get updates in riscv-binutils-gdb if you want them. Just cd into the dir, run "git branch" to see that HEAD is in a detached state on the riscv-binutils-2.29 branch. Then "git checkout riscv-binutils-2.29" to checkout the head of the branch, and then a "git pull" to get the latest version of it. Once you've done this, if you run a "git submodule update --init --recursive" in either or the two parent dirs, then you go back to the original state, and you will have to checkout and pull again to get the top of the release tree.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants