uboot 位置无关基础

转载 2013年12月01日 22:37:51

ARM的位置无关程序设计

作者:李智敏,华清远见嵌入式学院上海中心讲师。

ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运 行,其设计方法在嵌入式应用系统开发中具有重要的作用。尤其在裸机状态下开发Bootloader程序及进行内核初始化设计;利用位置无关的程序设计方法 还可以在具体应用中用于构建高效率动态链接库,因而了解位置无关的程序设计方法,有助于开发人员设计出结构简单、清晰的应用程序。

应用程序必须经过编译、汇编和链接后才变成可执行文件,在链接时,要对所有目标文件进行重 定位(relocation),建立符号引用规则,同时为变量、函数等分配运行地址。当程序执行时,系统必须把代码加载到链接时所指定的地址空间,以保证 程序在执行过程中对变量、函数等符号的正确引用,使程序正常运行。在具有操作系统的系统中,重定位过程由操作系统自动完成。

在设计Bootloader程序时,必须在裸机环境中进行,这时Bootloader映像 文件的运行地址必须由程序员设定。通常情况下,将Bootloader程序下载到ROM的0x0地址进行启动,而在大多数应用系统中,为了快速启动,首先 将Bootloader程序拷贝到SDRAM中再运行。一般情况下,这两者的地址并不相同,程序在SDRAM中的地址重定位过程必须由程序员完成。实际 上,由于Bootloader是系统上电后要执行的第一段程序,Bootloader程序的拷贝和在这之前的所有工作都必须由其自身来完成,而这些指令都 是在ROM中执行的。也就是说,这些代码即使不在链接时所指定的运行时地址空间,也可以正确执行。这就是位置无关代码,它是一段加载到任意地址空间都能正 常执行的特殊代码。

位置无关代码常用于以下场合:
        程序在运行期间动态加载到内存;
        程序在不同场合与不同程序组合后加载到内存(如共享的动态链接库);
        在运行期间不同地址相互之间的映射(如Bootloader程序)。

虽然在用GCC编译时,使用-fPIC选项可为C语言产生位置无关代码,但这并不能修正程序设计中固有的位置相关性缺陷。特别是汇编语言代码,必须由程序员遵循一定的程序设计准则,才能保证程序的位置无关性。

ARM程序的位置无关可执行文件PIE(PositionIndependent Executable)包括位置无关代码PIC和位置无关数据PID(PositionIndependent Data)两部分。

PID主要针对可读写数据段(.data段),其中保存已赋初值的全局变量。为实现其位置 无关性,通常使用寄存器R9作为静态基址寄存器,使其指向该可读写段的首地址,并使用相对于基址寄存器的偏移量来对该段的变量进行寻址。这种方法常用于为 可重入程序的多个实例产生多个独立的数据段。在程序设计中,一般不必考虑可读写段的位置无关性,这主要是因为可读写数据主要分配在SDRAM中。

PIC包括程序中的代码和只读数据(.text段),为保证程序能在ROM和SDRAM空间都能正确运行(如裸机状态下的Bootloader程序),必须采用位置无关代码程序设计。

PIC遵循只读段位置无关ROPI(ReadOnly Position Independence)的ATPCS(ARMThumb Procedure Call Standard)的程序设计规范:

(1) 程序设计规范1  

引用同一ROPI段或相对位置固定的另一ROPI段中的符号时,必须是基于PC的符号引用,即使用相对于当前PC的偏移量来实现跳转或进行常量访问。  

① 位置无关的程序跳转。在ARM汇编程序中,使用相对跳转指令B/BL实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置进行跳转,实现位置无关性。  

另外,还可使用ADR或ADRL伪指令将地址标号值读取到PC中实现程序跳转。这是因为ADR或ADRL等伪指令会被编译器替换为对基于PC的地址值进行操作,但这种方式所能读取的地址范围较小,并且会因地址值是否为字对齐而异。  

但在ARM程序中,使用LDR等指令直接将地址标号值读取到PC中实现程序跳转不是位置无关的。例如:  LDR PC, =main  

上面的伪指令编译后的结果为:  LDR PC, [PC, OFFSET_TO_LPOOL]
                                                              LPOOL 
                                                                                DCD main  

可见,虽然LDR是把基于PC的一个存储单元LPOOL的内容加载到PC中,但该存储单元中保存的却是链接时所决定的main函数入口的绝对地址,所以main函数实际所在的段不是位置无关。  

② 位置无关的常量访问。在应用程序中,经常要读写相关寄存器以完成必要的硬件初始化。为增强程序的可读性,利用EQU伪指令对一些常量进行赋值,但在访问过程中,必须实现位置无关性。下面以PXA270的GPIO初始化介绍位置无关的常量访问方法。

