博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (三) 14 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 boot 详细解析3 relocate_code
阅读量:4286 次
发布时间:2019-05-27

本文共 6901 字,大约阅读时间需要 23 分钟。

adr lr, here // 存放 lr, 为  b(跳转) 做准备		ldr r0, [r9, #76] // 将 new_gd 中的 reloc_off 存放到r0,用作新的lr的计算		add lr, lr, r0 	 // 更改lr ,让 relocate_code 返回时,跳转到 已经 搬移好的代码 中去,		ldr r0, [r9, #56] // 将 new_gd 中的 relocaddr存放到r0,作为第一个参数		b relocate_code			// 搬移 u-boot的 code 段			arch/arm/lib/relocate.S +80			搬移,修复绝对地址???
  • arch/arm/lib/relocate.S
// 拷贝, 从哪里(__image_copy_start)到哪里(relocaddr,已经存放在r0中),拷贝多少.globl relocate_code ; .align 0 ; relocate_code:/**	拷贝**/ // 将 拷贝源 的开始地址 __image_copy_start 放到 r1 中 ldr r1, =__image_copy_start // 计算 目标地址和源地址 差值 ,放到 r4  subs r4, r0, r1 beq relocate_done  // 计算 拷贝源 的末端地址 ldr r2, =__image_copy_endcopy_loop: // 将源数据放到r10 r11 中 ldmia r1!, {
r10-r11} // 将 r10 r11 放到 目标地址中 stmia r0!, {
r10-r11} cmp r1, r2 blo copy_loop/** fix 指的是 对引用地址的修改 对.code段 引用地址(变量地址,函数地址,指针地址等) 的修改**/// 链接器根据-pie参数才会生成rel.dyn段 // fix .rel.dyn relocations ldr r2, =__rel_dyn_start ldr r3, =__rel_dyn_endfixloop: // rel.dyn 段 是 gcc链接器根据-pie参数生成的 // 一个数对标识了一个 ??? ldmia r2!, {
r0-r1} and r1, r1, #0xff // rel.dyn段中每一个rel section(8个字节)第二个4字节,0x17,是一种label的类型R_ARM_RELATIVE // 这个是 gcc 做的标记, 表示 这个需要 relative fix cmp r1, #23 bne fixnext // relative fix: increase location by offset add r0, r0, r4 ldr r1, [r0] add r1, r1, r4 str r1, [r0] // 整个过程 中 看到 来来往往, 只有一条指令修改了内存中的值 // str r1, [r0] // 修改的是 一个地址中的值 ,这个地址是 (一个数对中的第二个数+offset) // 这个地址位于代码段中 // fixloop 具体做了什么事 // 全局搜索 fixloop做的事 // "fixloop做的事" 体现了 改了 一处值 , 但 实际上是改了 rel.dyn 段 内所有满足条件(数据对中第二个低八位为0x17(也就是十进制的23))的值fixnext: cmp r2, r3 blo fixlooprelocate_done: bx lr.type relocate_code STT_FUNC ; .size relocate_code, .-relocate_code

我的关于 rel.dyn段的实验

以变量 test_val  为参考对象探索copy_loop&fixloop前后的 test_val  地址变化 以及原因
  • 代码修改处
