This is the mail archive of the
mailing list for the binutils project.
Re: [Bug ld/21458] ld generates none ARM elf ABI compliant code that causes a hard fault.
- From: Andrew Goedhart <andrewgoedhart at gmail dot com>
- To: nickc at redhat dot com <sourceware-bugzilla at sourceware dot org>
- Cc: binutils at sourceware dot org
- Date: Wed, 10 May 2017 16:06:30 +0200
- Subject: Re: [Bug ld/21458] ld generates none ARM elf ABI compliant code that causes a hard fault.
- Authentication-results: sourceware.org; auth=none
- References: <firstname.lastname@example.org/bugzilla/> <bug-21458-10667-HYjdw5oZjR@http.sourceware.org/bugzilla/>
I had a look at the programmers reference guide for the cortext M3 and M4 .
I noticed that the instructions BL and B require a label not a
register. This is true for ARMV4-ARMV8 architectures. All the
architectures that support thumb and where a .thumb_func symbol would
Only BLX and BX can and must use a register as an operand. i.e. BLX
R0 Again true from ARMV4-ARMV8.
That means in thumb code you cannot branch on a register unless it is
a MOV PC or BLX and BX instruction
However for BLX and BX you want to set the lsb bit to 1 for a thumb
target (.thumb_func). If you use a MOV, bit is ignored and set to 0
so setting it to 1 does not cause failure
If you are loading the address of a constant it would not be
appropriate to set the lsb bit to 1 but then the target of the load
would not be a STT_FUNC. or .thumb_func
Now for Cortext M0, M3, M4, M7 and ARMV6T
Some Interesting excerpts from ARMv6 architecture
Mov PC, Rx
When Rd is the PC in a MOV instruction:
* Bit of the result is discarded.
* A branch occurs to the address created by forcing bit of the
result to 0. The T-bit remains unmodified.
for BX and BLX
* The BX and BLX instructions result in a HardFault exception if
bit of Rm is 0.
ARMV4T & ARMV5T
Also from page A4-43 of the architecture reference manual for ARM5(T)
When the PC is the destination of the instruction, a branch occurs.
The instruction: MOV PC, LR can therefore be used to return from a
subroutine (see instructions B, BL on page A4-10). In T variants of
architecture 4 and in architecture 5 and above, the instruction BX LR
must be used in place of MOV PC, LR, as the BX instruction
automatically switches back to Thumb state if appropriate (but see
also The T and J bits on page A2-15 for operation on non-T variants of
ARM architecture version 5)
also from A2-10 of the architecture reference manual:
'The precise rules depend on the current instruction set state and the
• In T variants of ARMv4 and above, including all variants of ARMv6
and above, bit of a value written to R15 in Thumb state is ignored
unless the instruction description says otherwise. If bit of the PC
is implemented (which depends on whether and how the Jazelle Extension
is implemented), then zero must be written to it regardless of the
value written to bit of R15.
• In ARMv6 and above, bits[1:0] of a value written to R15 in ARM state
are ignored unless the instruction description says otherwise. Bit
of the PC must be written as zero regardless of the value written to
bit of R15. If bit of the PC is implemented (which depends on
how the Jazelle Extension is implemented), then zero must be written
to it. '
So if thumb is supported and a MOV PC, Rx is used the lsb bit is
ignored on all targets upto and including V7.
This means that if the target is a .thumbfunc, when doing an ADR, the
lsb can be set without breaking code unless that code was loading an
address for another reason other then branching to it.
So if we adjusted ADR to include setting the thumb bit for targets of
ADR R0 FunctionPtr
MOV PC, R0
would function correctly.
On Wed, May 10, 2017 at 2:10 PM, nickc at redhat dot com
> --- Comment #7 from Nick Clifton <nickc at redhat dot com> ---
> (In reply to Andrew Goedhart from comment #6)
> Hi Andrew,
>> Unfortunately we may potentially have another problem. When trying to
>> generate a test case I came across the following.
>> ADR R0,__testFnPtr
>> BLX R0
>> The problem is that the thumb bit is not set ( subw r0, pc, #8
>> results in an even address) and that this code causes a hard fault.
>> Now I don't know my assembly as well as I should so there might be
>> wrong/missing directives in the above file. Comment welcome
> Hmm, it appears that the ADR pseudo-instruction may not actually support
> encoding thumb function addresses in the bottom bit. It is not mentioned
> in the description of the instruction in the ARM ARM. (I am looking at
> section A8.8.12 of the ARM DDI 0406C.b document).
> The intent, I think, is that the value loaded by an ADR instruction will
> be used by a B or BL instruction, but not a BLX instruction.
> Except that there is a special case when the destination register of the
> ADR instruction is the PC and the processor supports the ARMv7 ISA.
> In this cae the instruction acts like a BX instruction. Prior to ARMv7
> however ADR PC, <label> would act as a B instruction.
> Changing the behaviour of the ADR instruction now, would I think, be a
> very dangerous thing to do. Presumably there is already (lots of) code
> out there that is using it in its current state, and fixing this bug, if
> it really is a bug, would have the potential to break things.
> I will however ping the guys at ARM to see if they have an opinion.
> You are receiving this mail because:
> You are on the CC list for the bug.
> You reported the bug.
Tel: +27 84 924 5225
Simple Power Solutions, 14 Heron Way, Pinelands, 7405