Chinaunix首页 | 论坛 | 博客
  • 博客访问: 217632
  • 博文数量: 49
  • 博客积分: 2101
  • 博客等级: 大尉
  • 技术积分: 525
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-07 10:38
文章分类

全部博文(49)

文章存档

2010年(49)

我的朋友

分类: 嵌入式

2010-09-07 14:40:10

Uboot的在启动后,是要拷贝代码到ram中运行的。拷贝到内存的什么地方呢?

一开始,在网络上搜索,发现都说config.mk文件中定义的TEXT_BASE地址是拷贝到内存时的地址。

首先,在连接的时候确实有TEXT_BASE作为链接地址;

其次,TEXT_BASE确实是RAM的地址;

但是,发现一个问题,网上讨论的硬件基础都是arm,在arm的开发版中,都是flash的基址为0RAM的基址更高,这样TEXT_BASE刚好处于RAM的范围内,很好理解。

 

ppc,则不同。在start.s中,由relocate_code部分代码看出,实际上TEXT_BASEppc中反而成为了拷贝ubootram中的source addr。而目标地址需要看调用relocate_code()函数的地方即board_init_f (ulong bootflag)末尾。

但是,问题随之而来,uboot编译的时候,TEXT_BASE明明是做为链接地址的啊?

通过查看编译程序,对于board.c文件编译之后是首先和其它.o做成.a库文件才和start.o链接起来。但是依然不能解释我的疑问。

问了好几个人了,没人说的清,但是uboot肯定有自己的解决办法。

最有可能是uboot自己执行的时候去计算便宜量。

当然,如果此时启动了MMU功能,那么编译的链接地址就属于虚拟内存空间,而在物理内存中的位置是任意的,mmu会进行地址的转换。

继续讨论上面的问题,mmu功能当前肯定是没开的。

 

那答案何在?

这时看到了start.s中在拷贝结束后,使用了GOT这个东东?GOT,搜索了一下是Global offset table的缩写,在linux中,got技术用于动态链接。GOT 表中是各个函数的动态链接地址。所以uboot参考了linuxgot技术,使用了got表来保证rom拷贝到ram后程序能够在ram中执行。

另外,我发现在uboot中,只有ppc系列的cpu才会使用got技术,其它的cpu都没有使用。因为比如arm,它编译uboot时的连接地址就在ram中,所以拷贝到ramok了。但是偏偏ppcboot编译的连接地址是在flash中,所以需要使用got技术才能保证程序在ram中执行。

下述为从网上看到的讨论

 

如题

有朋友和我一样在读ppcboot的启动代码, 或者已经读过呢(我看的是mpc860)

我看到有关GOT的部分, 现在十分困惑. 经过近两周的分析和查找资料后, 初步有以下理解, 但是并没有弄清楚GOTppcboot中扮演的作用.






#define START_GOT
.section ".got2","aw";
.LCTOC1 = .+32768


#define END_GOT
.text

#define GET_GOT
bl 1f ;
.text 2 ;
0: .long .LCTOC1-1f ;
.text ;
1: mflr r14 ;
lwz r0,0b-1b(r14) ;
add r14,r0,r14 ;

#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME

#define GOT(NAME) .L_ ## NAME (r14)



宏定义在include/ppc_asm.tmpl
应用在start.S

我在网页上搜索到关于GOT的内容, 自然就关联到了ELFGOT, 我大致看了一下, 我想这两种应该是一样的, 就是ppcboot只是使用了GOT这种技术.

不知道我理解的对不对
GOT
是为了实现位置无关(position-independent)的代码. 例如在x86架构下, Linux系统下, 如果我们运行的程序调用了某个标准库, 当调用具体的函数时, 程序讲跳转到PLT, 然后从PIT跳转到GOT, 这样才会找到具体的库函数的位置.

但是我很困惑, ppcbootstart.S只有in_flash标签下才使用了一次"GET_GOT", 而在开始处定义的
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)

GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
GOT_ENTRY(transfer_to_handler)

GOT_ENTRY(_end)
GOT_ENTRY(.bss)
#if defined(CONFIG_FADS) || defined(CONFIG_ICU862)
GOT_ENTRY(environment)
#endif
END_GOT
我没有看到到底起了什么作用?

我迫切希望大家能一起讨论一下, 不明白一件事情, 真的很痛苦.

 

1

知道一点点,不知对否

START_GOT
END_GOT 里放的变量,是为了方便将来程序从ROM搬至RAMGOT表里放的应该是ROMRAM都需用到的变量,将来搬移时只需在它基础上加偏移量即可。

访问变量时看后面的GET_GOT
lwz r6, GOT(transfer_to_handler)

 

2

动态库要解决的一个问题是代码/变量地址在编译时不能确定,GOT就是用来解决这个问题的技术。
u-boot
运行时要从Flash搬到RAM高端,RAM大小是运行时检测出来的,编译时不能确定,这和动态库面对的问题相同,正好可以用GOT技术解决。

阅读(1313) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~