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