[英]x86-64 Linux No seg fault on stack misalignment
I'm just working through Nick Desaulniers: Let's Write Some X86-64 File h4.s:我只是通过 Nick Desaulniers 工作: 让我们写一些 X86-64文件 h4.s:
.text
.globl main
main:
# subq $8, %rsp
movq $0, %rdi
call _exit
He's running on a Mac and says running the above will give a segmentation fault.他在 Mac 上运行,并说运行上面的会出现分段错误。 I'm running on opensuse 13.1 just calling
我在 opensuse 13.1 上运行只是调用
gcc h4.s
to compile and link.编译和链接。 I don't get a seg fault when the stack pointer is adjusted or when the line is commented out.
调整堆栈指针或注释掉该行时,我不会收到段错误。 Does anyone know why not?
有谁知道为什么不? Doesn't the SP need to be aligned to a 16 byte boundary?
SP 不需要与 16 字节边界对齐吗?
The x86-64 System V ABI requires the stack pointer to be 8 mod 16 bytes on entry to a routine (16B aligned before the call
, 16+8 after with a return address pushed on the stack). x86-64 System V ABI 要求堆栈指针在进入例程时为 8 mod 16 字节(
call
前 16B 对齐, call
后 16+8 对齐,返回地址压入堆栈)。
Only SSE instructions require this (like movaps
/ movdqa
), which most library functions happen not to use.只有 SSE 指令需要这个(如
movaps
/ movdqa
),大多数库函数碰巧不使用。 Especially simple ones like _exit
could be as simple as mov $231, %eax
/ syscall
.特别简单的像
_exit
可以像mov $231, %eax
/ syscall
一样简单。
However, if the stack is misaligned and someone at some point wants to do something that is based on the assumption that they have a 16B aligned stack.但是,如果堆栈未对齐,并且某人在某个时候想要做一些基于他们有 16B 对齐堆栈的假设的事情。 For example, issue an aligned xmm instructions like "movdqa [rsp],...", then you can get an actual seg fault.
例如,发出像“movdqa [rsp],...”这样的对齐的 xmm 指令,那么您会得到一个实际的段错误。 Or hypothetically some other error for some other kind of assumption of stack alignment.
或者假设其他一些堆栈对齐假设的其他错误。
In summary : Simply misaligning the stack before a call will usually not fault.总结:在调用之前简单地错位堆栈通常不会出错。
Just like C undefined behaviour, it's not required to fail if you violate the rules, but it can fail.就像 C 的未定义行为一样,如果您违反规则,它不需要失败,但它可能会失败。 And what happens to work now might break in the future or on other systems.
现在发生的事情可能会在将来或在其他系统上中断。
Compilers are allowed to use SSE anywhere to copy 16 bytes at a time to / from local variables, because of the ABI guarantee , and because x86-64 guarantees at least SSE2.编译器允许使用SSE任何地方同时从局部变量/复制16个字节, 因为ABI保障的,因为X86-64保证至少SSE2。
For example, glibc scanf Segmentation faults when called from a function that doesn't align RSP - modern builds of glibc include a movaps
to copy 16 bytes at once to a local struct or array.例如, 从与 RSP 不对齐的函数调用时, glibc scanf 出现分段错误- glibc 的现代构建包括一次将 16 个字节复制到本地结构或数组的
movaps
。 Older builds of glibc didn't require stack alignment (when you properly set AL=0).较旧的 glibc 版本不需要堆栈对齐(当您正确设置 AL=0 时)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.