We demonstrate the use of symbol versioning via an example...
First we create a library that contains a single definition of a function, and build that library with a version script:
bash$ cat sv_lib_v1.c #includevoid xyz(void) { printf("v1 xyz\n"); } bash$ cat sv_v1.map VER_1 { global: xyz; local: *; # Hide all other symbols }; bash$ gcc -g -c -fPIC -Wall sv_lib_v1.c bash$ gcc -g -shared -o libsv.so sv_lib_v1.o \ -Wl,--version-script,sv_v1.map
The symbols listed under VER_1 are associated with that tag.
We then build a program that uses "version 1" of our function:
bash$ cat sv_prog.c #include <stdlib.h> int main(int argc, char *argv[]) { void xyz(void); xyz(); exit(EXIT_SUCCESS); } bash$ gcc -g -o p1 sv_prog.c libsv.so
Running the program produces the expected result:
bash$ LD_LIBRARY_PATH=. ./p1 v1 xyz
Suppose we want to modify the definition of our function xyz(), but still want to ensure that p1 continues to use the old definition.
We create a modified version of the shared library source file:
bash$ cat sv_lib_v2.c #include__asm__(".symver xyz_old,xyz@VER_1"); __asm__(".symver xyz_new,xyz@@VER_2"); void xyz_old(void) { printf("v1 xyz\n"); } void xyz_new(void) { printf("v2 xyz\n"); } void pqr(void) { printf("v2 pqr()\n"); }
Exactly one definition must be marked with @@.
bash$ cat sv_v2.map VER_1 { global: xyz; local: *; # Hide all other symbols }; VER_2 { global: xyz; pqr; local: *; # Hide all other symbols };
(C) 2006, Michael Kerrisk