ntdll: Call the thread entry point through BaseThreadInitThunk().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-09-01 12:48:04 +02:00
parent 81a08cea79
commit 1a9558cf9b
6 changed files with 72 additions and 21 deletions

View File

@ -182,7 +182,7 @@
@ stub BaseProcessInitPostImport
# @ stub BaseQueryModuleData
# @ stub BaseSetLastNTError
# @ stub BaseThreadInitThunk
@ stdcall -fastcall BaseThreadInitThunk(long ptr ptr)
@ stub BaseUpdateAppcompatCache
# @ stub BaseVerifyUnicodeString
# @ stub Basep8BitStringToDynamicUnicodeString

View File

@ -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)

View File

@ -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.@)
*/

View File

@ -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 );

View File

@ -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;

View File

@ -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") )
"movl %ebx,8(%esp)\n\t" /* arg */
"movl %eax,4(%esp)\n\t" /* entry */
"jmp " __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,
/* 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)
{