Module: wine Branch: master Commit: 1a9558cf9bda654950e389532b400023ecbd81c0 URL: https://source.winehq.org/git/wine.git/?a=commit;h=1a9558cf9bda654950e389532...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Sep 1 12:48:04 2020 +0200
ntdll: Call the thread entry point through BaseThreadInitThunk().
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/tests/thread.c | 18 ++++++++++++++++++ dlls/kernel32/thread.c | 29 +++++++++++++++++++++++++++++ dlls/ntdll/loader.c | 8 ++++++++ dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/thread.c | 37 ++++++++++++++++--------------------- 6 files changed, 73 insertions(+), 22 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 38eb1d5ece..e1c1319375 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -182,7 +182,7 @@ @ stub BaseProcessInitPostImport # @ stub BaseQueryModuleData # @ stub BaseSetLastNTError -# @ stub BaseThreadInitThunk +@ stdcall -fastcall BaseThreadInitThunk(long ptr ptr) @ stub BaseUpdateAppcompatCache # @ stub BaseVerifyUnicodeString # @ stub Basep8BitStringToDynamicUnicodeString diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c index bd9fe7fece..a6c923dc06 100644 --- a/dlls/kernel32/tests/thread.c +++ b/dlls/kernel32/tests/thread.c @@ -1176,10 +1176,24 @@ static void test_SetThreadContext(void) CloseHandle( thread ); }
+static DWORD WINAPI test_stack( void *arg ) +{ + DWORD *stack = (DWORD *)(((DWORD)&arg & ~0xfff) + 0x1000); + + ok( stack == NtCurrentTeb()->Tib.StackBase, "wrong stack %p/%p\n", + stack, NtCurrentTeb()->Tib.StackBase ); + ok( !stack[-1], "wrong data %p = %08x\n", stack - 1, stack[-1] ); + ok( stack[-2] == (DWORD)arg, "wrong data %p = %08x\n", stack - 2, stack[-2] ); + ok( stack[-3] == (DWORD)test_stack, "wrong data %p = %08x\n", stack - 3, stack[-3] ); + ok( !stack[-4], "wrong data %p = %08x\n", stack - 4, stack[-4] ); + return 0; +} + static void test_GetThreadContext(void) { CONTEXT ctx; BOOL ret; + HANDLE thread;
memset(&ctx, 0xcc, sizeof(ctx)); ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; @@ -1188,6 +1202,10 @@ static void test_GetThreadContext(void) ok(ctx.ContextFlags == CONTEXT_DEBUG_REGISTERS, "ContextFlags = %x\n", ctx.ContextFlags); ok(!ctx.Dr0, "Dr0 = %x\n", ctx.Dr0); ok(!ctx.Dr1, "Dr0 = %x\n", ctx.Dr0); + + thread = CreateThread( NULL, 0, test_stack, (void *)0x1234, 0, NULL ); + WaitForSingleObject( thread, 1000 ); + CloseHandle( thread ); }
static void test_GetThreadSelectorEntry(void) diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index 7fdec7b2ff..6e82a1e8c4 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -31,9 +31,38 @@ #include "winerror.h" #include "winternl.h"
+#include "wine/asm.h" #include "kernel_private.h"
+#ifdef __i386__ +__ASM_STDCALL_FUNC( __fastcall_BaseThreadInitThunk, 12, + "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") + "movl 8(%ebp),%ebx\n\t" + /* deliberately mis-align the stack by 8, Doom 3 needs this */ + "pushl 4(%ebp)\n\t" /* Driller expects readable address at this offset */ + "pushl 4(%ebp)\n\t" + "pushl %ebx\n\t" + "call *%edx\n\t" + "movl %eax,(%esp)\n\t" + "call " __ASM_STDCALL( "RtlExitUserThread", 4 )) +#endif + +/*********************************************************************** + * BaseThreadInitThunk (KERNEL32.@) + */ +void __fastcall BaseThreadInitThunk( DWORD unknown, LPTHREAD_START_ROUTINE entry, void *arg ) +{ + RtlExitUserThread( entry( arg ) ); +} + + /*********************************************************************** * FreeLibraryAndExitThread (KERNEL32.@) */ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 57fc75cef4..6d2115644f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -58,6 +58,7 @@ WINE_DECLARE_DEBUG_CHANNEL(imports); typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID); typedef void (CALLBACK *LDRENUMPROC)(LDR_DATA_TABLE_ENTRY *, void *, BOOLEAN *);
+void (FASTCALL *pBaseThreadInitThunk)(DWORD,LPTHREAD_START_ROUTINE,void *) = NULL; static void (WINAPI *kernel32_start_process)(LPTHREAD_START_ROUTINE,void *);
const struct unix_funcs *unix_funcs = NULL; @@ -4008,6 +4009,13 @@ static void process_init(void) MESSAGE( "wine: could not find __wine_start_process in kernel32.dll, status %x\n", status ); NtTerminateProcess( GetCurrentProcess(), status ); } + RtlInitAnsiString( &func_name, "BaseThreadInitThunk" ); + if ((status = LdrGetProcedureAddress( wm->ldr.DllBase, &func_name, + 0, (void **)&pBaseThreadInitThunk )) != STATUS_SUCCESS) + { + MESSAGE( "wine: could not find BaseThreadInitThunk in kernel32.dll, status %x\n", status ); + NtTerminateProcess( GetCurrentProcess(), status ); + }
init_locale( wm->ldr.DllBase );
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 86bdc9d44f..58e118011b 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -82,6 +82,7 @@ extern const WCHAR windows_dir[] DECLSPEC_HIDDEN; extern const WCHAR system_dir[] DECLSPEC_HIDDEN; extern const WCHAR syswow64_dir[] DECLSPEC_HIDDEN;
+extern void (FASTCALL *pBaseThreadInitThunk)(DWORD,LPTHREAD_START_ROUTINE,void *) DECLSPEC_HIDDEN; extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
extern void init_directories(void) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index ab34f0ba96..d718acd9d8 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -105,37 +105,32 @@ void WINAPI RtlExitUserThread( ULONG status ) */ #ifdef __i386__ __ASM_STDCALL_FUNC( RtlUserThreadStart, 8, - "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" /* arg */ - "pushl %eax\n\t" /* entry */ - "call " __ASM_NAME("call_thread_func") ) - -/* wrapper for apps that don't declare the thread function correctly */ -extern DWORD call_thread_func_wrapper( PRTL_THREAD_START_ROUTINE entry, void *arg ); -__ASM_GLOBAL_FUNC(call_thread_func_wrapper, + "movl %ebx,8(%esp)\n\t" /* arg */ + "movl %eax,4(%esp)\n\t" /* entry */ + "jmp " __ASM_NAME("call_thread_func") ) + +/* wrapper to call BaseThreadInitThunk */ +extern void DECLSPEC_NORETURN call_thread_func_wrapper( void *thunk, PRTL_THREAD_START_ROUTINE entry, void *arg ); +__ASM_GLOBAL_FUNC( call_thread_func_wrapper, "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") - "subl $4,%esp\n\t" - "pushl 12(%ebp)\n\t" - "call *8(%ebp)\n\t" - "leave\n\t" - __ASM_CFI(".cfi_def_cfa %esp,4\n\t") - __ASM_CFI(".cfi_same_value %ebp\n\t") - "ret" ) + "subl $4,%esp\n\t" + "andl $~0xf,%esp\n\t" + "xorl %ecx,%ecx\n\t" + "movl 12(%ebp),%edx\n\t" + "movl 16(%ebp),%eax\n\t" + "movl %eax,(%esp)\n\t" + "call *8(%ebp)" )
void DECLSPEC_HIDDEN call_thread_func( PRTL_THREAD_START_ROUTINE entry, void *arg ) { __TRY { TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( call_thread_func_wrapper( entry, arg )); + call_thread_func_wrapper( pBaseThreadInitThunk, entry, arg ); } __EXCEPT(call_unhandled_exception_filter) { @@ -151,7 +146,7 @@ void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ) __TRY { TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( ((LPTHREAD_START_ROUTINE)entry)( arg )); + pBaseThreadInitThunk( 0, (LPTHREAD_START_ROUTINE)entry, arg ); } __EXCEPT(call_unhandled_exception_filter) {