摘要:介绍连接脚本中的段描述
关键字: 连接脚本 linker script 输出段 output section description
正文:
输出端的完整说明大致如下:
1: section [address] [(type)] :
2: [AT(lma)]
3: [ALIGN(section_align)]
4: [SUBALIGN(subsection_align)]
5: [constraint]
6: {
7: output-section-command
8: output-section-command
9: ...
10: } [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
其中很多的可选的段属性并不常用。
section (段名)(前)后的空格是必须的,这使得段的名称是明确的。冒号与大括号也是不可缺少的,换行以及其他的空格是可选的。
输出段命令(output-section-command)有下面几种形式:
- 一个符号赋值 ( a symbol assignment )
- 一个输入段描述 ( an input section description )
- (直接指定)包含的值 ( data values to include directly )
- 一个特殊的输出段关键字 ( a speciall output section keyword )
例如:
1: .my_section :
2: {
3: __symbol_define = . ;
4: * (.my_section_func) ;
5: BYTE(2);
6: }
BYTE(1):属于直接赋值,表示在输入段.my_section_func后面直接分配一个1字节的空间,存放数据2。上面示例中没有输出段关键字,相关内容可以直接查看原英文文档。
输出段丢弃
连接器不会创建那些不含有任何内容的输出段。这是为了引用那些可能出现或不出现在任何输入文件中的输入段时方便。比如:
.foo { *(.foo) }
如果至少在一个输入文件中有“.foo”段,连接器才会在输出文件中创建一个“.foo”段。当然,分配空间的指令也会导致连接器创建输出段。
连接器将会忽略被丢弃段上的地址赋值(段名后面),除非在输出段中有符号定义,在这种情况下,连接器将继续遵循段地址的赋值,就算该段将会被丢弃。例如:
1: //语句1
2: .DISCARD ALIGN(0x10) :
3: {
4: *(.my_discard);
5: }
6:
7: //语句2
8: .DISCARD ALIGN(0x10) :
9: {
10: __symbol_define = . ;
11: *(.my_discard);
12: }
上面代码中,如果输入文件中没有.my_discard段,对于语句1,ALIGN(0x10)将会与该段一起被丢弃,但是语句2中的段,由于使用了符号赋值,ALIGN(0x10)将会有效,当然,最后该段同样会丢弃,但是__symbol_define的值确是被(0x10)对齐了。其实就相当于:
1: . = ALIGN(0x10) ;
2: __symbol_define = . ;
一个特殊的输出节名`/DISCARD/'可以被用来丢弃输入节。任何被分配到名为`/DISCARD/'的输出节中的输入节不包含在输出文件中。(在源程序中,可以使用__attribute__((section(“”)))关键字将变量或者函数指定到该段,这不会导致编译器报错,但是不能使用这些变量和函数)。
参考:
http://sourceware.org/binutils/docs/ld/Output-Section-Description.html#Output-Section-Description
http://sourceware.org/binutils/docs/ld/Output-Section-Discarding.html#Output-Section-Discarding