$ git diff  lib/display_options.c diff --git a/lib/display_options.c b/lib/display_options.cindex b2025ee..487bfe0 100644--- a/lib/display_options.c+++ b/lib/display_options.c@@ -40,6 +40,28 @@ char *display_options_get_banner(bool newlines, char *buf, int size)        return display_options_get_banner_priv(newlines, BUILD_TAG, buf, size); } +void test_func(void)+{
+ printf("test func\n");++}++static void * test_func_val = test_func;+int test_val = 10; ++void rel_dyn_test()+{
+ test_val += 20; + printf("test_val = 0x%x\n", test_val);+ printf("test_val addr = 0x%x\n", &test_val);+ printf("test = 0x%x\n", test_func);+ printf("test_func = 0x%x\n", test_func_val);+ test_func();++}+++ int display_options(void) {
char buf[DISPLAY_OPTIONS_BANNER_LENGTH];@@ -47,6 +69,8 @@ int display_options(void) display_options_get_banner(true, buf, sizeof(buf)); printf("%s", buf); + rel_dyn_test();+ return 0; }$ git diff common/board_r.cdiff --git a/common/board_r.c b/common/board_r.cindex 29dd7d2..590c74b 100644--- a/common/board_r.c+++ b/common/board_r.c@@ -898,6 +898,8 @@ static init_fnc_t init_sequence_r[] = {
run_main_loop, }; +extern int test_val;+ void board_init_r(gd_t *new_gd, ulong dest_addr) {
/*@@ -919,11 +921,15 @@ void board_init_r(gd_t *new_gd, ulong dest_addr) #endif gd->flags &= ~GD_FLG_LOG_READY; + printf("after relocate test_val = 0x%x\n", test_val);+ printf("after relocate test_val addr = 0x%x\n", &test_val);+ #ifdef CONFIG_NEEDS_MANUAL_RELOC for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++) init_sequence_r[i] += gd->reloc_off; #endif + if (initcall_run_list(init_sequence_r)) hang();
  • 打印的数据
test_val = 0x1etest_val addr = 0x5fb35f4ctest = 0x5fb21ff0test_func = 0x5fb21ff0test funcRelocation Offset is: 004b3000after relocate test_val = 0x1eafter relocate test_val addr = 0x5ffe8f4c
  • 反汇编的数据(被 — 包围起来的数据为重点参考数据)
5fb08fb8 
:5fb08fb8: e92d4010 push {
r4, lr}5fb08fbc: e5993004 ldr r3, [r9, #4]---5fb08fc0: e59f4060 ldr r4, [pc, #96] ; 5fb09028
---5fb08fc4: e59f5060 ldr r5, [pc, #96] ; 5fb0902c
5fb08fc8: e3c33902 bic r3, r3, #32768 ; 0x80005fb08fcc: e5893004 str r3, [r9, #4]5fb08fd0: e5941000 ldr r1, [r4]5fb08fd4: e59f0054 ldr r0, [pc, #84] ; 5fb09030
5fb08fd8: eb006ec2 bl 5fb24ae8
5fb08fdc: e1a01004 mov r1, r45fb08fe0: e59f004c ldr r0, [pc, #76] ; 5fb09034
5fb08fe4: eb006ebf bl 5fb24ae8
5fb08fe8: e1a06005 mov r6, r55fb08fec: e4953004 ldr r3, [r5], #45fb08ff0: e3530000 cmp r3, #05fb08ff4: 0a00000a beq 5fb09024
5fb08ff8: e5994004 ldr r4, [r9, #4]5fb08ffc: e2144001 ands r4, r4, #15fb09000: 1599404c ldrne r4, [r9, #76] ; 0x4c5fb09004: e12fff33 blx r35fb09008: e2503000 subs r3, r0, #05fb0900c: 0afffff5 beq 5fb08fe8
5fb09010: e5962000 ldr r2, [r6]5fb09014: e59f1010 ldr r1, [pc, #16] ; 5fb0902c
5fb09018: e59f0018 ldr r0, [pc, #24] ; 5fb09038
5fb0901c: e0422004 sub r2, r2, r45fb09020: eb006eb0 bl 5fb24ae8
5fb09024: eb006577 bl 5fb22608
---5fb09028: 5fb35f4c svcpl 0x00b35f4cfixloop做的事 就是 将 这一行的 5fb35f4c 改为 5ffe8f4c (5fb35f4c+004b3000)---5fb0902c: 5fb359f0 svcpl 0x00b359f05fb09030: 5fb2becd svcpl 0x00b2becd5fb09034: 5fb2beed svcpl 0x00b2beed5fb09038: 5fb2be70 svcpl 0x00b2be70---5fb35f4c
:5fb35f4c: 0000000a andeq r0, r0, sl---Disassembly of section .rel.dyn:......---5fb37d30: 5fb09028 svcpl 0x00b090285fb37d34: 00000017 andeq r0, r0, r7, lsl r0---......---5fb39c68: 5fb220f8 svcpl 0x00b220f85fb39c6c: 00000017 andeq r0, r0, r7, lsl r0---......
  • 模型
// copy_loop前// 注意: 加载位置和链接位置是一样的.rel.dyn	存储了C.code		值B 和  存储B的地址C.data	值A 和 存储A的地址B---------------------// copy_loop后,fixloop前.rel.dyn	存储了C // 通过 C+gd->reloc_off 得到 C_.code		值B 和  存储B的地址C_ // 通过 B+gd->reloc_off 得到 B_ .data	值A 和 存储A的地址B_ ---------------------// copy_loop后,fixloop后.rel.dyn	存储了C // 通过 C+gd->reloc_off 得到 C_.code		值B_ 和  存储B_的地址C_ // 通过 B+gd->reloc_off 得到 B_ // 然后将B_写入 C_.data	值A 和 存储A的地址B_
  • 模型对应的数据
// copy_loop前// 注意: 加载位置和链接位置是一样的.rel.dyn	存储了C (5fb09028    svcpl   0x00b09028)	.code		值B(5fb35f4c) 和  存储B的地址C(5fb09028).data	值A(0000000a) 和 存储A的地址B(5fb35f4c)---------------------// copy_loop后,fixloop前.rel.dyn	存储了C (5fb09028    svcpl   0x00b09028) // 通过 C+gd->reloc_off 可得到 C_.code		值B(5fb35f4c) 和  存储B的地址C_(5fb09028+004b3000=0x5FFBC028) // 通过 B+gd->reloc_off 得到 B_ .data	值A(0000000a) 和 存储A的地址B_(5fb35f4c+004b3000=0x5ffe8f4c)---------------------// copy_loop后,fixloop后.rel.dyn	存储了C (5fb09028    svcpl   0x00b09028) // 通过 C+gd->reloc_off 可得到 C_.code		值B_(5fb35f4c+004b3000=0x5ffe8f4c) 和  存储B_的地址C_(5fb09028+004b3000=0x5ffbc028) // 通过 B+gd->reloc_off 得到 B_ // 然后将B_写入 C_.data	值A(0000000a) 和 存储A的地址B_(5fb35f4c+004b3000=0x5ffe8f4c)

思考

// 具体参考 https://blog.csdn.net/skyflying2012/article/details/37660265u-boot 之所以能做 fixloop ,是 gcc 支持 .rel.dyn 这项技术而u-boot 做的 fixloop 也就是 gcc 打开 .rel.dyn 技术 后,代码需要做的部分而已所以想知道更多,请查阅 gcc 文档 或 gcc 代码

代码运行时的地址与 u-boot.map

u-boot.map 中的地址为 链接地址,和 链接选项 -Ttext 0x5FB00000 有关如果加载的时候加载到了 0x5FB00000  ,那么u-boot代码函数 relocate 前的运行地址 等于 链接地址(也即是 u-boot.map 中的地址)在此情况下,重定位后的代码函数 和 u-boot.map中的关系addr in u-boot.map  	+ 		gd->reloc_off 		= 		重定位后的代码函数地址
你可能感兴趣的文章
DOM笔记(一):HTMLDocument接口
查看>>
DOM笔记(二):Node接口
查看>>
DOM笔记(三):Element接口和HTMLElement接口
查看>>
DOM笔记(四):HTML 5 DOM复杂数据类型
查看>>
DOM笔记(五):JavaScript的常见事件和Ajax小结
查看>>
DOM笔记(六):怎么进行JQuery扩展?
查看>>
搜索和网页排名的数学原理
查看>>
DOM笔记(八):JavaScript执行环境和垃圾收集
查看>>
响应式下的下拉菜单
查看>>
DOM笔记(九):引用类型、基本包装类型和单体内置对象
查看>>
也谈学习
查看>>
DOM笔记(十):JavaScript正则表达式
查看>>
如何高效编写可维护代码?
查看>>
DOM笔记(十一):JavaScript对象的基本认识和创建
查看>>
DOM笔记(十二):又谈原型对象
查看>>
DOM笔记(十三):JavaScript的继承方式
查看>>
CSS:响应式下的折叠菜单(条纹式)
查看>>
响应式设计三部曲
查看>>
45种Javascript技巧大全
查看>>
PDO学习笔记
查看>>