Using a dedicated exit jmpbuf and removing the need for assembly routines.
When Wine handles an exception in unix code, we return to user mode by jumping to the last syscall frame. This can leave some pthread cancel cleanups registered, in the pthread internal linked list, and at the same time later overwrite the stack frame they were registered for.
In the same way, jumping to the exit frame on thread exit or abort, can also leave some cleanup handlers registered for invalid stack frames.
Depending on the implementation, calling pthread_exit will cause all the registered pthread cleanup handlers to be called, possibly jumping back to now overwritten stack frames and causing segmentation faults.
Exiting a pthread normally, by returning from its procedure, or calling exit(0) for the main thread doesn't run pthread_exit and doesn't call cleanup handlers, avoiding that situation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213
### Additional note:
For robustness, we should probably try to execute these cleanup handlers when unwinding the stack frames, as we would otherwise leave pthread objects in a potential problematic state (like a mutex locked, etc).
It is however hard to do so when the handlers are registered from some C code: pthread C implementation is done by calling some internal pthread functions to register the handlers, and they aren't registered as standard unwind handlers.
Only pthread_cancel and pthread_exit can unwind and call / unregister the C handlers, but interrupting that procedure, for instance calling setjmp / longjmp from withing our own handler isn't supported.
From C++ code, pthread cleanup handlers are registered through C++ class constructors / destructors, and it would then be possible to partially unwind and call them at the same time.
-- v6: ntdll: Remove now unnecessary arch-specific exit frame. ntdll: Avoid calling pthread_exit on thread exit. ntdll: Return entry and suspend from server_init_process_done. ntdll: Create a pthread for the main thread.
From: Rémi Bernon rbernon@codeweavers.com
So that we can safely call pthread_exit from the unix main thread, and wait for all other threads to exit. The last win32 thread will actually terminate the process directly by calling _exit.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54346 --- dlls/ntdll/unix/loader.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 65934acfc36..dd5636eec2d 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -2071,14 +2071,13 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
#endif /* _WIN64 */
-/*********************************************************************** - * start_main_thread - */ -static void start_main_thread(void) +static void *pthread_main_wrapper( void *arg ) { SYSTEM_SERVICE_TABLE syscall_table = { (ULONG_PTR *)syscalls, NULL, ARRAY_SIZE(syscalls), syscall_args }; TEB *teb = virtual_alloc_first_teb(); + sigset_t *blocked_signals = arg;
+ pthread_sigmask( SIG_UNBLOCK, blocked_signals, NULL ); signal_init_threading(); signal_alloc_thread( teb ); dbg_init(); @@ -2101,6 +2100,24 @@ static void start_main_thread(void) ntdll_init_syscalls( 0, &syscall_table, p__wine_syscall_dispatcher ); *p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher; server_init_process_done(); + return 0; +} + +/*********************************************************************** + * start_main_thread + */ +static void start_main_thread(void) +{ + static sigset_t blocked_signals; + pthread_t thread; + void *ret; + + /* block all signals for this thread, it cannot handle them */ + sigfillset( &blocked_signals ); + pthread_sigmask( SIG_BLOCK, &blocked_signals, NULL ); + pthread_create( &thread, NULL, pthread_main_wrapper, &blocked_signals ); + pthread_join( thread, &ret ); + pthread_exit( ret ); }
#ifdef __ANDROID__
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54346 --- dlls/ntdll/unix/loader.c | 5 ++++- dlls/ntdll/unix/server.c | 10 ++++------ dlls/ntdll/unix/unix_private.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index dd5636eec2d..dc8b8948912 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -2076,6 +2076,8 @@ static void *pthread_main_wrapper( void *arg ) SYSTEM_SERVICE_TABLE syscall_table = { (ULONG_PTR *)syscalls, NULL, ARRAY_SIZE(syscalls), syscall_args }; TEB *teb = virtual_alloc_first_teb(); sigset_t *blocked_signals = arg; + BOOL suspend; + void *entry;
pthread_sigmask( SIG_UNBLOCK, blocked_signals, NULL ); signal_init_threading(); @@ -2099,7 +2101,8 @@ static void *pthread_main_wrapper( void *arg ) load_apiset_dll(); ntdll_init_syscalls( 0, &syscall_table, p__wine_syscall_dispatcher ); *p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher; - server_init_process_done(); + server_init_process_done( &entry, &suspend ); + signal_start_thread( entry, peb, suspend, NtCurrentTeb() ); return 0; }
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 75a766078cd..1cd55d859cb 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1572,11 +1572,10 @@ size_t server_init_process(void) /*********************************************************************** * server_init_process_done */ -void server_init_process_done(void) +void server_init_process_done( void **entry, BOOL *suspend ) { - void *entry, *teb; + void *teb; unsigned int status; - int suspend; FILE_FS_DEVICE_INFORMATION info;
if (!get_device_info( initial_cwd, &info ) && (info.Characteristics & FILE_REMOVABLE_MEDIA)) @@ -1606,13 +1605,12 @@ void server_init_process_done(void) req->ldt_copy = wine_server_client_ptr( &__wine_ldt_copy ); #endif status = wine_server_call( req ); - suspend = reply->suspend; - entry = wine_server_get_ptr( reply->entry ); + *suspend = reply->suspend; + *entry = wine_server_get_ptr( reply->entry ); } SERVER_END_REQ;
assert( !status ); - signal_start_thread( entry, peb, suspend, NtCurrentTeb() ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 8821cd78491..e6628b434fc 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -174,7 +174,7 @@ extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *u extern void wine_server_send_fd( int fd ) DECLSPEC_HIDDEN; extern void process_exit_wrapper( int status ) DECLSPEC_HIDDEN; extern size_t server_init_process(void) DECLSPEC_HIDDEN; -extern void server_init_process_done(void) DECLSPEC_HIDDEN; +extern void server_init_process_done( void **entry, BOOL *suspend ) DECLSPEC_HIDDEN; extern void server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN; extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
From: Rémi Bernon rbernon@codeweavers.com
Using a dedicated exit jmpbuf and removing the need for assembly routines.
When Wine handles an exception in unix code, we return to user mode by jumping to the last syscall frame. This can leave some pthread cancel cleanups registered, in the pthread internal linked list, and at the same time later overwrite the stack frame they were registered for.
In the same way, jumping to the exit frame on thread exit or abort, can also leave some cleanup handlers registered for invalid stack frames.
Depending on the implementation, calling pthread_exit will cause all the registered pthread cleanup handlers to be called, possibly jumping back to now overwritten stack frames and causing segmentation faults.
Exiting a pthread normally, by returning from its procedure doesn't run pthread_exit and doesn't call cleanup handlers, avoiding that situation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54346 --- dlls/ntdll/unix/loader.c | 3 +- dlls/ntdll/unix/signal_arm.c | 14 -------- dlls/ntdll/unix/signal_arm64.c | 12 ------- dlls/ntdll/unix/signal_i386.c | 25 ------------- dlls/ntdll/unix/signal_x86_64.c | 21 ----------- dlls/ntdll/unix/thread.c | 64 ++++++++++++++++++++++----------- dlls/ntdll/unix/unix_private.h | 4 ++- 7 files changed, 47 insertions(+), 96 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index dc8b8948912..0f2622eb747 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -2102,8 +2102,7 @@ static void *pthread_main_wrapper( void *arg ) ntdll_init_syscalls( 0, &syscall_table, p__wine_syscall_dispatcher ); *p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher; server_init_process_done( &entry, &suspend ); - signal_start_thread( entry, peb, suspend, NtCurrentTeb() ); - return 0; + return thread_start( entry, peb, suspend, NtCurrentTeb() ); }
/*********************************************************************** diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 8180bc52b46..2333f0e2813 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -1638,20 +1638,6 @@ __ASM_GLOBAL_FUNC( signal_start_thread, "bl " __ASM_NAME("call_init_thunk") )
-/*********************************************************************** - * signal_exit_thread - */ -__ASM_GLOBAL_FUNC( signal_exit_thread, - __ASM_EHABI(".cantunwind\n\t") - "ldr r3, [r2, #0x1d4]\n\t" /* arm_thread_data()->exit_frame */ - "mov ip, #0\n\t" - "str ip, [r2, #0x1d4]\n\t" - "cmp r3, ip\n\t" - "it ne\n\t" - "movne sp, r3\n\t" - "blx r1" ) - - /*********************************************************************** * __wine_syscall_dispatcher */ diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index bd9818c808a..b3940c738c5 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -1434,18 +1434,6 @@ __ASM_GLOBAL_FUNC( signal_start_thread, "1:\tmov sp, x8\n\t" "bl " __ASM_NAME("call_init_thunk") )
-/*********************************************************************** - * signal_exit_thread - */ -__ASM_GLOBAL_FUNC( signal_exit_thread, - "stp x29, x30, [sp,#-16]!\n\t" - "ldr x3, [x2, #0x2f0]\n\t" /* arm64_thread_data()->exit_frame */ - "str xzr, [x2, #0x2f0]\n\t" - "cbz x3, 1f\n\t" - "mov sp, x3\n" - "1:\tldp x29, x30, [sp], #16\n\t" - "br x1" ) -
/*********************************************************************** * __wine_syscall_dispatcher diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 1cea685d995..cec97be9b1f 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -2508,31 +2508,6 @@ __ASM_GLOBAL_FUNC( signal_start_thread, "call " __ASM_NAME("call_init_thunk") )
-/*********************************************************************** - * signal_exit_thread - */ -__ASM_GLOBAL_FUNC( signal_exit_thread, - "movl 8(%esp),%ecx\n\t" - "movl 12(%esp),%esi\n\t" - "xorl %edx,%edx\n\t" - /* fetch exit frame */ - "xchgl %edx,0x1f4(%esi)\n\t" /* x86_thread_data()->exit_frame */ - "testl %edx,%edx\n\t" - "jnz 1f\n\t" - "jmp *%ecx\n\t" - /* switch to exit frame stack */ - "1:\tmovl 4(%esp),%eax\n\t" - "movl %edx,%ebp\n\t" - __ASM_CFI(".cfi_def_cfa %ebp,4\n\t") - __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") - __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t") - __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") - __ASM_CFI(".cfi_rel_offset %edi,-12\n\t") - "leal -20(%ebp),%esp\n\t" - "pushl %eax\n\t" - "call *%ecx" ) - - /*********************************************************************** * __wine_syscall_dispatcher */ diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 54babc7d964..a34b15ab039 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2607,27 +2607,6 @@ __ASM_GLOBAL_FUNC( signal_start_thread, "call " __ASM_NAME("call_init_thunk"))
-/*********************************************************************** - * signal_exit_thread - */ -__ASM_GLOBAL_FUNC( signal_exit_thread, - /* fetch exit frame */ - "xorl %ecx,%ecx\n\t" - "xchgq %rcx,0x320(%rdx)\n\t" /* amd64_thread_data()->exit_frame */ - "testq %rcx,%rcx\n\t" - "jnz 1f\n\t" - "jmp *%rsi\n" - /* switch to exit frame stack */ - "1:\tmovq %rcx,%rsp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t") - __ASM_CFI(".cfi_rel_offset %rbp,48\n\t") - __ASM_CFI(".cfi_rel_offset %rbx,40\n\t") - __ASM_CFI(".cfi_rel_offset %r12,32\n\t") - __ASM_CFI(".cfi_rel_offset %r13,24\n\t") - __ASM_CFI(".cfi_rel_offset %r14,16\n\t") - __ASM_CFI(".cfi_rel_offset %r15,8\n\t") - "call *%rsi" ) - /*********************************************************************** * __wine_syscall_dispatcher */ diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index d56962e1721..591bf2a1fd8 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1047,36 +1047,58 @@ static void contexts_from_server( CONTEXT *context, context_t server_contexts[2] else context_from_server( wow_context, &server_contexts[0], main_image_info.Machine ); }
- /*********************************************************************** - * pthread_exit_wrapper - */ -static void pthread_exit_wrapper( int status ) -{ - close( ntdll_get_thread_data()->wait_fd[0] ); - close( ntdll_get_thread_data()->wait_fd[1] ); - close( ntdll_get_thread_data()->reply_fd ); - close( ntdll_get_thread_data()->request_fd ); - pthread_exit( UIntToPtr(status) ); -} - - -/*********************************************************************** - * start_thread + * pthread_start_wrapper * * Startup routine for a newly created thread. */ -static void start_thread( TEB *teb ) +static void *pthread_start_wrapper( void *arg ) { + TEB *teb = arg; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; BOOL suspend;
thread_data->pthread_id = pthread_self(); pthread_setspecific( teb_key, teb ); server_init_thread( thread_data->start, &suspend ); - signal_start_thread( thread_data->start, thread_data->param, suspend, teb ); + return thread_start( thread_data->start, thread_data->param, suspend, teb ); +} + +static void thread_exit_cleanup( struct ntdll_thread_data *thread_data ) +{ + close( thread_data->wait_fd[0] ); + close( thread_data->wait_fd[1] ); + close( thread_data->reply_fd ); + close( thread_data->request_fd ); +} + +void *thread_start( PRTL_THREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb ) +{ + struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; + __wine_jmp_buf exit_buf = {0}; + int ret; + + if (!(ret = __wine_setjmpex( (thread_data->exit_buf = &exit_buf), NULL ))) + signal_start_thread( entry, arg, suspend, teb ); + + if (ret > 0) thread_exit_cleanup( thread_data ); + else process_exit_wrapper( (UINT_PTR)thread_data->param ); + return thread_data->param; }
+static void DECLSPEC_NORETURN thread_exit( int status, BOOL process, TEB *teb ) +{ + struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; + + thread_data->param = (void *)(UINT_PTR)status; + + /* return to thread_start and exit thread to avoid calling cancel handlers */ + if (thread_data->exit_buf) __wine_longjmp( thread_data->exit_buf, process ? -1 : 1 ); + + /* if thread isn't started yet, just call pthread_exit */ + thread_exit_cleanup( thread_data ); + pthread_exit( thread_data->param ); +}
/*********************************************************************** * get_machine_context_size @@ -1353,7 +1375,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT pthread_attr_setguardsize( &pthread_attr, 0 ); pthread_attr_setscope( &pthread_attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ InterlockedIncrement( &nb_threads ); - if (pthread_create( &pthread_id, &pthread_attr, (void * (*)(void *))start_thread, teb )) + if (pthread_create( &pthread_id, &pthread_attr, pthread_start_wrapper, teb )) { InterlockedDecrement( &nb_threads ); virtual_free_teb( teb ); @@ -1381,7 +1403,7 @@ void abort_thread( int status ) { pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if (InterlockedDecrement( &nb_threads ) <= 0) abort_process( status ); - signal_exit_thread( status, pthread_exit_wrapper, NtCurrentTeb() ); + thread_exit( status, FALSE, NtCurrentTeb() ); }
@@ -1414,7 +1436,7 @@ static DECLSPEC_NORETURN void exit_thread( int status ) virtual_free_teb( teb ); } } - signal_exit_thread( status, pthread_exit_wrapper, NtCurrentTeb() ); + thread_exit( status, FALSE, NtCurrentTeb() ); }
@@ -1424,7 +1446,7 @@ static DECLSPEC_NORETURN void exit_thread( int status ) void exit_process( int status ) { pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); - signal_exit_thread( get_unix_exit_code( status ), process_exit_wrapper, NtCurrentTeb() ); + thread_exit( get_unix_exit_code( status ), TRUE, NtCurrentTeb() ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index e6628b434fc..24439120226 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -66,6 +66,7 @@ struct ntdll_thread_data PRTL_THREAD_START_ROUTINE start; /* thread entry point */ void *param; /* thread entry point parameter */ void *jmp_buf; /* setjmp buffer for exception handling */ + void *exit_buf; /* setjmp buffer for thread exit */ };
C_ASSERT( sizeof(struct ntdll_thread_data) <= sizeof(((TEB *)0)->GdiTebBatch) ); @@ -240,7 +241,8 @@ extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN; extern void signal_init_process(void) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb ) DECLSPEC_HIDDEN; -extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int), TEB *teb ) DECLSPEC_HIDDEN; +extern void *thread_start( PRTL_THREAD_START_ROUTINE entry, void *arg, + BOOL suspend, TEB *teb ) DECLSPEC_HIDDEN; extern SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4] DECLSPEC_HIDDEN; extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN; extern void WINAPI DECLSPEC_NORETURN __wine_syscall_dispatcher_return( void *frame, ULONG_PTR retval ) DECLSPEC_HIDDEN;
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52213 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54346 --- dlls/ntdll/signal_i386.c | 2 -- dlls/ntdll/unix/signal_arm.c | 25 ++++++--------- dlls/ntdll/unix/signal_arm64.c | 26 ++++++--------- dlls/ntdll/unix/signal_i386.c | 41 +++++++++--------------- dlls/ntdll/unix/signal_x86_64.c | 56 +++++++++++---------------------- 5 files changed, 52 insertions(+), 98 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 9709be34f8c..f730d8cf69b 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -47,12 +47,10 @@ struct x86_thread_data DWORD dr3; /* 1e8 */ DWORD dr6; /* 1ec */ DWORD dr7; /* 1f0 */ - void *exit_frame; /* 1f4 exit frame pointer */ };
C_ASSERT( sizeof(struct x86_thread_data) <= 16 * sizeof(void *) ); C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
static inline struct x86_thread_data *x86_thread_data(void) { diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 2333f0e2813..f19813dd180 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -205,13 +205,11 @@ C_ASSERT( sizeof( struct syscall_frame ) == 0x160);
struct arm_thread_data { - void *exit_frame; /* 1d4 exit frame pointer */ - struct syscall_frame *syscall_frame; /* 1d8 frame pointer on syscall entry */ + struct syscall_frame *syscall_frame; /* 1d4 frame pointer on syscall entry */ };
C_ASSERT( sizeof(struct arm_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm_thread_data, exit_frame ) == 0x1d4 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm_thread_data, syscall_frame ) == 0x1d8 ); +C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm_thread_data, syscall_frame ) == 0x1d4 );
static inline struct arm_thread_data *arm_thread_data(void) { @@ -1169,9 +1167,9 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "str r6, [r5, #0x80]\n\t" #endif "sub sp, sp, #0x160\n\t" /* sizeof(struct syscall_frame) + registers */ - "ldr r5, [r4, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "ldr r5, [r4, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "str r5, [sp, #0x4c]\n\t" /* frame->prev_frame */ - "str sp, [r4, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "str sp, [r4, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "ldr r6, [r5, #0x50]\n\t" /* prev_frame->syscall_table */ "str r6, [sp, #0x50]\n\t" /* frame->syscall_table */ "mov ip, r0\n\t" @@ -1186,9 +1184,9 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, extern void CDECL DECLSPEC_NORETURN user_mode_callback_return( void *ret_ptr, ULONG ret_len, NTSTATUS status, TEB *teb ) DECLSPEC_HIDDEN; __ASM_GLOBAL_FUNC( user_mode_callback_return, - "ldr r4, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "ldr r4, [r3, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "ldr r5, [r4, #0x4c]\n\t" /* frame->prev_frame */ - "str r5, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "str r5, [r3, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "add r5, r4, #0x160\n\t" #ifndef __SOFTFP__ "vldm r5, {d8-d15}\n\t" @@ -1626,14 +1624,11 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B */ __ASM_GLOBAL_FUNC( signal_start_thread, __ASM_EHABI(".cantunwind\n\t") - "push {r4-r12,lr}\n\t" - /* store exit frame */ - "str sp, [r3, #0x1d4]\n\t" /* arm_thread_data()->exit_frame */ /* set syscall frame */ - "ldr r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "ldr r6, [r3, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "cbnz r6, 1f\n\t" "sub r6, sp, #0x160\n\t" /* sizeof(struct syscall_frame) */ - "str r6, [r3, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "str r6, [r3, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "1:\tmov sp, r6\n\t" "bl " __ASM_NAME("call_init_thunk") )
@@ -1644,7 +1639,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread, __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, __ASM_EHABI(".cantunwind\n\t") "mrc p15, 0, r1, c13, c0, 2\n\t" /* NtCurrentTeb() */ - "ldr r1, [r1, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "ldr r1, [r1, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "add r0, r1, #0x10\n\t" "stm r0, {r4-r12,lr}\n\t" "add r2, sp, #0x10\n\t" @@ -1722,7 +1717,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, __ASM_EHABI(".cantunwind\n\t") "mrc p15, 0, r1, c13, c0, 2\n\t" /* NtCurrentTeb() */ - "ldr r1, [r1, #0x1d8]\n\t" /* arm_thread_data()->syscall_frame */ + "ldr r1, [r1, #0x1d4]\n\t" /* arm_thread_data()->syscall_frame */ "add ip, r1, #0x10\n\t" "stm ip, {r4-r12,lr}\n\t" "str sp, [r1, #0x38]\n\t" diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index b3940c738c5..787776fef4b 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -150,13 +150,11 @@ C_ASSERT( sizeof( struct syscall_frame ) == 0x330 );
struct arm64_thread_data { - void *exit_frame; /* 02f0 exit frame pointer */ - struct syscall_frame *syscall_frame; /* 02f8 frame pointer on syscall entry */ + struct syscall_frame *syscall_frame; /* 02f0 frame pointer on syscall entry */ };
C_ASSERT( sizeof(struct arm64_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, exit_frame ) == 0x2f0 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, syscall_frame ) == 0x2f8 ); +C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct arm64_thread_data, syscall_frame ) == 0x2f0 );
static inline struct arm64_thread_data *arm64_thread_data(void) { @@ -904,9 +902,9 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "ldr x6, [x18]\n\t" /* teb->Tib.ExceptionList */ "stp x5, x6, [x29, #0xb0]\n\t"
- "ldr x7, [x18, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "ldr x7, [x18, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "sub x5, sp, #0x330\n\t" /* sizeof(struct syscall_frame) */ - "str x5, [x18, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "str x5, [x18, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "ldr x8, [x7, #0x118]\n\t" /* prev_frame->syscall_table */ "ldp x0, x1, [x17]\n\t" /* id, args */ "ldr x2, [x17, #0x10]\n\t" /* len */ @@ -921,9 +919,9 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, extern void CDECL DECLSPEC_NORETURN user_mode_callback_return( void *ret_ptr, ULONG ret_len, NTSTATUS status, TEB *teb ) DECLSPEC_HIDDEN; __ASM_GLOBAL_FUNC( user_mode_callback_return, - "ldr x4, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "ldr x4, [x3, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "ldr x5, [x4, #0x110]\n\t" /* prev_frame */ - "str x5, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "str x5, [x3, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "add x29, x4, #0x330\n\t" /* sizeof(struct syscall_frame) */ "ldp x5, x6, [x29, #0xb0]\n\t" "str x6, [x3]\n\t" /* teb->Tib.ExceptionList */ @@ -1422,15 +1420,11 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B * signal_start_thread */ __ASM_GLOBAL_FUNC( signal_start_thread, - "stp x29, x30, [sp,#-16]!\n\t" - /* store exit frame */ - "mov x29, sp\n\t" - "str x29, [x3, #0x2f0]\n\t" /* arm64_thread_data()->exit_frame */ /* set syscall frame */ - "ldr x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "ldr x8, [x3, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "cbnz x8, 1f\n\t" "sub x8, sp, #0x330\n\t" /* sizeof(struct syscall_frame) */ - "str x8, [x3, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "str x8, [x3, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "1:\tmov sp, x8\n\t" "bl " __ASM_NAME("call_init_thunk") )
@@ -1455,7 +1449,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, "ldr x30, [sp, #80]\n\t" "ldp x0, x1, [sp], #96\n\t"
- "ldr x10, [x18, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "ldr x10, [x18, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "stp x18, x19, [x10, #0x90]\n\t" "stp x20, x21, [x10, #0xa0]\n\t" "stp x22, x23, [x10, #0xb0]\n\t" @@ -1575,7 +1569,7 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, "ldp x2, x30,[sp, #16]\n\t" "ldp x0, x1, [sp], #32\n\t"
- "ldr x10, [x18, #0x2f8]\n\t" /* arm64_thread_data()->syscall_frame */ + "ldr x10, [x18, #0x2f0]\n\t" /* arm64_thread_data()->syscall_frame */ "stp x18, x19, [x10, #0x90]\n\t" "stp x20, x21, [x10, #0xa0]\n\t" "stp x22, x23, [x10, #0xb0]\n\t" diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index cec97be9b1f..70cdcb9312d 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -480,14 +480,12 @@ struct x86_thread_data UINT dr3; /* 1e8 */ UINT dr6; /* 1ec */ UINT dr7; /* 1f0 */ - void *exit_frame; /* 1f4 exit frame pointer */ - struct syscall_frame *syscall_frame; /* 1f8 frame pointer on syscall entry */ + struct syscall_frame *syscall_frame; /* 1f4 frame pointer on syscall entry */ };
C_ASSERT( sizeof(struct x86_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) ); C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f8 ); +C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f4 );
/* flags to control the behavior of the syscall dispatcher */ #define SYSCALL_HAVE_XSAVE 1 @@ -1593,13 +1591,13 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "subl $0x384,%esp\n\t" /* sizeof(struct syscall_frame) + ebp */ "andl $~63,%esp\n\t" "movl %ebp,0x380(%esp)\n\t" - "movl 0x1f8(%edx),%ecx\n\t" /* x86_thread_data()->syscall_frame */ + "movl 0x1f4(%edx),%ecx\n\t" /* x86_thread_data()->syscall_frame */ "movl (%ecx),%eax\n\t" /* frame->syscall_flags */ "movl %eax,(%esp)\n\t" "movl 0x38(%ecx),%eax\n\t" /* frame->syscall_table */ "movl %eax,0x38(%esp)\n\t" "movl %ecx,0x3c(%esp)\n\t" /* frame->prev_frame */ - "movl %esp,0x1f8(%edx)\n\t" /* x86_thread_data()->syscall_frame */ + "movl %esp,0x1f4(%edx)\n\t" /* x86_thread_data()->syscall_frame */ "movl 8(%ebp),%ecx\n\t" /* func */ "movl 12(%ebp),%esp\n\t" /* stack */ "xorl %ebp,%ebp\n\t" @@ -1613,9 +1611,9 @@ extern void CDECL DECLSPEC_NORETURN user_mode_callback_return( void *ret_ptr, UL NTSTATUS status, TEB *teb ) DECLSPEC_HIDDEN; __ASM_GLOBAL_FUNC( user_mode_callback_return, "movl 16(%esp),%edx\n" /* teb */ - "movl 0x1f8(%edx),%eax\n\t" /* x86_thread_data()->syscall_frame */ + "movl 0x1f4(%edx),%eax\n\t" /* x86_thread_data()->syscall_frame */ "movl 0x3c(%eax),%ecx\n\t" /* frame->prev_frame */ - "movl %ecx,0x1f8(%edx)\n\t" /* x86_thread_data()->syscall_frame */ + "movl %ecx,0x1f4(%edx)\n\t" /* x86_thread_data()->syscall_frame */ "movl 0x380(%eax),%ebp\n\t" /* call_user_mode_callback ebp */ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") @@ -2479,32 +2477,21 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B * signal_start_thread */ __ASM_GLOBAL_FUNC( signal_start_thread, - "pushl %ebp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") "movl %esp,%ebp\n\t" __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") - "pushl %ebx\n\t" - __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t") - "pushl %esi\n\t" - __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") - "pushl %edi\n\t" - __ASM_CFI(".cfi_rel_offset %edi,-12\n\t") - /* store exit frame */ - "movl 20(%ebp),%ecx\n\t" /* teb */ - "movl %ebp,0x1f4(%ecx)\n\t" /* x86_thread_data()->exit_frame */ + "movl 16(%ebp),%ecx\n\t" /* teb */ /* set syscall frame */ - "movl 0x1f8(%ecx),%eax\n\t" /* x86_thread_data()->syscall_frame */ + "movl 0x1f4(%ecx),%eax\n\t" /* x86_thread_data()->syscall_frame */ "orl %eax,%eax\n\t" "jnz 1f\n\t" "leal -0x380(%esp),%eax\n\t" /* sizeof(struct syscall_frame) */ "andl $~63,%eax\n\t" - "movl %eax,0x1f8(%ecx)\n" /* x86_thread_data()->syscall_frame */ + "movl %eax,0x1f4(%ecx)\n" /* x86_thread_data()->syscall_frame */ "1:\tmovl %eax,%esp\n\t" "pushl %ecx\n\t" /* teb */ - "pushl 16(%ebp)\n\t" /* suspend */ - "pushl 12(%ebp)\n\t" /* arg */ - "pushl 8(%ebp)\n\t" /* entry */ + "pushl 12(%ebp)\n\t" /* suspend */ + "pushl 8(%ebp)\n\t" /* arg */ + "pushl 4(%ebp)\n\t" /* entry */ "call " __ASM_NAME("call_init_thunk") )
@@ -2512,7 +2499,7 @@ __ASM_GLOBAL_FUNC( signal_start_thread, * __wine_syscall_dispatcher */ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, - "movl %fs:0x1f8,%ecx\n\t" /* x86_thread_data()->syscall_frame */ + "movl %fs:0x1f4,%ecx\n\t" /* x86_thread_data()->syscall_frame */ "movw $0,0x02(%ecx)\n\t" /* frame->restore_flags */ "popl 0x08(%ecx)\n\t" /* frame->eip */ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") @@ -2704,7 +2691,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, * __wine_unix_call_dispatcher */ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, - "movl %fs:0x1f8,%ecx\n\t" /* x86_thread_data()->syscall_frame */ + "movl %fs:0x1f4,%ecx\n\t" /* x86_thread_data()->syscall_frame */ "movw $0,0x02(%ecx)\n\t" /* frame->restore_flags */ "popl 0x08(%ecx)\n\t" /* frame->eip */ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index a34b15ab039..0df7af1a6e4 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -424,16 +424,14 @@ struct amd64_thread_data DWORD_PTR dr3; /* 0308 */ DWORD_PTR dr6; /* 0310 */ DWORD_PTR dr7; /* 0318 */ - void *exit_frame; /* 0320 exit frame pointer */ - struct syscall_frame *syscall_frame; /* 0328 syscall frame pointer */ - void *pthread_teb; /* 0330 thread data for pthread */ - DWORD fs; /* 0338 WOW TEB selector */ + struct syscall_frame *syscall_frame; /* 0320 syscall frame pointer */ + void *pthread_teb; /* 0328 thread data for pthread */ + DWORD fs; /* 0330 WOW TEB selector */ };
C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, exit_frame ) == 0x320 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, syscall_frame ) == 0x328 ); -C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, pthread_teb ) == 0x330 ); +C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, syscall_frame ) == 0x320 ); +C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, pthread_teb ) == 0x328 );
static inline struct amd64_thread_data *amd64_thread_data(void) { @@ -1616,7 +1614,7 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "subq $0x410,%rsp\n\t" /* sizeof(struct syscall_frame) + ebp + exception */ "andq $~63,%rsp\n\t" "movq %rbp,0x400(%rsp)\n\t" - "movq 0x328(%r11),%r10\n\t" /* amd64_thread_data()->syscall_frame */ + "movq 0x320(%r11),%r10\n\t" /* amd64_thread_data()->syscall_frame */ "movq (%r11),%rax\n\t" /* NtCurrentTeb()->Tib.ExceptionList */ "movq %rax,0x408(%rsp)\n\t" "movq 0xa8(%r10),%rax\n\t" /* prev_frame->syscall_table */ @@ -1624,11 +1622,11 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, "movl 0xb0(%r10),%r14d\n\t" /* prev_frame->syscall_flags */ "movl %r14d,0xb0(%rsp)\n\t" /* frame->syscall_flags */ "movq %r10,0xa0(%rsp)\n\t" /* frame->prev_frame */ - "movq %rsp,0x328(%r11)\n\t" /* amd64_thread_data()->syscall_frame */ + "movq %rsp,0x320(%r11)\n\t" /* amd64_thread_data()->syscall_frame */ #ifdef __linux__ "testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */ "jz 1f\n\t" - "movw 0x338(%r11),%fs\n" /* amd64_thread_data()->fs */ + "movw 0x330(%r11),%fs\n" /* amd64_thread_data()->fs */ "1:\n\t" #endif "movq %rcx,%r9\n\t" /* func */ @@ -1646,9 +1644,9 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback, extern void CDECL DECLSPEC_NORETURN user_mode_callback_return( void *ret_ptr, ULONG ret_len, NTSTATUS status, TEB *teb ) DECLSPEC_HIDDEN; __ASM_GLOBAL_FUNC( user_mode_callback_return, - "movq 0x328(%r9),%r10\n\t" /* amd64_thread_data()->syscall_frame */ + "movq 0x320(%r9),%r10\n\t" /* amd64_thread_data()->syscall_frame */ "movq 0xa0(%r10),%r11\n\t" /* frame->prev_frame */ - "movq %r11,0x328(%r9)\n\t" /* amd64_thread_data()->syscall_frame = prev_frame */ + "movq %r11,0x320(%r9)\n\t" /* amd64_thread_data()->syscall_frame = prev_frame */ "movq 0x400(%r10),%rbp\n\t" /* call_user_mode_callback rbp */ __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") __ASM_CFI(".cfi_rel_offset %rbx,-0x08\n\t") @@ -2578,31 +2576,13 @@ void DECLSPEC_HIDDEN call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, B * signal_start_thread */ __ASM_GLOBAL_FUNC( signal_start_thread, - "subq $56,%rsp\n\t" - __ASM_SEH(".seh_stackalloc 56\n\t") - __ASM_SEH(".seh_endprologue\n\t") - __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t") - "movq %rbp,48(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %rbp,48\n\t") - "movq %rbx,40(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %rbx,40\n\t") - "movq %r12,32(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r12,32\n\t") - "movq %r13,24(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r13,24\n\t") - "movq %r14,16(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r14,16\n\t") - "movq %r15,8(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r15,8\n\t") - /* store exit frame */ - "movq %rsp,0x320(%rcx)\n\t" /* amd64_thread_data()->exit_frame */ /* set syscall frame */ - "movq 0x328(%rcx),%rax\n\t" /* amd64_thread_data()->syscall_frame */ + "movq 0x320(%rcx),%rax\n\t" /* amd64_thread_data()->syscall_frame */ "orq %rax,%rax\n\t" "jnz 1f\n\t" "leaq -0x400(%rsp),%rax\n\t" /* sizeof(struct syscall_frame) */ "andq $~63,%rax\n\t" - "movq %rax,0x328(%rcx)\n" /* amd64_thread_data()->syscall_frame */ + "movq %rax,0x320(%rcx)\n" /* amd64_thread_data()->syscall_frame */ "1:\tmovq %rax,%rsp\n\t" "call " __ASM_NAME("call_init_thunk"))
@@ -2613,9 +2593,9 @@ __ASM_GLOBAL_FUNC( signal_start_thread, __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, #ifdef __APPLE__ "movq %gs:0x30,%rcx\n\t" - "movq 0x328(%rcx),%rcx\n\t" + "movq 0x320(%rcx),%rcx\n\t" #else - "movq %gs:0x328,%rcx\n\t" /* amd64_thread_data()->syscall_frame */ + "movq %gs:0x320,%rcx\n\t" /* amd64_thread_data()->syscall_frame */ #endif "popq 0x70(%rcx)\n\t" /* frame->rip */ __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") @@ -2696,7 +2676,7 @@ __ASM_GLOBAL_FUNC( __wine_syscall_dispatcher, #ifdef __linux__ "testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */ "jz 2f\n\t" - "movq %gs:0x330,%rsi\n\t" /* amd64_thread_data()->pthread_teb */ + "movq %gs:0x328,%rsi\n\t" /* amd64_thread_data()->pthread_teb */ "testl $8,%r14d\n\t" /* SYSCALL_HAVE_WRFSGSBASE */ "jz 1f\n\t" "wrfsbase %rsi\n\t" @@ -2838,9 +2818,9 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, "movq %rcx,%r10\n\t" #ifdef __APPLE__ "movq %gs:0x30,%rcx\n\t" - "movq 0x328(%rcx),%rcx\n\t" + "movq 0x320(%rcx),%rcx\n\t" #else - "movq %gs:0x328,%rcx\n\t" /* amd64_thread_data()->syscall_frame */ + "movq %gs:0x320,%rcx\n\t" /* amd64_thread_data()->syscall_frame */ #endif "popq 0x70(%rcx)\n\t" /* frame->rip */ __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") @@ -2882,7 +2862,7 @@ __ASM_GLOBAL_FUNC( __wine_unix_call_dispatcher, "testl $12,%r14d\n\t" /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */ "jz 2f\n\t" "movw %fs,0x7e(%rcx)\n\t" - "movq %gs:0x330,%rsi\n\t" /* amd64_thread_data()->pthread_teb */ + "movq %gs:0x328,%rsi\n\t" /* amd64_thread_data()->pthread_teb */ "testl $8,%r14d\n\t" /* SYSCALL_HAVE_WRFSGSBASE */ "jz 1f\n\t" "wrfsbase %rsi\n\t"
Although this shows the feasibility, I'm going to leave the proper unwinding for a later MR. I think that not calling `pthread_exit` is a good first step, although it doesn't call pthread cancel handlers and may leave objects in invalid state, it still solves the mentioned bugs.
Proper unwinding is a bit more complicated, and for instance the version I pushed earlier didn't handle legacy code with threads created without a syscall frame, which could nonetheless use pthread condition variables in a unix / win32 code mix (we have such things in Proton for instance).