I am using the GCC options -mpic-data-is-text-relative
and -fpic
to generate position independent code. This works fine for my C code.
But I also have assembly code that needs to use PIC. The problem is I cannot find an example on how to achieve this. Are there some ARM GCC assembly keywords, do I need to set up my own GOT table or are there any neat tricks?
I'm trying to reach a variable from my code using PIC:
.section .data @HWA_SWI_HND_DATA, "w"
hwa_ext_reset_hnd:
.word 0x00000000
.section .text @HWA_SWI_HND_CODE, "x"
.code 32
.list
.global hwa_reset_cb_attach
hwa_reset_cb_attach:
ldr r1, =hwa_ext_reset_hnd
str r0, [r1]
bx lr
As seen above in the ldr r1, =hwa_ext_reset_hnd
call I want this address fetch to be PIC.
The Elf DATA follows text and the offset to data can be known at link time. You need to add the PC to an offset between known location and data to access the data. See ARM ELF and Linkers and loader chp8 by John Levine.
Obviously, if this is hosted by an OS and loader, you will need to use the conventions of the platform. The following is written for a bare metal system or places where you have the option to choose.
For example,
.global hwa_reset_cb_attach
hwa_reset_cb_attach:
adr r2, 1f ; pc relative value of label '1'
ldr r1, [r2] ; offset between label and data to r1
add r1, r1, r2 ; pc relative '1' label + offset there
str r0, [r1] ; store to corrected address.
bx lr
1: .word hwa_ext_reset_hnd-. ; offset from here to data fixed at link.
This works for PIC code with data following immediately. If you have many occurrences, you can create a macro to access the data. If there are a lot of references, it maybe easier to keep a register loaded with the beginning of the .data section. The static base with the compiler options -msingle-pic-base
and -mpic-register=
reg; static base is typically r9
. So the load time start of data is put in r9
once and only use str rx,[r9, #hwa_ext_reset-start_of_data]
. This is a tactic used by u-boot and you can even relocate the data sections (moving from iram to SDRAM, etc). However, it consumes an extra register.