分类: LINUX
2009-03-24 11:26:27
Linker Scripts
Ld --verbose
可以查看默认的连接脚本
VMA, or virtual memory address 运行地址
LMA, or load memory address 装载地址
Objdump 的 –h 参数可以查看 section 。
(一)一个最简单的例子
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
1, SECTIONS 是最重要的命令,必须包含。
2, . 表示当前地址值,这个地址是运行时地址,也就是 VMA
Entry point
The first instruction to execute in a program is called the entry point
第一条执行的指令叫 entry point
ENTRY(symbol)
Ld按照如下的顺序确认entry point
1,-e 参数指定。
3,ENTRY(symbol)符号指定的地址
4,
Start
符号的定义
5,
.text
中的第一条指令
6,
地址0
处理文件包含
INCLUDE
filename
查找当前目录,还有-L 指定的搜索目录,include可以嵌套最多10层。
floating_point = 0;
SECTIONS
{
.text :
{
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 3;
.data : { *(.data) }
}
定义符号的用法。
_bdata = (. + 3) & ~ 3; 下一个4字节对齐地址的用法。
完整的 section 的定义是,
section [address] [(type)] : [AT(lma)]
{
output-section-command
output-section-command
...
} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
地址 VMA的分配
.text . : { *(.text) }
.text : { *(.text) }
两个表达式不完全相同,第一个是分配当前地址,而第二个确实分配当前的对齐地址。
如果需要边界对齐,可以用下面的:
.text ALIGN(0x10) : { *(.text) }
ALIGN(0x10) 会将地址值向前增加,直到 0x10 字节对齐为止。
Input Section Description
*(.text)
最简单的形式,匹配所有文件所有的 .text 段
(*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors))
包含除了*crtend.o 和 *otherfile.o 中的所有输入object文件的 .ctors段
*(.text .rdata)
*(.text) *(.rdata)
包含多个段的两种形式,其中第一种表示两个段混合在一起分配,第二种表示先分配所有的 .text 段,然后再分配所有的 .rdata 段。
data.o(.data)
指定包含obj文件中的某个段
SECTIONS {
.text : { *(.text) }
.DATA : { [A-Z]*(.data) }
.data : { *(.data) }
.bss : { *(.bss) }
}
输入段的通配符的用法。有点类似shell的正则表达式,不过这里很简单。
.bss { *(.bss) *(COMMON) }
一般需要包含 COMMON段。
--gc-sections
(garbage section)
用来标记没有用的段。连接器可以通过关键字 KEEP 来防止删除。
Output Section LMA
LMA的用法,这里比较重要,是设置装在地址的。默认是 VMA 和 LMA是同一个地址的。
SECTIONS
{
.text 0x1000 : { *(.text) _etext = . ; }
.mdata 0x2000 :
AT ( ADDR (.text) + SIZEOF (.text) )
{ _data = . ; *(.data); _edata = . ; }
.bss 0x3000 :
{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;}
}
例子, 其中ADDR返回的是MVA段的开始地址,SIZEOF返回的是段的大小。
相应的RUN TIME初始化代码可以这样来处理
extern char _etext, _data, _edata, _bstart, _bend;
char *src = &_etext;
char *dst = &_data;
/* ROM has data at end of text; copy it. */
while (dst < &_edata) {
*dst++ = *src++;
}
/* Zero bss */
for (dst = &_bstart; dst< &_bend; dst++)
*dst = 0;