On Tue, Sep 21, 2010 at 9:29 PM, Wolfgang Denk wd@denx.de wrote:
Dear Dave Martin,
In message AANLkTikHv1SpjcyRbRxGK2QeCoq96tsTken3LmP5bsse@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).
- 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