I have a shared library ./dir/liba.so and a shared library ./libb.so with DT_RPATH "dir" and DT_NEEDED "liba.so". Now, if I compile an executable with -L. -lb, I get: "warning: liba.so, needed by ./libb.so, not found (try using -rpath or -rpath-link)". It works when using an absolute DT_RPATH or when using gold. The resulting binary works with a relative RPATH. Here's a test case: ===> a.c <=== void a() {} ===> b.c <=== extern void a(); void b() {a();} ===> main.c <=== extern void b(); void main() {b();} $ mkdir dir $ gcc -fPIC -shared a.c -o dir/liba.so # Make libb with relative RPATH $ gcc -fPIC -shared -Ldir -Wl,-rpath,dir b.c -la -o libb.so # Fail linking in relative-RPATH libb with ld.bfd $ gcc main.c -L. -Wl,-rpath,. -lb -o main /usr/bin/ld.bfd.real: warning: liba.so, needed by ./libb.so, not found (try using -rpath or -rpath-link) ./libb.so: undefined reference to `a' collect2: error: ld returned 1 exit status # Succeed linking in relative-RPATH libb with gold $ gcc main.c -fuse-ld=gold -L. -Wl,-rpath,. -lb -o main # Run binary with relative-RPATH libb $ ./main # Make libb with absolute RPATH $ gcc -fPIC -shared -Ldir -Wl,-rpath,$(pwd)/dir b.c -la -o libb.so # Succeed linking in absolute-RPATH libb with ld.bfd $ gcc main.c -L. -Wl,-rpath,. -lb -o main # Run binary with absolute-RPATH libb $ ./main # Make libb with relative RPATH $ gcc -fPIC -shared -Ldir -Wl,-rpath,dir b.c -la -o libb.so # Run binary with relative-RPATH libb $ ./main
(In reply to Jethro Beekman from comment #0) > $ gcc main.c -L. -Wl,-rpath,. -lb -o main > /usr/bin/ld.bfd.real: warning: liba.so, needed by ./libb.so, not found (try > using -rpath or -rpath-link) > ./libb.so: undefined reference to `a' > collect2: error: ld returned 1 exit status I asked the reporter to file this bug, but I've just tried it with binutils-2.25-9.fc22.x86_64 and don't see this warning.
I tried this on a variety of OS'es, including various versions of Debian, Ubuntu, RHEL and SunOS and so far I can only reproduce this on Ubuntu 14.04.
are you using gold there ? compare `ld --version | head -1`.
This will be because your linker is configured with a sysroot, and is prepending the sysroot to relative paths. I'm guessing --with-sysroot=/
This indeed seems to be the case. In particular, on Ubuntu 14.04, this patch is not applied: http://apt-browse.org/browse/debian/wheezy/main/all/binutils-source/2.22-8/file/usr/src/binutils/patches/158_ld_system_root.patch . It is applied on all other versions of Debian/Ubuntu I have tested. On all these OS'es, the linker is invoked with --sysroot=/ but it only has any effect on Ubuntu 14.04, and from the strace log I can indeed see that the linker tries to access /dir/liba.so. I don't think the sysroot should be prepended to relative paths. Here's a patch to fix: diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 682f5e5..a70b138 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1282,9 +1282,12 @@ fragment <<EOF rp = bfd_elf_get_runpath_list (link_info.output_bfd, &link_info); for (; !found && rp != NULL; rp = rp->next) { - char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); + char *tmpname = NULL, *name; + if (rp->name[0] == '/') + tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); + name = tmpname ? tmpname : rp->name; found = (rp->by == l->by - && gld${EMULATION_NAME}_search_needed (tmpname, + && gld${EMULATION_NAME}_search_needed (name, &n, force)); free (tmpname);
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3074964fcfff45aef4584b84550eeef84f902fc4 commit 3074964fcfff45aef4584b84550eeef84f902fc4 Author: Alan Modra <amodra@gmail.com> Date: Thu Sep 24 13:13:57 2015 +0930 Relative DT_RPATH/DT_RUNPATH vs. sysroot capable ld. This fixes two problems. First, the --sysroot option wasn't available with a ld configured without --with-sysroot, a historical accident. This led to people configuring binutils with --with-sysroot=/ in order to enable sysroot support, which exposes a case where ld wrongly prepends the sysroot to a relative path. PR ld/18992 * ldmain.c (main): Always enable --sysroot. * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Don't prepend sysroot to relative rpath/runpath.
Fixed a while ago.