我应该如何让gcc在进入函数的过程中将堆栈指针重新对齐到16字节边界?

我应该如何让gcc在进入函数的过程中将堆栈指针重新对齐到16字节边界?,gcc,x86-64,mingw-w64,memory-alignment,stack-pointer,Gcc,X86 64,Mingw W64,Memory Alignment,Stack Pointer,我正在尝试使用mingw64在Windows x86_64上运行现有的JIT 当JIT调用回预编译代码时,我得到了SEGFULTS,而该代码调用Windows API,因为Windows API实现中的对齐移动指令(如movaps)是用%rsp调用的,而不是16的倍数,即堆栈没有对齐到16字节的边界 Thread 1 hit Catchpoint 2 (signal SIGSEGV), 0x00007fff5865142d in KERNELBASE!FindFirstFileA () from

我正在尝试使用mingw64在Windows x86_64上运行现有的JIT

当JIT调用回预编译代码时,我得到了SEGFULTS,而该代码调用Windows API,因为Windows API实现中的对齐移动指令(如
movaps
)是用
%rsp
调用的,而不是16的倍数,即堆栈没有对齐到16字节的边界

Thread 1 hit Catchpoint 2 (signal SIGSEGV), 0x00007fff5865142d in KERNELBASE!FindFirstFileA () from C:\WINDOWS\System32\KernelBase.dll
1: x/i $pc
=> 0x7fff5865142d <KERNELBASE!FindFirstFileA+125>:      movaps 0x60(%rsp),%xmm0
2: /x $rsp = 0xd8edd8
奇怪的是,这实际上是在放入
和q$-16,%rsp
(将堆栈指针对齐到16的倍数),尽管我们说更喜欢8字节对齐

我对这些选项或它们的工作案例有什么误解

gcc的版本是MSYS2 mingw64的10.2.0:

$ gcc --version
gcc.exe (Rev4, Built by MSYS2 project) 10.2.0

正确的解决方法是
-mincoming stack boundary=3
:您应该告诉编译器,它编译的函数可能会使用未对齐的堆栈调用(因此是“传入”而不是“首选”:您不需要将首选对齐提高到默认值之上)

至于该属性不起作用的原因,您似乎发现了一个特定于64位Microsoft ABI的编译器后端错误。该属性在以Linux为目标时的工作方式与您预期的一样,但在后端有一些针对Microsoft(和Apple)ABI的特殊外壳,并且代码可能与预期行为不一致:

6089/*64位MS ABI似乎要求堆栈对齐始终为16,
6090除函数序言、叶函数和当defult
6091传入堆栈边界在命令行或通过
6092强制对齐参数指针属性。
6093
6094达尔文的ABI为32位和64位变体指定128b对齐
6095,包括配置文件函数调用。
6096  */
6097中频((目标64位MS ABI目标男性)
6098&&crtl->首选\u堆栈\u边界<128)
6099&(!crtl->is|u leaf|cfun->calls_alloca!=0
6100 | | ix86(当前)函数(调用)tls(描述符)
6101 | |(目标机器和crtl->外形)
6102 | | ix86(输入(堆栈)边界<128))
6103     {
6104 crtl->首选_堆栈_边界=128;
6105 crtl->堆栈对齐所需=128;
6106     }
6107

(请注意注释是如何引用属性的,但代码显然不是这样工作的)

最后,我将不再需要这种对齐修复,通过将JIT中的堆栈分配固定为对齐16—通过手动修补机器代码块—但我很好奇为什么这些gcc选项不能像tin.Ah上所说的那样工作。昨天我在
i386.c
的其他地方研究了
force_align_arg_pointer
属性的用法,发现
ix86_minimum_incoming_stack_boundary()
()将
incoming_stack_boundary
转储到最小值,如果设置了该属性,但是我在试图协调下面代码中的重写条件时迷失了方向,而没有真正弄清楚这是否应该起作用。
$ gcc --version
gcc.exe (Rev4, Built by MSYS2 project) 10.2.0