深入理解计算机系统:链接(第二章:符号解析、重定位和可执行目标文件)

本文详细探讨了计算机系统中链接器在符号解析和重定位过程中的工作原理。首先,解释了全局符号解析,特别是如何处理多重定义的全局符号,以及静态库的链接方式。接着,介绍了重定位的两个阶段,包括节和符号定义的重定位以及节中符号引用的重定位。最后,概述了可执行目标文件的结构和加载到内存的过程。通过理解这些概念,读者可以更好地了解程序从源代码到运行状态的转换过程。
摘要由CSDN通过智能技术生成

1、符号解析

链接器解析符号引用的方法是将每个引用与它输入的可重定位目标文件的符号表中的一个确定的符号定义关联起来,即使用的符号一定要找到相应的定义。可分为局部符号解析和全局符号解析。

局部符号解析:引用定义在相同模块中的局部符号的引用,符号解析非常的简单明了,就不用介绍了。
全局符号解析:当编译器遇到一个不是当前模块中定义的符号时,会假设该符号时在其他某个模块中定义的,生成一个连接器符号表条目,并把它交给链接器处理。如果链接器在它的任何输入模块中都找不到这个符号的定义,就输出一条错误信息并终止。

全局符号解析还因为多个目标文件可能会定义相同的名字的全局符号。在这种情况下,链接器必须要么标志一个错误,要么以某种方法选出一个定义并抛弃其它定义。

1.1、解析多重定义的全局符号

链接器的输入是一组可重定位目标模块。每个模块定义一组符号,有些是局部的(只对定义该符号的模块可见),有些是全局的(对其它模块也可见)。如果多个模块定义同名的全局符号,连接器会进行筛选。

在编译时,编译器向汇编输出每个全局符号,或者是强或者是弱,而汇编器把这个信息隐含地编码在可重定位目标文件的符号表中。函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号

根据强弱符号的定义,Linux链接器使用下面的规则来处理多重定义的符号名:

  1. 不允许有多个同名的强符号
  2. 如果有一个强符号和多个弱符号同名,那么选择强符号
  3. 如果有多个弱符号同名,那么从这些弱符号中任意选择一个

规则2和规则3的应用会造成一些不易察觉的运行时错误,对于不警觉的程序员来说,是很难理解的,尤其是如果重复的符号定义还有不同的类型时。如下,x在一个模块中为int,而在另一个模块中为double:

foo.c 文件中

void f(void);

int y = 15212;
int x = 15213;

int main()
{
	f();
	printf("x=0x%x y = 0x%x \n", x,y);
	return 0;
}

bar.c 文件中

double x;

void f()
{
	x = -0.0;
}

在64位系统上,double类型是8个字节&#x

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值