Very strange linker behavior

65,269

Solution 1

The explanation to what's happening is very simple:

  1. Your libgplot.a depends on libm.so, yet the order of -lm and -lgplot on the link line is wrong. The order of libraries on the link line does matter. In general, system libraries (-lpthread, -lm, -lrt, -ldl) should follow everything else on the link line.

  2. When you remove -lm from the link line, libm.so.6 is still pulled into the link by some other library that appears later on the link line (libgd, libxml2 or libcurl) because that library depends on libm.so.6. But now libm.so.6 is in correct place on the link line, and so everything works.

if I put -lm at the end of the link command, listing it as the last library, I do not get the error.

That confirms above explanation.

Solution 2

I've solved the same problem with export LDFLAGS="$LDFLAGS -lm"

Solution 3

Perhaps, your library search paths (/usr/local/lib/ or /usr/lib/, ...) do not contain 64bit libm so gcc cannot locate it if you specify with l flag. If you only specify only the directory it looks like it can find the right one. So you can try:

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu

and use -lm

Solution 4

Hard to tell. Because there are custom library directories in the command line it's conceivable that -lm links an incompatible alternative version. Without -lm the linker could pull in another version of it because it's needed by one of the libraries you link.

To make sure strace both invocations and see where libm.so is coming from in both cases.

BTW, -Wl switch seems to do nothing and -L/usr/lib/x86_64-linux-gnu is mentioned twice.

Solution 5

Just to add to the list of answers, http://fedoraproject.org/wiki/UnderstandingDSOLinkChange It is informative. It isn't relevant to the question asked above, but, the explanation relates to the error message /usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line

Share:
65,269

Related videos on Youtube

Don Wool
Author by

Don Wool

Updated on July 09, 2022

Comments

  • Don Wool
    Don Wool almost 2 years

    This is strange because I was able to get the error below to go away by removing the reference to libm.

    gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu   -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/gd1_3ret -lgd -lxml2 -lcurl
    /usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor@@GLIBC_2.2.5'
    /usr/bin/ld: note: 'floor@@GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
    /usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
    collect2: ld returned 1 exit status
    

    So, if I remove the -lm part of the command, I do not get the error. However, I wonder if anyone knows as to why removing a reference to a library that is needed would fix this. How does the linker know which library to look in? Also - is there a way to query a built executable and say 'which library did you resolve the reference to 'floor'? obviously, there is something going on that I don't understand, and that bothers me...

    • Andre Holzner
      Andre Holzner about 11 years
      the -Wl option is normally followed by a comma (to pass the text after the comma as an option to the linker), what do you intend to do with it ?
  • Maxim Egorushkin
    Maxim Egorushkin about 12 years
    Note, that the symbol is versioned. Does it still apply?
  • Andrew Tomazos
    Andrew Tomazos about 12 years
    @MaximYegorushkin: Not sure sorry. I think the version of the undefined symbol is orthogonal to my possible diagnosis.
  • Don Wool
    Don Wool about 12 years
    ok I played around some more, and if I put -lm at the end of the link command, listing it as the last library, I do not get the error. The theory of a non 64bit libm might still be the case, as perhaps it can 'find the right one' before it gets to -lm at the end of the command, so the -lm is essentially ignored. fyi - I queried the libm via 'ar -t' and it listed the contents of the library ok. so that would imply its 64 bit/searchable.
  • Don Wool
    Don Wool about 12 years
    open("/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0pU\0\0\0\0\0\‌​0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=1022320, ...}) = 0
  • Don Wool
    Don Wool about 12 years
    it turned out to be the same for both.. <br>kensey@kensey:~/cdev$ strace ./example 2>&1 | grep libm open("/usr/lib/x86_64-linux-gnu/libmysqlclient.so.18", O_RDONLY|O_CLOEXEC) = 3 open("/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 <br>so, I am not sure why this was a problem, but luckily it went away. I guess the lesson is : make sure libraries come after other libraries that may reference them. there is probably a way with strace to do more investigation, but I am new to that tool. thx for the help!
  • Andre Holzner
    Andre Holzner about 11 years
    in fact, it seems to me this is a change of behaviour with respect to earlier versions of the GNU toolchain. If I remember correctly, was the order of the libraries given irrelevant in the past for gcc and it was smart enough to find the symbols. With xlC on AIX, the order was important if I remember correctly also in the past...
  • Jonathan Wakely
    Jonathan Wakely about 11 years
    The GCC version is irrelevant, you're talking about a linker change not a compiler one.
  • wukong
    wukong almost 11 years
    Thanks for this very detailed explanation
  • Qix - MONICA WAS MISTREATED
    Qix - MONICA WAS MISTREATED over 9 years
    Yep; explicitly adding -lm was the issue. Thank you!
  • lesolorzanov
    lesolorzanov almost 9 years
    Can you explain what this does?
  • dmnc
    dmnc over 8 years
    -lm for linking against the standard C math library
  • Colin Keenan
    Colin Keenan over 7 years
    My problem wasn't exactly the original question, but adding -lm in the makefile at the end of my LDFLAGS definition worked. Thanks.