简体   繁体   English

x86-64 Linux 堆栈未对齐时无段错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM