-soname= --version-script 函数接口导出控制和版本控制
从glibc 源码中学习到的,库函数接口的 版本控制。主要使用soname和 version-script 两个知识点
相关源码:
https://github.com/zhiwei122126/zzwlib
目标:假设我们创建一个 名称为 zzw 的库。
1、它的大版本号为 1
2、只导出我们想要导出的接口,其他接口不能导出。
3、第一版为 1.1 ,即libzzw.so.1.1,里面有一个接口add
4、第二版为 1.2, 即大版本号不变,即保持接口向前兼容。新增一个接口 mul。
5、main.elf 作为测试程序,它编译时,使用 libzzw.so.1 名称进行库的链接。
5.1 如果main.elf 中只使用 1.1 版本的接口,那么1.1 和 1.2 版本的so 都支持 main.elf 的运行。
5.2 如果main.elf 中使用 1.2 版本才加入的接口,那么编译时有 1.2 版本的库支持才可以链接通过,否则会包 找不到符号。
5.3 如果 main.elf 编译时使用 1.2 版本的库【也成功了】,后来又因为xx原因,把 zzw 库的版本降低到了 1.1 ; 那么main.elf 运行错误,报找不到对应版本的接口。
1、目录设置
.
├── README.md
├── build.sh
├── main.c
└── zzwlib
├── a.c
├── a.h
└── ver.map
2、1.1 版本
a.c
int add_local(int a, int b) // 不希望 add_local 接口导出 { return a+b; } int add(int a, int b){ return add_local(a,b); }
a.h
extern int add(int a, int b);
ver.map
ZZWLIB_1.1{ global: add; local: *; };
编译
gcc -fPIC -shared zzwlib/a.c -Wl,-soname=libzzw.so.1 -o zzwlib/libzzw.so.1.1 -Wl,--version-script zzwlib/ver.map
main.c
#include#include "zzwlib/a.h" int main(void){ printf("add result is %d \n", add(2,3) ); return 0; }
测试
zhiwei@LAPTOP-CVSMCC72:~/work/c/version$ ./main.elf add result is 5
导出符号和非导出符号
1、a.h 中只导出了 add 符号,不导出 add_local 【但是 objdump 还可以看到 add_local; 并没限制 main.c 里面使用 add_local 】。
2、ver.map 中只把 add 加入到global 中,add_local 不导出 【非导出符号,在 strip 时会被删除掉; objdump 时看到add_local 函数符号为local 类型,main.c 中无法使用】
3、ver.map 中定义了 add 符号的版本为 ZZWLIB_1.1
用 没有 strip 的libzzw.so.1.1测试 - 还可以找到 非导出符号
gdb 调试时,可以直接在符号 add_local 上面下断点 - 3
用 strip 后的libzzw.so.1.1测试 - 没导出的符号被删除
从7 可以看出,strip 后,libzzw.so 里面,add_local 符号已经删除掉了。无法使用了。
3、1.2 版本
a.c - 增加
int mul(int a, int b){ return a*b; }
a.h
extern int add(int a, int b); extern int mul(int a, int b);
ver.map
ZZWLIB_1.1{ global: add; local: *; }; ZZWLIB_1.2{ global: mul; } ZZWLIB_1.1;
编译
gcc -fPIC -shared zzwlib/a.c -Wl,-soname=libzzw.so.1 -o zzwlib/libzzw.so.1.2 -Wl,--version-script zzwlib/ver.map
main.c
#include#include "zzwlib/a.h" int main(void){ printf("add result is %d \n", add(2,3) ); printf("mul result is %d \n", mul(2,3) ); return 0; }
测试
zhiwei@LAPTOP-CVSMCC72:~/work/c/version$ ./main.elf add result is 5
mul result is 6