GPIO_BASE EQU 0x40e00000; GPIO基址寄存器地址
        GPDR0 EQU 0x00c; 相对于GPIO基址寄存器的偏移量
        init_GPDR0 EQU 0xfffbfe00; 寄存器GPDR0初值
        LDR R1, =GPIO_BASE  
        LDR R0, =init_GPDR0
        STR R0, [R1, #GPDR0]

上述汇编代码段经编译后的结果为:

LDR R1, [PC, OFFSET_TO_GPIO_BASE]
        LDR R0, [PC, OFFSET_TO_init_GPDR0]
        STR R0, [R1, #0xc]
        GPIO_BASE
        DCD 0x40e00000 
        GPDR0
        DCD 0x00c 
        init_GPDR0
        DCD 0xfffbfe00  

可见,LDR伪指令实际上使用基于PC的偏移量来对符号常量GPIO_BASE和 init_GPDR0进行引用,因而是位置无关的。由此可以得出如下结论:使用LDR伪指令将一个常量读取到非PC的其他通用寄存器中可实现位置无关的常 量访问;但将一个地址值读取到PC中进行程序跳转时,跳转目标则是位置相关的。

(2) 程序设计规范2  

其他被ROPI段中的代码引用的必须是绝对地址,或者是基于可读写位置无关(RWPI)段的静态基址寄存器的可写数据。  

使用绝对地址只能引用被重定位到特定位置的代码段中的符号,通过在位置无关代码中引入绝对 地址,可以让程序跳转到指定位置。例如,假设Bootloader的阶段1将其自身代码拷贝到链接时所指定的SDRAM地址空间后,当要跳转到阶段2的C 程序入口时,可以使用指令“LDR PC, =main”跳转到程序在SDRAM中的main函数入口地址开始执行。这是因为程序在编译链接时给main函数分派绝对地址,系统通过将main函数的 绝对地址直接赋给PC实现程序跳转。如果使用相对跳转指令“B main”,那么只会跳转到启动ROM内部的main函数入口(这种情况反而不能写 B main了,但要写之前是不是之前 写一句 ldr pc,= xx也可以?by imjacob)。

位置无关码、位置有关码、链接地址、加载地址

在移植 uboot 时,接触到一个概念叫做 位置无关码,那么与它对应的就是位置有关码。提到这两个概念就还得提一提链接地址、加载地址。     链接地址,链接脚本里指定的,理论上程序运行时所处的地址。在...
  • lizuobin2
  • lizuobin2
  • 2016年07月27日 23:48
  • 2018

bootloader与linux中位置无关代码的分析理解

声明本文转载http://blog.csdn.net/zhou1232006/article/details/6215361的文章,由于这段时间要深入的分析linux各个环节想收集点资料 首先,需要...
  • Soar_dream
  • Soar_dream
  • 2016年06月05日 22:55
  • 1133

位置无关(PIC)代码原理剖析

共享库的一个关键目的是为了使多个进程能够共享内存中的同一份代码拷贝,已达到节约内存资源的目的。如何做到呢?一种方法是预先为每一个共享库指定好加载的地址范围,然后要求加载器总是将共享库加载至指定的位置。...
  • loushuai
  • loushuai
  • 2016年01月10日 20:32
  • 1920

编译链接之----地址无关代码(PIC)总结

动态链接的进程空间分布:动态链接库的最终装载地址在编译的时候并不能确定,而是在装载时,装载器根据当前进程地址空间的空闲情况,动态的分配一块足够大小的地址空间给动态链接库。 这样对地址的引用就可以采用地...
  • keep_moving_cqu
  • keep_moving_cqu
  • 2013年11月10日 01:28
  • 2258

位置无关代码码与位置相关代码

位置无关代码码与位置相关代码     位置无关与位置相关代码是关于arm程序在跳转时的寻址方式的两种,一般情况下两种方法都能达到跳转到目的地址的目标,但是在某些特定的环境下,两种跳转方法得到的结果相...
  • zhaigch
  • zhaigch
  • 2014年09月20日 17:58
  • 1184

共享库中的位置无关代码(PIC)

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-li...
  • wuhui_gdnt
  • wuhui_gdnt
  • 2016年04月08日 11:11
  • 1863

uboot中位置无关代码的程序设计

ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。本文首先 介绍位置无关代码的基本概念和实现原理,然后阐述基于A...
  • upc886
  • upc886
  • 2017年12月19日 22:05
  • 5

ARM的位置无关程序设计

ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。尤其在裸机状态下开发Bootloader程序及进行内核初始化设计;...
  • arick2013
  • arick2013
  • 2015年11月11日 00:05
  • 500

uboot中位置无关代码的程序设计

ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运行,其设计方法在嵌入式应用系统开发中具有重要的作用。本文首先 介绍位置无关代码的基本概念和实现原理,然后阐述基于AR...
  • u010661782
  • u010661782
  • 2015年10月10日 10:53
  • 323

uboot位置无关码码

RM的位置无关程序设计 作者:李智敏,华清远见嵌入式学院上海中心讲师。 ARM处理器支持位置无关的程序设计,这种程序加载到存储器的任意地址空间都可以正常运 行,其设计方法在嵌入式应用系统开...
  • wenxiHuang
  • wenxiHuang
  • 2017年05月20日 22:29
  • 66
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uboot 位置无关基础
举报原因:
原因补充:

(最多只允许输入30个字)