Chinaunix首页 | 论坛 | 博客
  • 博客访问: 656530
  • 博文数量: 516
  • 博客积分: 4119
  • 博客等级: 上校
  • 技术积分: 4288
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-30 17:29
文章分类

全部博文(516)

文章存档

2014年(4)

2013年(160)

2012年(352)

分类:

2012-11-01 11:20:19

原文地址:链接原理 作者:graylocus

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)重定位符号引用:合并段后,各个文件中对符号的引用都已经是无效的,因为现在是一个整体段。链接器要修改这些符号的地址,使其指向正确的运行地址。
阅读(223) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~