ntdll: Run the entire thread initialization code on the thread stack on i386.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Alexandre Julliard 2017-12-01 19:18:44 +01:00
parent 8b2f586343
commit a89fdd58ec
1 changed files with 123 additions and 87 deletions

View File

@ -2602,79 +2602,6 @@ void signal_init_process(void)
}
struct startup_info
{
LPTHREAD_START_ROUTINE entry;
void *arg;
};
static void thread_startup( void *param )
{
struct startup_info *info = param;
call_thread_entry_point( info->entry, info->arg );
}
/***********************************************************************
* signal_start_thread
*/
void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
CONTEXT context = { 0 };
struct startup_info info = { entry, arg };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.SegCs = wine_get_cs();
context.SegDs = wine_get_ds();
context.SegEs = wine_get_es();
context.SegFs = wine_get_fs();
context.SegGs = wine_get_gs();
context.SegSs = wine_get_ss();
context.Eax = (DWORD)entry;
context.Ebx = (DWORD)arg;
context.Esp = (DWORD)NtCurrentTeb()->Tib.StackBase - 16;
context.Eip = (DWORD)call_thread_entry_point;
((void **)context.Esp)[1] = entry;
((void **)context.Esp)[2] = arg;
if (suspend) wait_suspend( &context );
wine_call_on_stack( attach_dlls, (void *)1, NtCurrentTeb()->Tib.StackBase );
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
wine_switch_to_stack( thread_startup, &info, NtCurrentTeb()->Tib.StackBase );
}
/**********************************************************************
* signal_start_process
*/
void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend )
{
CONTEXT context = { 0 };
/* build the initial context */
context.ContextFlags = CONTEXT_FULL;
context.SegCs = wine_get_cs();
context.SegDs = wine_get_ds();
context.SegEs = wine_get_es();
context.SegFs = wine_get_fs();
context.SegGs = wine_get_gs();
context.SegSs = wine_get_ss();
context.Eax = (DWORD)entry;
context.Ebx = (DWORD)NtCurrentTeb()->Peb;
context.Esp = (DWORD)NtCurrentTeb()->Tib.StackBase - 16;
context.Eip = (DWORD)call_thread_entry_point;
((void **)context.Esp)[1] = kernel32_start_process;
((void **)context.Esp)[2] = entry;
if (suspend) wait_suspend( &context );
wine_call_on_stack( attach_dlls, (void *)1, (char *)NtCurrentTeb()->Tib.StackBase - page_size );
virtual_clear_thread_stack();
set_cpu_context( &context );
}
#ifdef __HAVE_VM86
/**********************************************************************
@ -2921,8 +2848,9 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
}
extern void DECLSPEC_NORETURN call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg );
__ASM_GLOBAL_FUNC( call_thread_entry_point,
extern void DECLSPEC_NORETURN start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend,
void *relay, void **exit_frame );
__ASM_GLOBAL_FUNC( start_thread,
"pushl %ebp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
@ -2934,10 +2862,33 @@ __ASM_GLOBAL_FUNC( call_thread_entry_point,
__ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
"pushl %edi\n\t"
__ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
"pushl %ebp\n\t"
"pushl 12(%ebp)\n\t"
"pushl 8(%ebp)\n\t"
"call " __ASM_NAME("call_thread_func") );
/* store exit frame */
"movl 24(%ebp),%eax\n\t"
"movl %ebp,(%eax)\n\t"
/* build initial context on thread stack */
"movl %fs:4,%eax\n\t" /* NtCurrentTeb()->StackBase */
"leal -0x2dc(%eax),%ecx\n\t" /* sizeof(context) + 16 */
"movl $0x10007,(%ecx)\n\t" /* context->ContextFlags = CONTEXT_FULL */
"movw %cs,0xbc(%ecx)\n\t" /* context->SegCs */
"movw %ds,0x98(%ecx)\n\t" /* context->SegDs */
"movw %es,0x94(%ecx)\n\t" /* context->SegEs */
"movw %fs,0x90(%ecx)\n\t" /* context->SegFs */
"movw %gs,0x8c(%ecx)\n\t" /* context->SegGs */
"movw %ss,0xc8(%ecx)\n\t" /* context->SegSs */
"movl 8(%ebp),%eax\n\t"
"movl %eax,0xb0(%ecx)\n\t" /* context->Eax = entry */
"movl 12(%ebp),%eax\n\t"
"movl %eax,0xa4(%ecx)\n\t" /* context->Ebx = arg */
"movl 20(%ebp),%eax\n\t"
"movl %eax,0xb8(%ecx)\n\t" /* context->Eip = relay */
"leal 0x2cc(%ecx),%eax\n\t"
"movl %eax,0xc4(%ecx)\n\t" /* context->Esp */
/* switch to thread stack and call thread_startup() */
"leal -12(%ecx),%esp\n\t"
"pushl 16(%ebp)\n\t" /* suspend */
"pushl %ecx\n\t" /* context */
"xorl %ebp,%ebp\n\t"
"call " __ASM_NAME("thread_startup") )
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), void *frame );
__ASM_GLOBAL_FUNC( call_thread_exit_func,
@ -2953,8 +2904,30 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
"pushl %eax\n\t"
"call *%ecx" );
extern void call_thread_entry(void) DECLSPEC_HIDDEN;
__ASM_GLOBAL_FUNC( call_thread_entry,
"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") )
extern void call_process_entry(void) DECLSPEC_HIDDEN;
__ASM_GLOBAL_FUNC( call_process_entry,
"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_process_func") )
/* wrapper for apps that don't declare the thread function correctly */
extern void DECLSPEC_NORETURN call_thread_func_wrapper( LPTHREAD_START_ROUTINE entry, void *arg );
extern DWORD call_thread_func_wrapper( LPTHREAD_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")
@ -2964,20 +2937,20 @@ __ASM_GLOBAL_FUNC(call_thread_func_wrapper,
"subl $4,%esp\n\t"
"pushl 12(%ebp)\n\t"
"call *8(%ebp)\n\t"
"leal -4(%ebp),%esp\n\t"
"pushl %eax\n\t"
"call " __ASM_NAME("exit_thread") "\n\t"
"int $3" )
"leave\n\t"
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
/***********************************************************************
* call_thread_func
*/
void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg, void *frame )
void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg )
{
x86_thread_data()->exit_frame = frame;
__TRY
{
call_thread_func_wrapper( entry, arg );
TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg );
RtlExitUserThread( call_thread_func_wrapper( entry, arg ));
}
__EXCEPT(unhandled_exception_filter)
{
@ -2987,6 +2960,69 @@ void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg,
abort(); /* should not be reached */
}
/***********************************************************************
* call_process_func
*/
void DECLSPEC_HIDDEN call_process_func( LPTHREAD_START_ROUTINE entry, void *arg )
{
__TRY
{
RtlExitUserThread( kernel32_start_process( entry ));
}
__EXCEPT(unhandled_exception_filter)
{
NtTerminateThread( GetCurrentThread(), GetExceptionCode() );
}
__ENDTRY
abort(); /* should not be reached */
}
/***********************************************************************
* thread_startup
*/
void DECLSPEC_HIDDEN thread_startup( CONTEXT *context, BOOL suspend )
{
if (suspend) wait_suspend( context );
attach_dlls( context );
virtual_clear_thread_stack();
set_cpu_context( context );
}
/***********************************************************************
* signal_start_thread
*
* Thread startup sequence:
* signal_start_thread()
* -> start_thread()
* -> thread_startup()
* -> call_thread_entry()
* -> call_thread_func()
*/
void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend )
{
start_thread( entry, arg, suspend, call_thread_entry, &x86_thread_data()->exit_frame );
}
/**********************************************************************
* signal_start_process
*
* Process startup sequence:
* signal_start_process()
* -> start_thread()
* -> thread_startup()
* -> call_process_entry()
* -> call_process_func()
* -> kernel32_start_process()
*/
void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend )
{
start_thread( entry, NtCurrentTeb()->Peb, suspend,
call_process_entry, &x86_thread_data()->exit_frame );
}
/***********************************************************************
* RtlExitUserThread (NTDLL.@)
*/