1. 程式人生 > 其它 >-soname= --version-script 函式介面匯出控制和版本控制

-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

4、版本交錯測試

1.1 的 main.c 使用 1.2 的 libzzw,ok

1.2 的main.c 使用 1.2 的libzzw, OK

1.1 的main.c 使用 1.1 的libzzw OK

1.2 的main.c 使用 1.1 的libzzw,編譯錯誤

1.2 的main.c 【編譯使用1.2,編譯完成後,手動修改連結到1.1】 執行錯誤