u-boot2016 ARMv8架构编译链接rela.dyn段理解

本文详细解析了 ARMv8 架构下 u-boot 的编译过程,特别是 rela.dyn 段的生成与作用。通过实例分析,介绍了如何解决 u-boot 移植过程中遇到的 rela.dyn 段缺失问题,包括链接参数 -pie 的使用,静态 rela.dyn 修复的方法,以及 c 文件中定义特定符号的重要性。

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29963649&id=5765650

 

序言

1.为什么写这篇文章

前段时间在做一个ARMv8的u-boot移植工作,接触到新版的u-boot2016,对其编译rela.dyn段摸摸索索一段时间,在网上找这方面的资料感觉不是很多。在移植基本完成后,想对其一番理解总结出来,对自己算是一个总结的过程,对大家若有遇到类似的问题或许有帮助。一举两得之事,何乐不为?

2.这方面的总结文章以前有哪些?

以下是我看到过的对此文阅读有帮助的博文:

uboot的relocation原理详细分析博主:做一个有技术追求的人

http://blog.youkuaiyun.com/skyflying2012/article/details/37660265

这篇博文写得不错,对ARM relocation原理的理解不仅有详细描述而且用实例测验了这些原理,很是深刻。非常推荐阅读并深入一番。

而我所接触的问题不仅仅是relocation原理理解的问题,还有ARMv8编译过程参数的问题。

 

U-boot ARMv8 board_init_r 之前流程分析

_main:

    bl board_init_f_alloc_reserve

    bl board_init_f_init_reserve

    bl board_init_f

 

adr lr, relocation_return

    ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd-="">reloc_off */

    add lr, lr, x9 /* new return address after relocation */

    ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd-="">relocaddr */

b relocate_code //进入relocation,但是relocation返回后仍是返回relocation_return,也就是这个语句之后

 

ENTRY(relocate_code)

copy_loop: //实现对代码段的copy到RAM

ldp x10, x11, [x1], #16 /* copy from source address [x1] */

stp x10, x11, [x0], #16 /* copy to   target address [x0] */

cmp x1, x2 /* until source end address [x2] */

b.lo copy_loop

str x0, [sp, #24]

/*

 * Fix .rela.dyn relocations

 */

ldr x2, =__rel_dyn_start /* x2 <- SRC &__rel_dyn_start */

ldr x3, =__rel_dyn_end /* x3 <- SRC &__rel_dyn_end */

fixloop: //以下这段就是对rela.dyn的内容重定向

ldp x0, x1, [x2], #16 /* (x0,x1) <- (SRC location, fixup) ,x0=[x2], x1=[x2+8],x2+=16*/

ldr x4, [x2], #8 /* x4 <- addend */ x4=[x2],x2+=8

and x1, x1, #0xffffffff

cmp x1, #1027 /* relative fixup?  1027=0x403*/

bne fixnext

由上可知x9 <- relocation offset

/* relative fix: store addend plus offset at dest location */

add x0, x0, x9

add x4, x4, x9

str x4, [x0] //*(x0+offs)=(x4+offs)

fixnext:

cmp x2, x3

b.lo fixloop

 

以下是rela.dyn的数据,

60144c00: 601001b0

60144c04: 00000000 x0=0x00000000601001b0,address

60144c08: 00000403

60144c0c: 00000000 x1=0x0000000000000403,type

60144c10: 601003d0 x2=0x0000000060344c10

60144c14: 00000000 x4=0x00000000601003d0,data

上面最后fixloop就是个根据rela.dyn段修复代码中的label(就是address的位置),address+offset后的值进行重定向,*(address+offset)=(data+offset)

对于AArch64架构,一组rela.dyn数据有3个64位数据组成,从上到下分别是需要重定向的原始地址,重定向类型,重定向的原始数据。

有了需要重定向的原始地址和重定向的原始数据、offset(偏移)就可以对需要重定向的标号,为什么还是type呢?原因是有很多类型的重定向,比如R_ARM_RELATIVE,R_ARM_ABS64。这些内容在百度可以查到。

 

 

ARMv8架构编译链接生成rela.dyn段

1.链接参数-pie

链接器根据-pie参数才会生成rela.dyn段,若移植的时候发生没有生成rela.dyn段,检查这个参数是否包含。

# needed for relocation

LDFLAGS_u-boot += -pie

本人在做项目的时候,因为是移植一个厂家的驱动到低版本的uboot,还不支持ARMv8架构,所以arch/arch目录也要移植,移植的时候加了这个参数,但是还是出现了问题。就是移植时没加这个参数时本身代码是可以运行到打印的,加了这个参数直接不能打印了。最后发现的原因就是下面要说的第二点静态rela.dyn修复这段命令没有增加。

 

2.静态rela.dyn修复

 

当时出现的现象生成的u-boot.bin中label直接为0,如下bin文件反汇编示意

bin文件反汇编示意

601001b0: 00000000 //称之为label

601001b4: 00000000

rela.dyn段

60144c00: 601001b0

60144c04: 00000000 x0=0x00000000601001b0,address

60144c08: 00000403

60144c0c: 00000000 x1=0x0000000000000403,type

60144c10: 601003d0 x2=0x0000000060344c10

60144c14: 00000000 x4=0x00000000601003d0,data

 

最后是通过Demo u-boot的编译过程发现了,还有使用relocate-rela工具对对u-boot.bin静态reloc的过程。命令如下:

# Statically apply RELA-style relocations (currently arm64 only)

ifneq ($(CONFIG_STATIC_RELA),)

# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base

DO_STATIC_RELA = \

start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \

end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \

tools/relocate-rela $(2) $(3) $$start $$end

else

DO_STATIC_RELA =

Endif

 

DO_STATIC_RELA动作生成的目标是u-boot-nodtb.bin

u-boot-nodtb.bin: u-boot FORCE

$(call if_changed,objcopy)

$(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))

