链接的目的链接过程

1.  链接的目的

    源代码经过编译后,生成了一系列的目标文件。每一个目标文件,具有自己的代码段、数据段、符号表、重定位表等信息(参考目标文件结构介绍)。

    在代码段中,编译生成的机器代码需要访问数据段的数据,或是代码段的函数。但在单个目标文件中,只有局部的数据和代码信息。如下例:

    文件a.c:

    unsigned long a = 10;

     

    void main()

    {

        print_a();

    }

 

    文件b.c:

    #include <stdio.h>

    extern unsigned long a;

    void print_a()

    {

        printf(“%d”,a);

    }

    编译后,a.c和b.c分别生成了a.o和b.o文件。在a.o中,数据段中为a,代码段中有main;在b.o中,代码段中有print_a函数。

    a.o中,访问了b.o中的print_a函数,而b.o中访问了a.o中的数据a。但问题是每一个.o都只能知道自已的局部数据和函数的地址,因此就需要通过链接过程,对a.o和b.o中的指令(调用print_a函数及访问a数据)进行重点位。这也是静态链接的主要目的所在。

 

    2.  链接的过程

    链接主要分为两个步骤以:

    1)  空间与地址分配

        每个.o文件中都有自己的代码段和数据段,在多个文件合并后,这些指令和数据如何组织?通常是采用相似段合并的方式,将多个.o文件中的代码段合并为一个代码段,数据段合并为一个数据段。

        这样做的好处是可以空间消耗(因为操作系统在分配空间时最小单位是页),并且可以提高内存访问的命中率。

        在进行相似段合并时,链接器会根据.o中每个段的长度、属性和位置等,计算出合并后的长度与位置,然后并每一个.o的中的符号合并到全局符号表,记录每一个符号的新的位置。

 

    2)  符号解析与重定位

        这一步是链接过程中核心,链接器通过重定位表,获取到每一个需要进行重定位的指令的位置以及符号,然后通过符号表查询符号的地址,修改指令中访问的地址。

        如果在这个过程中,无法在符号表中找到需要重定位的符号,就会出现链接失败,也就是我们常见的”undefined reference to ‘xxx’”错误。

 

        在符号表中,除了全局符号外,COMMON类型的符号也需要进行重定位,又称为COMMON块。COMMON块通常用来处理弱符号。

        编译器将未初始化的全局变量定义为弱符号。当多个源代码文件中存在相同的弱符号时,链接器采用如下策略决定弱符号的大小:

        (1)    存在同名的强符号时,以强符号为准

        (2)    不存在同名强符号时,以最大的弱符号为准

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值