【发布时间】:2017-09-19 20:13:54
【问题描述】:
我正在尝试使用参数创建一个简单的控制台汇编程序。代码如下:
.section __TEXT,__text
.globl _main
_main:
movl $0, %edi
callq _exit
这是编译和链接脚本:
as test.s -o test.o
ld test.o -e _main -o test -lc
现在程序要么因分段错误而失败,要么执行时没有错误,具体取决于参数计数:
$ ./test
Segmentation fault: 11
$ ./test 1
$ ./test 1 2
$ ./test 1 2 3
Segmentation fault: 11
$ ./test 1 2 3 4
$ ./test 1 2 3 4 5
Segmentation fault: 11
等等。
在 LLDB 下,我看到了更多信息错误:
Process 16318 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x00007fffad14b2fa libdyld.dylib`stack_not_16_byte_aligned_error
libdyld.dylib`stack_not_16_byte_aligned_error:
-> 0x7fffad14b2fa <+0>: movdqa %xmm0, (%rsp)
0x7fffad14b2ff <+5>: int3
libdyld.dylib`_dyld_func_lookup:
0x7fffad14b300 <+0>: pushq %rbp
0x7fffad14b301 <+1>: movq %rsp, %rbp
确实,如果我在程序的第一行停止执行,我会看到堆栈对于某些参数计数不是 16 字节对齐的,而对于另一个参数计数是对齐的。虽然System V ABI for AMD64 声明:
堆栈指针保存地址最低的字节的地址 这是堆栈的一部分。它保证在 16 字节对齐 进程入口。
我错过了什么?
【问题讨论】:
-
看起来 OS X 在某些长度的参数上违反了 ABI。 (希望他们从未声称完全遵循该 ABI?不过我认为他们也这样做了。)您是否尝试过不使用 libc,只是在进程进入静态链接二进制文件时自己(使用调试器)检查堆栈对齐,该二进制文件以直接
syscall? (或设置退出状态 =rsp & 0xf和./test 1 2 3 ; echo $?以查看堆栈对齐)。