adr lr, here
ldr r0, [r9, #76]
add lr, lr, r0
ldr r0, [r9, #56]
b relocate_code
arch/arm/lib/relocate.S +80
搬移,修复绝对地址???
.globl relocate_code ; .align 0 ; relocate_code:
ldr r1, =__image_copy_start
subs r4, r0, r1
beq relocate_done
ldr r2, =__image_copy_end
copy_loop:
ldmia r1!, {
r10-r11}
stmia r0!, {
r10-r11}
cmp r1, r2
blo copy_loop
ldr r2, =__rel_dyn_start
ldr r3, =__rel_dyn_end
fixloop:
ldmia r2!, {
r0-r1}
and r1, r1, #0xff
cmp r1, #23
bne fixnext
add r0, r0, r4
ldr r1, [r0]
add r1, r1, r4
str r1, [r0]
fixnext:
cmp r2, r3
blo fixloop
relocate_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.c
index 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.c
diff --git a/common/board_r.c b/common/board_r.c
index 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)
{
test_val = 0x1e
test_val addr = 0x5fb35f4c
test = 0x5fb21ff0
test_func = 0x5fb21ff0
test func
Relocation Offset is: 004b3000
after relocate test_val = 0x1e
after relocate test_val addr = 0x5ffe8f4c
- 反汇编的数据(被 — 包围起来的数据为重点参考数据)
5fb08fb8 <board_init_r>:
5fb08fb8: e92d4010 push {
r4, lr}
5fb08fbc: e5993004 ldr r3, [r9, #4]
---
5fb08fc0: e59f4060 ldr r4, [pc, #96] ; 5fb09028 <board_init_r+0x70>
---
5fb08fc4: e59f5060 ldr r5, [pc, #96] ; 5fb0902c <board_init_r+0x74>
5fb08fc8: e3c33902 bic r3, r3, #32768 ; 0x8000
5fb08fcc: e5893004 str r3, [r9, #4]
5fb08fd0: e5941000 ldr r1, [r4]
5fb08fd4: e59f0054 ldr r0, [pc, #84] ; 5fb09030 <board_init_r+0x78>
5fb08fd8: eb006ec2 bl 5fb24ae8 <printf>
5fb08fdc: e1a01004 mov r1, r4
5fb08fe0: e59f004c ldr r0, [pc, #76] ; 5fb09034 <board_init_r+0x7c>
5fb08fe4: eb006ebf bl 5fb24ae8 <printf>
5fb08fe8: e1a06005 mov r6, r5
5fb08fec: e4953004 ldr r3, [r5], #4
5fb08ff0: e3530000 cmp r3, #0
5fb08ff4: 0a00000a beq 5fb09024 <board_init_r+0x6c>
5fb08ff8: e5994004 ldr r4, [r9, #4]
5fb08ffc: e2144001 ands r4, r4, #1
5fb09000: 1599404c ldrne r4, [r9, #76] ; 0x4c
5fb09004: e12fff33 blx r3
5fb09008: e2503000 subs r3, r0, #0
5fb0900c: 0afffff5 beq 5fb08fe8 <board_init_r+0x30>
5fb09010: e5962000 ldr r2, [r6]
5fb09014: e59f1010 ldr r1, [pc, #16] ; 5fb0902c <board_init_r+0x74>
5fb09018: e59f0018 ldr r0, [pc, #24] ; 5fb09038 <board_init_r+0x80>
5fb0901c: e0422004 sub r2, r2, r4
5fb09020: eb006eb0 bl 5fb24ae8 <printf>
5fb09024: eb006577 bl 5fb22608 <hang>
---
5fb09028: 5fb35f4c svcpl 0x00b35f4c
fixloop做的事 就是 将 这一行的 5fb35f4c 改为 5ffe8f4c (5fb35f4c+004b3000)
---
5fb0902c: 5fb359f0 svcpl 0x00b359f0
5fb09030: 5fb2becd svcpl 0x00b2becd
5fb09034: 5fb2beed svcpl 0x00b2beed
5fb09038: 5fb2be70 svcpl 0x00b2be70
---
5fb35f4c <test_val>:
5fb35f4c: 0000000a andeq r0, r0, sl
---
Disassembly of section .rel.dyn:
...
...
---
5fb37d30: 5fb09028 svcpl 0x00b09028
5fb37d34: 00000017 andeq r0, r0, r7, lsl r0
---
...
...
---
5fb39c68: 5fb220f8 svcpl 0x00b220f8
5fb39c6c: 00000017 andeq r0, r0, r7, lsl r0
---
...
...
.rel.dyn
存储了C
.code
值B 和 存储B的地址C
.data
值A 和 存储A的地址B
---------------------
.rel.dyn
存储了C
.code
值B 和 存储B的地址C_
.data
值A 和 存储A的地址B_
---------------------
.rel.dyn
存储了C
.code
值B_ 和 存储B_的地址C_
.data
值A 和 存储A的地址B_
.rel.dyn
存储了C (5fb09028 svcpl 0x00b09028)
.code
值B(5fb35f4c) 和 存储B的地址C(5fb09028)
.data
值A(0000000a) 和 存储A的地址B(5fb35f4c)
---------------------
.rel.dyn
存储了C (5fb09028 svcpl 0x00b09028)
.code
值B(5fb35f4c) 和 存储B的地址C_(5fb09028+004b3000=0x5FFBC028)
.data
值A(0000000a) 和 存储A的地址B_(5fb35f4c+004b3000=0x5ffe8f4c)
---------------------
.rel.dyn
存储了C (5fb09028 svcpl 0x00b09028)
.code
值B_(5fb35f4c+004b3000=0x5ffe8f4c) 和 存储B_的地址C_(5fb09028+004b3000=0x5ffbc028)
.data
值A(0000000a) 和 存储A的地址B_(5fb35f4c+004b3000=0x5ffe8f4c)
思考
u-boot 之所以能做 fixloop ,是 gcc 支持 .rel.dyn 这项技术
而u-boot 做的 fixloop 也就是 gcc 打开 .rel.dyn 技术 后,代码需要做的部分而已
所以想知道更多,请查阅 gcc 文档 或 gcc 代码