Skip to content

Commit 6a54545

Browse files
committed
Align stack for GCC on incoming stdcall (x86 only)
This GCC bug has had a wide impact since 2008. It affects nearly every x86 program with a foreign-facing stdcall function, except WinMain and wWinMain (covered by a CRT special case). That includes callbacks like WNDPROC and APCs, thread procedures for CreateThread and _beginthreadex, and entry points like mainCRTStartup and WinMainCRTStartup. Programs included in w64dk have workarounds as needed, though between Binutils 2.42 (6bf81ff) and this patch, they're redundant. But still needed, of course, when compiled with other Mingw-w64 toolchains. Some cases are still affected, most commonly _beginthread, whose thread procedure is _not_ stdcall, but is still called with a stack unsuitably aligned for GCC. This case is less arguably a GCC bug, though neither MSVC nor Clang are affected by this issue (due to not assuming 16-byte stack alignment).
1 parent 6bf81ff commit 6a54545

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/gcc-stdcall-align.patch

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
GCC requires 16-byte stack alignment on function entry, but x86 calling
2+
conventions only provide 4-byte alignment. Entry points, such as thread
3+
procedures, callbacks, and process entry points, are likely called on a
4+
stack not aligned to GCC's expectations. Since these functions are also
5+
typically __stdcall, silently add the force_align_arg_pointer attribute
6+
to such functions so that GCC re-aligns the stack.
7+
8+
Note: main, wmain, WinMain, and wWinMain are special cases which the CRT
9+
calls with 16-byte alignment.
10+
11+
--- a/gcc/config/i386/i386-options.cc
12+
+++ b/gcc/config/i386/i386-options.cc
13+
@@ -3689,7 +3689,7 @@
14+
arguments as in struct attribute_spec.handler. */
15+
16+
static tree
17+
-ix86_handle_cconv_attribute (tree *node, tree name, tree args, int,
18+
+ix86_handle_cconv_attribute (tree *node, tree name, tree args, int flags,
19+
bool *no_add_attrs)
20+
{
21+
if (TREE_CODE (*node) != FUNCTION_TYPE
22+
@@ -3773,6 +3773,11 @@
23+
sseregparm. */
24+
else if (is_attribute_p ("stdcall", name))
25+
{
26+
+ if (!TARGET_64BIT)
27+
+ {
28+
+ tree attr = tree_cons (get_identifier ("force_align_arg_pointer"), NULL_TREE, NULL_TREE);
29+
+ decl_attributes (node, attr, flags);
30+
+ }
31+
if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
32+
{
33+
error ("stdcall and cdecl attributes are not compatible");

0 commit comments

Comments
 (0)