Module: wine Branch: master Commit: 1cc0649755c8817004901f0e0d9a970367a43b3c URL: https://source.winehq.org/git/wine.git/?a=commit;h=1cc0649755c8817004901f0e0...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Jun 1 15:16:23 2021 +0200
ntdll: Store exception jump buffer in the per-thread data.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/signal_arm.c | 6 +++--- dlls/ntdll/unix/signal_arm64.c | 6 +++--- dlls/ntdll/unix/signal_i386.c | 6 +++--- dlls/ntdll/unix/signal_x86_64.c | 6 +++--- dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 33 ++++++++++++++++++++++++++++++--- 6 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 8ecdaa3995b..ccd01e16f16 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -536,7 +536,6 @@ __ASM_GLOBAL_FUNC( call_user_exception_dispatcher, static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) { struct syscall_frame *frame = arm_thread_data()->syscall_frame; - __WINE_FRAME *wine_frame = (__WINE_FRAME *)NtCurrentTeb()->Tib.ExceptionList; DWORD i;
if (!frame) return FALSE; @@ -557,12 +556,13 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) (DWORD)IP_sig(context), (DWORD)SP_sig(context), (DWORD)LR_sig(context), (DWORD)PC_sig(context), (DWORD)CPSR_sig(context) );
- if ((char *)wine_frame < (char *)frame) + if (ntdll_get_thread_data()->jmp_buf) { TRACE( "returning to handler\n" ); - REGn_sig(0, context) = (DWORD)&wine_frame->jmp; + REGn_sig(0, context) = (DWORD)ntdll_get_thread_data()->jmp_buf; REGn_sig(1, context) = 1; PC_sig(context) = (DWORD)__wine_longjmp; + ntdll_get_thread_data()->jmp_buf = NULL; } else { diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index e696ba41a66..248097ce80a 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -676,7 +676,6 @@ __ASM_GLOBAL_FUNC( call_user_exception_dispatcher, static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) { struct syscall_frame *frame = arm64_thread_data()->syscall_frame; - __WINE_FRAME *wine_frame = (__WINE_FRAME *)NtCurrentTeb()->Tib.ExceptionList; DWORD i;
if (!frame) return FALSE; @@ -712,12 +711,13 @@ static BOOL handle_syscall_fault( ucontext_t *context, EXCEPTION_RECORD *rec ) (DWORD64)REGn_sig(28, context), (DWORD64)FP_sig(context), (DWORD64)LR_sig(context), (DWORD64)SP_sig(context) );
- if ((char *)wine_frame < (char *)frame) + if (ntdll_get_thread_data()->jmp_buf) { TRACE( "returning to handler\n" ); - REGn_sig(0, context) = (ULONG_PTR)&wine_frame->jmp; + REGn_sig(0, context) = (ULONG_PTR)ntdll_get_thread_data()->jmp_buf; REGn_sig(1, context) = 1; PC_sig(context) = (ULONG_PTR)__wine_longjmp; + ntdll_get_thread_data()->jmp_buf = NULL; } else { diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 707e965d8b3..db93d3f6ed0 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1779,7 +1779,6 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, EXCEPTION_RECORD *rec, CONTEXT *context ) { struct syscall_frame *frame = x86_thread_data()->syscall_frame; - __WINE_FRAME *wine_frame = (__WINE_FRAME *)NtCurrentTeb()->Tib.ExceptionList; DWORD i;
if (!frame) return FALSE; @@ -1796,7 +1795,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, context->Ebp, context->Esp, context->SegCs, context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags );
- if ((char *)wine_frame < (char *)frame) + if (ntdll_get_thread_data()->jmp_buf) { /* stack frame for calling __wine_longjmp */ struct @@ -1809,10 +1808,11 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, TRACE( "returning to handler\n" ); stack = virtual_setup_exception( stack_ptr, sizeof(*stack), rec ); stack->retval = 1; - stack->jmp = &wine_frame->jmp; + stack->jmp = ntdll_get_thread_data()->jmp_buf; stack->retaddr = (void *)0xdeadbabe; ESP_sig(sigcontext) = (DWORD)stack; EIP_sig(sigcontext) = (DWORD)__wine_longjmp; + ntdll_get_thread_data()->jmp_buf = NULL; } else { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 1ab991d3cb5..4f28d498cc2 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2253,7 +2253,6 @@ static inline BOOL handle_interrupt( ucontext_t *sigcontext, EXCEPTION_RECORD *r static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, CONTEXT *context ) { struct syscall_frame *frame = amd64_thread_data()->syscall_frame; - __WINE_FRAME *wine_frame = (__WINE_FRAME *)NtCurrentTeb()->Tib.ExceptionList; DWORD i;
if (!frame) return FALSE; @@ -2272,12 +2271,13 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", context->R12, context->R13, context->R14, context->R15 );
- if ((char *)wine_frame < (char *)frame) + if (ntdll_get_thread_data()->jmp_buf) { TRACE( "returning to handler\n" ); - RCX_sig(sigcontext) = (ULONG_PTR)&wine_frame->jmp; + RCX_sig(sigcontext) = (ULONG_PTR)ntdll_get_thread_data()->jmp_buf; RDX_sig(sigcontext) = 1; RIP_sig(sigcontext) = (ULONG_PTR)__wine_longjmp; + ntdll_get_thread_data()->jmp_buf = NULL; } else { diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 5b9af322a68..cf3b8280200 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -68,6 +68,7 @@ struct ntdll_thread_data struct list entry; /* entry in TEB list */ PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ + void *jmp_buf; /* setjmp buffer for exception handling */ };
C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 2ef72220a45..9796451f58f 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -104,7 +104,34 @@ struct file_view unsigned int protect; /* protection for all pages at allocation time and SEC_* flags */ };
-#define __EXCEPT_SYSCALL __EXCEPT_HANDLER(0) +#undef __TRY +#undef __EXCEPT +#undef __ENDTRY + +#define __TRY \ + do { __wine_jmp_buf __jmp; \ + int __first = 1; \ + assert( !ntdll_get_thread_data()->jmp_buf ); \ + for (;;) if (!__first) \ + { \ + do { + +#define __EXCEPT \ + } while(0); \ + ntdll_get_thread_data()->jmp_buf = NULL; \ + break; \ + } else { \ + if (__wine_setjmpex( &__jmp, NULL )) { \ + do { + +#define __ENDTRY \ + } while (0); \ + break; \ + } \ + ntdll_get_thread_data()->jmp_buf = &__jmp; \ + __first = 0; \ + } \ + } while (0);
/* per-page protection flags */ #define VPROT_READ 0x01 @@ -3428,7 +3455,7 @@ BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) dummy = p[0]; dummy = p[count - 1]; } - __EXCEPT_SYSCALL + __EXCEPT { return FALSE; } @@ -3461,7 +3488,7 @@ BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) p[0] |= 0; p[count - 1] |= 0; } - __EXCEPT_SYSCALL + __EXCEPT { return FALSE; }