Gold and ld behave differently when a shared library is first mentioned when -as-needed is in effect, and then again after -no-as-needed. Ld generates a DT_NEEDED entry for such library, and gold does not. $ cat 1.c int main() { return 0; } # BFD linker $ g++ 1.c -Wl,-as-needed -lutil -Wl,-no-as-needed -lutil -fuse-ld=bfd && readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libutil.so.1] 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6] 0x0000000000000001 (NEEDED) Shared library: [libm.so.6] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] # Gold linker $ g++ 1.c -Wl,-as-needed -lutil -Wl,-no-as-needed -lutil -fuse-ld=gold && readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6] 0x0000000000000001 (NEEDED) Shared library: [libm.so.6] 0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
> Gold and ld behave differently when a shared library is first mentioned when > -as-needed is in effect, and then again after -no-as-needed. Ld generates a > DT_NEEDED entry for such library, and gold does not. Why are you expecting a NEEDED entry for libutil? There's nothing in your main program that depends on anything in that library, so by the definition of the --as-needed option, gold is doing exactly what I would expect. Your command line lists "-lutil" twice, once between the as-needed options, and once after. Gold ignores any shared library listed on the command line that it has already processed. If you want the library in your DT_NEEDED list, remove the first copy from your command line (the one between --as-needed and --no-as-needed).
There is some context here: https://llvm.org/bugs/show_bug.cgi?id=15823 In the clang driver, we add a static library that implements wrappers for libutil functions, i.e. it exports functions with the same names and calls the real libutil functions with dlsym(RTLD_NEXT). To ensure that the executable still depends on libutil, we add -no-as-needed -lutil to the end of the link line - otherwise the linker thinks that all libutil dependencies are already satisfied by the wrapper library. The first "-as-needed -lutil" comes from the clang command line.
OK, I have a patch in the works to have gold mark the shared object as --no-as-needed if it appears anywhere on the command line when --no-as-needed is in effect. As an aside, though, have you considered using --wrap for your wrapper functions? Your use case is exactly what that option was designed for.
Thank you! --wrap does not work for prebuilt shared libraries, and we need to intercept at least some functions in those, too (ex. malloc).
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4bfacfd359a1f8d026d1a350f56f2f5d70b6cb65 commit 4bfacfd359a1f8d026d1a350f56f2f5d70b6cb65 Author: Cary Coutant <ccoutant@gmail.com> Date: Fri Aug 21 12:32:33 2015 -0700 Fix --no-as-needed when shared library is listed twice on the command line. When a shared library is listed twice on the command line, the linker ignores the second mention. If the first mention is in the scope of an --as-needed option, and the second one is under the scope of a --no-as-needed option, the --no-as-needed should take effect, but doesn't. This patch keeps track of the objects we've already seen, and updates the --as-needed flag so that if a shared object is ever seen with --no-as-needed, it will be marked as such. gold/ PR gold/18859 * object.cc (Input_objects::add_object): Store objects in a map, indexed by soname; update as-needed flag when necessary. * object.h (Object::clear_as_needed): New method. (Input_objects::so_names_): Change from set to map.
Fixed on master.