I'm using GNU AS as assembler and I'm trying to write a position independent binary and I have some problems writing the PC relative address of an external symbols. Normaly a relative address is loaded with
adr r0, symbol
but that only works for symbols defined in the same section in the assembly file. The other method to load a symbol is
ldr r0, =symbol
which stores the absolute address of the symbol in a constant and loads it pc relative from there. So you get code like this:
48: e59f0008 ldr r0, [pc, #8] ; 58 <text+0xc>
...
58: 00000008 .word 0x00200018
58: R_ARM_ABS32 symbol
But what I need is a R_ARM_REL32 linker reference.
What I have come up with is this code:
tmp1: ldr r0, [pc, #tmp2 - tmp1 - 8]
ldr r0, [pc, r0]
tmp2: .word symbol - tmp1
This produces:
0000003c <tmp1>:
3c: e59f0000 ldr r0, [pc] ; 44 <tmp2>
40: e79f0000 ldr r0, [pc, r0]
00000044 <tmp2>:
44: 00000008 .word 0x00000008
44: R_ARM_REL32 symbol
I can nearly put that into a macro so it is reusesable for whatever symbol I need. Except I don't know how to tell the assembler that tmp2 needs to go to the constants block instead of ending up right there in the middle of the code.
But isn't there already some existing syntax or macro for that in GNU AS?
adrl
? This should allow larger references and you can use-fwhole-program
. I don't think you can do this in 'C' without some sort of relocation (like plt, glt, etc). Typically, 'C' thinks you can do thing like access global variables, etc. For the ARM ABI, .text and .data can be far apart and the compiler needs to support this. There is also this question. That said, u-boot does this with a 'sb'. – artless noise