一、链接地址与运行地址
链接地址: 链接时指定的地址。
运行地址: 程序运行时的实际地址。
链接地址在Makefile中用-Ttext
来指定(例如-Ttext 0x0f),运行地址由实际运行时加载的内存地址决定。如果运行地址必须设置为链接地址,这就叫位置有关码,否则称为位置无关码。
二、程序段的概念
- 段包括代码段,数据段,bss段(ZI段)和自定义段。
- 段就是程序的一部分,我们把整个程序分成了一个一个段,给每个段起个名字,然后在链接时就可以用这个名字来指示这些段。也就是说给段命名就是为了在链接脚本中用段名来让段站在合适的位置。
- 代码段(.text),又叫文件段,其实就是函数编译后生成的文件
- 数据段(.data),就是C语言中有显式初始化为非0的全局变量
- bss段(.bss),又叫ZI(zero initial)段,就是零初始化段,对应C语言中初始化为0的全局变量
- 自定义段:段名由程序员自己定义,段的属性和特征也由程序员自己定义
三、链接脚本
- 链接脚本是一个规则文件,它是程序员指挥链接器工作的。
- 链接器会参考链接脚本,并且使用其中规定的规则来处理.o文件中的那些段,将其链接成一个可执行程序。
- 链接脚本的关键内容有两部分:段名 + 地址(作为链接地址的内存地址)
- 例如下面的uboot的链接脚本,所有说明直接写到脚本中
/*指定输出可执行文件是elf格式,32位ARM指令,小端*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm) /*输出为ARM*/
ENTRY(_start) /*起始代码段为_start*/
SECTIONS
{
. = 0x00000000; /*从0x0位置开始*/
. = ALIGN(4); /*4字节对齐*/
.text :
{
cpu/s5pc11x/start.o (.text) /*依次定义程序运行的先后顺序*/
cpu/s5pc11x/s5pc110/cpu_init.o (.text)
board/samsung/x210/lowlevel_init.o (.text)
cpu/s5pc11x/onenand_cp.o (.text)
cpu/s5pc11x/nand_cp.o (.text)
cpu/s5pc11x/movi.o (.text)
common/secure_boot.o (.text)
common/ace_sha1.o (.text)
cpu/s5pc11x/pmic.o (.text)
*(.text) /*其它代码部分*/
}
. = ALIGN(4);
.rodata : { *(.rodata) } /*只读数据段*/
. = ALIGN(4);
.data : { *(.data) } /*读/写数据段*/
. = ALIGN(4);
.got : { *(.got) } /*指定got段, got段式是uboot自定义的一个段, 非标准段*/
__u_boot_cmd_start = .; /*设置u_boot_cmd段起始位置*/
.u_boot_cmd : { *(.u_boot_cmd) } /*指定u_boot_cmd段, 将所有的uboot命令放在该段.*/
__u_boot_cmd_end = .; /*设置u_boot_cmd段结束位置*/
. = ALIGN(4);
.mmudata : { *(.mmudata) } /*mmu(内存管理单元)段*/
. = ALIGN(4);
__bss_start = .; /*把bss段的开始位置*/
.bss : { *(.bss) } /*指定bss段*/
_end = .; /*bss段的结束位置*/
}
下面是uboot编译最后的链接命令
arm-none-linux-gnueabi-ld -Bstatic -T /root/workspace/qt_x210v3/uboot/board/samsung/x210/u-boot.lds \
-Ttext 0xc3e00000 $UNDEF_SYM cpu/s5pc11x/start.o \
--start-group lib_generic/libgeneric.a 省略部分输出 \
--end-group -L /opt/arm-2009q3/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.1 \
-lgcc -Map u-boot.map -o u-boot
由上可知,其引用了链接脚本的规划,设置链接地址为我们设置的0xc3e00000
,上电启动后,第一阶段的代码就会把u-boot自身搬运到内存的0xc3e00000
位置去运行。