Alexandre Julliard : ntdll: Call the thread entry point through BaseThreadInitThunk().
Alexandre Julliard
julliard at winehq.org
Tue Sep 1 15:43:30 CDT 2020
Module: wine
Branch: master
Commit: 1a9558cf9bda654950e389532b400023ecbd81c0
URL: https://source.winehq.org/git/wine.git/?a=commit;h=1a9558cf9bda654950e389532b400023ecbd81c0
Author: Alexandre Julliard <julliard at 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 at 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)
{
More information about the wine-cvs
mailing list