考虑这个适用于 AMD64 Linux 的 GNU 汇编程序:
.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"
当我使用它构建gcc -nostdlib -static-pie
并运行它时,它失败了,并且 strace 告诉我发生了这种情况:
execve("/bin/echo", [0x301d, 0x3022], 0x7fff9bbe5a08 /* 28 vars */) = -1 EFAULT (Bad address)
不过,如果我将它构建为静态非 PIE 二进制文件或动态 PIE 二进制文件,它工作正常。看起来问题是重定位没有得到处理。
在动态 PIE 二进制文件中,动态链接器会执行此操作,而在非 PIE 静态二进制文件中,您不需要运行时重定位;静态地址是链接时间常数。
但是静态 PIE 二进制文件应该如何工作?他们只是根本不应该有任何搬迁,还是应该有其他东西来处理它们?