From: Yuxuan Shui yshui@codeweavers.com
If wine dlls are built with frame pointers enabled, the frame pointer will be used during unwinding.
If we don't restore frame pointer before calling the user mode callback, then later when the unwinder encounters the user mode callback frame, it will set the frame pointer to something unexpected (depends on what it was during `call_user_mode_callback`). Then for the subsequent frame it adjusts the stack pointer based on the frame pointer, thus derailing the unwinding process. --- dlls/ntdll/unix/signal_x86_64.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 6ec662b9850..a3adf24c64f 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1613,7 +1613,7 @@ NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context /*********************************************************************** * call_user_mode_callback */ -extern NTSTATUS call_user_mode_callback( ULONG64 user_rsp, void **ret_ptr, ULONG *ret_len, void *func, TEB *teb ); +extern NTSTATUS call_user_mode_callback( ULONG64 user_rsp, void **ret_ptr, ULONG *ret_len, void *func, TEB *teb, ULONG64 user_rbp ); __ASM_GLOBAL_FUNC( call_user_mode_callback, "subq $0x58,%rsp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 0x58\n\t") @@ -1648,6 +1648,7 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "testl $1,0x380(%r13)\n\t" /* thread_data->syscall_trace */ "jz 1f\n\t" "movq %rdi,%r12\n\t" /* user_rsp */ + "movq %r9,%r14\n\t" /* user_rbp */ "movl 0x2c(%r12),%edi\n\t" /* id */ "movq %rdi,-0x50(%rbp)\n\t" "movq %rcx,%r15\n\t" /* func */ @@ -1655,9 +1656,11 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "movl 0x28(%r12),%edx\n\t" /* len */ "call " __ASM_NAME("trace_usercall") "\n\t" "movq %r12,%rdi\n\t" /* user_rsp */ + "movq %r14,%r9\n\t" /* user_rbp */ "movq %r15,%rcx\n" /* func */ /* switch to user stack */ "1:\tmovq %rdi,%rsp\n\t" /* user_rsp */ + "movq %r9,%rbp\n\t" /* user_rbp */ #ifdef __linux__ "movw 0x338(%r13),%ax\n" /* amd64_thread_data()->fs */ "testw %ax,%ax\n\t" @@ -1768,7 +1771,7 @@ NTSTATUS KeUserModeCallback( ULONG id, const void *args, ULONG len, void **ret_p stack->machine_frame.rip = frame->rip; stack->machine_frame.rsp = frame->rsp; memcpy( stack->args_data, args, len ); - return call_user_mode_callback( rsp, ret_ptr, ret_len, pKiUserCallbackDispatcher, NtCurrentTeb() ); + return call_user_mode_callback( rsp, ret_ptr, ret_len, pKiUserCallbackDispatcher, NtCurrentTeb(), frame->rbp ); }