LXR | KVM | PM | Time | Interrupt | Systems Performance | Bootup Optimization

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没有匹配上。

posted on 2020-08-22 00:00  ArnoldLu  阅读(2268)  评论(0编辑  收藏  举报

导航