U-Boot源码分析start.S中重定位代码
1. 将NOR Flash中的程序复制到SDRAM中
r0–addr_sp; r1–ip; r2–addr(33F41000);
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq clear_bss /* skip relocation */
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r1!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
2. 把”基于0地址编译得到的地址”改为新地址
需要结合反汇编文件u-boot.dis
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE // r0=0,代码基地址
sub r9, r6, r0 // r9 = r6-r0 = r2-r0 = 33F41000-0=33F41000
ldr r10, _dynsym_start_ofs // r10 = _dynsym_start_ofs = 00073608
add r10, r10, r0 // r10 = r10 + 0 = 00073608
ldr r2, _rel_dyn_start_ofs // r2 = 0006b568
add r2, r2, r0 // r2 = r2 + 0 = 0006b568
ldr r3, _rel_dyn_end_ofs // r3 = 00073608
add r3, r3, r0 // r3 = r3 + 0 = 00073608
fixloop:
ldr r0, [r2]
// 第1次循环. r0 = [0006b568] = 00000020
add r0, r0, r9
// 第1次循环. r0 = r0 +r9 = 00000020 + 33F41000 = 33F41020
ldr r1, [r2, #4]
// 第1次循环. r1 = [0006b568 + 4] = 00000017
and r7, r1, #0xff
// 第1次循环. r7 = r1 & 0xff = 00000017
cmp r7, #23
// 第1次循环. r7 == 23(0x17)
beq fixrel
// 跳转到fixrel
cmp r7, #2
beq fixabs
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4] /* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
// 第1次循环. r1 = [00000020] = 000001e0
add r1, r1, r9
// 第1次循环. r1 = r1 + r9 = 000001e0 + 33F41000 = 33F411e0
fixnext:
str r1, [r0]
// 第1次循环. [33F41020] = 33F411e0
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
// 第1次循环. r2 = r2 + 8 = 0006b568 + 8 = 0006b570
cmp r2, r3
// 第1次循环. 0006b570 与 00073608 比较
blo fixloop
// 上面比较为假,再次跳转到fixloop
#endif