This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: ld emitting blx immdetiate for Cortex M3
Am 16.03.2012 um 14:46 schrieb Matthew Gretton-Dann:
> On Fri, Mar 16, 2012 at 01:04:53PM +0000, Benjamin Hase wrote:
>>
>> Am 16.03.2012 um 13:09 schrieb Matthew Gretton-Dann:
>>
>>> On Fri, Mar 16, 2012 at 08:34:46AM +0000, Benjamin Hase wrote:
<snip>
>>>>
>>>> arm-none-eabi-objdump -d shows in strtol_r (which is internally called from newlib) blx instructions:
>>>>
>>>> 80a2: 1c30 adds r0, r6, #0
>>>> 80a4: 4651 mov r1, sl
>>>> 80a6: f000 e910 blx 82c8 <__aeabi_uidivmod>
>>>> 80aa: 1c30 adds r0, r6, #0
>>>> 80ac: 4689 mov r9, r1
>>>> 80ae: 4651 mov r1, sl
>>>> 80b0: f000 e88c blx 81cc <__aeabi_uidiv>
>>>> 80b4: 2603 movs r6, #3
>>>
>>> Take a look at __aeabi_uidivmod and __aeabi_uidiv - I think you will find
>>> that they are in ARM state, and so the BLX is valid.
>>
>> Is it possible to recognize for which state functions are compiled? I tried objdump -x (full output below),
<snip>
> If you want to know whether a function is ARM or Thumb state use readelf -s.
> If the FUNC symbol has an odd value then it is in Thumb state, if it is even
> its in ARM state.
>
> On an image based on your test case I get the following:
>
> $ arm-none-readelf -s t.axf | grep FUNC
> 40: 000082f8 8 FUNC LOCAL DEFAULT 1 ____aeabi_idiv0_from_arm
> 44: 000081d4 252 FUNC GLOBAL DEFAULT 1 __udivsi3
> 47: 000081b5 32 FUNC GLOBAL DEFAULT 1 strtol
> 48: 00008035 16 FUNC GLOBAL DEFAULT 1 _atoi_r
> 51: 000082f1 2 FUNC WEAK DEFAULT 1 __aeabi_ldiv0
> 53: 00008001 36 FUNC GLOBAL DEFAULT 1 main
> 54: 000081d4 0 FUNC GLOBAL DEFAULT 1 __aeabi_uidiv
> 55: 00008045 368 FUNC GLOBAL DEFAULT 1 _strtol_r
> 58: 000082d0 32 FUNC GLOBAL DEFAULT 1 __aeabi_uidivmod
> 62: 00008025 16 FUNC GLOBAL DEFAULT 1 atoi
> 64: 000082f1 2 FUNC WEAK DEFAULT 1 __aeabi_idiv0
>
> So strtol, _atoi_r, __aeabi_ldiv0, main, strtol_r, atoi, __aeabi_idiv0 are
> Thumb state entry points, and all the other function entry points are in ARM
> state.
arm-none-eabi-readelf -a toolchain-test.elf | grep FUNC
40: 000002f0 8 FUNC LOCAL DEFAULT 1 ____aeabi_idiv0_from_arm
46: 000001cc 252 FUNC GLOBAL DEFAULT 1 __udivsi3
49: 000001ad 32 FUNC GLOBAL DEFAULT 1 strtol
51: 00000039 16 FUNC GLOBAL DEFAULT 1 _atoi_r
53: 000002e9 2 FUNC WEAK DEFAULT 1 __aeabi_ldiv0
54: 00000001 38 FUNC GLOBAL DEFAULT 1 main
55: 000001cc 0 FUNC GLOBAL DEFAULT 1 __aeabi_uidiv
56: 00000049 356 FUNC GLOBAL DEFAULT 1 _strtol_r
58: 000002c8 32 FUNC GLOBAL DEFAULT 1 __aeabi_uidivmod
62: 00000029 16 FUNC GLOBAL DEFAULT 1 atoi
64: 000002e9 2 FUNC WEAK DEFAULT 1 __aeabi_idiv0
This tells me, that __aeabi_idiv0_from_arm, __udivsi3, __aeabi_uidiv and __aeabi_uidivmod are in ARM state, right?
That fits also with the output of objdump.
>
>>> This is because you have not set up your multilibs correctly for Cortex-M3
>>> and so (at a guess) you have linked v7-M code against v4-T code containing
>>> ARM state code. The linker will not complain about this as it views the two
>>> as being compatible - the linker has no idea about which core you are
>>> targeting your image at.
>> There are two questions for me:
>> a) it seems as if the linker tries to do the right thing, the used libraries are below thumb/,
>> according to the linker trace. That, of course, does not ensure the libraries itself are right???
>> b) If the linker is allowed to change opcodes (as it looks like in this example), shouldn't
>> he know about which opcodes are allowed? And this is architecture dependent IMHO.
When looking at objects with arm-none-eabi-readelf -A, it looks like a toolchain problem for me (like you first suspected :-):
toolchain-test.elf:
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "Cortex-M3"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Microcontroller
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: small
Tag_ABI_optimization_goals: Aggressive Debug
lib_a-strtol.o:
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "ARM7TDMI"
Tag_CPU_arch: v4T
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: small
Tag_ABI_optimization_goals: Aggressive Speed
Tag_DIV_use: Not allowed
So I think the following is happening (please correct me, when I am wrong)
- the linker starts with my application object, sees (by compiler option) architecture arm-v7
- resolves atoi, strtol -> pulls lib_a-strtol.o
- sees in lib_a-strtol.o architecture arm-v4t and enables ARM mode
- arm-v4t does not know blx either, but since arm-v7 is already accepted (which can do blx),
he is happy to change bl with blx
>>
>>>
>>> Configuring and building a suitable toolchain for this is non-trivial.
>>>
>>> The following website gives a pre-built GCC 4.6 based toolchain with Cortex-M
>>> libraries. It also gives instructions for how to build such a toolchain
>>> from scratch if the options provided are not suitable for you.
>> A link would have been nice :-)
>
> Sorry - I shouldn't send emails immediately before lunch :-). Here you go:
>
> https://launchpad.net/gcc-arm-embedded
Looks promising, I will try it next week :-)
Thank you
Benjamin
---
Benjamin Hase
Forschung & Entwicklung
Tel.: +49 (0) 23 24 / 96 48-0
---------------------------------------------------------------------
RESOL - Elektronische Regelungen GmbH
Heiskampstr. 10 - 45527 Hattingen / Germany
Sitz Hattingen - Geschäftsführer: Rudolf Pfeil
Amtsgericht - Registergericht - Essen - HRB 15674
---------------------------------------------------------------------