I am trying to build and link a single image to load as an OS kernel (ie. in QEMU) targeting aarch64-unknown-none-softfloat. I use a custom linker.ld file which sets the entry point for the kernel ENTRY(_reset) and positions the image
. = 0x40080000
where the program counter (PC) is on reset.
It works ok until I map the pages at 0x40080000 to high memory where the kernel will reside and enable virtual memory translation. To ensure the debugging information meshes after the switch, I change the nominal image position to
. = 0xffffff8200000000
and rebuild.
I have discovered that access:
- to some (pub extern) statics, and
- by certain core library functions
is by reading the absolute address from somewhere in .rodata. This breaks the code when it is running before mapping. And if I change it back it will break the code when I run it after mapping.
The code it is generating looks a bit like this at O1 (indirect through PC-relative page):
adrp x0, 0x10000 // page offset from PC up to rodata
add x0, 0x120 // byte offset from page in rodata
ldr x0, [x0] // use as address
What I need is truly position independent code across code and data so that it works at both locations in memory without referring to any stored absolute addresses, even if those addresses are available relative to PC.
I've tried the other relocation-models including Pic and RopiRwpi but I can't see it generating different code.
Thanks!
EDIT: Thanks very much for the suggestions to temporarily map. I have seen that used. I am more interested in compiler options that will enable -no-dynamic-linker to work, avoiding generating code that requires R_AARCH64_ABS64 relocations on the strength of a guarantee that code and data will be a set distance apart..