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