makefile、relocate_code、uboot.lds
.makefile
.relocate_code(uboot 自举)
https://blog.csdn.net/skyflying2012/article/details/37660265?spm=1001.2014.3001.5501
link 链接地址、load 加载地址、运行地址。
将 uboot 重新定位到 SDRAM上部一个位置,原因可能是为 kernel 腾出低端空间。
// _main
...
#if ! defined(CONFIG_SPL_BUILD)
// gd 更新
ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
sub r9, r9, #GD_SIZE /* new GD is below bd */
// 为 relocate 做准备
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
here:
...
// relocate.S
// relocate_code —— 将uboot code拷贝到relocaddr
#include <linux/linkage.h>
ENTRY(relocate_code)
ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */
subs r4, r0, r1 /* r4 <- relocation offset */
beq relocate_done /* skip relocation */
ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */
copy_loop:
ldmia r1!, {r10-r11} /* copy from source address [r1] */
stmia r0!, {r10-r11} /* copy to target address [r0] */
cmp r1, r2 /* until source end address [r2] */
blo copy_loop
/*
* fix .rel.dyn relocations
*/
ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */
ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
fixloop:
ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */
and r1, r1, #0xff
cmp r1, #23 /* relative fixup? */
bne fixnext
/* relative fix: increase location by offset */
add r0, r0, r4
ldr r1, [r0]
add r1, r1, r4
str r1, [r0]
fixnext:
cmp r2, r3
blo fixloop
relocate_done:
#ifdef __XSCALE__
/*
* On xscale, icache must be invalidated and write buffers drained,
* even with cache disabled - 4.2.7 of xscale core developer's manual
*/
mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */
mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
#endif
/* ARMv4- don't know bx lr but the assembler fails to see that */
#ifdef __ARM_ARCH_4__
mov pc, lr
#else
bx lr
#endif
ENDPROC(relocate_code)
查看包含有调试信息的镜像文件:
arm-linux-readelf -r u-boot | less
利用了 PIC 位置无关代码,通过为编译器指定编译选项 -fpic
或 -fpie
产生。
// arch/arm/config.mk
# needed for relocation
LDFLAGS_u-boot += -pie
使用 -pie
选项的 compiler,将全局变量地址、函数入口地址存储在rel.dyn
段中,relocate_code 遍历 rel.dyn 段,根据 rel.dyn 中存储的值,对以(这些值+offset)为地址上的值进行了 relocate,完成对所有需要 relocate 的变量的修改。在 relocate_code 中 rel.dyn 不仅没有拷贝,也没有修改,修改只是针对 rel.dyn+offset 为地址上的值。
uboot 只指定了-pie
给 ld,指定 -pie
后编译生成的 uboot 就会有一个 rel.dyn 段,uboot 就是靠 rel.dyn 实现了完美的 relocation。
relocate 主要问题是修改函数标号的地址,先从 rel 段找到需要修改的标号,从 image 中找到该标号位置,将该位置增加 offset 后写入到新的标号处。
. /arch/arm/cpu/u-boot.lds
uboot 的入口地址由链接脚本(链接器)决定,在配置文件中由 CONFIG_SYS_TEXT_BASE
指定,会在编译时加载 ld 链接器的选项-T text
中,脚本规定了 start.o 作为 uboot 的起点。
目的:为了将 uboot 中多个目标文件的 .text、.data 和 .bss 等段链接在一起,提供该脚本文件告知链接器从什么地址开始放置这些段,怎么安排这些段的顺序。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") // 指定输出可执行文件是elf格式,32位ARM指令,小端格式
OUTPUT_ARCH(arm) // 指定输出的可执行文件的平台为ARM
ENTRY(_start) // 链接完毕后的执行入口
SECTIONS
{
. = 0x00000000; // 指定 image 文件的全局入口点,通常在 flash 0x0 处
. = ALIGN(4); // 代码以4字节对齐
.text :
{
*(.__image_copy_start) // __image_copy_start 全局变量
CPUDIR/start.o (.text*) // 先放置 start.o
*(.text*) // 其它文件的代码段
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } // 只读数据段(排序)
. = ALIGN(4);
.data : { // 全局变量段
*(.data*)
}
. = ALIGN(4);
. = .;
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
.image_copy_end :
{
*(.__image_copy_end)
}
.rel_dyn_start : // 动态符号链接段
{
*(.__rel_dyn_start)
}
.rel.dyn : {
*(.rel*)
}
.rel_dyn_end :
{
*(.__rel_dyn_end)
}
_end = .;
. = ALIGN(4096);
.mmutable : { // 不再使用
*(.mmutable)
}
.bss_start __rel_dyn_start (OVERLAY) : { // 可变化的局部数据
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN(4);
__bss_limit = .;
}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
// 下面不使用
/DISCARD/ : { *(.dynsym) }
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.ARM.exidx*) }
/DISCARD/ : { *(.gnu.linkonce.armexidx.*) }
}