Understanding how dynamic linking works on UNIX Understanding how dynamic linking works on UNIX linux linux

Understanding how dynamic linking works on UNIX


The problem arises when you have not linked libfoo.so against libbar. When you are compiling an executable, by default the linker will not let you leave undefined references. However, when you're compiling a shared library, it will - and it will expect them to be satisfied at link time. This is so that libfoo can use functions exported by program itself - when you try to run it, the dynamic linker is expecting func_bar() to be supplied by program. The problem is illustrated like so:

(foo.c is selfcontained)

export LD_RUN_PATH=`pwd`gcc -Wall -shared foo.c -o libfoo.sogcc -Wall -L. p.c -lfoo -o p

At this point, ./p runs correctly, as you would expect. We then create libbar.so and modify foo.c to use it:

gcc -Wall -shared bar.c -o libbar.sogcc -Wall -shared foo.c -o libfoo.so

At this point, ./p gives the error you describe. If we check ldd libfoo.so, we notice that it does not have a dependency on libbar.so - this is the error. To correct the error, we must link libfoo.so correctly:

gcc -Wall -L. -lbar -shared foo.c -o libfoo.so

At this point, ./p again runs correctly, and ldd libfoo.so shows a dependency on libbar.so.


On Fedora dynamic linking is performed by ld-linux.so.2.The dynamic linker use /etc/ld.so.cache and /etc/ld.so.preload to find library files.

Run ldconfig to tell the system where libfoo should look for libbar.

ldconfig looks in /lib, /usr/lib and any directory listed in /etc/ld.so.conf.You can check which libraries a program uses with ldd.

More details are available on the manual pages for each command.

Here is an example of an application using shared libraries.
Program.cc

#include "foo.h"#include <iostream>int main(int argc, char *argv[]){    for (int i = 0; i < argc; ++i) {        std::cout << func_foo(argv[i]) << std::endl;    }}

foo.h

#ifndef FOO_H#define FOO_H#include <string>std::string func_foo(std::string const &);#endif

foo.cc

#include "foo.h"std::string func_foo(std::string const &arg){    return arg + "|" + __func__;}

bar.h

#ifndef BAR_H#define BAR_H#include <string>std::string func_bar();#endif

bar.cc

#include "bar.h"std::string func_bar(){    return __func__;}

Build with libfoo.so as a shared library.
g++ -Wall -Wextra -fPIC -shared foo.cc -o libfoo.so
g++ -lfoo -L./ -Wall -Wextra program.cc foo.h -o program
ldd program
...
libfoo.so => not found

Update /etc/ld.so.cache
sudo ldconfig /home/tobias/projects/stubs/so/

ldd shows that the dynamic linker finds libfoo.so
ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so (0x00007f0bb9f15000)

Add a call to libbar.so in libfoo.so
New foo.cc

#include "foo.h"#include "bar.h"std::string func_foo(std::string const &arg){    return arg + "|" + __func__ + "|" + func_bar();}

Build libbar.so and rebuild libfoo.so
g++ -Wall -Wextra -fPIC -shared bar.cc -o libbar.so
g++ -Wall -Wextra -fPIC -shared libbar.so foo.cc -o libfoo.so
ldd libfoo.so
...
libbar.so => not found

ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so (0x00007f49236c7000)
libbar.so => not found
This shows that the dynamic linker still finds libfoo.so but not libbar.so
Again update /etc/ld.so.cache and recheck.
sudo ldconfig /home/tobias/projects/stubs/so/
ldd libfoo.so
...
libbar.so => /home/tobias/projects/stubs/so/libbar.so (0x00007f935e0bd000)

ldd program
...
libfoo.so => /home/tobias/projects/stubs/so/libfoo.so (0x00007f2be4f11000)
libbar.so => /home/tobias/projects/stubs/so/libbar.so (0x00007f2be4d0e000)

Both libfoo.so and libbar.so are found.

Note this last step have no effect on the application program.If you are really strict running ldconfig is kind of relinking.Weird or not the linker need to know the dependencies of the libraries it links.There are a lot of other ways to implement this but this was chosen.


You did not give any system information, are you using glibc? If yes what is the output of this command:

LD_DEBUG=files program

Also check "How to write shared (ELF) libraries"(pdf) (whether you are using glibc or not)