链接:

链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可以被加载(复制)到内存并执行。链接可以执行于编译时,也就是在源代码被翻译成机器代码时;也可以执行于加载时,也就是在程序被加载器加载到内存并执行;甚至执行于运行时,也就是应用程序来执行。

首先:我们要了解目标文件

目标文件有三种形式:

  • 可重定位目标文件(二进制代码和数据)
  • 可执行目标文件(二进制代码和数据)
  • 共享目标文件

我们再来了解可重定位目标文件:

我们以典型的ELF可重定位目标文件举例,下面是ELF文件的格式:

ELF头
.text
.rodata
.data
.bss
.symtab
.ral.text
.rel.data
.debug
.line
.strtab
节头部表

其中:

  • ELF头

包括16字节的标识信息、文件类型(.o,exec,.so)、机器类型(如Intel 80386)、节头表的偏移、节头表的表项大小及表项个数。

  • .text节

编译后的代码部分。

  • .rodata节

只读数据,如 printf用到的格式串、switch跳转表等。

  • .data节

已初始化的全局变量和静态变量。

  • .bss节

未初始化全局变量和静态变量,仅是占位符,不占据任何磁盘空间。区分初始化和非初始化是为了空间效率。

  • .symtab节

存放函数和全局变量(符号表)的信息,它不包括局部变量。

  • .rel.text节

.text节的重定位信息,用于重新修改代码段的指令中的地址信息。

  • .rel.data节

.data节的重定位信息,用于对被模块使用或定义的全局变量进行重定位的信息。

  • .debug节

调试用的符号表(gcc -g)

  • .strtab节

包含 .symtab节和 .debug节中的符号及节名

  • 节头表(Section header table)

包含每个节的节名在.strtab节中的偏移、节的偏移和节的大小.

接下来我们看下符号和符号表:

计算机内部工作之——链接

符号就是其实程序中的变量名、函数名。

注意:局部变量temp分配在栈中,不会在函数外部被引用,因此不是符号定义。

符号定义的本质是:指被分配了存储空间。如果是函数名则指代码所在区;如果是变量名则指其所在的静态数据区。

所有定义的符号的值就是其目标所在的首地址。

因此,符号的解析就是将符号引用和符号定义建立关联后,将引用符号的地址重定位为相关联的符号定义的地址。

全局符号的强、弱

全局符号有强、弱的特性。

  • 强符号:函数名和已初始化的全局变量名是强符号。
  • 弱符号:未初始化的全局变量名是弱符号。

计算机内部工作之——链接

链接器对符号的解析规则
符号解析时,只能有一个确定的定义(即每个符号仅占一处存储空间)。
所以,如果碰到符号存在多重定义时,就得有相应的处理规则:

  • Rule 1:强符号不能多次定义

强符号只能被定义一次,否则链接错误。

  • Rule 2:若一个符号被定义为一次强符号和多次弱符号,则按强符号定义为准。
  • Rule 3:若有多个弱符号定义,则任选其中一个。

 

 

 

 

 

 

 

相关文章:

  • 2021-11-19
  • 2021-10-22
  • 2021-05-30
  • 2022-01-21
  • 2022-01-20
  • 2021-10-04
  • 2021-07-10
猜你喜欢
  • 2022-01-10
  • 2022-03-07
  • 2022-12-23
  • 2021-07-31
  • 2021-05-29
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案