[PATCH 1/8] ARM: assembler: introduce adr_l, ldr_l and str_l macros
Dave Martin
Dave.Martin at arm.com
Thu Aug 4 06:31:34 PDT 2016
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.
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