关于GCC动态库版本控制。

本文介绍了如何在Linux环境下使用GCC编译器和ld链接器通过版本脚本控制共享库的符号版本。通过实例展示了如何指定全局和局部符号,并演示了在链接阶段如何确保正确的符号版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Linux下链接一个共享库:
使用ld:使用“--version-script”参数;
使用gcc:使用“-Xlinker”参数加“--version-script”;
符号版本脚本文件为“lib.ver”,编译源代码“lib.c”:
gcc -shared -fPIC lib.c -Xlinker --version-script lib.ver -o lib.so
lib.ver内容如下:
VERS_1.2 {
 global:
  test0;
 local:
  *;
};
将main.c编译并且连接到当前版本的lib.so:

gcc main.c ./lib.so -o main

objdump -T lib.so 

DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND*  00000000              __gmon_start__
00000000  w   D  *UND*  00000000              _Jv_RegisterClasses
00000000      DF *UND*  00000000  GLIBC_2.0   printf
00000000  w   DF *UND*  00000000  GLIBC_2.1.3 __cxa_finalize
00000000 g    DO *ABS*  00000000  S_1.2       S_1.2
000003cc g    DF .text  00000026  S_1.2       test0

objdump -T main

DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND*  00000000              __gmon_start__
00000000  w   D  *UND*  00000000              _Jv_RegisterClasses
00000000      DF *UND*  00000000  GLIBC_2.0   __libc_start_main
00000000      DF *UND*  00000000  S_1.2       test0
00000000      DF *UND*  00000000  GLIBC_2.0   puts
0804850c g    DO .rodata        00000004  Base        _IO_stdin_used

如果你不加-Xlinker 

gcc -shared -fPIC lib.c  -o lib.so

objdump -T lib.so

DYNAMIC SYMBOL TABLE:
DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND*  00000000              __gmon_start__
00000000  w   D  *UND*  00000000              _Jv_RegisterClasses
00000000      DF *UND*  00000000  GLIBC_2.0   printf
00000000  w   DF *UND*  00000000  GLIBC_2.1.3 __cxa_finalize
000015c4 g    D  *ABS*  00000000  Base        _end
000015bc g    D  *ABS*  00000000  Base        _edata
000015bc g    D  *ABS*  00000000  Base        __bss_start
000002e4 g    DF .init  00000000  Base        _init
0000041c g    DF .text  00000026  Base        test0
00000488 g    DF .fini  00000000  Base        _fini

objdump -T main

DYNAMIC SYMBOL TABLE:
00000000  w   D  *UND*  00000000              __gmon_start__
00000000  w   D  *UND*  00000000              _Jv_RegisterClasses
00000000      DF *UND*  00000000              test0
00000000      DF *UND*  00000000  GLIBC_2.0   __libc_start_main
00000000      DF *UND*  00000000  GLIBC_2.0   puts
080496bc g    D  *ABS*  00000000  Base        _end
080496b4 g    D  *ABS*  00000000  Base        _edata
0804858c g    DO .rodata        00000004  Base        _IO_stdin_used
080496b4 g    D  *ABS*  00000000  Base        __bss_start
0804837c g    DF .init  00000000  Base        _init
0804856c g    DF .fini  00000000  Base        _fini

很明显你可以看到test0的那个版本号就没有了。所以说是GCC通过xlink --version-script 把版本号已经传给了库,库再传给main elf。(main elf 里面说这个test0你到libtest0.so去找,而且版本应该为S 1.2)

在运行加载的时候会对elf和搜索到库版本的符号进行比较。如果不对的话就会报错。

./main: /lib/libtest0.so: version `S_1.2' not found (required by ./main)



相关链接:

http://blog.sina.com.cn/s/blog_76fbd24d010142ob.html

http://www.360doc.com/content/12/0107/21/8093902_177973304.shtml









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值