[U-Boot] [PATCH] ARM: fixed relocation using proper alignment

Manfred Schlaegl manfred.schlaegl at ginzinger.com
Tue May 16 14:29:16 UTC 2017


On 2017-05-11 08:53, Lokesh Vutla wrote:
> 
> 
> On Wednesday 10 May 2017 07:11 PM, Manfred Schlaegl wrote:
>> Using u-boot-2017.05 on i.MX6UL we ran into following problem:
>> Initially U-Boot could be started normally.
>> If we added one random command in configuration, the newly generated
>> image hung at startup (last output was DRAM:  256 MiB).
>>
>> We tracked this down to a data abort within relocation (relocated_code).
>>
>> relocated_code in arch/arm/lib/relocate.S copies 8 bytes per loop
>> iteration until the source pointer is equal to __image_copy_end.
>> In a good case __image_copy_end was aligned to 8 bytes, so the loop
>> stopped as suggested, but in an errornous case __image_copy_end was
>> not aligned to 8 bytes, so the loop ran out of bounds and caused a
>> data abort exception.
> 
> Well I agree with this patch but I have a small query. Looking at the
> relocation code:
> 
> 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
> 
> IIUC, this loops exits as soon as r1 >= r2
> 
> In your case
> r1 is __image_copy_start
> r0 is relocation address
> r2 is __image_copy_end (which is 4 byte aligned)
> 
> In the corner case you mentioned there will be extra memcpy of 4 bytes
> from address in r1 to address in r0. I assume you are running from DDR
> and relocation offset is calculated such that (aligned to previous 4K
> page) it should be able to accommodate extra 4 bytes(I assume). I am
> wondering why should this give a data abort.
> 
> Thanks and regards,
> Lokesh
> 

Thanks a lot for your input!
The patch solved my problem randomly.

The loop terminates only one word beyond __image_copy_end.
This is not the problem in my case because both, the source and destination
pointers point to valid addresses in dram.
So the problem must be later in relocate_code.

I spent some time using a debugger and found that the data abort happens here

	/*
	 * 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, #R_ARM_RELATIVE
	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


Also I found out, that it's not the alignment of image_copy_end, but of rel_dyn_start
(which was also implicitly changed by my patch).

In a good case (rel_dyn_start aligned to 8 byte), u-boot is starting up normally
rel_dyn_start is 0x8785FC28
rel_dyn_end is 0x87857BD0
A dump of this memory area shows no abnormality

In a bad case (same source, but rel_dyn_start aligned to 4 byte), the data abort happens
rel_dyn_start is 0x8785FC24
rel_dyn_end is 0x87857BCC
So we have the same size of 32856 bytes but a memory dump showed exactly one difference, which is
very interesting:

At offset 0x610 (relative to rel_dyn_start) we have following difference
-00000610  30 3e 80 87 17 00 00 00  34 3e 80 87 00 00 00 00  |0>......4>......|
+00000610  30 3e 80 87 17 00 00 00  00 00 00 00 17 00 00 00  |0>..............|

Here is a pseudo-trace of fixloop in bad case starting at offset 0x618 (relative to rel_dyn_start)

fixloop:				// R2 = 0x878581E4, R4 = 0x08786000
	ldmia	r2!, {r0-r1}		// R0 = 0x00000000, R1 = 0x00000017, R2 = 0x878581EC
	and	r1, r1, #0xff
	cmp	r1, #R_ARM_RELATIVE
	bne	fixnext			// R1 == 0x17 -> no branch
	
	/* relative fix: increase location by offset */
	add	r0, r0, r4		// R0 = 0x08786000
	ldr	r1, [r0]		// ABORT while accessing 0x08786000 -> not a valid address in dram


It seems, that the entry 00 00 00 00 17 00 00 00 @ offset 0x618 is some how incorrect, or at least
produces some incorrect behavior. There are no similar entries in the table.

I'm not really experienced with these tables.
Has anyone suggestions, starting points, ideas/hints which could help me to track this down?

Thanks a lot!

Best regards,
Manfred







More information about the U-Boot mailing list