On Fri Nov 22 00:43:11 2024 +0000, Alexandre Julliard wrote:
Now that the PE separation is complete, GSBASE can be swapped when
entering/exiting PE code. This is done in the syscall dispatcher, unix-call dispatcher, and for user-mode callbacks. GSBASE also needs to be set to the macOS TSD when entering signal handlers (in `init_handler()`), and then restored to the Windows TEB when exiting (in `leave_handler()`). There is a special-case needed in `usr1_handler`: when inside a syscall (on the kernel stack), GSBASE may need to be reset to either the TEB or the TSD. The only way to tell is to determine what GSBASE was set to on entry to the signal handler. Other signals can also happen during syscalls. I think you should use the same mechanism as Linux in `leave_handler()` instead of special-casing SIGUSR1.
Ah true, I can do that: ``` if (!is_inside_signal_stack( (void *)RSP_sig(sigcontext )) && !is_inside_syscall(sigcontext)) _thread_set_tsd_base( (uint64_t)NtCurrentTeb() ); ```
That doesn't cover the scenario I added the special-case for though (and which needs to be addressed for other signal handlers too):
If a signal is delivered in `__wine_syscall_dispatcher_return` after the `_thread_set_tsd_base` call (setting GSBASE back to the TEB) but before switching back to the user stack, GSBASE needs to be reset to the TEB even though `is_inside_syscall()` is still TRUE. Rather than the `gs30` trick, maybe this could be detected by putting a label at the stack switch and then checking whether `RIP` is between `__wine_syscall_dispatcher_return` or the stack switch?
Also I don't think the `inside_syscall` case of `usr1_handler()` even calls `leave_handler()`? But that could be added.