Symbol Versioning for GCC:一種對動態庫符號進行版本控制的技術


關鍵詞:--version-script、Symbol Versioning等等。

gcc提供了Symbol Versioning,通過對Symbol進行版本化,可以達到symbol級別的兼容性檢查。

 

1. 概要介紹

Symbol Versinoning只適用於動態庫,首先對需要Versioning的Symbol通過--version-script指定,進行Versioning。

然后引用者可以指定所需要的Symbol並指定Version。

最后在運行時,動態庫加載時會對Symbol和Version進行匹配,失敗后會報錯並停止加載運行。

2. 相關參考文檔

3. 示例

3.1 創建示例程序

目錄結構如下,主程序main.c,以及庫文件liba和CMakeLists.txt。

├── CMakeLists.txt
├── liba
│   ├── a.c
│   ├── a.h
│   └── a.lds
└── main.c

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)

project(versionsymbol C CXX)

set(A_SRCS "")

include_directories("${PROJECT_SOURCE_DIR}/liba/")

file(GLOB_RECURSE  A_SRCS ${PROJECT_SOURCE_DIR}/liba/*.c)
file(GLOB_RECURSE  A_LDS ${PROJECT_SOURCE_DIR}/liba/a.lds)
message(${A_LDS})
add_library(a SHARED ${A_SRCS})
target_link_libraries(a "-Wl,--version-script=${A_LDS}")


set(MAIN_SRCS "")
file(GLOB_RECURSE  MAIN_SRCS ${PROJECT_SOURCE_DIR}/main.c)
add_executable(main ${MAIN_SRCS})
target_link_libraries(main a)

liba:

a.c:
#include <stdio.h>

int func_versioning()
{
        return 1;
}

a.h:
int func_versioning();

a.lds:
VER_1.0{
    func_versioning;
};

main:

#include <stdio.h>
#include <a.h>

int main(void)
{
  printf("func_versioning()=%d\n", func_versioning());
}

3.2 測試1

首先編譯VER_1.0版本的func_with_version,查看main和lib.so的符號:

File: liba.so

Symbol table '.dynsym' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
...
     8: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS VER_1.0
     9: 0000000000201028     0 NOTYPE  GLOBAL DEFAULT   23 _end
    10: 00000000000006c0    11 FUNC    GLOBAL DEFAULT   12 func_versioning@@VER_1.0
...

Symbol table '.symtab' contains 56 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
...
    46: 00000000000006c0    11 FUNC    GLOBAL DEFAULT   12 func_versioning
...

File: main

Symbol table '.dynsym' contains 21 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
...
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND func_versioning@VER_1.0 (4)
...
     9: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  ABS VER_1.0
...

Symbol table '.symtab' contains 70 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
...
    56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND func_versioning@@VER_1.0
...

即可生成帶版本號的符號。

修改a.lds為:

VER_2.0{
    func_versioning;
};

然后用VER_1.0的main和VER_2.0的liba.so:

./main_1.0: /home/al/versioned_symbol/liba.so: version `VER_1.0' not found (required by ./main_1.0)

用VER_2.0的main和VER_1.0的liba.so:

./main_2.0: /home/al/versioned_symbol/liba.so: version `VER_2.0' not found (required by ./main_2.0)

這是檢查Versioning版本號沒有報錯。

3.3 測試2

增加一個函數:

#include <stdio.h>

int func_versioning()
{
        return 1;
}

int func2_versioning()
{
        return 1;
}

前后兩次修改a.lds后如下:

VER_1.0{
    func_versioning;
    func2_versioning;
};

VER_2.0{
};

再次:

VER_1.0{
    func2_versioning;
};

VER_2.0{
    func_versioning;
};

執行結果如下:

./main_1.0: relocation error: ./main_1.0: symbol func_versioning, version VER_1.0 not defined in file liba.so with link time reference

這是檢查到了Versioning版本號,但是對應符號func_versioning的VER_1.0沒有匹配上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM