静态链接·重定位
静态链接过程会将汇编器生成的可重定位文件(*.o)合并到一个可执行文件中。当链接器完成符号解析后,就会执行重定位过程。重定位过程分为两步:
- 重定位节及符号定义。相同类型的节会被聚合到可执行文件的同一类型的节中,如下图的步骤一。符号解析过程已经确定了符号被定义的模块及节位置,所以重定位节后,每个符号的运行时地址也已经确定了。
- 重定位节中的符号引用。如下图的步骤二,在编译main.o时,引用的符号func是由其它模块定义的,编译器无法确定该符号的运时地址,此时编译器所做的是为每个引用的位置记录一个重定位条目信息。链接器根据此信息进行符号引用重定位。
程序代码
main.c
#include <stdio.h>
const static char *s_str = "a static string";
extern int g_num;
int func();
static int func_st()
{
return --g_num;
}
int main()
{
int ret = func();
int ret2 = func_st();
printf("str: %s, ret: %d, ret2: %d\n", s_str, ret, ret2);
return 0;
}
func.c
static int s_num = 200;
int g_num = 200;
int func()
{
s_num++;
return s_num;
}
链接示意
main.o中引用了三个外部符号,其中g_num、func由func.o定义,使用静态的链接方式。printf是标准库定义的函数,如果其它模块都没定义,链接器会默认从标准库libc.so中查找。可以使用-static选项表明要生成一个完全的可执行文件,这样链接器会选择从libc.a库静态链接相应模块到可执行文件里。