由glibc编译得到的动态库是libc.so, glibc可以通过改变soname来发布新的版本,比如libc.so.6等等, 在实际中, 改变soname通常是大的发布, 如果需要一些小的改动,可以通过Symbol Versioning的方式实现.
Symbol Versioning主要有以下作用:
当然symbol versioning不仅仅可以使用在glibc中,也可以使用到其它c语言的代码中.
这里按照Reference 3中的例子,来说明如何使用symbol versioning:
bash$ cat sv_lib_v1.c
#include
void 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
bash$ cat sv_prog.c
#include
int main(int argc, char *argv[])
{
void xyz(void);
xyz();
exit(EXIT_SUCCESS);
}
bash$ gcc -g -o p1 sv_prog.c libsv.so
$ 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");
}
bash$ cat sv_v2.map
VER_1 {
global: xyz;
local: *; # Hide all other symbols
};
VER_2 {
global: xyz; pqr;
local: *; # Hide all other symbols
};
bash$ gcc -g -c -fPIC -Wall sv_lib_v2.c
bash$ gcc -g -shared -o libsv.so sv_lib_v2.o -Wl,--version-script,sv_v2.map
$ gcc -g -o p2 sv_prog.c libsv.so.1
$ LD_LIBRARY_PATH=. ./p2
v2 xyz
$ LD_LIBRARY_PATH=. ./p1
v1 xyz
$ mv libsv.so libsv.so.bak
$ LD_LIBRARY_PATH=. ./p1
./p1: error while loading shared libraries: libsv.so: cannot open shared object file: No such file or directory
$ ln -sf libsv.so.1 libsv.so
$ LD_LIBRARY_PATH=. ./p1
v1 xyz
$ readelf -W --dyn-syms libsv.so.1 | grep @
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (4)
7: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (4)
8: 0000000000000709 18 FUNC GLOBAL DEFAULT 12 pqr@@VER_2
11: 00000000000006f7 18 FUNC GLOBAL DEFAULT 12 xyz@@VER_2
12: 00000000000006e5 18 FUNC GLOBAL DEFAULT 12 xyz@VER_1