Search code examples
gcclinkerstatic-librariesdynamic-libraryreadelf

Understanding why gcc/ld are linking a symbol from a particular library using readelf


I'm including several libraries with gcc (-llapacke -llapack -lcblas) and I'm receiving "undefined reference" errors unless I explicitly link to the static version of one them (lapacke). I'm trying to understand why by searching the various variants of the offending library with nm and readelf. Let's take the "undefined" function zsysv_rook_:

% readelf -Wa /usr/lib/liblapacke.so | grep zsysv_rook_

00000000003c3978  000008d600000007 R_X86_64_JUMP_SLOT     000000000016e340 LAPACKE_zsysv_rook_work + 0
00000000003c5f20  000003c300000007 R_X86_64_JUMP_SLOT     0000000000000000 zsysv_rook_ + 0
   963: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND zsysv_rook_
  2262: 000000000016e340   884 FUNC    GLOBAL DEFAULT   11 LAPACKE_zsysv_rook_work

That's the dynamic variant. This is the static variant:

% readelf -Wa /usr/lib/liblapacke.a | grep zsysv_rook_
00000000000000b2  0000000d00000004 R_X86_64_PLT32         0000000000000000 LAPACKE_zsysv_rook_work - 4
0000000000000146  0000000d00000004 R_X86_64_PLT32         0000000000000000 LAPACKE_zsysv_rook_work - 4
    13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND LAPACKE_zsysv_rook_work
File: /usr/lib/liblapacke.a(lapacke_zsysv_rook_work.o)
0000000000000186  0000000f00000004 R_X86_64_PLT32         0000000000000000 zsysv_rook_ - 4
0000000000000264  0000000f00000004 R_X86_64_PLT32         0000000000000000 zsysv_rook_ - 4
     9: 0000000000000000   884 FUNC    GLOBAL DEFAULT    1 LAPACKE_zsysv_rook_work
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND zsysv_rook_

Why does it compile only with the static version?


Solution

  • The symbol zsysv_rook_ is not defined by either library, so something in the library references it.

    A static library is basically an archive of object files and the linker looks into the archive and links to each object that resolves an undefined reference in your program. If there are objects that define symbols that your program doesn't need, those objects will not be linked to. I assume what is happening is that the object that references zsysv_rook_ doesn't define any symbols you need, so that object isn't linked to, and your program doesn't need to resolve the zsysv_rook_ symbol.

    When you link to a dynamic library (by default) you need to resolve all the undefined references needed by anything in the library, so because some part of the library refers to zsysv_rook_ you need to link to whatever provides it.

    So if you want to use the dynamic library you need to figure out which library defines zsysv_rook_ and link to it. It's probably one of the other LAPACK libs, maybe one you're already linking to but you might be putting the -l option in the wrong place in the link command - the library that provides zsysv_rook_ needs to come after -llapacke in order to resolve the reference to it.