了解链接器版本脚本

时间:2018-05-14 17:27:56

标签: c linker

我正在尝试了解用于解决重复符号问题的版本脚本。

我创建了一个包含以下内容的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

问题: -

  1. 为什么一个库的版本脚本不够,因为现在符号不同?如果我们创建两个版本脚本(一个用于libfun2_linux.so),它工作正常。

  2. 版本脚本的工作原理如何? (阅读一些链接,解释它是由creatig树工作,但没有完全得到它)。请提供一些清楚解释的链接。

0 个答案:

没有答案