1.什么是链接脚本?
链接器的作用主要有两个:
a.符号的解析
b.符号与地址的绑定
如何解析、如何绑定,这就涉及到链接脚本的作用了。通常链接器都有一个默认的链接脚本,大多数情况下,使用它来链接输入文件,并生成目标文件。我们也可以使用自定义的链接脚本来精确控制目标文件的格式。链接器的"-T"参数就是用来指定链接脚本的。
2.VMA与LMA
VMA:虚拟地址,就是我们通常所讲的虚拟地址
LMA:加载地址,即被加载到内存中的地址
对于应用程序来说,VMA与LMA时一致的。对于内核来说,LMA=VMA-0xC0000000。
内核虚拟地址 = 物理地址 + 0xC0000000。
3.ENTRY条目
指定了入口地址
4.链接脚本符号“.”
“.”是个位置计数器,记录着当前位置在目标文件中的虚拟地址;
“.”是个自动增加的计数器,当一个输出section生成后,会自动加上该section的长度
举例:
. = 0x100000;
_start_addr = .;
.text : {*(.text)}
_end_addr = .;
在此例中,首先给“.”赋初值0x100000,随后又将该值赋给_start_addr,它是.text section的起始地址;接着我们生成了一个.text section,此时"."自动加上该section的长度。
可描述为 . = . + SIZEOF(.text);最后将"."赋给_end_addr,记录下.text section的结束地址。
5.如何构造一个section?
.text.head : AT(ADDR(.text.head) - LOAD_OFFSET){
_text = .;
*(.text.head)
} : text = 0x9090
.text.head指定了section的名称;
AT指定了section的加载地址(LMA);
ADDR(section):计算section的虚拟地址;
对于Linux内核,LOAD_OFFSET为0xC0000000;
在此处,LMA = ADDR(.text.head) - LOAD_OFFSET.也就是物理地址;
*(.text.head)完成具体的section创建工作:“*”代表所有的.o输入文件,括号中.text.head指定了链接器感兴趣的sectiong,即所有.o输入文件中的.text.head section都被合并;
_text = . 指定了起始地址
“: text”指定了新生成的section所在的segment
“= 0x9090”指定了section的填充内容,用于代码对齐,0x90是汇编指令中NOP的操作码,故相当于在不连续的代码间填充空操作;
总结:
至此内核的第一个section就创建好了,它名为“.text.head”,由输入文件的.text.head组成,该section的虚拟地址(VMA)由"."的值确定,加载地址(LMA)为物理地址,section中不连续的区域产生的间隙由0x9090填充,最后再将该section放入 text segment中;
6.创建一个section的完整格式
section [address] [(type)] : [AT (lma)]
{
output-section-command
......................
}[>region] [:phdr :phdr...] [= fillexp]
其中:
[address]指定了section的虚拟地址(vma)
若没有指定该参数及region参数,则虚拟地址由"."指定
阅读(2037) | 评论(1) | 转发(0) |