You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

u-boot ARMv8架构重定位相关汇编与链接脚本代码疑问

问题1:__rel_dyn_start符号的来源

__rel_dyn_start和对应的__rel_dyn_end是GNU链接器(ld)在链接阶段自动生成的隐式全局符号,不需要在链接脚本中显式定义:

  • 你贴的链接脚本里定义了三个连续的输出段:.rel_dyn_start、.rela.dyn、.rel_dyn_end,刚好把所有重定位表项夹在中间
  • GNU ld默认会为每一个自定义输出段生成对应起止地址的符号,规则是将输出段名开头的.替换为__作为符号前缀,这里.rel_dyn_start段的起始地址就对应__rel_dyn_start符号,.rel_dyn_end段的结束地址对应__rel_dyn_end符号,方便汇编/C代码直接引用段的边界地址。

问题2:重定位逻辑的核心解释

你的推测是对的,x9确实存储的是U-Boot实际运行地址和链接时预设地址的偏移量,这部分逻辑的细节如下:

1. cmp w1, #1027的含义

1027是ELF规范中定义的AArch64平台R_AARCH64_RELATIVE重定位类型的编号。
U-Boot的重定位表每一项是标准的AArch64 Elf64_Rela结构体,固定24字节,三个成员依次是:

  • r_offset(8字节):链接时计算的、需要修改重定位值的内存虚拟地址,对应代码里的x0
  • r_info(8字节):低32位存重定位类型,高32位存关联的符号索引,对应代码里的x1,所以取低32位w1和1027比较,就是筛选出相对重定位项
  • r_addend(8字节):重定位计算用的加数,对应代码里的x4
    U-Boot的PIE(位置无关执行)编译模式下,只会生成R_AARCH64_RELATIVE类型的重定位项,其他类型的重定位要么在编译阶段就处理完成,要么不需要运行时修正,所以匹配失败就直接跳过当前项。

2. 修正操作的逻辑

当确认是相对重定位项时:

  • 给x0加x9:x0是链接时的虚拟地址,加上重定位偏移x9后,得到实际运行时需要修改的物理内存地址
  • 给x4加x9:x4是基于链接地址计算的加数,加上重定位偏移x9后,得到实际运行时的正确值
  • 把修正后的x4写入修正后的x0指向的地址,就完成了当前重定位项的修正
    循环遍历整个重定位表(直到x2等于x3),就完成了所有地址的重定位修正。

内容的提问来源于stack exchange,提问作者Chan Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:36:03