链接原理

链接原理 (2012-04-20 00:28)


1.链接器的任务

链接器将多个目标文件(可重定位目标文件)链接成一个完整的,可加载的,可执行的目标文件。
主要任务:
(1)符号解析:将目标文件内的引用符号和该符号的定义联系起来
(2)将符号定义与存储器的位置联系起来,修改对这些符号的引用
2.目标文件
(1)可重定位目标文件:这种文件包含二进制代码和数据,代码和数据已经转换成机器指令代码和数据。但是这种目标文件还不能被执行,因为这些指令和数据往往引用其他模块(目标文件)中的符号。其他模块的符号对于本模块是未知的。这些符号的解析需要链接器将所有的模块进行链接。这个操作叫做---重定位。
 
(2)可执行目标文件:这种文件也包含二进制代码和数据,但是已经被链接过,可以执行。
(3)共享目标文件:在需要他的程序运行或加载时,动态地加载到内存中运行。这种文件的后缀.so。共享目标文件又叫“共享库”或“动态库”文件。

3.elf格式的可重定位目标文件
ELF(Executable linkable file)是linux环境下常用的目标文件格式。大多数情况下,可重定位+可执行的目标文件都采用这种格式。
 ——————
 |  段头部表 |
|  ------------
|  | .strtab   |
|  ------------
|  | .line     |
|  ------------
|  | .debug    |
|  ------------
|  | .rel.data |
|  ------------
|  | .rel.text |
|  ------------
|  | .symtab   |
|        ------------
|  | .bss      |
|  ------------
|  | .data     |
|  ------------
|  | .rodata   |
|  ------------
|  | .text     |
|  ------------
|  | ELF 头    |
|  -------------

(1)ELF文件头的前16字节构成一个字节序,描述了生成该文件系统的字长和字节序。还有一些其他信息,包括ELF文件头的大小,目标文件的类型,目标机类型。
(2).text:代码段,存储二进制的机器代码。
(3).rodata:只读数据段
(4).data:数据段,如初始化的全局数据,包括全局变量和静态变量,都是初始化过的。
(5).bss:块存储段,存储未初始化的全局数据。在目标文件上,该段不占空间,仅仅是一个占位符(?),告知指定位置上应当预留全局数据的空间。
(6).symtab:符号表。存储定义和引用的函数和全局变量,链接过程中的重定位操作就是根据这个表来确定全局符号的位置
(7).rel.text:代码段需要重定位的信息。是一些需要靠重定位操作,来修改位置的符号的汇总。如函数名和标号
(8).rel.data:数据段需要重定位的信息。同上,这些符号在数据段,如全局变量
(9).debug:调试信息。gcc -g 选项可以生成该表。该表包含源程序中所有符号的定义及引用。
(10).line:源程序的行号映射。 也是-g选项生成该段。存储源程序中每一个语句的行号。
(11).strtab:字符串表。存储.symtab&.debug符号表中的名字,是一些字符串,以‘\0’结尾。

4.目标文件中的符号表
每个可重定位目标文件都有一个符号表:.symtab。
里面有三类符号:本模块中引用的其他模块定义的全局符号,本模块中定义的全局符号,本模块中定义和引用的局部符号
注:局部符号!=局部变量。局部变量在栈中,仅在内存出现,局部符号包括静态变量和局部标号,这些内容可能出现在磁盘文件中。

例子:add.c

点击(此处)折叠或打开

  1. void add()
  2. {
  3.     int static count = 2; //静态局部变量,局部符号
  4.     int a = 0; //局部变量
  5.     
  6.     count++; //静态局部变量累加
  7.     if(count>=10)
  8.          goto lab:
  9.     else{
  10.          printf("%d\t",count);
  11.          return;
  12.     }

  13. lab:
  14.     printf("count=%d\t",count);
  15.     a=10; 
  16.    printf("a=%d\n",a);
  17.    return ;
  18. }
编译得到add.o文件,使用readelf命令查看目标文件结构信息+符号表信息。
readelf -a add.o

5.符号解析
.symtab中的符号,链接器会查找所有参与链接的文件,找到该符号的定义,这个过程叫做符号解析

6.重定位操作
链接器在进行符号解析后,就要进行重定位操作了。链接器将所有参与链接的文件合并,并为每个符号分配存储内容的运行时地址
包括两方面:重定位段,重定位符号
(1)重定位段:将目标文件中同类型的段合并,生成一个大段。
(2)重定位符号引用:合并段后,各个文件中对符号的引用都已经是无效的,因为现在是一个整体段。链接器要修改这些符号的地址,使其指向正确的运行地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Makefile 是一个用于自动化构建的工具,通过 Makefile 可以定义编译和链接的规则,以及依赖关系。它使用了一种称为“依赖关系图”的数据结构来管理目标文件之间的依赖关系,并根据这些依赖关系来确定需要重新编译的文件。 在 Makefile 中,我们可以定义目标(Target)、依赖关系(Dependencies)和命令(Commands)。目标是我们要生成的文件,依赖关系是指生成目标文件所需要的其他文件,而命令则是生成目标文件的具体操作。 编译和链接原理如下: 1. 编译阶段:在编译阶段,Makefile 根据目标文件的依赖关系确定需要重新编译的文件,并执行相应的编译命令。编译命令将源代码转换为目标文件(通常是以 .o 结尾的文件)。这些目标文件包含了编译器将源代码转换为汇编代码、然后转换为机器码的过程。 2. 链接阶段:在链接阶段,Makefile 根据目标文件之间的依赖关系确定需要重新链接的文件,并执行相应的链接命令。链接命令将多个目标文件和库文件进行合并,生成最终的可执行文件。链接的过程包括符号解析、重定位和库文件处理,具体原理请参考前面回答的问题。 Makefile 通过检查目标文件和依赖文件的时间戳来确定是否需要重新编译和链接。如果目标文件不存在或者目标文件的依赖文件的时间戳比目标文件的时间戳要新,那么 Makefile 就会执行相应的编译和链接命令。 通过 Makefile 的自动化构建,我们可以方便地管理复杂的项目,减少重复编译和链接的工作量,并确保代码的正确性和一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值