U-Boot移植——链接地址、运行地址、加载地址、存储地址

0 前言

    U-Boot移植过程通常需要配置一些地址,因此本文对它们进行一些总结。

1 运行/链接地址

    根据参考资料[1]的说明,运行地址链接地址是等价的,只是两个不同的说法而已,指的是程序在SRAMSDRAM中执行时的地址,就是执行这条指令时,PC应该等于这个地址,换句话说,PC等于这个地址时,这条指令应该保存在这个地址内[1]。

    然而,根据参考资料[5]的分析,运行时地址链接地址有时候是不一致的[6],例如U-Boot启动时其_start标号的运行时地址0x00000000,但是其链接地址0x33f80000(见下文),因此可以通过判定运行时地址链接地址是否一致来判断U-Boot是在Nor Flash中与还是SDRAM中运行,这在代码重定位时会用到[4]P259。

    在代码重定位时,当然是按照参考资料[1]所说的,要将其重定位到SDRAM中与链接地址对应的地址处(其实用户可以定位到外部DRAM位置,但是运行时可能会出现不可预料的结果)。

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),为什么呢?答案是它其实是一个相对于下文TEXT_BASE的偏移地址。

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~0x340000000TEXT_BASE即为U-Boot代码段的起始地址,也就是链接的起始地址,其值正好与上述System.map的第1行的地址一致。

    既然找了设置链接地址的位置,那么TEXT_BASE是如何生效的呢?答案是它会被添加到下文的LDFLAGS中。

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_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

[5]从两句汇编认识运行时地址与链接地址

[6][BootLoader] 运行地址和链接地址不一致时如何用gdb进行调试?

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneSea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值