https://bugs.winehq.org/show_bug.cgi?id=53682
--- Comment #13 from Kevin Puetz PuetzKevinA@JohnDeere.com ---
The attached patch, with the separate "DECLSPEC_NORETURN __attribute__((noinline)) call_user_mode_callback", there's a much greater chance of this still holding up (with a noreturn function, there's little point for the compiler to store anything else on the stack.
No it's stronger than that. It's noinline that's controlling the compiler, noreturn is just descriptive. In that patch, the setjmp(&jmpbuf) is in KeUserModeCallback. But the callback_frame is in call_user_exception_dispatcher, which, always gets its *own* stack frame (because of noinline). We still smash up the stack of call_user_exception_dispatcher, just like it used to for KeUserModeCallback. But since the longjmp points to KeUserModeCallback, the epilogue of call_user_exception_dispatcher will never get a chance to care.
When setting up a new syscall_frame on the current stack, and calling __wine_syscall_dispatcher_return, we'd need to make sure that the new syscall_frame is at the very exact bottom of the stack.
Yes (given the current __wine_syscall_dispatcher_return). zf and I weren't sure whether that is just convenience, or if there was an actual reason why the stack and syscall_frame needed to be contiguous. If you think it's OK to just add an arbitrary gap, then it would seem more robust for asm code in __wine_syscall_dispatcher_return to simply preserve its own $sp value (which was properly set up by its caller), rather than overwriting it with $sp = syscall_frame. Then it's just going to naturally be the correct stack, rather than an arbitrary 0x100 offset.
(maybe this would mean we need a __wine_syscall_dispatcher_return_callback that differs from __wine_syscall_dispatcher_return, if the usage in handle_syscall_fault and call_init_thunk need to do this).
MSVC could leave a gap at the bottom of the stack
Yeah, and on x86_64 MSVC will *always* leave a gap at the bottom, beacuse that's just part of the ABI:
https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-170#stack-...
The parameter area is always at the bottom of the stack (even if alloca is used), so that it will always be adjacent to the return address during any function call. It contains at least four entries, but always enough space to hold all the parameters needed by any function that may be called. Note that space is always allocated for the register parameters, even if the parameters themselves are never homed to the stack; a callee is guaranteed that space has been allocated for all its parameters