arm thumb veneer question

Dave Martin dave.martin at linaro.org
Wed Sep 22 11:14:14 BST 2010


On Tue, Sep 21, 2010 at 9:29 PM, Wolfgang Denk <wd at denx.de> wrote:
> Dear Dave Martin,
>
> In message <AANLkTikHv1SpjcyRbRxGK2QeCoq96tsTken3LmP5bsse at mail.gmail.com> you wrote:
>>
>> 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.
>
> Stupid question: why not?

Because U-Boot doesn't build PIC for ARM (I notice it does for some
other arches).

u-boot$ grep -irl -- '-fpic\|-shared' `find . -name Makefile\* -o -name \*.mk`
./arch/mips/config.mk
./arch/sparc/cpu/leon2/config.mk
./arch/sparc/cpu/leon3/config.mk
./arch/powerpc/cpu/mpc85xx/config.mk
./arch/powerpc/cpu/mpc5xxx/config.mk
./arch/powerpc/cpu/mpc824x/config.mk
./arch/powerpc/cpu/mpc86xx/config.mk
./arch/powerpc/cpu/mpc83xx/config.mk
./arch/powerpc/cpu/mpc8xx/config.mk
./arch/powerpc/cpu/mpc8260/config.mk
./arch/powerpc/cpu/mpc8220/config.mk
./arch/powerpc/cpu/ppc4xx/config.mk
./arch/powerpc/cpu/74xx_7xx/config.mk
./arch/powerpc/cpu/mpc5xx/config.mk
./arch/powerpc/cpu/mpc512x/config.mk
./arch/avr32/config.mk
./arch/m68k/cpu/mcf5227x/config.mk
./arch/m68k/cpu/mcf547x_8x/config.mk
./arch/m68k/cpu/mcf532x/config.mk
./arch/m68k/cpu/mcf523x/config.mk
./arch/m68k/cpu/mcf5445x/config.mk

Note that ARM code is fairly PIC even without -fPIC, except for
references to data (which are usually absolute), and certain cases of
veneers/trampolines inserted by the linker (as we saw).

One think I'm confused about: why do references to read-only data not
cause a problem?  I would expect the read-only data to need to be
relocated along with .text, but currently u-boot.bin references these
with absolute addresses (because of no -fPIC).  Are we just tending to
get lucky, i.e., in practice U-Boot is usually run at the link address
and copied elsewhere?

To illustrate, here's an example: note the absense of a GOT or any
relocations in u-boot, and the non-relocatable absolute reference to a
string in .rodata.str1.1

u-boot$ objdump -dr net/net.o
[...]
000009d4 <ArpRequest>:
     ab8:	00000079 	.word	0x00000079
			ab8: R_ARM_ABS32	.rodata.str1.1
[...]

u-boot$ objdump -dh u-boot

u-boot:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00014c4c  06000000  06000000  00008000  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rodata       00000fdc  06014c4c  06014c4c  0001cc4c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .rodata.str1.1 00004180  06015c28  06015c28  0001dc28  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .data         00000914  06019da8  06019da8  00021da8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .u_boot_cmd   00000378  0601a6bc  0601a6bc  000226bc  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  5 .bss          00035f30  0601aa34  0601aa34  00022a34  2**2
                  ALLOC
  6 .ARM.attributes 0000002d  00000000  00000000  00022a34  2**0
                  CONTENTS, READONLY
  7 .comment      00000041  00000000  00000000  00022a61  2**0
                  CONTENTS, READONLY
  8 .debug_line   00005dd0  00000000  00000000  00022aa2  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_info   0001756a  00000000  00000000  00028872  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_abbrev 00006726  00000000  00000000  0003fddc  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_aranges 000006a0  00000000  00000000  00046508  2**3
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_loc    0000f178  00000000  00000000  00046ba8  2**0
                  CONTENTS, READONLY, DEBUGGING
 13 .debug_pubnames 000022f6  00000000  00000000  00055d20  2**0
                  CONTENTS, READONLY, DEBUGGING
 14 .debug_ranges 00000880  00000000  00000000  00058016  2**0
                  CONTENTS, READONLY, DEBUGGING
 15 .debug_str    00004cd5  00000000  00000000  00058896  2**0
                  CONTENTS, READONLY, DEBUGGING
 16 .debug_frame  00003178  00000000  00000000  0005d56c  2**2
                  CONTENTS, READONLY, DEBUGGING
[...]
06001a44 <ArpRequest>:
[...]
 6001b28:	06016065 	.word	0x06016065
[...]



As to why the linker doesn't automatically know that the expensive
veneers aren't needed, I don't think there's any really good reason;
it's just not implemented AFAIK.

ld doesn't know the target architecture in the same way that gcc does
--- I believe ld doesn't understand a -march= switch for most
architectures.

ld could guess the target architecture based on information the
compiler puts in the objects, but this might be a future thing.  Some
ARM toolchains do it, ld currently doesn't.  I think it may get done
in the future, but in the meantime we need to manage without :/

[...]

> Is there any information available about relative code sizes /
> performance numbers of "--emit-relocs" versus "--use-blx"?

I don't have numbers, but it's straightforward to answer: the
resulting code should be identical at run-time.  But --use-blx get the
linker to do the work for you, whereas --emit-relocs requires
something else in the build system to perform these fixups.  Both are
smaller and faster than branching via veneers (the current behaviour).

>> > 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
>> well.
>
> I think that should be fixed. I guess you will run intot hat again
> sooner or later.

Indeed... I believe it is being looked at in relation to multiarch;
there seems to be a general consensus is that multilibs isn't really
scalable enough.  But we're going to have to put up with this for a
while in the interim...

[...]

>        Can anybody shed some light on 1) when these routines have
>        been introduced ... ?

I think this was already answered, but to clarify from my side:
nothing has been introduced.  The observed behaviour is something the
linker does when it sees a mixture of ARM and Thumb code, so it
happens as a side-effect of using a toolchain which has a Thumb-2
libgcc to build ARM code (i.e., U-Boot).  Because most people have
non-Thumb toolchains, the problem hasn't been observed before...

This also means that using such a toolchain to build U-Boot for a
platform which doesn't support Thumb-2 will result in a broken build
containing Thumb-2 libgcc code that the target can't run.  But this
shouldn't affect toolchains which default to ARM (the usual case,
except for Ubuntu/linaro), and in particular shouldn't break any
toolchain/U-Boot/platform combinations which currently work.

Again, fixing this properly really requires the mutiple-libgcc problem
to be solved.


Cheers
---Dave



More information about the linaro-toolchain mailing list