While the prelink(8)
tool and concept are widely detested (and probably not shipped on your distribution), you may be able to use it to link libraries into a binary into low memory:
-r --reloc-only=ADDRESS
Instead of prelinking, just relink given shared libraries
to the specified base address.
Since the address that libraries will be mapped into the process is determined by ld(1)
, you might be able to modify your Makefile
to invoke ld
with different --section-start
values:
--section-start SECTION=ADDRESS
Set address of named section
-Tbss ADDRESS Set address of .bss section
-Tdata ADDRESS Set address of .data section
-Ttext ADDRESS Set address of .text section
-Ttext-segment ADDRESS Set address of text segment
I moved the text and bss segments down to lower addresses:
$ gcc -Wl,-Ttext-segment=0x200000 -Wl,-Tbss=0x400000 -o broken broken.c
$ readelf -a broken
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x200450
...
If you can move all the sections provided in the executable with --section-start
and move the libraries down with prelink(8)
, you might be able to get all the code loaded below 4 gigabytes.