1 运行地址/链接地址
根据参考资料[1]的说明,运行地址和链接地址是等价的,只是两个不同的说法而已,指的是程序在SRAM、SDRAM中执行时的地址,就是执行这条指令时,PC应该等于这个地址,换句话说,PC等于这个地址时,这条指令应该保存在这个地址内[1]。
2 加载地址/存储地址
根据参考资料[1]的说明,加载地址和存储地址是等价的,只是两个不同的说法而已,指的是程序保存在Nand Flash中的地址。
3 实例分析
编译U-Boot后,可以查看在顶级目录所生产的System.map了解各个符号的链接地址,也可以查看u-boot.map了解各个目标文件的连接顺序其连接地址,详见《U-Boot编译——System.map与u-boot.map》。
这里以u-boot-2010.03为例进行详细分析。将U-Boot配置成smdk2410开发板的默认配置,然后编译,得到其System.map前3行内容如下:
33f80000 T _start 33f80020 t _undefined_instruction 33f80024 t _software_interrupt ...由上可见,U-Boot被链接到地址 0x33f80000开始的地方,入口为 _start。那么这个链接地址是在哪里配置,又如何生效的呢?
3.1 u-boot.lds
u-boot.lds中指定的了链接的段和地址,详见《U-Boot源码——u-boot.lds》,其中部分内容如下:
SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { arch/arm/cpu/arm920t/start.o (.text) *(.text) ... }由上面第3行可见,指定链接的起始地址为 0x00000000,第8行指定链接到最前面的目标文件为 start.o。
将start.o到最前面倒是没错,但是起始地址为0x00000000就与System.map的结果不对应了(应该为0x33f80000),为什么呢?
3.2 config.mk
关于config.mk,详见《U-Boot源码——config.mk》,这里只是简单引用其部分内容进行说明。
3.2.1 开发板相关config.mk
参考资料[4]指出,链接时是根据开发板相关的config.mk指定的代码段起始地址以及u-boot.lds链接脚本进行链接[4]p257。
smdk2410的config.mk内容如下:
# SMDK2410 has 1 bank of 64 MB DRAM # # 3000'0000 to 3400'0000 # # Linux-Kernel is expected to be at 3000'8000, entry 3000'8000 # optionally with a ramdisk at 3080'0000 # # we load ourself to 33F8'0000 # # download area is 3300'0000 # TEXT_BASE = 0x33F80000由于上可见,smdk2410的DRAM地址范围为0x30000000~0x340000000, TEXT_BASE即为U-Boot代码段的起始地址,也就是链接的起始地址,其值正好与上述System.map的第1行的地址一致。
既然找了设置链接地址的位置,那么TEXT_BASE是如何生效的呢?
3.2.2 顶级config.mk
在顶级目录的config.mk中,有如下内容:
LDFLAGS += -Bstatic -T $(obj)u-boot.lds $(PLATFORM_LDFLAGS) ifneq ($(TEXT_BASE),) LDFLAGS += -Ttext $(TEXT_BASE) endif上面第3行通过 -Text TEXT_BASE,将链接地址添加到 LDFLAGS中。
3.3 Makefile
在顶级目录的Makfile中,有如下内容:
GEN_UBOOT = \ UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ -Map u-boot.map -o u-boot上面第4行引用到了 LDFLAGS,从而使得 TEXT_BASE所指定的代码段首地址生效。
参考资料
[1]链接地址和运行地址
[2]U-Boot移植过程中的运行地址和装载地址的区别
[3]运行地址,链接地址,加载地址,存储地址 位置无关码、位置有关码
[4]伟东山. 嵌入式Linux应用开发完全手册. 人民邮电出版社,2012