u-boot-spl.lds链接脚本文件,为编译器在编译过程中,依照该链接脚本,指定了SPL代码在SRAM中的链接地址。在嵌入式开发环境中,SRAM空间极其有限的时候,分析lds链接脚本,了解SPL代码在SRAM中的布局,尤为重要,当SRAM空间略微不足的,我们可以通过修改链接脚本加以适当调整。
分析lds脚本,请结合该链接脚本编译后生成的
u-boot-spl.map文件同步对比分析。该文件就是依照该链接脚本将SPL所有代码链接之后的map文件。可见就是按照lds文件指定的地址存放。
Linker script and memory map
.text 0x0000000040300000 0xf510
0x0000000040300000 __start = .
*(.vectors)
.vectors 0x0000000040300000 0x60 arch/arm/lib/built-in.o //可知最开始的代码路径
0x0000000040300000 _start
0x0000000040300020 _undefined_instruction
0x0000000040300024 _software_interrupt
0x0000000040300028 _prefetch_abort
0x000000004030002c _data_abort
0x0000000040300030 _not_used
0x0000000040300034 _irq
0x0000000040300038 _fiq
下面以TI J6中uboot中额u-boot-spl.lds(编译后)文件分析:
MEMORY { .sram : ORIGIN = 0x40300000, LENGTH = ((0x4037E000 - 0x00000400) - 0x40300000) }
MEMORY { .sdram : ORIGIN = 0x80a00000, LENGTH = 0x80000 }
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
.text :
{
__start = .;
*(.vectors)
arch/arm/cpu/armv7/start.o (.text*)
*(.text*)
}
>.sram
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) }
>.sram
. = ALIGN(4);
.data : { *(SORT_BY_ALIGNMENT(.data*)) }
>.sram
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
>.sram
. = ALIGN(4);
__image_copy_end = .;
.end :
{
*(.__end)
}
.bss :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
. = ALIGN(4);
__bss_end = .;
}
>.sdram
}
0.
MEMORY { .sram : ORIGIN = 0x40300000, LENGTH = ((0x4037E000 - 0x00000400) - 0x40300000) }
MEMORY { .sdram : ORIGIN = 0x80a00000, LENGTH = 0x80000 }
ORIGIN 指定J6内部SRAM的内存区域起始地址为0x40300000 ,LENGTH指定内存区域长度
1.
OUTPUT_FORMAT(
"elf32-littlearm"
,
"elf32-littlearm"
,
"elf32-littlearm"
)
/*指定输出可执行文件是elf格式,32位ARM指令,小端*/
OUTPUT_ARCH(arm)
/*指定输出可执行文件的平台为ARM*/
2.
ENTRY(_start)指定了该spl程序的入口地址为_start
关于入口点:
在程序运行时第一个被执行的指令称为“入口点”
有多种不同的方法来设置入口点,连接器会通过按顺序尝试以下的方法来设置入口点,如果成功了就会停止。
1)'-e' 入口命令行选项
2)连接脚本中的‘ENTRY(SYMBOL)’
3)如果定义了start,就使用start的值
4)如果存在,就是用‘.text’的首地址
5)地址'0'
3..text 定义text段,text段代表可执行程序的代码段,(接口函数)
.text :
{
__start = .; //定义__start标号的地址为当前地址
*(.vectors) //放所有链接目标文件的vectors段
arch/arm/cpu/armv7/start.o (.text*) //
放start.o的代码段?
*(.text*) //放所有输入文件可执行程序的代码段
}
>.sram //指定是sram,即J6内部SRAM
4.调整定位到4字节对齐处 . = ALIGN(4);
5.rodata 只读数据段,通常存放只读数据,如常量,常量字符串和常量数据等
.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
6. .data 数据段,通常代表数组,变量,结构体等。
data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
7.u_boot_list段,通常u-boot cmd会在u_boot_list段
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
7.__image_copy_end 整个image结束的地址
在u-boot-spl.map中可知:
0x000000004031b360 __image_copy_end
0x0000000040300000 _start
可知长度为:0x0001b360
在编译出的MLO(spl+header)的最后8个字节包含了该信息:
60 B3 01 00
00 00 30 40
: 大小端表示0x40300000 和0x0001B360