This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Bug ld/21458] ld generates none ARM elf ABI compliant code that causes a hard fault.


Hi Nic

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
be relevant.

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[0] 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

ARMV6T&ARMV7T
--------------------------
Now for Cortext M0, M3, M4, M7 and ARMV6T
Some Interesting excerpts from ARMv6 architecture
[https://developer.arm.com/docs/dui0662/latest/3-the-cortex-m0-instruction-set/35-general-data-processing-instructions/355-mov-and-mvn]

Mov PC, Rx

When Rd is the PC in a MOV instruction:
   * Bit[0] of the result is discarded.
   * A  branch occurs to the address created by forcing bit[0] 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[0] of Rm is 0.


ARMV4T & ARMV5T
---------------------------
Also  from page A4-43 of the architecture reference manual for ARM5(T)

from MOV
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
architecture version:

 • In T variants of ARMv4 and above, including all variants of ARMv6
and above, bit[0] of a value written to R15 in Thumb state is ignored
unless the instruction description says otherwise. If bit[0] 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[0] 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[1]
of the PC must be written as zero regardless of the value written to
bit[1] of R15. If bit[0] 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
type /thumb_func,

both

.thumb_func
FunctionPtr:

ADR R0 FunctionPtr
BLX R0

and

MOV PC, R0

would function correctly.



regards

Andrew



On Wed, May 10, 2017 at 2:10 PM, nickc at redhat dot com
<sourceware-bugzilla@sourceware.org> wrote:
> https://sourceware.org/bugzilla/show_bug.cgi?id=21458
>
> --- 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.
>
> Cheers
>   Nick
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.
> You reported the bug.

-- 
Andrew Goedhart
Tel: +27 84 924 5225
Simple Power Solutions, 14 Heron Way, Pinelands, 7405


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]