Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange linking behaviour and undefined symbols

Tags:

c

linux

icc

nm

I am linking an external library (via wierd process, mpicc + Cython + etc), but I have a weird behaviour of a linking procedure.

There are two .o files, libpetsc4py.o and PETSc.o they are linked into a .so file PETSc.so

One contains an undefined symbol __pyx_tp_new_8petsc4py_5PETSc_Object

[zheltkov@compiler-2 src]$ nm libpetsc4py.o | grep __pyx_tp_new_8petsc4py_5PETSc_Object
                       U __pyx_tp_new_8petsc4py_5PETSc_Object

It is defined in another .o file:

[zheltkov@compiler-2 src]$ nm PETSc.o | grep __pyx_tp_new_8petsc4py_5PETSc_Object
00000000001b92f0 t __pyx_tp_new_8petsc4py_5PETSc_Object

Then, then linking is done (the compile line is weird, sorry)

mpicc -pthread -fPIC -wd1572 -g -shared -fno-strict-aliasing -g -O2 -DNDEBUG -O2 -g
build/temp.linux-x86_64-2.7/arch-linux2-c-debug/src/PETSc.o build/temp.linux-x86_64-
2.7/arch-    linux2-c-debug/src/libpetsc4py.o -L/home/users/zheltkov/tmp/petsc-3.3/arch
-linux2-c-debug/lib -L/home/users/zheltkov/ivan/soft/epd7.2/lib 
-Wl,rpath,/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib 
-Wl,-rpath,/home/users/zheltkov/ivan/soft/epd7.2/lib -lpetsc -lpython2.7 -o
build/lib.linux-x86_64-2.7/petsc4py/lib/a    rch-linux2-c-debug/PETSc.so -lX11 -Wl,
-rpath,/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib 
-L/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib -lfftw3_mpi -lfftw3 -lHYPRE 
-Wl,-rpath,/opt/intel/impi/4.1.0.030/intel64/lib 
-L/opt/intel/impi/4.1.0.030/intel64/lib -Wl,
-rpath,/opt/intel/composer_xe_2013.2.146/mkl/lib/intel64 
-L/opt/intel/composer_xe_2013.2.146/mkl/lib/intel64 
-Wl,-rpath,/opt/intel/composer_xe_2013.2.146/compiler/lib/intel64 
-L/opt/intel/composer_xe_2013.2.146/compiler/lib/intel64 -Wl,
-rpath,/usr/lib/gcc/x86_64-redhat-linux/4.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6 
-Wl,- rpath,/mnt/data/users/dm4/vol9/zheltkov/tmp/petsc-3.3/-Xlinker -lmpigc4 
-Wl,-rpath,/opt/intel/mpi-rt/4.1 -lml -lpthread -Wl,-rpath,
/opt/intel/composer_xe_2013/mkl/lib/intel64 
-L/opt/intel/composer_xe_2013/mkl/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread
-lmkl_core -liomp5 -lifport -lifcore -lm -ldl -lmpigf -lmpi_dbg -lmpigi -lrt 
-limf -lsvml -lirng -lipgo -ldecimal -lcilkrts -lstdc++     -lgcc_s -lirc -lirc_s

But finally, the resulting files has two symbols with the same name, one of them is undefined and everything does not work:

[zheltkov@compiler-2 arch-linux2-c-debug]$ nm PETSc.so | grep __pyx_tp_new_8petsc4py_5PETSc_Object
0000000000200d20 t __pyx_tp_new_8petsc4py_5PETSc_Object
                 U __pyx_tp_new_8petsc4py_5PETSc_Object

What am I doing wrong? Why there are two symbols with the same name?

like image 749
Ivan Oseledets Avatar asked Mar 29 '13 14:03

Ivan Oseledets


1 Answers

In an object file t indicates that the function has internal linkage (i.e. is declared as static), while in another file, U indicates the function is referenced, but not defined. An external function is indicated with T.

When you link to create a shared library, the linker doesn't complain about unresolved references, so it includes the static function (available only in the file that defined it), and an external symbol marked as undefined.

Here's a simpler example. Two files:

foo.c

#include <stdio.h>

static void hello(void)
{
    printf("Hello\n");
}

bar.c

void sayhello(void)
{
    hello();
}

Compile the two:

$ gcc -c -fPIC foo.c
$ gcc -c -fPIC bar.c
$ nm foo.o
0000000000000000 t hello
$ nm bar.o
                 U hello
0000000000000000 T sayhello

Now create a shared library

$ gcc -shared -o libhello.so foo.o bar.o
$ nm libhello.so
0000000000000700 t hello
                 U hello

The result of this is that if I define a function hello and link against this library to create an executable, the library will call my function in sayhello - not the static one. If I don't define it, the linker will give an undefined symbol error.

like image 172
teppic Avatar answered Oct 22 '22 16:10

teppic