/* ldr pc, _undefined_instruction//位置无关,_undefined_instruction基于PC计算 _undefined_instruction: .word undefined_instruction//位置相关,undefined_instruction编译期间确定 Disassembly of section .text: 80800020 <_undefined_instruction>: 80800020: 808001a0 .word 0x808001a0 808001a0 <undefined_instruction>: 808001a0: e51fd154 ldr sp, [pc, #-340] ; 80800054 <IRQ_STACK_START_IN> Disassembly of section .rel.dyn 808648dc: 80800020 addhi r0, r0, r0, lsr #32 修复代码重定向之后某些位置相关的代码不能执行问题。 uboot 在ld时,指定 -pie,生成的uboot会包含_rel_dyn段, _rel_dyn段(808648dc)的作用就是保存“保存函数(text)、常量(rodata)绝对地址(808001a0:undefined_instruction)”的地址(80800020) 下面的代码就是遍历重定位的uboot的_rel_dyn段(还有dynsym段), 将_rel_dyn段(808648dc)中的每一个地址(80800020)所指向的地址(808001a0)加上relocation offset 80800020: 808001a0 .word 0x808001a0 变为 80800020: 808001a0+offset .word 0x808001a0 */ (uboot.dump1) ldr r0, _TEXT_BASE /* r0 <- Text base */ //r0=0x80800000 sub r9, r6, r0 /* r9 <- relocation offset */ //r9=0x9FB39000 - 0x80800000=1F339000 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ //r10=0x6d104(反汇编) add r10, r10, r0 /* r10 <- sym table in FLASH */ //r10=0x8086D104,_dynsym_start在sdram中的真实地址(未重定位) ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ //r2=0x64854(反汇编) add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ //r2=0x80864854,_rel_dyn_start在sdram中的真实地址(未重定位) ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ //r3=0x6d104(反汇编) add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ //r3=0x8086D104,_rel_dyn_end在sdram中的真实地址=_dynsym_start(u-boot.lds) fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ add r0, r0, r9 /* r0 <- location to fix up in RAM */ ldr r1, [r2, #4] and r7, r1, #0xff cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ 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] add r1, r1, r9 fixnext: str r1, [r0] add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ cmp r2, r3 blo fixloop b clear_bss _rel_dyn_start_ofs: .word __rel_dyn_start - _start _rel_dyn_end_ofs: .word __rel_dyn_end - _start _dynsym_start_ofs: .word __dynsym_start - _start /******************************************/ ldr r0, _TEXT_BASE /* r0 <- Text base */ //r0=0x80800000 sub r9, r6, r0 /* r9 <- relocation offset */ //r9=0x9FB39000 - 0x80800000=1F339000 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ //r10=0x6d104(反汇编) add r10, r10, r0 /* r10 <- sym table in FLASH */ //r10=0x8086D104,_dynsym_start在sdram中的真实地址(未重定位) ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ //r2=0x64854(反汇编) add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ //r2=0x80864854,_rel_dyn_start在sdram中的真实地址(未重定位) ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ //r3=0x6d104(反汇编) add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ //r3=0x8086D104,_rel_dyn_end在sdram中的真实地址=_dynsym_start(u-boot.lds) fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ //r0=[80864854]=80800020 add r0, r0, r9 /* r0 <- location to fix up in RAM */ //r0=80800020+1F339000=重定向后的80800020 ldr r1, [r2, #4] //r1=[80864854 + 4] =[80864858] = 0x00000017 and r7, r1, #0xff //r7=0x00000017&&0xff=0x17=23 cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ 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] //r1=[80800020+1F339000]= 808001a0 add r1, r1, r9 //r1=808001a0+1F339000=重定向后的808001a0 undefined_instruction fixnext: str r1, [r0] //[80800020+1F339000]=808001a0+1F339000//把.word中的值加上了relocation offset add r2, r2, #8 /* each rel.dyn entry is 8 bytes;8字节一个单元 */ //r2= 0x80864854 + 8=0x8086485c cmp r2, r3 blo fixloop b clear_bss /******************************************/ fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ //r0=[0x8086485c]=80800024 add r0, r0, r9 /* r0 <- location to fix up in RAM */ //r0=80800024+1F339000=重定向后的80800024 ldr r1, [r2, #4] //r1=[0x8086485c + 4] =[80864860] = 0x00000017 and r7, r1, #0xff //r7=0x00000017&&0xff=0x17=23 cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ 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] //r1=[80800024+1F339000]= 80800200 add r1, r1, r9 //r1=80800200+1F339000=重定向后的80800200 software_interrupt,位于text fixnext: str r1, [r0] //[80800024+1F339000]=80800200+1F339000//把.word中的值加上了relocation offset add r2, r2, #8 /* each rel.dyn entry is 8 bytes;8字节一个单元 */ r2= 0x8086485c + 8=80864864 cmp r2, r3 blo fixloop b clear_bss * * * //循环至r2=808649a4时,(uboot.dump_rel) fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ //r0=[808649a4]=808010ac 保存(test_func打印的字符串常量的地址,位于rodata)的Label add r0, r0, r9 /* r0 <- location to fix up in RAM */ //r0=808010ac+1F339000=重定向后的808010ac ldr r1, [r2, #4] //r1=[808649a4 + 4] =[808649a8] = 0x00000017 and r7, r1, #0xff //r7=0x00000017&&0xff=0x17=23 cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ 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] //r1=[808010ac+1F339000]= 80853f68 add r1, r1, r9 //r1=80853f68+1F339000=重定向后的80853f68 ----74736574 printf的参数:字符串常量,位于rodata fixnext: str r1, [r0] //[808010ac+1F339000]=80853f68+1F339000//把.word中的值加上了relocation offset add r2, r2, #8 /* each rel.dyn entry is 8 bytes;8字节一个单元 */ //r2= 808649a8 + 8=808649b0 cmp r2, r3 blo fixloop b clear_bss * * * * //循环至r2=0x8086D104(__dynsym_start=_rel_dyn_end)时,(uboot.dump1) * * //循环至r2=8086d118(__dynsym)时,(uboot.dump1) fixloop: ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ //r0=[8086d118]=80800000 text_base=_start add r0, r0, r9 /* r0 <- location to fix up in RAM */ //r0=80800000+1F339000=重定向后的80800000 ldr r1, [r2, #4] //r1=[8086d118 + 4] =[8086d11c] = 0x000000 and r7, r1, #0xff //r7=0x000000&&0xff=0x0=0 cmp r7, #23 /* relative fixup? */ beq fixrel cmp r7, #2 /* absolute fixup? */ beq fixabs /* ignore unknown type of fixup */ b fixnext fixabs: /* absolute fix: set location to (offset) symbol value */ mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ //r1=0 add r1, r10, r1 /* r1 <- address of symbol in table */ //r1=0+0x8086D104=0x8086D104 ldr r1, [r1, #4] /* r1 <- symbol value */ //r1=[8086d108]//not found in dump add r1, r1, r9 /* r1 <- relocated sym addr */ b fixnext fixrel: /* relative fix: increase location by offset */ ldr r1, [r0] //r1=[808010ac+1F339000]= 80853f68 add r1, r1, r9 //r1=80853f68+1F339000=重定向后的80853f68 ----74736574 printf的参数:字符串常量,位于rodata fixnext: str r1, [r0] //[808010ac+1F339000]=80853f68+1F339000//把.word中的值加上了relocation offset add r2, r2, #8 /* each rel.dyn entry is 8 bytes;8字节一个单元 */ r2= 808649a8 + 8=808649b0 cmp r2, r3 blo fixloop b clear_bss