arm thumb veneer question
dave.martin at linaro.org
Tue Sep 21 12:23:58 BST 2010
John Rigby wrote:
> 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>
I believe such calls are getting resolved via a veneer because of a
combination the thumb2-ness of libgcc and the toolchain being used.
In principle, the linker can know that it is linking for >= ARMv5T due
to the way it was configured and the way the input objects were built,
but GNU ld is conservative and doesn't do this automatically. As a
result, it has to generate a veneer, reached via a normal
non-interworking branch. ld has no way the veneer needs to be PIC and
use the GOT, so it isn't and doesn't.
The `--use-blx' switch enables the linker to use ARM/Thumb BLX
instructions (available on ARMv5t and above) in various situations.
Currently it is used to perform calls via the PLT from Thumb code using
BLX rather than using BX and a mode-switching stub before each PLT
entry. This should lead to such calls executing slightly faster.
...so you might explicitly want to enable this whenever building for
ARMv5 or later.
Wolfgang, can you foresee any reason not to do that? As far as I can
see it will be safe so long as we don't use it when building for
architectured <ARMv5 (where the BLX instruction isn't supported).
Otherwise, the only straightforward workaround is to build with cc
-fPIC and ld -shared, to guarantee that every absolute address is
resolved via the GOT instead of hard-coded veneers, then let U-Boot
patch it all up. This causes non-relative branches to jump a veneer
in .plt instead. If extra trampolines are needed to reach .plt, those
will be generated as PIC code in this case too. Of course, we don't
want the linker to resolve symbols using actual shared libraries, so
we need -nostdlib and explicit references to .a files if there might
be ambiguity about library selection. Since U-Boot is bare-metal, I'm
guessing these requirements are either met or nearly met already...
but there might be gotchas such as if the fixup code in U-Boot ends up
with fixups inside itself.
Alternatively, using ld --emit-relocs and then embedding the
relocation information in the image so that U-Boot can use it could
help to solve the problem. I'm guessing that isn't set up at present,
> 1) u-boot has its own private libgcc and if I use it the problem goes away.
Hopefully not necessary--- I agree with Wolfgang's concerns on relying on this.
> 2) is there an option for the toolchain to use an arm libgcc instead of thumb?
You'd need to rebuild the toolchain (or at least libgcc). I believe
that no ARM libgcc is built at present for the linaro/Ubuntu tools. I
don't think the GCC packages currently support this kind of thing
--use-blx is probably the better workaround.
> 3) is there a way to find the veneers at runtime and fix them up?
No. Even if you can find the veneers, you would need to make
assumptions about their structure which may break when the toolchain
gets upgraded... unless you write the veneers by hand in the first
So the options are to avoid the veneers using --use-blx; to
post-processing the relocations output from ld --emit-relocs; or to do
a fully PIC link with ld -shared. The latter options feel like
overkill, unless U-Boot already supports this, or evolves a general
need for it in the future.
More information about the linaro-toolchain