While trying out the u-boot-next branch I found a problem.  First some
explanation.  On most platforms, u-boot is linked to the address it
will first start running.  For example when using NOR flash U-Boot
will be linked to an address in flash.  Very early in the boot
process, U-Boot copies itself to the top and ram and jumps there.
This relocation has worked for years on powerpc and other arches.  The
-next tree adds this for arm and it almost works.

The part that does not work is that some veneer routines do not get fixed up.

Here is an example.  A routine called i2c_init calls __aeabi_idiv.
Here is the disassembly:

...
 288:   e59f0148        ldr     r0, [pc, #328]  ; 3d8 <i2c_init+0x1a4>
 28c:   e1a01083        lsl     r1, r3, #1
 290:   ebfffffe        bl      0 <__aeabi_idiv>
 294:   e2507006        subs    r7, r0, #6
 298:   4a000001        bmi     2a4 <i2c_init+0x70>

Later after this .o is linked with everything else and libgcc that morphs to:

8000b384:       e59f0148        ldr     r0, [pc, #328]  ; 8000b4d4
<_end+0xfff97c98>
8000b388:       e1a01083        lsl     r1, r3, #1
8000b38c:       eb00aa43        bl      80035ca0 <____aeabi_idiv_veneer>
8000b390:       e2507006        subs    r7, r0, #6
8000b394:       4a000001        bmi     8000b3a0 <i2c_init+0x70>

and the veneer version is at the end of text with other veneers:

80035ca0 <____aeabi_idiv_veneer>:
80035ca0:       e51ff004        ldr     pc, [pc, #-4]   ; 80035ca4
<_end+0xfffc2468>
80035ca4:       80035999        .word   0x80035999

80035ca8 <____aeabi_llsl_veneer>:
80035ca8:       e51ff004        ldr     pc, [pc, #-4]   ; 80035cac
<_end+0xfffc2470>
80035cac:       80035c7d        .word   0x80035c7d

80035cb0 <____aeabi_lasr_veneer>:
80035cb0:       e51ff004        ldr     pc, [pc, #-4]   ; 80035cb4
<_end+0xfffc2478>
80035cb4:       80035c61        .word   0x80035c61

80035cb8 <____aeabi_llsr_veneer>:
80035cb8:       e51ff004        ldr     pc, [pc, #-4]   ; 80035cbc
<_end+0xfffc2480>
80035cbc:       80035c49        .word   0x80035c49

80035cc0 <____aeabi_uidivmod_veneer>:
80035cc0:       e51ff004        ldr     pc, [pc, #-4]   ; 80035cc4
<_end+0xfffc2488>
80035cc4:       8003597d        .word   0x8003597d

80035cc8 <____aeabi_uidiv_veneer>:
80035cc8:       e51ff004        ldr     pc, [pc, #-4]   ; 80035ccc
<_end+0xfffc2490>
80035ccc:       80035721        .word   0x80035721

80035cd0 <____aeabi_idivmod_veneer>:
80035cd0:       e51ff004        ldr     pc, [pc, #-4]   ; 80035cd4
<_end+0xfffc2498>
80035cd4:       80035c2d        .word   0x80035c2d

then if we look at 80035998 we see some thumb code.

80035998 <__aeabi_idiv>:
80035998:       2900            cmp     r1, #0
8003599a:       f000 813e       beq.w   80035c1a <.divsi3_nodiv0+0x27c>

When u-boot copies itself to ram it relocates the jump tables it knows
about and could relocate the addresses in the veneer routines if it
knew about them.

There are at least three possible ways to fix these:

1) u-boot has its own private libgcc and if I use it the problem goes away.
2) is there an option for the toolchain to use an arm libgcc instead of thumb?
3) is there a way to find the veneers at runtime and fix them up?

All input welcome.
Thanks,
John

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to