Elven Relativism -- relocation and execution of aarch64 ELF relocatable objects (REL) on Linux and macOS.
Program loads a multitude of ELF REL files, resolves all relocations (currently only SHT_RELA) and if symbol _start
in some section .text
is found, passes control to the former.
- RELs loaded in the order specified on the command line; all relocations in a given REL performed at its loading time.
- Missing-symbol (SHN_UNDEF) resolution via reverse-direction search among the preceding RELs; first-match deterministic.
- Support for RO sections
.rodata
and.text
; every other type of section is RW. - Address-space sanitation (linux-only) -- disposing of pre-existing VMAs (VMA filtering) via string matching to VMA backing path.
- Relocation type SHT_REL; as needed.
- Explicit (CLI) control over the mapping addresses of each REL; as needed.
Files used, with or without modifications, from external repositories:
linux.org/ arch/arm64/include/asm/insn.h -> insn.h
linux.org/ arch/arm64/kernel/module.c -> reloc_add_aarch64.c
linux.org/ arch/arm64/lib/strlen.S -> strlen_linux.s
Sole prerequisite is libelf
. On macOS homebrew
provides v0.8.13; on Linux there should be a dedicated package with an up-to-date version for your distro of choice. That provided:
$ make all
If you have gas
on macOS and prefer to use that:
$ make AS=/full/path/to/gas all
Building gas
itself from source:
$ git clone git://sourceware.org/git/binutils-gdb.git && cd binutils-gdb
$ cd bfd
$ ./configure --target=aarch64-linux-gnu && make && cd -
$ cd libiberty
$ ./configure --target=aarch64-linux-gnu && make && cd -
$ cd opcodes
$ ./configure --target=aarch64-linux-gnu && make && cd -
$ cd gas
$ ./configure --target=aarch64-linux-gnu && make && cd -
$ ./elvenrel test_cross_0.o test_cross_1.o # order of RELs matters for symbol resolution; undefined symbols in later RELs are sought in earlier RELs
$ ./elvenrel test_rodata.o --filter /lib/aarch64-linux-gnu # before executing the REL dispose of VMAs from file mappings containing /lib/aarch64-linux-gnu in the path
$ ./elvenrel test_data.o --filter [heap] # before executing the REL dispose of the VMA designated as `[heap]`, i.e. the process heap
Using --break
raises a SIGTRAP
right before passing control to REL for quick debugging. Unfortunately both GDB and LLDB currently get stuck on the instruction that caused the trap. To progress one needs to manually move the program counter past the break point:
(gdb) set $pc += 4
(lldb) register write pc `$pc + 4`