Consider this GNU Assembler program for AMD64 Linux:
.globl _start
_start:
movl $59, %eax # SYS_execve
leaq .pathname(%rip), %rdi # position-independent addressing
leaq .argv(%rip), %rsi
movq (%rsp), %rdx
leaq 16(%rsp,%rdx,8), %rdx
syscall
movl $60, %eax # SYS_exit
movl $1, %edi
syscall
.section .data
.argv:
.quad .argv0 # Absolute address as static data
.quad .argv1
.quad 0
.pathname:
.ascii "/bin/"
.argv0:
.asciz "echo"
.argv1:
.asciz "hello"
When I build it with gcc -nostdlib -static-pie
and run it, it fails, and strace shows me that this happens:
execve("/bin/echo", [0x301d, 0x3022], 0x7fff9bbe5a08 /* 28 vars */) = -1 EFAULT (Bad address)
It works fine if I build it as a static non-PIE binary or as a dynamic PIE binary, though. It looks like the problem is that relocations aren't getting processed.
In dynamic PIE binaries, the dynamic linker does that, and in non-PIE static binaries, you don't need runtime relocations; static addresses are link time constants.
But how are static PIE binaries supposed to work? Are they just not supposed to have any relocations at all, or is something else supposed to process them?