0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

uboot开启地址无关后的重定位地址操作

麦辣鸡腿堡 来源:CSDN博客 作者:内核新视界 2023-12-07 11:25 次阅读

开启地址无关后的重定位地址操作

在由save_boot_params跳转回save_boot_params_ret后启动流程继续往下执行来到下面代码段:

save_boot_params_ret:

#if CONFIG_POSITION_INDEPENDENT
    /* Verify that we're 4K aligned.  */
    adr x0, _start
    ands x0, x0, #0xfff --------------------------------------------------------- (1)
    b.eq 1f
0:
    /*
     * FATAL, can't continue.
     * U-Boot needs to be loaded at a 4K aligned address.
     *
     * We use ADRP and ADD to load some symbol addresses during startup.
     * The ADD uses an absolute (non pc-relative) lo12 relocation
     * thus requiring 4K alignment.
     */
    wfi
    b 0b
1:

    /*
     * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
     * executed at a different address than it was linked at.
     */
pie_fixup:
    adr x0, _start  /* x0 < - Runtime value of _start */
    ldr x1, _TEXT_BASE  /* x1 < - Linked value of _start */
    subs x9, x0, x1  /* x9 < - Run-vs-link offset */
    beq pie_fixup_done ------------------------------------------------------------- (2)
    adrp    x2, __rel_dyn_start     /* x2 < - Runtime &__rel_dyn_start */ ----------- (3)
    add     x2, x2, #:lo12:__rel_dyn_start
    adrp    x3, __rel_dyn_end       /* x3 < - Runtime &__rel_dyn_end */
    add     x3, x3, #:lo12:__rel_dyn_end
pie_fix_loop: ---------------------------------------------------------------------- (4)
    ldp x0, x1, [x2], #16 /* (x0, x1) < - (Link location, fixup) */
    ldr x4, [x2], #8  /* x4 < - addend */
    cmp w1, #1027  /* relative fixup? */
    bne pie_skip_reloc
    /* relative fix: store addend plus offset at dest location */
    add x0, x0, x9
    add x4, x4, x9
    str x4, [x0]
pie_skip_reloc:
    cmp x2, x3
    b.lo pie_fix_loop
pie_fixup_done:
#endif

此部分的功能主要是在定义POSITION_INDEPENDENT后,进行地址无关的相对地址修复,以此保证后续在跳入c语言部分时可正常执行,一般不定义此配置则是继续往下执行boot流程。

  • • (1)正如在链接脚本中说的,地址无关功能最基本需要保证加载地址是4K对齐的,经过一些测试发现某些情况需要64K对齐,这里不展开说明。此处使用adr指令获取_start的运行时地址并检验是否是4K对齐,如果是则继续往下执行,如果不是则调用wfi指令挂死在此处。wfi为等待中断指令,只有在接收到中断事件是才会唤醒cpu继续往下执行。(补充一个知识点:wfi指令只能被中断唤醒,wfe指令可以被sev指令唤醒也可以被中断唤醒)
  • • (2)通过对运行时地址和加载地址相减得到一个地址偏移值,如果偏移值等于0,说明加载地址和运行时地址是一致的不需要进行地址修复,则直接跳pie_fixup_done继续下面流程初始化,否则就进入地址修复逻辑。
  • • (3)首先需要说明为什么不使用adr指令而是adrp指令,adr指令是一个小范围读相对pc指针地址内存的指令,可以使用adr说明读取的地址一定是离pc指针很近的位置,而当读取__rel_dyn_start这种并不能确定实际地址在哪里的地址时则只能使用大范围读地址指令的adrp指令,不过adrp指令是以页为单位进行读取的,所以add x2, x2, #:lo12:__rel_dyn_start的作用就是将__rel_dyn_start地址的页内偏移读取出来并与页对齐的运行地址相加得到实际的运行地址。(此操作指令在Linux上被封装为adr_l指令)
  • • (4)在对地址修复分析时,首先需要了解一个elf动态库重定位的知识点,先来看一个结构体定义:
typedef struct {
        Elf64_Addr      r_offset;
        Elf64_Xword     r_info;
        Elf64_Sxword    r_addend;
} Elf64_Rela;

当对动态库进行地址重定向时首先会去查找rela.dyn段中的信息,此段中每一组信息就是上面结构体定义的信息,对于64为系统的elf则是24字节为一个表,r_offset保存需要重定位作用的地址位置,r_info描述此表重定位类型此类型特定于处理器,如arm64位则是:

/* AArch64 relocs */
#define R_AARCH64_NONE  0 /* No relocation */
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base */

r_addend是一个常量加数,用于计算存储在可重定位字段中的值。 对表进行重定位有以下公式:

重定位为值 = *(r_offset + 实际偏移值) = 实际偏移值 + r_addend。

根据此公式则可以重定向每一个需要重定向的地址值。

因此在此处同样是如此,x0保存r_offset值,x1保存r_info值,x4保存r_addend,并通过x1与R_AARCH64_RELATIVE比较看是否属于aarch64相对地址类型,如果不是则不是需要重定向的一组表则跳到pie_skip_reloc判断是否完成所有rela.dyn段重定向,如果是则继续往下执行启动流程初始化,如果不是则跳回pie_fix_loop继续下一组表的重定向。

