一、链接的定义

链接(linking)是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。

二、链接的作用

  1. 链接将帮助我们构造大型程序

  2. 链接将帮助我们避免一些危险的编码错误

  3. 链接将帮助我们理解语言的作用域规则是如何实现的

  4. 链接将帮助我们理解其他重要的系统概念

  5. 链接将是我们能够利用共享库

三、链接过程那些事

在这段我将重点介绍 数据在ELF文件 (Executable and Linkable Format,可执行可链接格式)中位置信息。

1、程序员当然是从Hello World!开始啦!所以我们先创建一个main.c文件 如下

2、用 gcc -c main.c -o main.o main.c文件转化为main.o

3、用objdump -d main.o 我们将得到其汇编代码,如下:

从图中我们可以看到最左侧的0:表示的这个程序起始地址为0,造成这个的原因是我们还没链接,还没有重定位

4、objdump -s main.o 可以得到:

第二行.rodata是表明我们要打印的Hello World放入了只读数据区。.rodata节是放置printf语句中的格式串和switch语句的跳转表。

5、用gcc -O2 -o main main.c 得到名为main的可执行文件

6、再用objdump -d main可以看到如下:

它的起始地址是401000与图3的起始地址不同。

7、用objdump -s main可以得到:

emmm。。。这下面还有很长的信息没有显示出来,这些信息表示的是调用printf()函数的过程中,链接了C标准库中的文件。

readelf

在上面我们是用的objdump 命令来查看的汇编代码,下面让我们来看看 readelf命令吧!

在上面我们是用的objdump 命令来查看的汇编代码,下面让我们来看看 readelf命令吧!

1、之前我们已经得到了一个main.omain文件,用命令readelf -h  main.o 我们可以看到

Magic: 行中 45 4c 46 分别为E L FASCII码的16进制表示。

数据:行表明其内容为 二进制 补码 小端法表示的。

入口点地址:行表明起始地址为0与用objdump命令得到的结论相同

Start of section headers:它的值为672 表示节头表的起始地址是672个字节。

节头大小:表示一个节头表表项大小为64字节

节头数量: 表示节头表表项数量为13个,所以节头表全部大小为64*13 B

程序头起点:它的值为0表明没有程序头表

2、readelf -S main.o

从这张图我们可以得到:

  1. [0]起始地址为0;未进行重定位

2)从上述表中可看出各节的名称、类型、地址、大小等信息。

3、readelf -s main.o

从图中可以看到Value都为 0 那是因为.o文件未进行重定位,无法得知真实地址。

4、readelf -h main

现在让我们看看可执行文件main

比较与上面main.o的不同我们可以看出就就只有入口点地址不同这是因为可执行文件已进行重定位,系统为其分配了虚拟地址空间。

5、readelf -S main

比较main.o可以看出有一些段消失了如:.rela.text.rela.data

这些段存储着重定位的信息,可执行文件已经重定位了,所以这些段就被抛弃了。

6、readelf -s main

比较main.o可以看到Value不全为0了,这些值表示的是各段相对与节头的地址。