linker script ld链接脚本语法简介
链接脚本由一系列语句组成,语句分两种,一种是命令语句
,另外一种是赋值语句
。链接脚本语法像C语言,主要有如下几点相似之处。
语句之间使用分号";"作为分割符
。
原则上讲语句之间都要以";"作为分割符,但是对于命令语句来说也可以使用换行来结束该语句,对于赋值详吾句来说必须以";"结束表达式与运算符
脚本语言的语句中可以使用C语言类似的表达式和运算操作符,比如+、-、、/、+=、=、=等,甚至包括&、1、>>、<<等这些位操作符。注释和字符引用
使用/**/作为注释。脚本文件中使用到的文件名、格式名或段名等凡是包含";"或其他的分隔符的,都要使用双引号将该名字全称引用起来,如果文件名包含引号,则很不幸,无法处理。
SECTIONS命令
SECTIONS命令基本格式为:
SECTIONS
{
...
secname : {contents}
/DISCARD/:{*(.comment)}
}
secname表示输出段的段名,secname后面必须有一个空格符,这样使得输出段名不会有歧义,后面紧跟着冒号和一对大括号。大括号里面的contents描述了一套规则和条件,它表示符合这种条件的输入段将合并到这个输出段中。输出段名的命名方法必须符合输出文件格式的要求,比如,如果使用ld生产一个a.out格式的文件,那么输出段名就不可以使用除".text"、".data"和".bss"之外的任何名字,因为a.out格式规定段名只允许这三个名字。
有一个特殊的段名叫"/DISCARD/",如果使用这个名字作为输出段名,那么所有符合后面contents所规定的条件的段都将被丢弃,不输出到输出了文件中。
接着,我们最应该关心的是contents这个规则
。contents中可「以包含若干个条件,每个条件之间以空格隔开,如果输入段符合这些条件中的任意一个即表示这个输入段符合contents规则。条件的写法如下:
filename(sections)
filename表示输入文件名,sections表示输入段名。让我们举几个条件的例子来看看:
-
file1.o(.data)表示输入文件中名为filel.o的文件中名叫.data的身没符合条件
-
file1.o(.data .rodata)或file1.o(.data, .rodata)表示输入文件中名为filel.o的文件中的名叫.data或.rodata的段符合条件。
-
file1.o如果直接指定文件名而省略后面的小括号和段名,则表示file1.o的所有段都符
合条件。 -
*(.data)所有输入文件中的名字为.data的文件符合条件。*是通配符,类似于正则
其他命令
命令语句 | 说明 |
---|---|
ENTRY(symble) | 指定符号symbol的值为入口地址(EntryPoint)。入口地址即进程执行的第一条用户空间的指令在进程地址空间的地址,它被指定在ELF文件头Elf32_Ehdr的e_entry成员中。ld有多种方法可以设置进程入口地址,它们之间的优先级按以下顺序排列(编号越靠前,优先级越高): 1.ld命令行的-e选项 2.链接脚本的ENTRY(symbol)命令 3.如果定义了_start符号,使用_start符号值 4.如果存在.text段,使用.text段的第一字节的地址 5.使用值0 |
STARTUP(filename) | 将文件filename 作为链接过程中的第一个输入文件。 |
SEATCH_DIR(path) | 将路径path加入到ld链接器的库查找目录。 ld会根据指定的目录去查找相应的库。 |
INPUT(file,file,...) INPUT(file file ...) |
将指定文件作为链接过程中的输入文件 |
INCLUDE filename | 将指定文件包含进本链接脚本。 |
PROVIDE(symbol) | 在链接脚本中定义某个符号。该符号再程序中可以被引用,起始前文提到的特殊符号都是由系统默认的链接脚本通过PROVIDE 命令定义在脚本中的 |