没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
Linux 下的 lds 链接脚本基础
0. Contents
1. 概论
2. 基本概念
3. 脚本格式
4. 简单例子
5. 简单脚本命令
6. 对符号的赋值
7. SECTIONS 命令
8. MEMORY 命令
9. PHDRS 命令
10. VERSION 命令
11. 脚本内的表达式
12. 暗含的连接脚本
1. 概论
每一个链接过程都由链接脚本(linker script, 一般以 lds 作为文件的后缀
名)控制. 链接脚本主要用于规定如何把输入文件内的 section 放入输出文件内,
并控制输出文件内各部分在程序地址空间内的布局. 但你也可以用连接命令做
一些其他事情.
连接器有个默认的内置连接脚本, 可用 ld –verbose 查看. 连接选项-r 和
-N 可以影响默认的连接脚本(如何影响?).
-T 选项用以指定自己的链接脚本, 它将代替默认的连接脚本。你也可以使
用<暗含的连接脚本>以增加自定义的链接命令.
以下没有特殊说明,连接器指的是静态连接器.
2. 基本概念
链接器把一个或多个输入文件合成一个输出文件.
输入文件: 目标文件或链接脚本文件.
输出文件: 目标文件或可执行文件.
目标文件(包括可执行文件)具有固定的格式, 在 UNIX 或 GNU/Linux 平台下,
一般为 ELF 格式. 若想了解更多, 可参考 UNIX/Linux 平台可执行文件格式分
析
有时把输入文件内的 section 称为输入 section(input section), 把输出文
件内的 section 称为输出 section(output sectin).
目标文件的每个 section 至少包含两个信息: 名字和大小. 大部分 section
还包含与它相关联的一块数据, 称为 section contents(section 内容). 一个
section 可被标记为“loadable(可加载的)”或“allocatable(可分配的)”.
loadable section: 在输出文件运行时, 相应的 section 内容将被载入进
程地址空间中.
allocatable section: 内容为空的 section 可被标记为“可分配的”. 在输
出文件运行时, 在进程地址空间中空出大小同 section 指定大小的部分. 某些情
况下, 这块内存必须被置零.
如果一个 section 不是“可加载的”或“可分配的”, 那么该 section 通常包含
了调试信息. 可用 objdump -h 命令查看相关信息.
每个“可加载的”或“可分配的”输出 section 通常包含两个地址:
VMA(virtual memory address 虚拟内存地址或程序地址空间地址)和
LMA(load memory address 加载内存地址或进程地址空间地址). 通常 VMA
和 LMA 是相同的.
在目标文件中, loadable 或 allocatable 的输出 section 有两种地址:
VMA(virtual Memory Address)和 LMA(Load Memory Address). VMA 是
执行输出文件时 section 所在的地址, 而 LMA 是加载输出文件时 section 所在
的地址. 一般而言, 某 section 的 VMA == LMA. 但在嵌入式系统中, 经常存
在加载地址和执行地址不同的情况: 比如将输出文件加载到开发板的 flash 中
(由 LMA 指定), 而在运行时将位于 flash 中的输出文件复制到 SDRAM 中(由
VMA 指定).
可这样来理解 VMA 和 LMA, 假设:
(1) .data section 对应的 VMA 地址是 0×08050000, 该 section 内包含了 3
个 32 位全局变量, i、j 和 k, 分别为 1,2,3.
(2) .text section 内包含由”printf( “j=%d “, j );”程序片段产生的代码.
连接时指定.data section 的 VMA 为 0×08050000, 产生的 printf 指令
是将地址为 0×08050004 处的 4 字节内容作为一个整数打印出来。
如果.data section 的 LMA 为 0×08050000,显然结果是 j=2
如果.data section 的 LMA 为 0×08050004,显然结果是 j=1
还可这样理解 LMA:
.text section 内容的开始处包含如下两条指令(intel i386 指令是 10 字节,每
行对应 5 字节):
jmp 0×08048285
movl $0×1,%eax
如果.text section 的 LMA 为 0×08048280, 那么在进程地址空间内
0×08048280 处为“jmp 0×08048285”指令, 0×08048285 处为 movl
$0×1,%eax 指令. 假设某指令跳转到地址 0×08048280, 显然它的执行将导
致%eax 寄存器被赋值为 1.
如果.text section 的 LMA 为 0×08048285, 那么在进程地址空间内
0×08048285 处为“jmp 0×08048285”指令, 0×0804828a 处为 movl
$0×1,%eax 指令. 假设某指令跳转到地址 0×08048285, 显然它的执行又跳
转到进程地址空间内 0×08048285 处, 造成死循环.
符号(symbol): 每个目标文件都有符号表(SYMBOL TABLE), 包含已定
义的符号(对应全局变量和 static 变量和定义的函数的名字)和未定义符号(未定
义的函数的名字和引用但没定义的符号)信息.
符号值: 每个符号对应一个地址, 即符号值(这与 c 程序内变量的值不一样,
某种情况下可以把它看成变量的地址). 可用 nm 命令查看它们. (nm 的使用方
法可参考本 blog 的 GNU binutils 笔记)
3. 脚本格式
链接脚本由一系列命令组成, 每个命令由一个关键字(一般在其后紧跟相关
参数)或一条对符号的赋值语句组成. 命令由分号‘;’分隔开.
文件名或格式名内如果包含分号’;'或其他分隔符, 则要用引号‘”’将名字全
称引用起来. 无法处理含引号的文件名.
/* */之间的是注释。
4. 简单例子
在介绍链接描述文件的命令之前, 先看看下述的简单例子:
以下脚本将输出文件的 text section 定位在 0×10000, data section 定
位在 0×8000000:
SECTIONS
{
. = 0×10000;
.text : { *(.text) }
. = 0×8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
解释一下上述的例子:
. = 0×10000 : 把定位器符号置为 0×10000 (若不指定, 则该符号的初始值
为 0).
.text : { *(.text) } : 将所有(*符号代表任意输入文件)输入文件的.text
section 合并成一个.text section, 该 section 的地址由定位器符号的值指定,
即 0×10000.
. = 0×8000000 :把定位器符号置为 0×8000000
.data : { *(.data) } : 将所有输入文件的.data section 合并成一个.data
section, 该 section 的地址被置为 0×8000000.
.bss : { *(.bss) } : 将所有输入文件的.bss section 合并成一个.bss
section,该 section 的地址被置为 0×8000000+.data section 的大小.
连接器每读完一个 section 描述后, 将定位器符号的值*增加*该 section
的大小. 注意: 此处没有考虑对齐约束.
5. 简单脚本命令
- 1 -
ENTRY(SYMBOL) : 将符号 SYMBOL 的值设置成入口地址。
入口地址(entry point): 进程执行的第一条用户空间的指令在进程地
址空间的地址)
ld 有多种方法设置进程入口地址, 按一下顺序: (编号越前, 优先级越
高)
1, ld 命令行的-e 选项
2, 连接脚本的 ENTRY(SYMBOL)命令
3, 如果定义了 start 符号, 使用 start 符号值
4, 如果存在.text section, 使用.text section 的第一字节的位置值
5, 使用值 0
- 2 -INCLUDE filename : 包含其他名为 filename 的链接脚本
相当于 c 程序内的的#include 指令, 用以包含另一个链接脚本.
脚本搜索路径由-L 选项指定. INCLUDE 指令可以嵌套使用, 最大深度
为 10. 即: 文件 1 内 INCLUDE 文件 2, 文件 2 内 INCLUDE 文件 3… , 文
件 10 内 INCLUDE 文件 11. 那么文件 11 内不能再出现 INCLUDE 指令
了.
- 3 -INPUT(files): 将括号内的文件做为链接过程的输入文件
ld 首先在当前目录下寻找该文件, 如果没找到, 则在由-L 指定的搜索
路径下搜索. file 可以为 -lfile 形式,就象命令行的-l 选项一样. 如果该命
令出现在暗含的脚本内, 则该命令内的 file 在链接过程中的顺序由该暗含
的脚本在命令行内的顺序决定.
- 4 -GROUP(files) : 指定需要重复搜索符号定义的多个输入文件
file 必须是库文件, 且 file 文件作为一组被 ld 重复扫描,直到不在有新
的未定义的引用出现。
- 5 -OUTPUT(FILENAME) : 定义输出文件的名字
同 ld 的-o 选项, 不过-o 选项的优先级更高. 所以它可以用来定义默认
的输出文件名. 如 a.out
- 6 -SEARCH_DIR(PATH) :定义搜索路径,
同 ld 的-L 选项, 不过由-L 指定的路径要比它定义的优先被搜索。
- 7 -STARTUP(filename) : 指定 filename 为第一个输入文件
在链接过程中, 每个输入文件是有顺序的. 此命令设置文件 filename
为第一个输入文件。
- 8 – OUTPUT_FORMAT(BFDNAME) : 设置输出文件使用的 BFD
格式
同 ld 选项-o format BFDNAME, 不过 ld 选项优先级更高.
- 9 -OUTPUT_FORMAT(DEFAULT,BIG,LITTLE) : 定义三种输出
文件的格式(大小端)
若有命令行选项-EB, 则使用第 2 个 BFD 格式; 若有命令行选项-EL,
则使用第 3 个 BFD 格式.否则默认选第一个 BFD 格式.
TARGET(
BFDNAME):设置输入文件的 BFD 格式
同 ld 选项-b BFDNAME. 若使用了 TARGET 命令, 但未使用
OUTPUT_FORMAT 命令, 则最用一个 TARGET 命令设置的 BFD 格式将被
作为输出文件的 BFD 格式.
另外还有一些:
ASSERT(EXP, MESSAGE):如果 EXP 不为真,终止连接过程
EXTERN(SYMBOL SYMBOL …):在输出文件中增加未定义的符号,
如同连接器选项-u
剩余24页未读,继续阅读
资源评论
- zhangbai64022014-11-17很好的资源,对于学习链接文件有帮助!
MichaelShangZhao
- 粉丝: 1
- 资源: 35
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功