~steve/ex/dynamiclib
We’re going to build a dynamic library libgreeting and an application to link to it (and also do some bug fixes).
libgreeting
Start by reading the library source which consists of just a single .c file in libgreeting and a header file in libgreeting/include/greeting. (We’ll fix the typo later.)
.c
libgreeting/include/greeting
hello.c
$ clang -Wall -std=c11 -fPIC -Iinclude -c -o hello.o hello.c
$ clang -fPIC -shared -Wl,-soname=libgreeting.so.1 -o libgreeting.so.1.0.0 hello.o
libgreeting.so.1.0.0
$ file libgreeting.so.1.0.0
$ nm libgreeting.so.1.0.0 | grep hello
hello()
Next, we’re going to “install” the library and its header files for our program to use.
Copy libgreeting/libgreeting.so.1.0.0 into the lib directory.
libgreeting/libgreeting.so.1.0.0
lib
Copy libgreeting/include/greeting into the include directory.
include
Inside lib, we need to make two symlinks.
$ ln -s libgreeting.so.1.0.0 libgreeting.so $ ln -s libgreeting.so.1.0.0 libgreeting.so.1
Our library is installed, so it’s time to build our application which is in the src directory.
src
The first step is to compile the source files to object files (this could be omitted, especially since it’s just a single file for the program, but we’re going to do it here).
We need to tell clang where to find the header files.
clang
$ clang -Wall -std=c11 -I../include -c -o main.o main.c
libgreeting.so
$ clang -L../lib -o prog main.o -lgreeting
$./prog
$ LD_LIBRARY_PATH=../lib ./prog
LD_LIBRARY_PATH
$ clang -L../lib -Wl,-rpath='$ORIGIN/../lib' -o prog main.o -lgreeting
../lib
bin
Build a new version of the library. Make sure you rebuild the object file!
Since this version is compatible with the existing version, use the same soname of libgreeting.so.1 but change the output file to libgreeting.so.1.0.1.
libgreeting.so.1
libgreeting.so.1.0.1
Run the program which should still be in bin: $ bin/prog.
$ bin/prog
If all has gone well, then without needing any changes to the binary, it should be using the new version of the dynamic library.
strace
$ strace -o syscalls -f -e openat clang -L../lib -Wl,-rpath='$ORIGIN/../lib' -o prog main.o -lgreeting
This will write the trace to the syscalls file, trace the children of clang (because clang will be invoking the linker), and only trace the openat system call.
syscalls
openat
Open syscalls up in an editor and search for greeting. Which file did it open?
greeting
prog
$ strace -e openat ./prog
Which of the libgreeting.so files did it open? How did it know to open that one when the one opened by the linker in the previous step was different?