The error messages when linking a binary with a missing library and --no-copy-dt-needed-entries (the new default) is confusing: gcc -fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -DDATADIR='"/usr/share/bb/"' -I/usr/include -pthread -D_REENTRANT -D SOUNDDIR=\"/usr/share/bb\" -o bb autopilo.o backconv.o bb.o credits.o credits2.o ctrl87.o fk1.o fk2.o fk3.o fk4.o formulas.o hh1.o hh2.o hh3.o hh4.o image.o julia.o kt1.o kt2.o kt3.o kt4.o main.o messager.o ms1.o ms2.o ms3.o ms4.o print.o scene1.o scene2.o scene3.o scene4.o scene5.o scene7.o scene8.o scene9.o tex.o textform.o timers.o uncompfn.o zeb.o zoom.o -llzo2 -laa -L/usr/lib64 -lmikmod -ldl /usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/bin/ld: credits.o: undefined reference to symbol 'sincos@@GLIBC_2.2.5' /usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/bin/ld: note: 'sincos@@GLIBC_2.2.5' is defined in DSO /lib64/libm.so.6 so try adding it to the linker command line /lib64/libm.so.6: could not read symbols: Invalid operation collect2: ld returned 1 exit status make[1]: *** [bb] Error 1 The last line, /lib64/libm.so.6: could not read symbols: Invalid operation should probably not appear. Just for information, it's elf_link_add_object_symbols doing /* A symbol from a library loaded via DT_NEEDED of some other library is referenced by a regular object. Add a DT_NEEDED entry for it. Issue an error if --no-add-needed is used and the reference was not a weak one. */ if (undef_bfd != NULL && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0) { (*_bfd_error_handler) (_("%B: undefined reference to symbol '%s'"), undef_bfd, name); (*_bfd_error_handler) (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"), abfd, name); bfd_set_error (bfd_error_invalid_operation); goto error_free_vers; and the caller, gld${EMULATION_NAME}_try_needed issueing /* Add this file into the symbol table. */ if (! bfd_link_add_symbols (abfd, &link_info)) einfo ("%F%B: could not read symbols: %E\n", abfd); we could guard the latter with bfd_get_error () != bfd_error_invalid_operation or not set an error and guard it with bfd_get_error () != bfd_error_no_error. Why is the bfd_set_error (bfd_error_invalid_operation) there in the first place?
I'm running into this myself, so I made a minimal test case. set -ex rm -f libf1.so* app CFLAGS="-fno-builtin -Wl,--as-needed,--no-add-needed" echo "#include <math.h>" > f1.c echo "int f1(int x) { return x + 1 + sin(x / 100000.0); }" >> f1.c gcc $CFLAGS -fPIC -shared f1.c -Wl,-soname=libf1.so.1 -lm -o libf1.so.1 ln -s libf1.so.1 libf1.so echo "#include <math.h>" > app.c echo "int main(int argc, char** argv) { return f1(argc) + sin(argc / 100000.0); }" >> app.c gcc $CFLAGS app.c -L. -Wl,-rpath=. -lf1 -o app On Ubuntu 10.04, this reproduces the problem. (On Ubuntu 12.04, it doesn't; somehow app has libm.so.1 in NEEDED anyway.)
Created attachment 6791 [details] Improved error message
Hi Richard, Hi Dan, Please could you try out the uploaded patch and let me know what you think. The error value is set because that is what library functions should do - return an indication of what went wrong to the caller. There is no bfd_error value for missing-DSO-on-the-command-line, so invalid_operation seemed to be the nearest equivalent. Cheers Nick