Linux下动态链接的步骤与实现详解(2)

可以看到a1.c和a2.c中都定义了名字为a的函数,那么由于b1.c和b2.c都用到了外部函数“a”,但由于源代码中没有指定依赖于哪一个共享对象中的函数“a”,所以我们在编译时指定依赖关系。我们假设b1.so依赖于a1.so,b2.so依赖于a2.so,将b1.so与a1.so进行链接,b2.so与a2.so进行链接:

$gcc -fPIC -shared a1.c -o a1.so $gcc -fPIC -shared a2.c -o a2.so $gcc -fPIC -shared b1.c a1.so -o b1.so $gcc -fPIC -shared b2.c a2.so -o b2.so $ldd b1.so linux-gate.so.1 -> (0xffffe000) a1.so -> not found libc.so.6 -> /lib/tls/i686/cmov/libc.so.6 (0xb7e86000) /lib/ld-linux.so.2 (0x80000000) $ldd b2.so linux-gate.so.1 -> (0xffffe000) a2.so -> not found libc.so.6 -> /lib/tls/i686/cmov/libc.so.6 (0xb7e17000) /lib/ld-linux.so.2 (0x80000000)

Linux下动态链接的步骤与实现详解

那么当有程序同时使用b1.c中的函数b1和b2.c中的函数b2会怎么样呢?比如有程序

main.c

#include <stdio.h> void b1(); void b2(); int main() { b1(); b2(); return 0; }

然后我们将main.c编译成可执行文件并且运行:

$gcc main.c b1.so b2.so -o main -Xlinker -rpath ./ ./main a1.c a1.c

很明显,main依赖于b1.so和b2.so;b1.so依赖于a1.so;b2.so依赖于a2.so,所以当动态链接器对main程序进行动态链接时,b1.so、b2.so、a1.so和a2.so都会被装载到进程的地址空间,并且它们中的符号都会被并入到全局符号表,通过查看进程的地址空间信息可以看到:

Linux下动态链接的步骤与实现详解

这4个共享对象的确都被装载进来了,那a1.so中的函数a和a2.so中的函数a是不是冲突了呢?为什么main的输出结果是两个“al.c”呢?也就是说a2.so中的函数a似乎被忽略了。这种一个共享对象里面的全局符号被另一个共享对象的同名全局符号覆盖的现象又被称为共享对象全局符号介入(Global symbol interpose)

关于全局符号介入这个问题,实际上Linux下的动态链接器是这样处理的:它定义了一个规则,那就是当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略从动态链接器的装载顺序可以看到,它是按照广度优先的顺序进行装载的,首先是main,然后是b1.so、b2.so、a1.so,最后是a2.so。当a2.so中的函数a要被加入全局符号表时,先前装载a1.so时,al.o中的函数a已经存在于全局符号表,那么a2.so中的函数a只能被忽略。所以整个进程中,所有对于符合“a”的引用都会被解析到a1.so中的函数a,这也是为什么main打印出的结果是两个“a1.c”而不是理想中的“alc”和“a2.c”。

由于存在这种重名符号被直接忽略的问题,当程序使用大量共享对象时应该非常小心符号的重名问题,如果两个符号重名又执行不同的功能,那么程序运行时可能会将所有该符号名的引用解析到第-个被加入全局符号表的使用该符号名的符号,从而导致程序莫名其妙的错误。

全局符号介入与地址无关代码

前面介绍地址无关代码时,对于第一类模块内部调用或跳转的处理时,我们简单地将其当作是相对地址调用/跳转。但实际上这个问题比想象中要复杂,结合全局符号介入,关于调用方式的分类的解释会更加清楚。还是拿前面“pic.c”的例子来看,由于可能存在全局符号介入的问题,foo函数对于bar的调用不能够采用第一类模块内部调用的方法,因为一旦bar函数由于全局符号介入被其他模块中的同名函数覆盖,那么foo如果采用相对地址调用的话,那个相对地址部分就需要重定位,这又与共享对象的地址无关性矛盾。所以对于bar()函数的调用,编译器只能采用第三种,即当作模块外部符号处理,bar()函数被覆盖,动态链接器只需要重定位“.got .plt”,不影响共享对象的代码段

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d1529f1940a41c9a7205cdc6c4a42f1c.html