链接脚本的基本概念
链接脚本用于描述链接器如何将输入文件格式化为可执行的输出文件,所谓输入文件既为汇编后的目标文件(.o或.obj等结尾)。
基本命令:
ENTRY (Symbol)
用于设置程序第一个被执行到的指令,也叫入口点,默认链接脚本按照以下顺序指定入口点:
1、`-e'入口命令行选项;
2、 链接脚本中的`ENTRY (Symbol)'命令;
3、 如果定义了start, 就使用start的值;
4、 如果存在,就使用'.text'节的首地址;
5、 地址`0'.
INCLUDE FileName
包含FileName链接脚本,默认是在当前目录下搜索。可以使用'-L'指定搜索路径
INPUT (File1,File2....)或GROUP (File1,File2....)
用于指定链接时包含的文件,可以代替外部命令行输入目标文件名。
GROUP命令特指文件类型必须为档案。
OUTPUT (FileName)
指定链接输出文件名,与外部命令使用'-o'等效
SEARCH (PATH)
指定搜寻文件的路径,与外部命令'-L PATH'等效
STARTUP(FileName)
链接时包含文件FileName,并且把它作为第一个被链接的文件。
OUTPUT_formAT(BFDNAME)
OUTPUT_formAT(DEFAULT, BIG, LITTLE)
用于指定输出文件使用BFD格式名或输出格式。
当外部使用'-EB',输出格式为BIG。使用'-EL',输出格式为LITTLE。都不输入则为默认的DEFAULT。
TARGET(BFDNAME)
指定输入文件名的BFD格式,若没有使用OUTPUT_formAT,则输出也是这个格式。
与外部命令'-b BFDNAME'等效。
ASSERT(EXP, MESSAGE)
断言EXP若为假,则链接器停止并打印信息MESSAGE。
OUTPUT_ARCH(BFDARCH)
指定链接文件应用的机器架构,BFDARCH是BFD库中使用的一个名字。
可以用"objdump -f File"来查看File文件应用架构。
在链接脚本中自定义特殊符号:
特殊符号可以被工程代码文件引用,在最后的链接脚本中会指定其正确值。
SYMBOL = EXPRESSION ; SYMBOL += EXPRESSION ; SYMBOL -= EXPRESSION ; SYMBOL *= EXPRESSION ; SYMBOL /= EXPRESSION ; SYMBOL <<= EXPRESSION ; SYMBOL >>= EXPRESSION ; SYMBOL &= EXPRESSION ; SYMBOL |= EXPRESSION ; /* 与C中定义和赋值方法类似,同样也可以像这样使用注释 */
链接脚本的简易基本格式
脚本最基本命令为"SECTIONS",用于描述输出文件布局,此命令通过节或段来描述。
简易的基本格式:
SECTIONS { SECTIONS-COMMAND SECTIONS-COMMAND ... } /*每一个SECTIONS-COMMAND可能是: 'ENTRY'命令。 特殊符号语句。 输出段描述。 重叠描述。 */
输出段描述格式:
SectionName [StrAddr] [(Type)] : [AT(LMA)] { OUTPUT-SECTION-COMMAND OUTPUT-SECTION-COMMAND ... } [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP] /*
注意:每个元素之间要用空格做分隔
每一个OUTPUT-SECTION-COMMAND可能是如下的情况: 特殊符号语句. 输入段描述. 直接包含的数据值. 特定的输出段关键字. */
上述格式中,方括号"[]"中的内容可以省略,其他内容是必须的。
SectionName
输出段名称,一般取对应输入段中的名称(比如:.text .data .bss 等等)
StrAddr
定位计数器由符号'.'表示运行地址,可以对其赋值。每指定一个段的地址,定位器计数器都会根据这个段的大小增加,
有时为了对齐要求,段和段之间可能会有空格字节。
StrAddr是一个运行地址表达式,其实真正的运行地址是由'StrAddr'和'REGION'共同决定的,规则如下:
若有StrAddr也有REGION,则由StrAddr指定。
若无StrAddr但有REGION,则由REGION指定
若StrAddr和REGION都没有,则由当前定位计数器的值和输入节的最严格对齐要求共同指定。
StrAddr可以使用ALIGN(num)指定地址在定位计数器向上上对齐到num位的地址。
Type
表面一个段的属性,比较常用的是'(NOLOAD)',告诉加载器运行时不加载这段(一般用在操作系统下)。
AT(LMA)
LMA指定段的存储地址,也就是在最后生成的可执行文件中实实在在存储的起始位置。
若不使用这个参数,则存储地址和运行地址一样。
>REGION
用于把段赋给前面已经定义的一个内存区域,
MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 } SECTIONS { ROM : { *(.text) } >rom }
:PHDR
用于把一个段赋给前面已经定义的一个程序段。
PHDRS { text PT_LOAD ; }
SECTIONS { .text : { *(.text) } :text }
=FILLEXP
用于填充节与节之间的空白区域,比如SECTIONS { .text : { *(.text) } =0x90909090 }
输入段描述
1、指定某个文件使用 foo.o(.text)格式,可以单独定位这个文件代码段位置。
2、输入节可以使用Shell中的通配符,比如 *(.text) 代表所有文件中的代码段,
也可以用*(.text .data)代表所有文件中的代码和数据段,排列顺序是把一个文件代码段和数据段顺序排列后紧接着是下个文件的代码段和数据段。
2、使用命令'EXCLUDE_FILE '排除文件,比如 (*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors)),
会让除了`crtend.o'文件和`otherfile.o'文件之外的所有的文件中的所有的.ctors段被包含进来。
SECTIONS { .text : { *(.text) } .DATA : { [A-Z]*(.data) } .data : { *(.data) } .bss : { *(.bss) } } /* 所有的文件的代码'.text'段放到'.text', 所有的以一个大写字母开始的文件名中的初始化数据'.data'段放进'.DATA' 所有其他文件的初始化数据'.data'段放进'.data' 把所有文件的未初始化数据'.bss'段放到'.bss'. */
输出段数据包含
可以在输出段中包含一些特定数值,使用命令'BYTE' 'SHORT' 'LONG' 'QUAD' 'SQUAD'。
比如BYTE(1),会在当前定位计数器上增加一个字节,内容是数字1。
注意:只能在段中使用,不能再段与段之间使用。
参考链接:http://www.cnblogs.com/hpunix/articles/2109690.html