uboot relocation section .rel.dyn

U-boot version: GIT clone tag v2016.01-rc1

ARM gcc: arm-none-eabi-gcc 5.2.1


Trying to port U-boot to STM32F10x MCU, found U-boot .rel.dyn section is interesting. And it includes .dynsym and .dynstr section.

Now just write down how it works.


First let's see the example C-code.

unsigned long clock_get(enum clock clck)
{
	u32 sysclk = 0;
	u32 shift = 0;
	/* Prescaler table lookups for clock computation */
	u8 ahb_psc_table[16] = {
		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9
	};
	/*operations*/
} 

注意ahb_psc_table[]数组,relocation的对象就是数据。

The assemble code is:

 80005ac:       5cd3            ldrb    r3, [r2, r3]
 80005ae:       40d8            lsrs    r0, r3
 80005b0:       e000            b.n     80005b4 <clock_get+0x84>
 80005b2:       2000            movs    r0, #0
 80005b4:       b004            add     sp, #16
 80005b6:       bd70            pop     {r4, r5, r6, pc}
 80005b8:       08014766        stmdaeq r1, {r1, r2, r5, r6, r8, r9, sl, lr} /*0x8014766 is the ahb_psc_table[] array.0x80005b8 is the index of the array.*/
 80005bc:       40023808        andmi   r3, r2, r8, lsl #16
 80005c0:       40023804        andmi   r3, r2, r4, lsl #16
 80005c4:       007a1200        rsbseq  r1, sl, r0, lsl #4
 80005c8:       0801a7a6        stmdaeq r1, {r1, r2, r5, r7, r8, r9, sl, sp, pc}

可以看到ahb_psc_table[]数组的地址(0x8014766)被存放在函数尾部 0x080005b8的位置。


The ahb_psc_table[] is stored in .rodata section.

 8014764:       0000000f        andeq   r0, r0, pc                    /*0x8014766 start is ahb_psc_table[]={0,0,0,0,1,2,3,4,6,7,8,9}*/
 8014768:       00000000        andeq   r0, r0, r0
 801476c:       02010000        andeq   r0, r1, #0
 8014770:       07060403        streq   r0, [r6, -r3, lsl #8]
 8014774:       00000908        andeq   r0, r0, r8, lsl #18

这里是ahb_psc_table[]数据的实际存储位置。


The rel.dyn section is:

Disassembly of section .rel.dyn:

0801c3fc <__rel_dyn_end-0x48e0>:
 801c3fc:       08000528        stmdaeq r0, {r3, r5, r8, sl}
 801c400:       00000017        andeq   r0, r0, r7, lsl r0
 801c404:       080005b8        stmdaeq r0, {r3, r4, r5, r7, r8, sl} /*0x80005b8 is the index of ahb_psc_table[]*/
 801c408:       00000017        andeq   r0, r0, r7, lsl r0
 801c40c:       080005c8        stmdaeq r0, {r3, r6, r7, r8, sl}

the relocation table item 0x801c404 is the index of ahb_psc_table[] item. 

relocation表里存的是函数后面存放ahb_psc_table[]地址的单元的地址。



Then the question is how to use this relocation table. Let's check the code of arch/arm/lib/relocation.S(removed un-used code)

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             /*calculate 0x80005b8's RAM address*/
	ldr	r1, [r0]               /*read 0x80005b8's content--ahb_psc_table[] address*/
	add	r1, r1, r4             /*modify ahb_psc_table[] address to RAM(new address)*/
	str	r1, [r0]               /*write back ahb_psc_table[]'s new address to 0x80005b8's RAM address*/
fixnext:
	cmp	r2, r3
	blo	fixloop

relocate_done:

	bx	lr

ENDPROC(relocate_code)

Got it ? It looks complex.

其实relocation函数改变的是函数后面单元中存放的ahb_psc_table[]数组的地址。因为整个image被搬移到了新地址(relocation feature假设整个image都搬移了),所以函数后面单元中存放的ahb_psc_table[]数组的地址必须修改,不然就找不到正确的ahb_psc_table[]数组。


The idea is:

1. Each function has an index for each variable which is bigger than 4 bytes.

2. Put all variables' index into the relocation table. After copy the data section to the new address, the U-boot could easily modify the address of all variables.


Here should insert a picture to make it more clear.



But if you don't need relocation, how to disable it? Open arch/arm/config.mk file.

# needed for relocation
LDFLAGS_u-boot += -pie   /*This is for link process*/
This is the first place.

ifneq ($(CONFIG_SPL_BUILD),y)
# Check that only R_ARM_RELATIVE relocations are generated.
ALL-y += checkarmreloc
# The movt / movw can hardcode 16 bit parts of the addresses in the
# instruction. Relocation is not supported for that case, so disable
# such usage by requiring word relocations.
PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations)
endif
This is the second place and it is for gcc.

So disable these two places, you could disable the relocation feature. Attention, checkarmreloc need disable.



猜你喜欢

转载自blog.csdn.net/alex_mianmian/article/details/50582833