为什么 strace 报告我的 x64 FASM 程序以 32 位模式运行?

Why does strace report my x64 FASM program runs in 32-bit mode?

我的源文件顶部有 format ELF64 executable 3

我使用 fasm main.asm

编译了我的程序

输出:

flat assembler  version 1.73.13  (16384 kilobytes memory, x64)
3 passes, 319 bytes.

然后我尝试使用 strace ./main 运行 它,因为它没有按预期工作并且在输出中有 strace: [ Process PID=3012310 runs in 32 bit mode. ].

file main: main: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, no section header

uname -m: x86_64

使用syscall代替int 0x80

strace 是错误的,您的过程实际上不是 运行 在 32 位模式下,只是使用 32- bit int 0x80 系统调用 ABI.

您可以使用 gdb ./main 检查并使用 startiinfo regs会显示寄存器状态为64位,包括16个64位寄存器,不包括8个32位寄存器。或者更简单地说,layout reg.


我在使用 NASM 构建程序时看到相同的 strace 错误(?),该程序在 64 位模式下使用 32 位 int 0x80 ABI 来构建 exit 系统打电话。

我在第一次系统调用之前添加了一个延迟循环,我发现 strace 在进行系统调用之前不会打印出目标进程的位数。所以 显然 strace 从它是使用 64 位 syscall ABI 还是 32 位 int 0x80 / sysenter ABI 来推断!

也许这与 strace 试图弄清楚如何解码系统调用有关: strace 使用的 Linux ptrace API 没有'没有一个简单可靠的机制来判断进程调用了哪个系统调用 ABI。 https://superuser.com/questions/834122/how-to-distinguish-syscall-from-int-80h-when-using-ptrace

使用32位系统调用的64位进程过去只是根据64位调用号进行解码。但现在看来现代 strace 检查:

我用 eax=1 / syscall 调用 write,用 eax=1 / int 0x80 调用 exit , strace 正确解码了它们

execve("./nasm-test", ["./nasm-test"], 0x7ffdb8da5890 /* 52 vars */) = 0
write(0, NULL, 0)                       = 0
strace: [ Process PID=5219 runs in 32 bit mode. ]
exit(0)                                 = ?
+++ exited with 0 +++

这是 Linux 5.3.1-arch1-1-ARCH 上的 strace 5.3