程序员自我修养第三章__链接.

来源:互联网 发布:淘宝无线详情视频教程 编辑:程序博客网 时间:2024/05/18 06:42

程序员自我修养第四章读书笔记

一,静态链接:

链接就是将几个输入的目标文件加工合并成一个输出文件,加工合并的方法是将几个输入文件中相似的段合并,比如将所有输入文件的“.text”合并到一个输出文件的“.text”段。

现在连接器一般将整个链接过程分为两步:

1,空间与地址的分配,扫描所有输入的目标文件,获得它们各个段的长度和属性,位置,并且将输入目标文件中所有的符号(Symbol)定义和符号引用收集起来,统一放到一个全局符号表中,这一步连接器能够获得所有输入目标文件的段长度,并且将它们合并,计算出输出文件中各个段合并后的长度和位置,并且建立映射关系。
2,符号解析与重定位,使用第一步收集的所有信息,读取输入文件中段的数据,重定位信息,并且进行符号解析与重定位,调整代码中的地址等等。

比如有两个目标文件分别为a.o和b.o。使用如下命令将这两个输入目标文件链接成可执行文件ab,其中-e main表示的是main()函数作为程序的入口,ld连接器默认的程序入口是_start。   ld a.o b.o -e main -o ab

在linux下elf可执行文件的入口地址是0x08048000,由于各个目标文件中的符号相对于起始地址的偏移已经确定,所以链接的过程就是将各个目标文件的符号的便宜加上入口地址0x08048000。

符号解析与重定位:目标文件中有重定位表相关的段,比如代码段.text如有要被重定位的地方,那么会有一个相应叫.rel.text的重定位段,重定位表的数据结构是struct Elf32_Rel.


二:动态链接

动态链接:等程序运行的时候才进行连接,这是动态链接的基本思想。动态链接是把程序按照模块拆分成各个相对独立的部分,在程序运行时才将他们链接在一起形成一个完整的程序。程序与动态库文件的链接是由动态链接器来完成的,编译动态库文件(.so)的命令: gcc -shared -o lib.so lib.c
linux下的动态连接器是ld-2.6.so,共享对象(.so)的最终装载地址在编译的时候是不确定的,而是在装载的时候装载器根据当前地址空间的空闲情况,动态分配一块足够大小的虚拟地址空间给相应的共享对象。
动态链接的相关结构:
在动态链接情况下,操作系统在装载完可执行文件之后不能直接将控制权交给可执行文件,因为可执行文件依赖很多的共享对象,所以此时可执行文件里对于很多的外部符号引用还处于无效的状态,所以操作系统在映射完可执行文件之后会先启用一个动态连接器,在linux平台下动态连接器ld.so也是一个共享对象,操作系统同样通过映射的方式将其加入到进程地址空间,操作系统加载完连接器后就将控制权交给动态连接器的入口地址(与可执行文件一样,动态连接器也有入口地址)。
可执行文件(elf)中的.interp段指定了当前可执行文件用到的动态连接器的位置,比如为/lib/ld-linux.so.2,可以通过readelf -l a.out | greap interpreter命令来查看。
可执行文件的.dynamic段保存了动态连接器所需要的基本信息,比如依赖哪些共享对象,动态链接符号表的位置,动态链接重定位表的位置,该结构名字是Elf32_Dyn,定义在elf.h文件中。为了表示动态链接很多模块之间的符号导入导出关系,ELF专门有一个叫做动态符号表的段用来保存这些信息,这个段名字叫做.dynsym


三:链接脚本

由于bootloader 有些驱动等不能使用系统默认的ld连接器,所以需要自己编写相应的链接脚步。


0 0
原创粉丝点击