uboot relocation section .rel.dyn

本文详细介绍了如何将U-boot移植到STM32F10x MCU上,并解释了U-boot.rel.dyn节的作用及AHB_PSC_TABLE数组的存储和定位方式。通过分析动态链接节的内容,理解了relocation表是如何工作的,以及如何利用relocation函数改变函数后面单元中存放的数组地址,确保程序在不同地址下仍能正确运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值