我正在尝试了解用于解决重复符号问题的版本脚本。
我创建了一个包含以下内容的main_demo.c文件
#include<stdio.h>
extern void fun1_std(void);
extern void fun1_linux(void);
int main ()
{
fun1_linux(); //defined under libfun1_linux.c
fun1_std(); //defined under libfun2_std.c
return 0;
}
libfun1_std.c的内容
#include<stdio.h>
extern void fun (void);
void fun1_std()
{
fun();
}
libfun1_linux.c的内容
#include<stdio.h>
extern void fun (void);
void fun1_linux()
{
fun();
}
现在,我已经为上述文件(调用fun())分别创建了名为libfun1_std.so和libfun1_linux.so的共享对象。功能&#34; fun()&#34;在两个共享对象下定义,如下所示:
//library name ==> libfun2_linux.so
#include <stdio.h>
void fun()
{
printf("In fun of libfun2_linux\n");
//Similarly libfun2_std.so is printing "In fun of libfun2_std"
}
我的期望是符号&#34;有趣&#34;在libfun1_linux.so中使用的是由libfun2_linux.so解决的,类似的&#34; fun&#34; libfun2_std.so中使用的libfun2_std.so
我们可以看到,如果我们通过将主程序与所有上述共享库链接来创建可执行文件/进程,则进程将在其中获得重复符号的地址空间,即fun()。所以输出看起来像这样:
In fun of libfun2_std
In fun of libfun2_std
要解决此问题,我创建了一个将重命名该符号的版本脚本。 版本脚本的内容:
LIBFUN2_STD_1.0 {
global: *; //i.e, every symbol is global
};
并使用此版本脚本编译libfun2_std.so。 让我们再看一下这个符号: -
$ readelf -a libfun2_std.so | grep fun
13: 0000000000000735 18 FUNC GLOBAL DEFAULT 12 fun@@LIBFUN2_STD_1.0
35: 0000000000000000 0 FILE LOCAL DEFAULT ABS libfun2_std.c
48: 0000000000000735 18 FUNC GLOBAL DEFAULT 12 fun
000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: libfun2_std.so
也是来电者库的内容
nm libfun1_std.so | grep fun
0000000000000705 T fun1_std
U fun@@LIBFUN2_STD_1.0.
所以现在看来我们已经解决了重复的符号。让我们再次创建主要的可执行文件
gcc -Wall -o main_demo main_demo.c -lfun1_std -lfun2_std -lfun1_linux -
lfun2_linux
但在执行期间,我又得到了以下结果:
In fun of libfun2_std
In fun of libfun2_std
让我们看一下libfun2_linux.so的readelf内容
$ readelf -a libfun2_linux.so | grep fun
13: 00000000000006b5 18 FUNC GLOBAL DEFAULT 11 fun
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS libfun2_linux.c
47: 00000000000006b5 18 FUNC GLOBAL DEFAULT 11 fun
问题: -
为什么一个库的版本脚本不够,因为现在符号不同?如果我们创建两个版本脚本(一个用于libfun2_linux.so),它工作正常。
版本脚本的工作原理如何? (阅读一些链接,解释它是由creatig树工作,但没有完全得到它)。请提供一些清楚解释的链接。