链接器在合并各个目标文件中的段时需要将标识符的最终地址给确定了。这就是重定位的过程(确定各个段的最终起始地址以及各个标识符的地址)。
示例:
扫描二维码关注公众号,回复:
3661781 查看本文章
test.c如下:
func.c如下:
编译func.c,并查看符号信息:
可以看到func这个标识符相对于代码段的偏移位置为0。
g_pointer前面有一个C标志,意思是暂时还不知道该将g_pointer这个标识符放在哪一个段。能知道的就是这个标识符的大小为4个字节,就是前面显示的00000004。
标识符的具体地址是没有确定的,因此目标文件不能执行。
编译test.o:
上图中的func意味着在test.c文件中用到了func这个标识符,但是不是在test.c中定义的。这个标识符具体位于哪里是不清楚的。
g_pointer和printf是同样的道理。
这三个表示符都不是在test.c中定义的。
上图中还可以看出,g_global位于bss段(由前面的B指示),相对于bss段的起始地址为0.
g_test位于data段(由前面的D标识),相对于data段的偏移为0.
main位于text段,具体地址不确定。
开始进行链接:
nm查看符号:
链接之后这些符号都有了地址。
链接器对这些符号进行了重定位(指的是给段中的各个标识符一个最终的地址)。