当判断属于aarch64相对地址类型时进入重定向逻辑,首先需要知道x9是运行地址减去链接地址得到的偏移地址,那么实际运行地址也等于链接地址加上x9,所以add x0, x0, x9,add x4, x4, x9,x0是需要修复的重定位运行地址,x4是实际运行时需要附加的常量值,根据上面的公式,将x4这个由附加常量值加偏移值得到的运行时附加常量值写入到x0这个运行时重定向地址即可完成整个重定向修复功能。

此处没有实际代码或者流程图展示,逻辑比较绕,大致逻辑就是根据重定向段中每24个字节组成的一个表读取出实际需要进行重定向的地址,将这个地址的运行地址找出来并往这个地址写入附加常量值加偏移值即可完成一次重定向。在完成段中所有重定向后此时地址已经被修复好了,后续调用任何绝对地址引用的指令也不会出问题了。当然这个操作是耗时的,一般也不会有board会开启此功能。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9021

    浏览量

    366383
  • Uboot
    +关注

    关注

    4

    文章

    125

    浏览量

    28122
  • ARMv8
    +关注

    关注

    1

    文章

    35

    浏览量

    14130
收藏 人收藏

    评论

    相关推荐

    操作系统中的逻辑地址和物理地址

    本文是关于操作系统中逻辑地址和物理地址之间的区别。计算机操作系统中的内存使用两种不同类型的地址;物理地址
    发表于 09-14 14:26 3835次阅读

    uboot定位与搬移地址冲突

    是在板子目录下的config.mk中定义的,也就是说程序在sdram中的运行地址应该就是CONFIG_SYS_TEXT_BASE中指定的数字,但board_init_f程序执行的搬移地址
    发表于 07-08 05:45

    定位与链接脚本的使用方法

    嵌入式知识-ARM裸机-学习笔记(4):定位与链接脚本的使用一、定位1. 一些基本概念的引入位置有关编码: 汇编源码编码成二进制可执行程序
    发表于 12-23 07:12

    ARM裸机篇(三)——定位地址无关

    1、ARM定位地址无关码在上一节中,我们将第一个裸机程序编译,然后将映像文件
    发表于 04-15 17:56

    ARM裸机定位的目的是什么?如何实现

    脚本中加入AT()来指定加载地址,以防止编译出的代码过大。 链接脚本中,指定程序运行地址位于SDRAM,上电从片内0地址开始运行,所以
    发表于 05-16 14:32

    ARM为什么需要定位?如何去实现呢

    的// 汇编最后的这个死循环不能丢 b . 总结:由上面我们可以看到:定位的时候,先使用一段位置无关码来对重定位地址那里的内存进行一些
    发表于 05-18 16:42

    IP地址及网卡MAC地址操作指南

      为便于各分公司及部门统计IP地址及网卡MAC地址,请按照以下步骤操作:   1、 点击“开始”,选择运行。   2、在“运行”中输入“cmd”,并点击
    发表于 09-03 16:12 0次下载

    IP地址,IP地址是什么意思

    IP地址,IP地址是什么意思 基本定义 IP地址都是一个十分要的概念,INTERNET的许多服务和特点都是通过IP地址体现出来的。
    发表于 04-03 15:12 1666次阅读

    ATM地址,ATM地址是什么意思

    ATM地址,ATM地址是什么意思 异 步传输模式(ATM)使用地址来确定和定位ATM设备。在ATM中,地址是呼叫建立过程中通过UNI信令确
    发表于 04-06 16:00 1513次阅读

    stm32位带操作及内存地址

    位待操作地址STM32地址地址、总线地址、寄存器地址是什么基
    发表于 01-12 18:21 1次下载
    stm32位带<b class='flag-5'>操作</b>及内存<b class='flag-5'>地址</b>

    伺服定位时如何切换定位地址

    在使用伺服的定位功能是,通常会有多个不同的定位地址,常用的处理方法是只写一个定位指令,然后把地址数据做成参数,每次要用时先传输
    的头像 发表于 05-23 10:03 900次阅读
    伺服<b class='flag-5'>定位</b>时如何切换<b class='flag-5'>定位</b><b class='flag-5'>地址</b>?

    虚拟地址翻译物理地址的流程有哪些呢?

    现代的操作系统将可执行文件加载,创建了进程,进程中每一条指令和数据都被分配了一个虚拟地址,CPU获取到这个虚拟地址,需要翻译成内存的物理
    的头像 发表于 08-14 10:30 1198次阅读
    虚拟<b class='flag-5'>地址</b>翻译物理<b class='flag-5'>地址</b>的流程有哪些呢?

    RA Flash地址绝对定位

    RA Flash地址绝对定位
    的头像 发表于 10-26 18:24 697次阅读
    RA Flash<b class='flag-5'>地址</b>绝对<b class='flag-5'>定位</b>

    IP地址定位与GPS定位:技术解析与应用比较

    IP地址定位和GPS定位是比较常见的定位技术。本文将与大家探讨这两种技术的工作原理、优缺点及其在实际应用中的比较和融合。 IP地址
    的头像 发表于 07-16 13:50 307次阅读

    GPS定位与IP地址定位的互联策略

    虽然GPS定位和IP地址定位在原理、精度以及应用场景上存在差异,但如果有一种互联的策略实施,两者的优势可以互补,由此也可以构建起更为灵活的定位解决方案。 GPS
    的头像 发表于 10-11 10:03 185次阅读