-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 <stdio.h> #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-ozzwlib/libzzw.so.1.2-Wl,--version-script zzwlib/ver.map
main.c
#include <stdio.h> #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