$(BOARD_SIZE_CHECK)

 

 

3.c文件定义__bss_start等符号

除了上面两部,还有要注意的一点就是不能在lds链接文件中定义__bss_start,__bss_end等符号,一定要在c文件中定义。

char __bss_start[0] __attribute__((section(".__bss_start")));

char __bss_end[0] __attribute__((section(".__bss_end")));

char __image_copy_start[0] __attribute__((section(".__image_copy_start")));

char __image_copy_end[0] __attribute__((section(".__image_copy_end")));

char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));

char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));


        原因从arch/arm/lib/section.c文件的注释中可以得知

/**

 * These two symbols are declared in a C file so that the linker

 * uses R_ARM_RELATIVE relocation, rather than the R_ARM_ABS32 one

 * it would use if the symbols were defined in the linker file.

 * Using only R_ARM_RELATIVE relocation ensures that references to

 * the symbols are correct after as well as before relocation.

链接规则决定了c文件中定义的符号按R_ARM_RELATIVE类型链接,否则会按R_ARM_ABS32类型链接。使用R_ARM_RELATIVE类型才能确保引用这些符号的地方在搬移前也是正确的。

<think>好的,我现在需要解决用户在构建U-Boot时遇到的“ERROR: Nopython2”错误。用户之前的问题是关于缺少Python2导致的问题,所以我得先回想一下常见的解决方法。首先,用户可能在系统里没有安装Python2,或者默认的Python指向了Python3。现在很多Linux发行版默认使用Python3,而U-Boot的某些构建脚本可能依赖Python2。所以第一步应该是检查系统是否安装了Python2。可以通过在终端输入`python2--version`来确认。如果提示命令未找到,说明需要安装Python2。接下来,安装Python2。不同的Linux发行版有不同的包管理工具。例如,Ubuntu或Debian可以使用`sudo aptinstall python2`,而CentOS或Fedora可能需要用`yum`或`dnf`。安装完成后,再次检查版本确保安装成功。 然后,可能需要设置Python2为默认版本。因为系统可能默认使用Python3,导致构建脚本找不到Python2。这里可以使用`update-alternatives`命令来配置默认的Python版本。例如,运行`sudoupdate-alternatives--configpython`并选择Python2的路径。不过需要注意的是,更改系统默认Python版本可能会影响其他依赖Python3的应用程序,所以需要谨慎操作,或者仅在构建U-Boot时临时切换。另一种方法是在构建U-Boot时指定Python2的路径。如果用户不想更改系统默认设置,可以通过环境变量或构建参数告诉U-Boot使用特定的Python解释器。例如,在make命令中添加`PYTHON=python2`,这样构建脚本就会使用指定的Python2执行相关任务。 另外,用户可能需要安装Python2的相关开发工具或库。有时候,构建过程不仅需要Python解释器,还需要某些模块或头文件。例如,安装`python2-dev`或类似的包,确保所有依赖项都满足。还有可能的情况是U-Boot的版本问题。如果用户使用的是较新的U-Boot版本,可能已经开始支持Python3。这时候,可以查看官方文档或更新日志,确认是否有相关改动。如果有,可以尝试升级U-Boot到支持Python3的版本,避免安装旧的Python2环境。最后,用户可能遇到环境变量的问题。例如,PATH变量中没有包含Python2的路径,或者虚拟环境配置不正确。检查环境变量,确保构建脚本能够正确找到Python2的位置。总结下来,步骤大概是:安装Python2,设置默认版本或指定路径,安装相关依赖,检查U-Boot版本,处理环境变量。需要根据具体情况选择合适的方法,同时注意系统兼容性,避免影响其他应用。</think>### 解决构建 u-boot 时因缺少 Python2 导致的错误 #### 问题根源分析 u-boot 部分构建脚本依赖 Python2 解释器,当系统默认配置为 Python3 或未安装 Python2 时,会触发`ERROR: No python2`报错[^1]。 #### 逐步解决方案 1. **验证 Python2 是否存在** 终端输入: ```bash python2 --version ``` 若返回`Python 2.x.x`则跳过安装步骤,否则继续 2. **安装 Python2** - Ubuntu/Debian: ```bash sudo apt install python2 ``` - CentOS/RHEL: ```bash sudo yum install python2 ``` 3. **创建软链接(关键步骤)** ```bash sudo ln -s /usr/bin/python2 /usr/bin/python # 强制指定python指向python2 ``` > *注意:此操作会暂时覆盖系统默认python解释器,建议完成u-boot构建后恢复原配置* 4. **验证配置有效性** ```bash python --version # 应显示Python 2.x.x ``` 5. **恢复系统默认配置(可选)** 构建完成后执行: ```bash sudo ln -sf /usr/bin/python3 /usr/bin/python # 重新指向Python3 ``` #### 替代方案(推荐) 通过环境变量直接指定 Python2 路径,避免修改系统配置: ```bash export PYTHON=python2 make [your_target] # 构建时自动调用指定解释器 ``` #### 注意事项 - 若遇到`ImportError: No module named...`,需安装 Python2 的额外模块: ```bash sudo apt install python2-dev # 开发依赖包 ``` - 部分旧版 u-boot 可能要求特定 Python2 版本(如 2.7),可通过`python2 -V`确认版本 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值