1、链接
通过链接器可以把一个或多个输入文件合成一个输出文件,输入文件可以是目标文件或链接脚本文件,输出文件可以是目标文件或可执行文件。
目标文件或可执行文件都有固定的格式,例如在linux/unix操作系统中为elf格式,每个目标文件一般都由若干个sections和符号表组成。对于sections有时把输入文件内的section称为输入section(input section), 把输出文件内的section称为输出section(output sectin)。而每个section都至少包含名字和大小两个信息,大部分section还包含与它相关联的一块数据, 称为section contents(section内容),并且该section可以被标记为loadable(可加载的)或allocatable(可分配的),如果一个section不是“可加载的”或“可分配的”, 那么该section通常包含了调试信息。每个“可加载的”或“可分配的”输出section通常包含两个地址:VMA(virtual memory address虚拟内存地址或程序地址空间地址)和LMA(load memory address加载内存地址或进程地址空间地址)。对于符号表(SYMBOL TABLE),包含已定义的符号(对应全局变量和static变量和定义的函数的名字)和未定义符号(未定义的函数的名字和引用但没定义的符号)信息,各个符号的值对应该符号的地址。可以通过命令objdump -h查看目标文件各个section的头部信息,通过命令nm查看目标文件的符号列表,通过objdump -f命令查看目标文件的整体头部摘要信息。
2、链接脚本
每一个链接过程都由链接脚本(linker script, 一般以lds作为文件的后缀名)控制. 链接脚本主要用于规定如何把输入文件内的section放入输出文件内, 并控制输出文件内各部分在程序地址空间内的布局。
ld链接器有自己的默认脚本,可以通过命令ld --verbose查看,连接选项-r和-N可以影响默认的连接脚本,-T选项用以指定自己的链接脚本, 它将代替默认的连接脚本。你也可以使用<暗含的连接脚本>以增加自定义的链接命令.
- 脚本格式
链接脚本由一系列命令组成, 每个命令由一个关键字(一般在其后紧跟相关参数)或一条对符号的赋值语句组成。 命令由分号‘;’分隔开。文件名或格式名内如果包含分号';'或其他分隔符, 则要用引号‘"’将名字全称引用起来。 否则无法处理含引号的文件名。/* */之间的是注释。
链接脚本的格式如下,它的的核心部分是段(Section)
SECTIONS{
...
secname start ALIGN(align) (NOLOAD) : AT(ldadr) {contents} >region : phdr =fill
...
}
说明:
secname 和 contents是必须的,前者用来命名这个段,后者用来确保代码中什么部分放在这个段中。
start 是这个端的重定位地址,也称为运行地址。如果代码中有位置有关指令,程序运行时,这个段必须放在这个地址上。
ALIGN(align):指定运行地址对齐要求
(NOLOAD):告诉加载器,运行的时候不用加载这个段,这个选项在有操作系统的情况下才有意义。
AT(ldadr):指定这个段的在编译出来的映像文件中的地址——加载地址(load address)。如果不使用这个选项,则加载地址等于运行地址。