Linux下动态链接实现原理
作者:网络转载 发布时间:[ 2014/12/16 14:47:17 ] 推荐标签:Linux 操作系统
符号重定位
讲动态链接之前,得先说说符号重定位。
c/c++ 程序的编译是以文件为单位进行的,因此每个 c/cpp 文件也叫作一个编译单元(translation unit), 源文件先是被编译成一个个目标文件, 再由链接器把这些目标文件组合成一个可执行文件或库,链接的过程,其核心工作是解决模块间各种符号(变量,函数)相互引用的问题,对符号的引用本质是对其在内存中具体地址的引用,因此确定符号地址是编译,链接,加载过程中一项不可缺少的工作,这是所谓的符号重定位。
因为编译是以源文件为单位进行的,编译器此时并没有一个全局的视野,因此对一个编译单元内的符号它是无力确定其终地址的,而对于可执行文件来说,在现代操作系统上,程序加载运行的地址是固定或可以预期的,因此在链接时,链接器可以直接计算分配该文件内各种段的或相对地址,所以对于可执行文件来说,符号重定位是在链接时完成的,但对动态链接库来说,因为动态库的加载是在运行时,且加载的地址不固定,因此没法事先确定该模块的起始地址,所以对动态库的符号重定位,只能推迟。
符号重定位既指在当前目标文件内进行重定位,也包括在不同目标文件,甚至不同模块间进行重定位,这里面有什么不同吗?如果是同一个目标文件内,或者在同一个模块内,链接后,各个符号的相对地址已经确定了,看起来似乎不用非得要知道后的地址才能引用这些符号,这说起来好像也有道理,但事实不是这样,x86 上 mov 之类访问程序中数据段的指令,它要求操作数是地址,而对于函数调用,虽然是以相对地址进行调用,但计算相对地址也只限于在当前目标文件内进行,跨目标文件跨模块间的调用,编译期也是做不到的,只能等链接时或加载时才能进行相对地址的计算,因此重定位这个过程是不能缺少的,事实上目前来说,对于动态链接即使是当前目标文件内,如果是全局非静态函数,那么它也是需要进行重定位的,当然这里面有别的原因,比如说使得能实现 LD_PRELOAD 的功能等。
链接时符号重定位
链接时符号重定位指的是在链接阶段对符号进行重定位,一般来说,构建一个可执行文件可以简单分为两个步骤:编译及链接,如下例子,我们尝试使用静态链接的方式构建一个可执行文件:
// file: a.c
int g_share = 1;
int g_func(int a)
{
g_share += a;
return a * 3;
}
// file: main.c
extern int g_share;
extern int g_func(int a);
int main()
{
int a = 42;
a = g_func(a);
return 0;
}
正如前面所说,此时符号的重定位在链接时进行,那么在编译时,编译器是怎么生成代码来引用那些还没有重定位的符号呢?让我们先编译一下,再来看看目标文件的内容:
// x86_64, linux 2.6.9
-bash-3.00$ gcc -c a.c main.c -g
-bash-3.00$ objdump -S a.o
然后得到如下输出(对于 main.o 中对 g_func 的引用,实现是一样的,故略):
a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <g_func>:
int g_share = 1;
int g_func(int a)
{
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,0xfffffffffffffffc(%rbp)
g_share += a;
7: 8b 45 fc mov 0xfffffffffffffffc(%rbp),%eax
a: 01 05 00 00 00 00 add %eax,0(%rip) # 10 <g_func+0x10>
return a * 2;
10: 8b 45 fc mov 0xfffffffffffffffc(%rbp),%eax
13: 01 c0 add %eax,%eax
}
15: c9 leaveq
16: c3 retq
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11