This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Behavior change, PLT entries for R_X86_64_PLT32 relocations with undefined symbol


tl;dr: The linker produced PLT entries for undefined symbols with R_X86_64_PLT32 relocations up through Ubuntu 16.04; but produces calls to empty PLT entries in Ubuntu 18.04. Has this usage ever been legal, and if so how can it be made to work now?

(very simplified) reproduction case, x86_64:

----

library.c

int answer() {
    return 42;
}

----

executable.c

#include <dlfcn.h>

int answer();

int main()
{
    void *lib = dlopen("./library.so", RTLD_LAZY | RTLD_GLOBAL);
    if (!lib) {
        printf("dlopen failed");
    }
    printf("The answer is %d\n", answer());
    return 0;
}

----


Compile and link:

gcc -fpic library.c -c -o library.o
gcc -shared -o library.so library.o

gcc -c -fPIC executable.c -o executable.o
gcc executable.o -lc -ldl -Wl,--unresolved-symbols=ignore-all -o executable

---

This produces a functional executable in Ubuntu versions up to and including 16.04 (gcc 5.4.0, ld 2.26.1) but fails in Ubuntu 18.04 (gcc 7.3.0, ld 2.30). Another difference is that Ubuntu 18.04 configures with --enable-default-pie. Full configuration info below for reference.

In the success case, ld produces a PLT entry for the symbol "answer" and the call to answer() goes to that entry. In the failure case, the call to answer() goes to an offset in the PLT, but that offset in the PLT is empty (zeroes).

THE QUESTION: Is it supported usage to expect the linker to produce a PLT entry from a R_X86_64_PLT32 relocation, even if the symbol is undefined? And if so, is the failure I'm seeing a matter of incorrect invocation, or a bug?

Why do I want this to work? The code base I work with has been using this for quite a few years (long before I got involved). There are two shared libraries that each implement the same few hundred functions, but implement them differently (one locally, the other via RPC). By having the executable dlopen() the version it wants to use, it can choose the implementation at runtime rather than at link time.

Thanks for considering this question. Let me know if I've been unclear or omitted any useful information.

Regards,
-Martin




Configuration for Ubuntu 16.04:

Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.11' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --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 --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu

Configuration for Ubuntu 18.04:

Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04' --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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]