《linux lds 文件格式详细分析资料》由会员分享,可在线阅读,更多相关《linux lds 文件格式详细分析资料(37页珍藏版)》请在金锄头文库上搜索。
1、LDS 文件格式分析文件格式分析 连接脚本的格式 = 连接脚本是文本文件. 你写了一系列的命令作为一个连接脚本. 每一个命令是一个带有参数的关键字,或者是一个 对符号的赋值. 你可 以用分号分隔命令. 空格一般被忽略. 文件名或格式名之类的字符串一般可以被直接键入. 如果文件名含有特殊字符,比如一般作 为分隔文件名用的逗 号, 你可以把文件名放到双引号中. 文件名中间无法使用双引号. 你可以象在 C 语言中一样,在连接脚本中使用注释, 用/*和*/隔开. 就像在 C 中,注释在语法 上等同于空格. 简单的连接脚本示例 = 许多脚本是相当的简单的. 可能的最简单的脚本只含有一个命令: SECTI
2、ONS. 你可以使用SECTIONS来描述输出文 件的内存布局. SECTIONS是一个功能很强大的命令. 这里这们会描述一个很简单的使用. 让我们假设你 的程序只有代码节, 初始化过的数据节, 和未初始化过的数据节. 这些会存在于.text,.data和.bss节, 另外, 让我 们进一 步假设在你的输入文件中只有这些节. 对于这个例子, 我们说代码应当被载入到地址0x10000处, 而数据应当从 0x8000000 处开始. 下面是一个实现 这个功能的脚本: SECTIONS . = 0x10000; .text : *(.text) . = 0x8000000; .data : *(.d
3、ata) .bss : *(.bss) 你使用关键字SECTIONS写了这个 SECTIONS 命令, 后面跟有一串放在花括号中的符号赋 值和输出节描述的内容. 上例中, 在SECTIONS命令中的第一行是对一个特殊的符号.赋值, 这是一个定位计数器. 如果你没有以其 它的方式指定输出节的地址(其他方式在后面会描述), 那地址值就会被设为定位计数器的现 有值. 定位计数器 然后被加上输出节的尺寸. 在SECTIONS命令的开始处, 定位计数器拥有值0. 第二行定义一个输出节,.text. 冒号是语法需要,现在可以被忽略. 节名后面的花括号中,你列 出所有应当被 放入到这个输出节中的输入节的名字
4、. *是一个通配符,匹配任何文件名. 表达式*(.text)意 思是所有的输 入文件中的.text输入节. 因为当输出节.text定义的时候, 定位计数器的值是0x10000,连接器会把输出文件中的.text 节的地址设 为0x10000. 余下的内容定义了输出文件中的.data节和.bss节. 连接器会把.data输出节放到地址 0x8000000处. 连接 器放好.data输出节之后, 定位计数器的值是0x8000000加上.data输出节的长度. 得到的结 果是连接器会 把.bss输出节放到紧接.data节后面的位置. 连接器会通过在必要时增加定位计数器的值来保证每一个输出节具有它所需的
5、对齐. 在这 个例子中, 为.text 和.data节指定的地址会满足对齐约束, 但是连接器可能会需要在.data和.bss节之间创建一 个小的缺口. 就这样,这是一个简单但完整的连接脚本. 简单的连接脚本命令. = 在本章中,我们会描述一些简单的脚本命令. 设置入口点. - 在运行一个程序时第一个被执行到的指令称为“入口点“. 你可以使用ENTRY连接脚本命令 来设置入口点.参数 是一个符号名: ENTRY(SYMBOL) 有多种不同的方法来设置入口点.连接器会通过按顺序尝试以下的方法来设置入口点, 如果 成功了,就会停止. * -e入口命令行选项; * 连接脚本中的ENTRY(SYMBOL
6、)命令; * 如果定义了 start, 就使用 start 的值; * 如果存在,就使用.text节的首地址; * 地址0. 处理文件的命令. - 有几个处理文件的连接脚本命令. INCLUDE FILENAME 在当前点包含连接脚本文件 FILENAME. 在当前路径下或用-L选项指定的所有路径下搜索 这个文件, 你可以嵌套使用INCLUDE达 10 层. INPUT(FILE, FILE, .) INPUT(FILE FILE .) INPUT命令指示连接器在连接时包含文件, 就像它们是在命令行上指定的一样. 比如,如果你在连接的时候总是要包含文件subr.o,但是你对每次连接时要在命令行
7、上输入感 到厌烦 , 你就可以在你的连接脚本中输入INPUT (subr.o). 事实上,如果你喜欢,你可以把你所有的输入文件列在连接脚本中, 然后在连接的时候什么也 不需要, 只要一个-T选项就够了. 在一个系统根前缀被配置的情况下, 一个文件名如果以/字符打头, 并且脚本也存放在系统 根 前缀的某个子目录下, 文件名就会被在系统根前缀下搜索. 否则连接器就会企图打开当前目 录下的文 件. 如果没有发现, 连接器会通过档案库搜索路径进行搜索. 如果你使用了INPUT (-lFILE), ld会把文件名转换为libFILE.a, 就象命令行参数-l一样. 当你在一个隐式连接脚本中使用INPUT
8、命令的时候, 文件就会在连接时连接脚本文件被包 含的点上 被包含进来. 这会影响到档案搜索. GROUP(FILE, FILE, .) GROUP(FILE FILE .) 除了文件必须全是档案文件之外, GROUP命令跟INPUT相似, 它们会被反复搜索,直至没 有未定义 的引用被创建. OUTPUT(FILENAME) OUTPUT命令命名输出文件. 在连接脚本中使用OUTPUT(FILENAME)命令跟在命令行中 使用-o FILENAME命令是完全等效的. 如果两个都使用了, 那命令行选项优先. 你可以使用OUTPUT命令为输出文件创建一个缺省的文件名,而不是常用的a.out. SEA
9、RCH_DIR(PATH) SEARCH_DIR 命 令 给 ld 用 于 搜 索 档 案 文 件 的 路 径 中 再 增 加 新 的 路 径 . 使 用 SEARCH_DIR(PATH)跟在 命令行上使用-L PATH选项是完全等效的. 如果两个都使用了, 那连接器会两个路径都搜索. 用命 令行选项指定的路径首先被搜索. STARTUP(FILENAME) 除了 FILENAME 会成为第一个被连接的输入文件, STARTUP命令跟INPUT命令完全相似, 就象这个文 件是在命令行上第一个被指定的文件一样. 如果在一个系统中, 入口点总是存在于第一个文 件中,那 这个就很有用. 处理目标文件
10、格式的命令. - 有两个处理目标文件格式的连接脚本命令. OUTPUT_formAT(BFDNAME) OUTPUT_formAT(DEFAULT, BIG, LITTLE) OUTPUT_formAT 命 令 为 输 出 文 件 使 用 的BFD格 式 命 名 . 使 用 OUTPUT_formAT(BFDNAME)跟在命令行上 使用-oformat BFDNAME是完全等效的. 如果两个都使用了, 命令行选项优先. 你可在使用OUTPUT_formAT时带有三个参数以使用不同的基于-EB和-EL的命令行选项 的格式. 如果-EB和-EL都没有使用, 那输出格式会是第一个参数 DEFAULT
11、, 如果使用了-EB,输出 格式会是 第二个参数 BIG, 如果使用了-EL, 输出格式会是第三个参数, LITTLE. 比如, 缺省的基于 MIPS ELF 平台连接脚本使用如下命令: OUTPUT_formAT(elf32-bigmips, elf32-bigmips, elf32-littlemips) 这表示缺省的输出文件格式是elf32-bigmips, 但是当用户使用-EL命令行选项的时候, 输出文件就会 被以elf32-littlemips格式创建. TARGET(BFDNAME) TARGET命令在读取输入文件时命名BFD格式. 它会影响到后来的INPUT和GROUP命令. 这
12、个命令跟 在命令行上使用-b BFDNAME相似. 如果使用了TARGET命令但OUTPUT_formAT没有 指定, 最后的 TARGET命令也被用来设置输出文件的格式. 其它的连接脚本命令. - 还有一些其它的连接脚本命令. ASSERT(EXP, MESSAGE) 确保 EXP 不等于零,如果等于零, 连接器就会返回一个错误码退出,并打印出 MESSAGE. EXTERN(SYMBOL SYMBOL .) 强制SYMBOL作为一个无定义的符号输入到输出文件中去. 这样做了,可能会引发从标准库 中连接一些 节外的库. 你可以为每一个 EXTERN列出几个符号, 而且你可以多次使用EXTER
13、N. 这个 命令跟-u 命令行选项具有相同的效果. FORCE_COMMON_ALLOCATION 这个命令跟命令行选项-d具有相同的效果: 就算指定了一个可重定位的输出文件(-r),也让 ld 为普通符号分配空间. INHIBIT_COMMON_ALLOCATION 这个命令跟命令行选项-no-define-common具有相同的效果: 就算是一个不可重位输出文 件, 也让 ld忽略为普通符号分配的空间. NOCROSSREFS(SECTION SECTION .) 这个命令在遇到在某些特定的节之间引用的时候会产生一条错误信息. 在某些特定的程序中, 特别是在使用覆盖技术的嵌入式系统中, 当
14、一个节被载入内存时,另 外一个节 就不会在内存中. 任何在两个节之间的直接引用都会是一个错误. 比如, 如果节 1 中的代码 调用了另 一个节中的一个函数,这就会产生一个错误. NOCROSSREFS命令带有一个输出节名字的列表. 如果ld遇到任何在这些节之间的交叉引 用, 它就 会报告一个错误,并返回一个非零退出码. 注意, NOCROSSREFS命令使用输出节名,而不是 输入节名. OUTPUT_ARCH(BFDARCH) 指定一个特定的输出机器架构. 这个参数是 BFD 库中使用的一个名字. 你可以通过使用带 有-f选项 的objdump程序来查看一个目标文件的架构. 为符号赋值. =
15、你可以在一个连接脚本中为一个符号赋一个值. 这会把一个符号定义为一个全局符号. 简单的赋值. - 你可以使用所有的 C 赋值符号为一个符号赋值. SYMBOL = EXPRESSION ; SYMBOL += EXPRESSION ; SYMBOL -= EXPRESSION ; SYMBOL *= EXPRESSION ; SYMBOL /= EXPRESSION ; SYMBOL REGION ATLMA_REGION :PHDR :PHDR . =FILLEXP 大多数输出节不使用这里的可选节属性. SECTION 边上的空格是必须的, 所以节名是明确的. 冒号跟花括号也是必须的. 断行