[PATCH 1/8] ARM: assembler: introduce adr_l, ldr_l and str_l macros
Ard Biesheuvel
ard.biesheuvel at linaro.org
Thu Aug 4 06:46:53 PDT 2016
On 4 August 2016 at 15:31, Dave Martin <Dave.Martin at arm.com> wrote:
> On Thu, Aug 04, 2016 at 01:34:03PM +0200, Ard Biesheuvel wrote:
>> On 4 August 2016 at 13:30, Dave Martin <Dave.Martin at arm.com> wrote:
>> > On Thu, Aug 04, 2016 at 01:10:55PM +0200, Ard Biesheuvel wrote:
>> >> On 4 August 2016 at 13:08, Dave Martin <Dave.Martin at arm.com> wrote:
>> >
>> > [...]
>> >
>> >> > or, for ldr_l:
>> >> >
>> >> > 0: add \dst, pc, #-8
>> >> > 1: add \dst, \dst, #-4
>> >> > 2: ldr [\dst, #0]
>> >> >
>> >> > .reloc 0b, R_ARM_ALU_PC_G0_NC, \sym
>> >> > .reloc 1b, R_ARM_ALU_PC_G1_NC, \sym
>> >> > .reloc 2b, R_ARM_LDR_PC_G2, \sym
>> >> >
>> >> > ... should produce precisely the same result at the .o stage.
>> >> >
>> >>
>> >> Yes, but how is LD going to perform the arithmetic involved in
>
> [...]
>
>> >> handling these relocations? That's is the more interesting part, and
>> >> that is not implemented either in binutils < 2.18
>> >
>> > What arithmetic?
>> >
>>
>> The arithmetic involved in populating the immediate fields of these
>> instructions based on the actual offset between the Place and the
>> Symbol in the final image.
>
> <digression>
>
> Just for interest...
>
>
> For the linker this is just ordinary relocation processing -- there's
> nothing unusual going on, except that neither GCC nor gas usually
> emit these particular insn relocs automatically.
>
There is no such thing as 'ordinary' relocation processing. Each
relocation type requires its own specific handling, and pre-2.18 LD
simply does not come equipped with the routines to perform the
calculations that the ARM/ELF spec defines for these particular
relocation types. Whether GAS or any other assembler can produce them
is irrelevant, my claim is that pre-2.18 LD does not know how to
/consume/ them.
> I think the ARM RVCT compiler could generate them for producing
> ROM-able position independent code in some confgurations. I suspect
> they were supported by ld from the start though, or at least pretty
> early on.
>
>
> When you write
>
> add \dst, pc, #:pc_g0_nc:\sym - (. + 8)
>
> the arithmetic is somewhat bogus -- the assembler does not (and can't)
> do it, because neither the value of \sym, nor of ., is known. Only the
> invariant bit (the - 8) can be processed at assembly time. The
> irreducible part (\sym - .) has to be emitted as a reloc.
>
> Thus, the assembler really does emit
>
> .reloc ., R_ARM_ALU_PC_G0_NC, \sym
> add \dst, pc, #-8
>
> (The "- ." is effectively part of the definition of R_ARM_ALU_PC_G0_NC
> here).
>
>
> For comparison:
>
> $ as <<EOF -o a.o
> .reloc ., R_ARM_ALU_PC_G0_NC, foo
> add r0, pc, #-8
> .reloc ., R_ARM_ALU_PC_G1_NC, foo
> add r0, r0, #-4
> .reloc ., R_ARM_ALU_PC_G2, foo
> add r0, r0, #0
>
> add r0, pc, #:pc_g0_nc:foo - . - 8
> add r0, r0, #:pc_g1_nc:foo - . - 4
> add r0, r0, #:pc_g2:foo - .
> EOF
>
> $ objdump -dr a.o
> 00000000 <.text>:
> 0: e24f0008 sub r0, pc, #8
> 0: R_ARM_ALU_PC_G0_NC foo
> 4: e2400004 sub r0, r0, #4
> 4: R_ARM_ALU_PC_G1_NC foo
> 8: e2800000 add r0, r0, #0
> 8: R_ARM_ALU_PC_G2 foo
> c: e24f0008 sub r0, pc, #8
> c: R_ARM_ALU_PC_G0_NC foo
> 10: e2400004 sub r0, r0, #4
> 10: R_ARM_ALU_PC_G1_NC foo
> 14: e2800000 add r0, r0, #0
> 14: R_ARM_ALU_PC_G2 foo
>
> $ ld --defsym foo=0x4000000 -o a a.o
> $ objdump -dr a
> 00008054 <__bss_end__-0x8018>:
> 8054: e28f07ff add r0, pc, #66846720 ; 0x3fc0000
> 8058: e2800bdf add r0, r0, #228352 ; 0x37c00
> 805c: e2800fe9 add r0, r0, #932 ; 0x3a4
> 8060: e28f07ff add r0, pc, #66846720 ; 0x3fc0000
> 8064: e2800bdf add r0, r0, #228352 ; 0x37c00
> 8068: e2800fe6 add r0, r0, #920 ; 0x398
>
>
>> Yes, .reloc is implemented, but that is not sufficient.
>
> </digression>
>
> Cheers
> ---Dave
More information about the linux-arm-kernel
mailing list