From afb16abc0f058df09a379020704e0f5553ddd7b9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 29 Nov 2017 17:11:10 +0100 Subject: [PATCH] ntdll: Add a platform-specific helper for starting a process. Signed-off-by: Alexandre Julliard --- dlls/ntdll/loader.c | 20 ++------------ dlls/ntdll/ntdll_misc.h | 5 ++-- dlls/ntdll/server.c | 6 ++--- dlls/ntdll/signal_arm.c | 32 +++++++++++++++++------ dlls/ntdll/signal_arm64.c | 36 ++++++++++++++++++++++--- dlls/ntdll/signal_i386.c | 52 +++++++++++++++++++++++++------------ dlls/ntdll/signal_powerpc.c | 36 ++++++++++++++++++++++--- dlls/ntdll/signal_x86_64.c | 42 ++++++++++++++++++++++-------- 8 files changed, 165 insertions(+), 64 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index f7fd8da1e59..4940462954c 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -3028,6 +3028,7 @@ NTSTATUS attach_dlls( void *reserved ) goto done; } attach_implicitly_loaded_dlls( reserved ); + virtual_release_address_space(); } else { @@ -3094,14 +3095,6 @@ static void load_global_options(void) } -/*********************************************************************** - * start_process - */ -static void start_process( void *arg ) -{ - call_thread_entry_point( kernel32_start_process, arg ); -} - /****************************************************************** * LdrInitializeThunk (NTDLL.@) * @@ -3113,7 +3106,6 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2, NTSTATUS status; WINE_MODREF *wm; PEB *peb = NtCurrentTeb()->Peb; - CONTEXT context = { 0 }; kernel32_start_process = kernel_start; if (main_exe_file) NtClose( main_exe_file ); /* at this point the main module is created */ @@ -3145,15 +3137,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2, InsertHeadList( &peb->LdrData->InMemoryOrderModuleList, &wm->ldr.InMemoryOrderModuleList ); if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0, 0 )) != STATUS_SUCCESS) goto error; - if ((status = server_init_process_done( &context )) != STATUS_SUCCESS) goto error; - - status = wine_call_on_stack( attach_dlls, (void *)1, (char *)NtCurrentTeb()->Tib.StackBase - page_size ); - if (status != STATUS_SUCCESS) goto error; - - virtual_release_address_space(); - virtual_clear_thread_stack(); - if (context.ContextFlags) NtSetContextThread( GetCurrentThread(), &context ); - wine_switch_to_stack( start_process, wm->ldr.EntryPoint, NtCurrentTeb()->Tib.StackBase ); + status = server_init_process_done(); error: ERR( "Main exe initialization for %s failed, status %x\n", diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index c8a870cb5de..cab8d6da371 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -67,7 +67,8 @@ extern LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) DECLSPEC_HI extern NTSTATUS signal_alloc_thread( TEB **teb ) DECLSPEC_HIDDEN; extern void signal_free_thread( TEB *teb ) DECLSPEC_HIDDEN; extern void signal_init_thread( TEB *teb ) DECLSPEC_HIDDEN; -extern void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) DECLSPEC_HIDDEN; +extern void signal_init_process(void) DECLSPEC_HIDDEN; +extern NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) DECLSPEC_HIDDEN; extern void version_init( const WCHAR *appname ) DECLSPEC_HIDDEN; extern void debug_init(void) DECLSPEC_HIDDEN; extern HANDLE thread_init(void) DECLSPEC_HIDDEN; @@ -82,7 +83,7 @@ extern timeout_t server_start_time DECLSPEC_HIDDEN; extern unsigned int server_cpus DECLSPEC_HIDDEN; extern BOOL is_wow64 DECLSPEC_HIDDEN; extern void server_init_process(void) DECLSPEC_HIDDEN; -extern NTSTATUS server_init_process_done( CONTEXT *context ) DECLSPEC_HIDDEN; +extern NTSTATUS server_init_process_done(void) DECLSPEC_HIDDEN; extern size_t server_init_thread( void *entry_point ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN terminate_thread( int status ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 4c329d092f6..a57c3a8ea29 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -1430,7 +1430,7 @@ void server_init_process(void) /*********************************************************************** * server_init_process_done */ -NTSTATUS server_init_process_done( CONTEXT *context ) +NTSTATUS server_init_process_done(void) { PEB *peb = NtCurrentTeb()->Peb; IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); @@ -1444,7 +1444,7 @@ NTSTATUS server_init_process_done( CONTEXT *context ) * We do need the handlers in place by the time the request is over, so * we set them up here. If we segfault between here and the server call * something is very wrong... */ - signal_init_process( context, entry ); + signal_init_process(); /* Signal the parent process to continue */ SERVER_START_REQ( init_process_done ) @@ -1460,7 +1460,7 @@ NTSTATUS server_init_process_done( CONTEXT *context ) } SERVER_END_REQ; - if (suspend) wait_suspend( context ); + if (!status) status = signal_start_process( entry, suspend ); return status; } diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 2102dd0c604..2a68946277c 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -975,7 +975,7 @@ void signal_init_thread( TEB *teb ) /********************************************************************** * signal_init_process */ -void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) +void signal_init_process(void) { struct sigaction sig_act; @@ -1004,13 +1004,6 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) sig_act.sa_sigaction = trap_handler; if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; #endif - - /* set the initial context */ - context->ContextFlags = CONTEXT_FULL; - context->R0 = (DWORD)kernel32_start_process; - context->R1 = (DWORD)entry; - context->Sp = (DWORD)NtCurrentTeb()->Tib.StackBase; - context->Pc = (DWORD)call_thread_entry_point; return; error: @@ -1019,6 +1012,29 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) } +/********************************************************************** + * signal_start_process + */ +NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + CONTEXT context = { 0 }; + NTSTATUS status; + + /* build the initial context */ + context.ContextFlags = CONTEXT_FULL; + context.R0 = (DWORD)kernel32_start_process; + context.R1 = (DWORD)entry; + context.Sp = (DWORD)NtCurrentTeb()->Tib.StackBase; + context.Pc = (DWORD)call_thread_entry_point; + + if (suspend) wait_suspend( &context ); + + if (!(status = wine_call_on_stack( attach_dlls, (void *)1, (char *)NtCurrentTeb()->Tib.StackBase ))) + set_cpu_context( &context ); + return status; +} + + /********************************************************************** * __wine_enter_vm86 (NTDLL.@) */ diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 7f2977d9d3f..d1e40219112 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -846,7 +846,7 @@ void signal_init_thread( TEB *teb ) /********************************************************************** * signal_init_process */ -void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) +void signal_init_process(void) { struct sigaction sig_act; @@ -875,8 +875,6 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) sig_act.sa_sigaction = trap_handler; if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; #endif - - /* FIXME: set the initial context */ return; error: @@ -885,6 +883,38 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) } +/*********************************************************************** + * start_process + */ +static void start_process( void *arg ) +{ + CONTEXT *context = arg; + call_thread_entry_point( (LPTHREAD_START_ROUTINE)context->X0, (void *)context->X1 ); +} + +/********************************************************************** + * signal_start_process + */ +NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + CONTEXT context = { 0 }; + NTSTATUS status; + + /* build the initial context */ + context.ContextFlags = CONTEXT_FULL; + context.X0 = (DWORD_PTR)kernel32_start_process; + context.X1 = (DWORD_PTR)entry; + context.Sp = (DWORD_PTR)NtCurrentTeb()->Tib.StackBase; + context.Pc = (DWORD_PTR)call_thread_entry_point; + + if (suspend) wait_suspend( &context ); + + if (!(status = wine_call_on_stack( attach_dlls, (void *)1, (void *)context.Sp ))) + wine_switch_to_stack( start_process, &context, (void *)context.Sp ); + return status; +} + + /********************************************************************** * __wine_enter_vm86 (NTDLL.@) */ diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 671c35f35b5..7914ff520fa 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -2551,7 +2551,7 @@ void signal_init_thread( TEB *teb ) /********************************************************************** * signal_init_process */ -void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) +void signal_init_process(void) { struct sigaction sig_act; @@ -2593,21 +2593,6 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) #endif wine_ldt_init_locking( ldt_lock, ldt_unlock ); - - /* 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; return; error: @@ -2616,6 +2601,41 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) } +/********************************************************************** + * signal_start_process + */ +NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + CONTEXT context = { 0 }; + NTSTATUS status; + + /* 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 ); + + if (!(status = wine_call_on_stack( attach_dlls, (void *)1, + (char *)NtCurrentTeb()->Tib.StackBase - page_size ))) + { + virtual_clear_thread_stack(); + set_cpu_context( &context ); + } + return status; +} + + #ifdef __HAVE_VM86 /********************************************************************** * __wine_enter_vm86 (NTDLL.@) diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 2d3bd0a2b6b..209339a9122 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -1048,7 +1048,7 @@ void signal_init_thread( TEB *teb ) /********************************************************************** * signal_init_process */ -void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) +void signal_init_process(void) { struct sigaction sig_act; @@ -1077,8 +1077,6 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) sig_act.sa_sigaction = trap_handler; if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; #endif - - /* FIXME: set the initial context */ return; error: @@ -1087,6 +1085,38 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) } +/*********************************************************************** + * start_process + */ +static void start_process( void *arg ) +{ + CONTEXT *context = arg; + call_thread_entry_point( (LPTHREAD_START_ROUTINE)context->Gpr3, (void *)context->Gpr4 ); +} + +/********************************************************************** + * signal_start_process + */ +NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + CONTEXT context = { 0 }; + NTSTATUS status; + + /* build the initial context */ + context.ContextFlags = CONTEXT_FULL; + context.Gpr1 = (DWORD)NtCurrentTeb()->Tib.StackBase; + context.Gpr3 = (DWORD)kernel32_start_process; + context.Gpr4 = (DWORD)entry; + context.Iar = (DWORD)call_thread_entry_point; + + if (suspend) wait_suspend( &context ); + + if (!(wine_call_on_stack( attach_dlls, (void *)1, (void *)context.Gpr1 ))) + wine_switch_to_stack( start_process, &context, (void *)context.Gpr1 ); + return status; +} + + /********************************************************************** * __wine_enter_vm86 (NTDLL.@) */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index a052a4824e8..b81bfc0063b 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -3106,7 +3106,7 @@ void signal_init_thread( TEB *teb ) /********************************************************************** * signal_init_process */ -void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) +void signal_init_process(void) { struct sigaction sig_act; @@ -3135,16 +3135,6 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) sig_act.sa_sigaction = trap_handler; if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; #endif - - /* build the initial context */ - context->ContextFlags = CONTEXT_FULL; - __asm__( "movw %%cs,%0" : "=m" (context->SegCs) ); - __asm__( "movw %%ss,%0" : "=m" (context->SegSs) ); - __asm__( "fxsave %0" : "=m" (context->u.FltSave) ); - context->Rcx = (ULONG_PTR)entry; - context->Rdx = (ULONG_PTR)NtCurrentTeb()->Peb; - context->Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28; - context->Rip = (ULONG_PTR)start_process; return; error: @@ -3153,6 +3143,36 @@ void signal_init_process( CONTEXT *context, LPTHREAD_START_ROUTINE entry ) } +/********************************************************************** + * signal_start_process + */ +NTSTATUS signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) +{ + CONTEXT context = { 0 }; + NTSTATUS status; + + /* build the initial context */ + context.ContextFlags = CONTEXT_FULL; + __asm__( "movw %%cs,%0" : "=m" (context.SegCs) ); + __asm__( "movw %%ss,%0" : "=m" (context.SegSs) ); + __asm__( "fxsave %0" : "=m" (context.u.FltSave) ); + context.Rcx = (ULONG_PTR)entry; + context.Rdx = (ULONG_PTR)NtCurrentTeb()->Peb; + context.Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28; + context.Rip = (ULONG_PTR)start_process; + + if (suspend) wait_suspend( &context ); + + if (!(status = wine_call_on_stack( attach_dlls, (void *)1, + (char *)NtCurrentTeb()->Tib.StackBase - page_size ))) + { + virtual_clear_thread_stack(); + set_cpu_context( &context ); + } + return status; +} + + /********************************************************************** * RtlAddFunctionTable (NTDLL.@) */