From be0eb9c92eb7a4fcd9d0d48568c8ed5e8326ef0b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Wed, 3 Jun 2020 16:32:02 +0200 Subject: [PATCH] ntdll: Move the thread startup code to the Unix library. Signed-off-by: Alexandre Julliard <julliard@winehq.org> --- dlls/ntdll/ntdll_misc.h | 26 --- dlls/ntdll/process.c | 2 +- dlls/ntdll/server.c | 2 +- dlls/ntdll/signal_arm.c | 106 ------------ dlls/ntdll/signal_arm64.c | 144 ----------------- dlls/ntdll/signal_i386.c | 276 -------------------------------- dlls/ntdll/signal_powerpc.c | 90 ----------- dlls/ntdll/signal_x86_64.c | 130 --------------- dlls/ntdll/thread.c | 74 ++++++++- dlls/ntdll/unix/loader.c | 3 +- dlls/ntdll/unix/signal_arm.c | 63 ++++++++ dlls/ntdll/unix/signal_arm64.c | 103 ++++++++++++ dlls/ntdll/unix/signal_i386.c | 88 ++++++++++ dlls/ntdll/unix/signal_x86_64.c | 84 ++++++++++ dlls/ntdll/unix/thread.c | 33 +++- dlls/ntdll/unix/unix_private.h | 8 +- dlls/ntdll/unix/virtual.c | 15 ++ dlls/ntdll/unixlib.h | 5 +- dlls/ntdll/virtual.c | 27 ---- 19 files changed, 467 insertions(+), 812 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index e9a3230e814..116e072a4a6 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -78,8 +78,6 @@ extern LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) DECLSPEC_HI extern SIZE_T signal_stack_size DECLSPEC_HIDDEN; extern SIZE_T signal_stack_mask DECLSPEC_HIDDEN; extern void signal_init_process(void) DECLSPEC_HIDDEN; -extern void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) DECLSPEC_HIDDEN; -extern void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) DECLSPEC_HIDDEN; extern void version_init(void) DECLSPEC_HIDDEN; extern void debug_init(void) DECLSPEC_HIDDEN; extern TEB *thread_init(void) DECLSPEC_HIDDEN; @@ -175,30 +173,6 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S UINT disposition ) DECLSPEC_HIDDEN; /* virtual memory */ -extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, - const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, - ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; -extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN; -extern TEB * virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_alloc_teb( TEB **teb ) DECLSPEC_HIDDEN; -extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, - SIZE_T commit_size, SIZE_T *pthread_size ) DECLSPEC_HIDDEN; -extern void virtual_clear_thread_stack( void *stack_end ) DECLSPEC_HIDDEN; -extern int virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN; -extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) DECLSPEC_HIDDEN; -extern unsigned int virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN; -extern ssize_t virtual_locked_read( int fd, void *addr, size_t size ) DECLSPEC_HIDDEN; -extern ssize_t virtual_locked_pread( int fd, void *addr, size_t size, off_t offset ) DECLSPEC_HIDDEN; -extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN; -extern BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) DECLSPEC_HIDDEN; -extern SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; -extern NTSTATUS virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; -extern void VIRTUAL_SetForceExec( BOOL enable ) DECLSPEC_HIDDEN; -extern void virtual_release_address_space(void) DECLSPEC_HIDDEN; -extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index c066610ebca..f47d3c4bc6c 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -734,7 +734,7 @@ NTSTATUS WINAPI NtSetInformationProcess( return STATUS_INVALID_PARAMETER; } execute_flags = *(ULONG *)ProcessInformation; - VIRTUAL_SetForceExec( enable ); + unix_funcs->virtual_set_force_exec( enable ); } break; diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index c7788b99e2d..bde4a2add18 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -299,5 +299,5 @@ void server_init_process_done(void) SERVER_END_REQ; assert( !status ); - signal_start_process( entry, suspend ); + unix_funcs->start_process( entry, suspend, kernel32_start_process ); } diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index b7e387babf1..8ff9f66d3f0 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -61,7 +61,6 @@ #include "winnt.h" WINE_DEFAULT_DEBUG_CHANNEL(seh); -WINE_DECLARE_DEBUG_CHANNEL(relay); /*********************************************************************** * signal context platform-specific definitions @@ -867,111 +866,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; } -/*********************************************************************** - * call_thread_entry_point - */ -static void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) -{ - __TRY - { - TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( entry( arg )); - } - __EXCEPT(call_unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - abort(); /* should not be reached */ -} - -extern void DECLSPEC_NORETURN start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, - void *relay, TEB *teb ); -__ASM_GLOBAL_FUNC( start_thread, - ".arm\n\t" - "push {r4-r12,lr}\n\t" - /* store exit frame */ - "ldr r4, [sp, #40]\n\t" /* teb */ - "str sp, [r4, #0x1d4]\n\t" /* teb->SystemReserved2 */ - /* switch to thread stack */ - "ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */ - "sub sp, r4, #0x1000\n\t" - /* attach dlls */ - "bl " __ASM_NAME("attach_thread") "\n\t" - "mov sp, r0\n\t" - /* clear the stack */ - "and r0, #~0xff0\n\t" /* round down to page size */ - "bl " __ASM_NAME("virtual_clear_thread_stack") "\n\t" - /* switch to the initial context */ - "mov r0, sp\n\t" - "b " __ASM_NAME("set_cpu_context") ) - -/*********************************************************************** - * init_thread_context - */ -static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) -{ - context->R0 = (DWORD)entry; - context->R1 = (DWORD)arg; - context->Sp = (DWORD)NtCurrentTeb()->Tib.StackBase; - context->Pc = (DWORD)relay; -} - - -/*********************************************************************** - * attach_thread - */ -PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, - BOOL suspend, void *relay ) -{ - CONTEXT *ctx; - - if (suspend) - { - CONTEXT context = { CONTEXT_ALL }; - - init_thread_context( &context, entry, arg, relay ); - wait_suspend( &context ); - ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; - *ctx = context; - } - else - { - ctx = (CONTEXT *)NtCurrentTeb()->Tib.StackBase - 1; - init_thread_context( ctx, entry, arg, relay ); - } - ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 ); - return ctx; -} - - -/*********************************************************************** - * signal_start_thread - * - * Thread startup sequence: - * signal_start_thread() - * -> thread_startup() - * -> call_thread_entry_point() - */ -void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) -{ - start_thread( entry, arg, suspend, call_thread_entry_point, NtCurrentTeb() ); -} - -/********************************************************************** - * signal_start_process - * - * Process startup sequence: - * signal_start_process() - * -> thread_startup() - * -> kernel32_start_process() - */ -void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) -{ - start_thread( entry, NtCurrentTeb()->Peb, suspend, kernel32_start_process, NtCurrentTeb() ); -} - /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index c2dd129a569..104ffbf6df9 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -64,7 +64,6 @@ #include "winnt.h" WINE_DEFAULT_DEBUG_CHANNEL(seh); -WINE_DECLARE_DEBUG_CHANNEL(relay); /* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */ struct MSVCRT_JUMP_BUFFER @@ -1880,149 +1879,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; } -/*********************************************************************** - * call_thread_entry_point - */ -static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) -{ - __TRY - { - TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( entry( arg )); - } - __EXCEPT(call_unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - abort(); /* should not be reached */ -} - -extern void DECLSPEC_NORETURN start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, - void *relay, TEB *teb ); -__ASM_GLOBAL_FUNC( start_thread, - "stp x29, x30, [sp,#-16]!\n\t" - "mov x18, x4\n\t" /* teb */ - /* store exit frame */ - "mov x29, sp\n\t" - "str x29, [x4, #0x300]\n\t" /* arm64_thread_data()->exit_frame */ - /* switch to thread stack */ - "ldr x5, [x4, #8]\n\t" /* teb->Tib.StackBase */ - "sub sp, x5, #0x1000\n\t" - /* attach dlls */ - "bl " __ASM_NAME("attach_thread") "\n\t" - "mov sp, x0\n\t" - /* clear the stack */ - "and x0, x0, #~0xfff\n\t" /* round down to page size */ - "bl " __ASM_NAME("virtual_clear_thread_stack") "\n\t" - /* switch to the initial context */ - "mov x0, sp\n\t" - "ldp q0, q1, [x0, #0x110]\n\t" /* context->V[0,1] */ - "ldp q2, q3, [x0, #0x130]\n\t" /* context->V[2,3] */ - "ldp q4, q5, [x0, #0x150]\n\t" /* context->V[4,5] */ - "ldp q6, q7, [x0, #0x170]\n\t" /* context->V[6,7] */ - "ldp q8, q9, [x0, #0x190]\n\t" /* context->V[8,9] */ - "ldp q10, q11, [x0, #0x1b0]\n\t" /* context->V[10,11] */ - "ldp q12, q13, [x0, #0x1d0]\n\t" /* context->V[12,13] */ - "ldp q14, q15, [x0, #0x1f0]\n\t" /* context->V[14,15] */ - "ldp q16, q17, [x0, #0x210]\n\t" /* context->V[16,17] */ - "ldp q18, q19, [x0, #0x230]\n\t" /* context->V[18,19] */ - "ldp q20, q21, [x0, #0x250]\n\t" /* context->V[20,21] */ - "ldp q22, q23, [x0, #0x270]\n\t" /* context->V[22,23] */ - "ldp q24, q25, [x0, #0x290]\n\t" /* context->V[24,25] */ - "ldp q26, q27, [x0, #0x2b0]\n\t" /* context->V[26,27] */ - "ldp q28, q29, [x0, #0x2d0]\n\t" /* context->V[28,29] */ - "ldp q30, q31, [x0, #0x2f0]\n\t" /* context->V[30,31] */ - "ldr w1, [x0, #0x310]\n\t" /* context->Fpcr */ - "msr fpcr, x1\n\t" - "ldr w1, [x0, #0x314]\n\t" /* context->Fpsr */ - "msr fpsr, x1\n\t" - "ldp x1, x2, [x0, #0x10]\n\t" /* context->X1,2 */ - "ldp x3, x4, [x0, #0x20]\n\t" /* context->X3,4 */ - "ldp x5, x6, [x0, #0x30]\n\t" /* context->X5,6 */ - "ldp x7, x8, [x0, #0x40]\n\t" /* context->X7,8 */ - "ldp x9, x10, [x0, #0x50]\n\t" /* context->X9,10 */ - "ldp x11, x12, [x0, #0x60]\n\t" /* context->X11,12 */ - "ldp x13, x14, [x0, #0x70]\n\t" /* context->X13,14 */ - "ldp x15, x16, [x0, #0x80]\n\t" /* context->X15,16 */ - "ldp x17, x18, [x0, #0x90]\n\t" /* context->X17,18 */ - "ldp x19, x20, [x0, #0xa0]\n\t" /* context->X19,20 */ - "ldp x21, x22, [x0, #0xb0]\n\t" /* context->X21,22 */ - "ldp x23, x24, [x0, #0xc0]\n\t" /* context->X23,24 */ - "ldp x25, x26, [x0, #0xd0]\n\t" /* context->X25,26 */ - "ldp x27, x28, [x0, #0xe0]\n\t" /* context->X27,28 */ - "ldp x29, x30, [x0, #0xf0]\n\t" /* context->Fp,Lr */ - "ldr x17, [x0, #0x100]\n\t" /* context->Sp */ - "mov sp, x17\n\t" - "ldr x17, [x0, #0x108]\n\t" /* context->Pc */ - "ldr x0, [x0, #0x8]\n\t" /* context->X0 */ - "br x17" ) - -/*********************************************************************** - * init_thread_context - */ -static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) -{ - context->u.s.X0 = (DWORD64)entry; - context->u.s.X1 = (DWORD64)arg; - context->u.s.X18 = (DWORD64)NtCurrentTeb(); - context->Sp = (DWORD64)NtCurrentTeb()->Tib.StackBase; - context->Pc = (DWORD64)relay; -} - -/*********************************************************************** - * attach_thread - */ -PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, - BOOL suspend, void *relay ) -{ - CONTEXT *ctx; - - if (suspend) - { - CONTEXT context = { CONTEXT_ALL }; - - init_thread_context( &context, entry, arg, relay ); - wait_suspend( &context ); - ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; - *ctx = context; - } - else - { - ctx = (CONTEXT *)NtCurrentTeb()->Tib.StackBase - 1; - init_thread_context( ctx, entry, arg, relay ); - } - ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 ); - return ctx; -} - -/*********************************************************************** - * signal_start_thread - * - * Thread startup sequence: - * signal_start_thread() - * -> start_thread() - * -> call_thread_func() - */ -void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) -{ - start_thread( entry, arg, suspend, call_thread_entry_point, NtCurrentTeb() ); -} - -/********************************************************************** - * signal_start_process - * - * Process startup sequence: - * signal_start_process() - * -> start_thread() - * -> kernel32_start_process() - */ -void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) -{ - start_thread( entry, NtCurrentTeb()->Peb, suspend, kernel32_start_process, NtCurrentTeb() ); -} - /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 78d03f669d7..1b0b9352a87 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -63,7 +63,6 @@ #undef ERR /* Solaris needs to define this */ WINE_DEFAULT_DEBUG_CHANNEL(seh); -WINE_DECLARE_DEBUG_CHANNEL(relay); /* not defined for x86, so copy the x86_64 definition */ typedef struct DECLSPEC_ALIGN(16) _M128A @@ -959,26 +958,6 @@ static inline void restore_fpu( const CONTEXT *context ) } -/*********************************************************************** - * restore_fpux - * - * Restore the FPU extended context to a sigcontext. - */ -static inline void restore_fpux( const CONTEXT *context ) -{ -#ifdef __GNUC__ - /* we have to enforce alignment by hand */ - char buffer[sizeof(XMM_SAVE_AREA32) + 16]; - XMM_SAVE_AREA32 *state = (XMM_SAVE_AREA32 *)(((ULONG_PTR)buffer + 15) & ~15); - - memcpy( state, context->ExtendedRegisters, sizeof(*state) ); - /* reset the current interrupt status */ - state->StatusWord &= state->ControlWord | 0xff80; - __asm__ __volatile__( "fxrstor %0" : : "m" (*state) ); -#endif -} - - /*********************************************************************** * fpux_to_fpu * @@ -1155,101 +1134,6 @@ __ASM_STDCALL_FUNC( RtlCaptureContext, 4, __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") "ret $4" ) -/*********************************************************************** - * set_full_cpu_context - * - * Set the new CPU context. - */ -extern void set_full_cpu_context( const CONTEXT *context ); -__ASM_GLOBAL_FUNC( set_full_cpu_context, - "movl 4(%esp),%ecx\n\t" - "movw 0x8c(%ecx),%gs\n\t" /* SegGs */ - "movw 0x90(%ecx),%fs\n\t" /* SegFs */ - "movw 0x94(%ecx),%es\n\t" /* SegEs */ - "movl 0x9c(%ecx),%edi\n\t" /* Edi */ - "movl 0xa0(%ecx),%esi\n\t" /* Esi */ - "movl 0xa4(%ecx),%ebx\n\t" /* Ebx */ - "movl 0xb4(%ecx),%ebp\n\t" /* Ebp */ - "movw %ss,%ax\n\t" - "cmpw 0xc8(%ecx),%ax\n\t" /* SegSs */ - "jne 1f\n\t" - /* As soon as we have switched stacks the context structure could - * be invalid (when signal handlers are executed for example). Copy - * values on the target stack before changing ESP. */ - "movl 0xc4(%ecx),%eax\n\t" /* Esp */ - "leal -4*4(%eax),%eax\n\t" - "movl 0xc0(%ecx),%edx\n\t" /* EFlags */ - "movl %edx,3*4(%eax)\n\t" - "movl 0xbc(%ecx),%edx\n\t" /* SegCs */ - "movl %edx,2*4(%eax)\n\t" - "movl 0xb8(%ecx),%edx\n\t" /* Eip */ - "movl %edx,1*4(%eax)\n\t" - "movl 0xb0(%ecx),%edx\n\t" /* Eax */ - "movl %edx,0*4(%eax)\n\t" - "pushl 0x98(%ecx)\n\t" /* SegDs */ - "movl 0xa8(%ecx),%edx\n\t" /* Edx */ - "movl 0xac(%ecx),%ecx\n\t" /* Ecx */ - "popl %ds\n\t" - "movl %eax,%esp\n\t" - "popl %eax\n\t" - "iret\n" - /* Restore the context when the stack segment changes. We can't use - * the same code as above because we do not know if the stack segment - * is 16 or 32 bit, and 'movl' will throw an exception when we try to - * access memory above the limit. */ - "1:\n\t" - "movl 0xa8(%ecx),%edx\n\t" /* Edx */ - "movl 0xb0(%ecx),%eax\n\t" /* Eax */ - "movw 0xc8(%ecx),%ss\n\t" /* SegSs */ - "movl 0xc4(%ecx),%esp\n\t" /* Esp */ - "pushl 0xc0(%ecx)\n\t" /* EFlags */ - "pushl 0xbc(%ecx)\n\t" /* SegCs */ - "pushl 0xb8(%ecx)\n\t" /* Eip */ - "pushl 0x98(%ecx)\n\t" /* SegDs */ - "movl 0xac(%ecx),%ecx\n\t" /* Ecx */ - "popl %ds\n\t" - "iret" ) - - -/*********************************************************************** - * set_cpu_context - * - * Set the new CPU context. Used by NtSetContextThread. - */ -void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) -{ - DWORD flags = context->ContextFlags & ~CONTEXT_i386; - - if ((flags & CONTEXT_EXTENDED_REGISTERS) && has_fpux()) restore_fpux( context ); - else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context ); - - if (flags & CONTEXT_DEBUG_REGISTERS) - { - x86_thread_data()->dr0 = context->Dr0; - x86_thread_data()->dr1 = context->Dr1; - x86_thread_data()->dr2 = context->Dr2; - x86_thread_data()->dr3 = context->Dr3; - x86_thread_data()->dr6 = context->Dr6; - x86_thread_data()->dr7 = context->Dr7; - } - if (flags & CONTEXT_FULL) - { - if (!(flags & CONTEXT_CONTROL)) - FIXME( "setting partial context (%x) not supported\n", flags ); - else if (flags & CONTEXT_SEGMENTS) - set_full_cpu_context( context ); - else - { - CONTEXT newcontext = *context; - newcontext.SegDs = get_ds(); - newcontext.SegEs = get_ds(); - newcontext.SegFs = get_fs(); - newcontext.SegGs = get_gs(); - set_full_cpu_context( &newcontext ); - } - } -} - /*********************************************************************** * NtGetContextThread (NTDLL.@) @@ -2248,166 +2132,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, } -extern void DECLSPEC_NORETURN start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, - void *relay ); -__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") - "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") - "pushl %esi\n\t" - __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") - "pushl %edi\n\t" - __ASM_CFI(".cfi_rel_offset %edi,-12\n\t") - /* store exit frame */ - "movl %ebp,%fs:0x1f4\n\t" /* x86_thread_data()->exit_frame */ - /* switch to thread stack */ - "movl %fs:4,%eax\n\t" /* NtCurrentTeb()->StackBase */ - "leal -0x1000(%eax),%esp\n\t" - /* attach dlls */ - "pushl 20(%ebp)\n\t" /* relay */ - "pushl 16(%ebp)\n\t" /* suspend */ - "pushl 12(%ebp)\n\t" /* arg */ - "pushl 8(%ebp)\n\t" /* entry */ - "xorl %ebp,%ebp\n\t" - "call " __ASM_NAME("attach_thread") "\n\t" - "movl %eax,%esi\n\t" - "leal -12(%eax),%esp\n\t" - /* clear the stack */ - "andl $~0xfff,%eax\n\t" /* round down to page size */ - "movl %eax,(%esp)\n\t" - "call " __ASM_NAME("virtual_clear_thread_stack") "\n\t" - /* switch to the initial context */ - "movl %esi,(%esp)\n\t" - "call " __ASM_NAME("set_cpu_context") ) - -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") ) - -/* wrapper for apps that don't declare the thread function correctly */ -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") - __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" ) - -/*********************************************************************** - * call_thread_func - */ -void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ) -{ - __TRY - { - TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( call_thread_func_wrapper( entry, arg )); - } - __EXCEPT(call_unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - abort(); /* should not be reached */ -} - - -/*********************************************************************** - * init_thread_context - */ -static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) -{ - context->SegCs = get_cs(); - context->SegDs = get_ds(); - context->SegEs = get_ds(); - context->SegFs = get_fs(); - context->SegGs = get_gs(); - context->SegSs = get_ds(); - context->EFlags = 0x202; - context->Eax = (DWORD)entry; - context->Ebx = (DWORD)arg; - context->Esp = (DWORD)NtCurrentTeb()->Tib.StackBase - 16; - context->Eip = (DWORD)relay; - context->FloatSave.ControlWord = 0x27f; - ((XMM_SAVE_AREA32 *)context->ExtendedRegisters)->ControlWord = 0x27f; - ((XMM_SAVE_AREA32 *)context->ExtendedRegisters)->MxCsr = 0x1f80; -} - - -/*********************************************************************** - * attach_thread - */ -PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, - BOOL suspend, void *relay ) -{ - CONTEXT *ctx; - - if (suspend) - { - CONTEXT context = { CONTEXT_ALL }; - - init_thread_context( &context, entry, arg, relay ); - wait_suspend( &context ); - ctx = (CONTEXT *)((ULONG_PTR)context.Esp & ~15) - 1; - *ctx = context; - } - else - { - ctx = (CONTEXT *)((char *)NtCurrentTeb()->Tib.StackBase - 16) - 1; - init_thread_context( ctx, entry, arg, relay ); - } - ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; - LdrInitializeThunk( ctx, (void **)&ctx->Eax, 0, 0 ); - return ctx; -} - - -/*********************************************************************** - * signal_start_thread - * - * Thread startup sequence: - * signal_start_thread() - * -> start_thread() - * -> 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 ); -} - -/********************************************************************** - * signal_start_process - * - * Process startup sequence: - * signal_start_process() - * -> start_thread() - * -> kernel32_start_process() - */ -void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) -{ - start_thread( entry, NtCurrentTeb()->Peb, suspend, kernel32_start_process ); -} - - /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 75b18e1e933..7e73322cbeb 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -58,7 +58,6 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(seh); -WINE_DECLARE_DEBUG_CHANNEL(relay); /*********************************************************************** * signal context platform-specific definitions @@ -720,95 +719,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; } -/*********************************************************************** - * call_thread_entry_point - */ -static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) -{ - __TRY - { - TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( entry( arg )); - } - __EXCEPT(call_unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - abort(); /* should not be reached */ -} - -typedef void (WINAPI *thread_start_func)(LPTHREAD_START_ROUTINE,void *); - -struct startup_info -{ - thread_start_func start; - LPTHREAD_START_ROUTINE entry; - void *arg; - BOOL suspend; -}; - -/* FIXME: should set the full context instead */ -extern void DECLSPEC_NORETURN switch_to_stack( void (*func)(void *), void *arg, void *stack ); -__ASM_GLOBAL_FUNC( switch_to_stack, - "subi 5, 5, 16\n\t" /* reserve space on new stack */ - "mtctr 3\n\t" /* func -> ctr */ - "mr 3,4\n\t" /* args -> function param 1 (r3) */ - "mr 1,5\n\t" /* stack */ - "li 0, 0\n\t" /* zero */ - "stw 0, 0(1)\n\t" /* bottom of stack */ - "stwu 1, -16(1)\n\t" /* create a frame for this function */ - "bctrl" ) /* call ctr */ - -/*********************************************************************** - * thread_startup - */ -static void thread_startup( void *param ) -{ - CONTEXT context = { 0 }; - struct startup_info *info = param; - - /* build the initial context */ - context.ContextFlags = CONTEXT_FULL; - context.Gpr1 = (DWORD)NtCurrentTeb()->Tib.StackBase; - context.Gpr3 = (DWORD)info->entry; - context.Gpr4 = (DWORD)info->arg; - context.Iar = (DWORD)info->start; - - if (info->suspend) wait_suspend( &context ); - LdrInitializeThunk( &context, (void **)&context.Gpr3, 0, 0 ); - - ((thread_start_func)context.Iar)( (LPTHREAD_START_ROUTINE)context.Gpr3, (void *)context.Gpr4 ); -} - -/*********************************************************************** - * signal_start_thread - * - * Thread startup sequence: - * signal_start_thread() - * -> thread_startup() - * -> call_thread_entry_point() - */ -void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) -{ - struct startup_info info = { call_thread_entry_point, entry, arg, suspend }; - switch_to_stack( thread_startup, &info, NtCurrentTeb()->Tib.StackBase ); -} - -/********************************************************************** - * signal_start_process - * - * Process startup sequence: - * signal_start_process() - * -> thread_startup() - * -> kernel32_start_process() - */ -void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) -{ - struct startup_info info = { kernel32_start_process, entry, NtCurrentTeb()->Peb, suspend }; - switch_to_stack( thread_startup, &info, NtCurrentTeb()->Tib.StackBase ); -} - /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7cefd1403f3..0ccc7cbceb6 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -75,7 +75,6 @@ #endif WINE_DEFAULT_DEBUG_CHANNEL(seh); -WINE_DECLARE_DEBUG_CHANNEL(relay); typedef struct _SCOPE_TABLE { @@ -3661,135 +3660,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, } -/*********************************************************************** - * call_thread_func - */ -static void WINAPI call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ) -{ - __TRY - { - TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); - RtlExitUserThread( entry( arg )); - } - __EXCEPT(call_unhandled_exception_filter) - { - NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); - } - __ENDTRY - abort(); /* should not be reached */ -} - - -extern void DECLSPEC_NORETURN start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, - void *relay ); -__ASM_GLOBAL_FUNC( start_thread, - "subq $56,%rsp\n\t" - __ASM_SEH(".seh_stackalloc 56\n\t") - __ASM_SEH(".seh_endprologue\n\t") - __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t") - "movq %rbp,48(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %rbp,48\n\t") - "movq %rbx,40(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %rbx,40\n\t") - "movq %r12,32(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r12,32\n\t") - "movq %r13,24(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r13,24\n\t") - "movq %r14,16(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r14,16\n\t") - "movq %r15,8(%rsp)\n\t" - __ASM_CFI(".cfi_rel_offset %r15,8\n\t") - /* store exit frame */ - "movq %gs:0x30,%rax\n\t" - "movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */ - /* switch to thread stack */ - "movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */ - "leaq -0x1000(%rax),%rsp\n\t" - /* attach dlls */ - "call " __ASM_NAME("attach_thread") "\n\t" - "movq %rax,%rsp\n\t" - /* clear the stack */ - "andq $~0xfff,%rax\n\t" /* round down to page size */ - "movq %rax,%rdi\n\t" - "call " __ASM_NAME("virtual_clear_thread_stack") "\n\t" - /* switch to the initial context */ - "movq %rsp,%rdi\n\t" - "call " __ASM_NAME("set_cpu_context") ) - -/*********************************************************************** - * init_thread_context - */ -static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) -{ - __asm__( "movw %%cs,%0" : "=m" (context->SegCs) ); - __asm__( "movw %%ss,%0" : "=m" (context->SegSs) ); - context->Rcx = (ULONG_PTR)entry; - context->Rdx = (ULONG_PTR)arg; - context->Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28; - context->Rip = (ULONG_PTR)relay; - context->EFlags = 0x200; - context->u.FltSave.ControlWord = 0x27f; - context->u.FltSave.MxCsr = context->MxCsr = 0x1f80; -} - - -/*********************************************************************** - * attach_thread - */ -PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, - BOOL suspend, void *relay ) -{ - CONTEXT *ctx; - - if (suspend) - { - CONTEXT context = { 0 }; - - context.ContextFlags = CONTEXT_ALL; - init_thread_context( &context, entry, arg, relay ); - wait_suspend( &context ); - ctx = (CONTEXT *)((ULONG_PTR)context.Rsp & ~15) - 1; - *ctx = context; - } - else - { - ctx = (CONTEXT *)((char *)NtCurrentTeb()->Tib.StackBase - 0x30) - 1; - init_thread_context( ctx, entry, arg, relay ); - } - ctx->ContextFlags = CONTEXT_FULL; - LdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 ); - return ctx; -} - - -/*********************************************************************** - * signal_start_thread - * - * Thread startup sequence: - * signal_start_thread() - * -> start_thread() - * -> call_thread_func() - */ -void signal_start_thread( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend ) -{ - start_thread( entry, arg, suspend, call_thread_func ); -} - - -/********************************************************************** - * signal_start_process - * - * Process startup sequence: - * signal_start_process() - * -> start_thread() - * -> kernel32_start_process() - */ -void signal_start_process( LPTHREAD_START_ROUTINE entry, BOOL suspend ) -{ - start_thread( entry, NtCurrentTeb()->Peb, suspend, kernel32_start_process ); -} - - /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index f9ea9203ed8..51777ae6a9a 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -47,6 +47,7 @@ #include "wine/exception.h" WINE_DEFAULT_DEBUG_CHANNEL(thread); +WINE_DECLARE_DEBUG_CHANNEL(relay); #ifndef PTHREAD_STACK_MIN #define PTHREAD_STACK_MIN 16384 @@ -335,6 +336,73 @@ void WINAPI RtlExitUserThread( ULONG status ) } +/*********************************************************************** + * call_thread_entry_point + */ +#ifdef __i386__ + +extern void call_thread_entry_point(void) DECLSPEC_HIDDEN; +__ASM_GLOBAL_FUNC( call_thread_entry_point, + "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( 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") + __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" ) + +void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); + RtlExitUserThread( call_thread_func_wrapper( entry, arg )); + } + __EXCEPT(call_unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +#else /* __i386__ */ + +static void WINAPI call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) +{ + __TRY + { + TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", entry, arg ); + RtlExitUserThread( entry( arg )); + } + __EXCEPT(call_unhandled_exception_filter) + { + NtTerminateThread( GetCurrentThread(), GetExceptionCode() ); + } + __ENDTRY + abort(); /* should not be reached */ +} + +#endif /* __i386__ */ + + /*********************************************************************** * start_thread * @@ -342,7 +410,6 @@ void WINAPI RtlExitUserThread( ULONG status ) */ static void start_thread( struct startup_info *info ) { - BOOL suspend; TEB *teb = info->teb; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; struct debug_info debug_info; @@ -350,10 +417,7 @@ static void start_thread( struct startup_info *info ) debug_info.str_pos = debug_info.out_pos = 0; thread_data->debug_info = &debug_info; thread_data->pthread_id = pthread_self(); - - unix_funcs->init_thread( teb ); - unix_funcs->server_init_thread( info->entry_point, &suspend, NULL, NULL, NULL ); - signal_start_thread( (LPTHREAD_START_ROUTINE)info->entry_point, info->entry_arg, suspend ); + unix_funcs->start_thread( info->entry_point, info->entry_arg, call_thread_entry_point, teb ); } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 0f342e8277e..8692dd931c3 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1035,7 +1035,8 @@ static struct unix_funcs unix_funcs = virtual_release_address_space, virtual_set_large_address_space, init_threading, - init_thread, + start_thread, + start_process, abort_thread, exit_thread, exit_process, diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 8228f3f92a2..cd35c23aa91 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -363,6 +363,69 @@ void signal_init_thread( TEB *teb ) } +/*********************************************************************** + * init_thread_context + */ +static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) +{ + context->R0 = (DWORD)entry; + context->R1 = (DWORD)arg; + context->Sp = (DWORD)NtCurrentTeb()->Tib.StackBase; + context->Pc = (DWORD)relay; +} + + +/*********************************************************************** + * attach_thread + */ +PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, + BOOL suspend, void *relay ) +{ + CONTEXT *ctx; + + if (suspend) + { + CONTEXT context = { CONTEXT_ALL }; + + init_thread_context( &context, entry, arg, relay ); + wait_suspend( &context ); + ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; + *ctx = context; + } + else + { + ctx = (CONTEXT *)NtCurrentTeb()->Tib.StackBase - 1; + init_thread_context( ctx, entry, arg, relay ); + } + ctx->ContextFlags = CONTEXT_FULL; + LdrInitializeThunk( ctx, (void **)&ctx->R0, 0, 0 ); + return ctx; +} + + +/*********************************************************************** + * signal_start_thread + */ +__ASM_GLOBAL_FUNC( signal_start_thread, + ".arm\n\t" + "push {r4-r12,lr}\n\t" + /* store exit frame */ + "ldr r4, [sp, #40]\n\t" /* teb */ + "str sp, [r4, #0x1d4]\n\t" /* teb->SystemReserved2 */ + /* switch to thread stack */ + "ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */ + "sub sp, r4, #0x1000\n\t" + /* attach dlls */ + "bl " __ASM_NAME("attach_thread") "\n\t" + "mov sp, r0\n\t" + /* clear the stack */ + "and r0, #~0xff0\n\t" /* round down to page size */ + "bl " __ASM_NAME("virtual_clear_thread_stack") "\n\t" + /* switch to the initial context */ + "mov r0, sp\n\t" + "b " __ASM_NAME("set_cpu_context") ) + + extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb ); __ASM_GLOBAL_FUNC( call_thread_exit_func, ".arm\n\t" diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index ca47481b194..add8b4385c4 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -370,6 +370,109 @@ void signal_init_thread( TEB *teb ) } +/*********************************************************************** + * init_thread_context + */ +static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) +{ + context->u.s.X0 = (DWORD64)entry; + context->u.s.X1 = (DWORD64)arg; + context->u.s.X18 = (DWORD64)NtCurrentTeb(); + context->Sp = (DWORD64)NtCurrentTeb()->Tib.StackBase; + context->Pc = (DWORD64)relay; +} + + +/*********************************************************************** + * attach_thread + */ +PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, + BOOL suspend, void *relay ) +{ + CONTEXT *ctx; + + if (suspend) + { + CONTEXT context = { CONTEXT_ALL }; + + init_thread_context( &context, entry, arg, relay ); + wait_suspend( &context ); + ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; + *ctx = context; + } + else + { + ctx = (CONTEXT *)NtCurrentTeb()->Tib.StackBase - 1; + init_thread_context( ctx, entry, arg, relay ); + } + ctx->ContextFlags = CONTEXT_FULL; + LdrInitializeThunk( ctx, (void **)&ctx->u.s.X0, 0, 0 ); + return ctx; +} + + +/*********************************************************************** + * signal_start_thread + */ +__ASM_GLOBAL_FUNC( signal_start_thread, + "stp x29, x30, [sp,#-16]!\n\t" + "mov x18, x4\n\t" /* teb */ + /* store exit frame */ + "mov x29, sp\n\t" + "str x29, [x4, #0x300]\n\t" /* arm64_thread_data()->exit_frame */ + /* switch to thread stack */ + "ldr x5, [x4, #8]\n\t" /* teb->Tib.StackBase */ + "sub sp, x5, #0x1000\n\t" + /* attach dlls */ + "bl " __ASM_NAME("attach_thread") "\n\t" + "mov sp, x0\n\t" + /* clear the stack */ + "and x0, x0, #~0xfff\n\t" /* round down to page size */ + "bl " __ASM_NAME("virtual_clear_thread_stack") "\n\t" + /* switch to the initial context */ + "mov x0, sp\n\t" + "ldp q0, q1, [x0, #0x110]\n\t" /* context->V[0,1] */ + "ldp q2, q3, [x0, #0x130]\n\t" /* context->V[2,3] */ + "ldp q4, q5, [x0, #0x150]\n\t" /* context->V[4,5] */ + "ldp q6, q7, [x0, #0x170]\n\t" /* context->V[6,7] */ + "ldp q8, q9, [x0, #0x190]\n\t" /* context->V[8,9] */ + "ldp q10, q11, [x0, #0x1b0]\n\t" /* context->V[10,11] */ + "ldp q12, q13, [x0, #0x1d0]\n\t" /* context->V[12,13] */ + "ldp q14, q15, [x0, #0x1f0]\n\t" /* context->V[14,15] */ + "ldp q16, q17, [x0, #0x210]\n\t" /* context->V[16,17] */ + "ldp q18, q19, [x0, #0x230]\n\t" /* context->V[18,19] */ + "ldp q20, q21, [x0, #0x250]\n\t" /* context->V[20,21] */ + "ldp q22, q23, [x0, #0x270]\n\t" /* context->V[22,23] */ + "ldp q24, q25, [x0, #0x290]\n\t" /* context->V[24,25] */ + "ldp q26, q27, [x0, #0x2b0]\n\t" /* context->V[26,27] */ + "ldp q28, q29, [x0, #0x2d0]\n\t" /* context->V[28,29] */ + "ldp q30, q31, [x0, #0x2f0]\n\t" /* context->V[30,31] */ + "ldr w1, [x0, #0x310]\n\t" /* context->Fpcr */ + "msr fpcr, x1\n\t" + "ldr w1, [x0, #0x314]\n\t" /* context->Fpsr */ + "msr fpsr, x1\n\t" + "ldp x1, x2, [x0, #0x10]\n\t" /* context->X1,2 */ + "ldp x3, x4, [x0, #0x20]\n\t" /* context->X3,4 */ + "ldp x5, x6, [x0, #0x30]\n\t" /* context->X5,6 */ + "ldp x7, x8, [x0, #0x40]\n\t" /* context->X7,8 */ + "ldp x9, x10, [x0, #0x50]\n\t" /* context->X9,10 */ + "ldp x11, x12, [x0, #0x60]\n\t" /* context->X11,12 */ + "ldp x13, x14, [x0, #0x70]\n\t" /* context->X13,14 */ + "ldp x15, x16, [x0, #0x80]\n\t" /* context->X15,16 */ + "ldp x17, x18, [x0, #0x90]\n\t" /* context->X17,18 */ + "ldp x19, x20, [x0, #0xa0]\n\t" /* context->X19,20 */ + "ldp x21, x22, [x0, #0xb0]\n\t" /* context->X21,22 */ + "ldp x23, x24, [x0, #0xc0]\n\t" /* context->X23,24 */ + "ldp x25, x26, [x0, #0xd0]\n\t" /* context->X25,26 */ + "ldp x27, x28, [x0, #0xe0]\n\t" /* context->X27,28 */ + "ldp x29, x30, [x0, #0xf0]\n\t" /* context->Fp,Lr */ + "ldr x17, [x0, #0x100]\n\t" /* context->Sp */ + "mov sp, x17\n\t" + "ldr x17, [x0, #0x108]\n\t" /* context->Pc */ + "ldr x0, [x0, #0x8]\n\t" /* context->X0 */ + "br x17" ) + + extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb ); __ASM_GLOBAL_FUNC( call_thread_exit_func, "stp x29, x30, [sp,#-16]!\n\t" diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 8902be00cd1..515090d9af8 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -960,6 +960,94 @@ void signal_init_thread( TEB *teb ) } +/*********************************************************************** + * init_thread_context + */ +static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) +{ + context->SegCs = get_cs(); + context->SegDs = get_ds(); + context->SegEs = get_ds(); + context->SegFs = get_fs(); + context->SegGs = get_gs(); + context->SegSs = get_ds(); + context->EFlags = 0x202; + context->Eax = (DWORD)entry; + context->Ebx = (DWORD)arg; + context->Esp = (DWORD)NtCurrentTeb()->Tib.StackBase - 16; + context->Eip = (DWORD)relay; + context->FloatSave.ControlWord = 0x27f; + ((XMM_SAVE_AREA32 *)context->ExtendedRegisters)->ControlWord = 0x27f; + ((XMM_SAVE_AREA32 *)context->ExtendedRegisters)->MxCsr = 0x1f80; +} + + +/*********************************************************************** + * attach_thread + */ +PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, + BOOL suspend, void *relay ) +{ + CONTEXT *ctx; + + if (suspend) + { + CONTEXT context = { CONTEXT_ALL }; + + init_thread_context( &context, entry, arg, relay ); + wait_suspend( &context ); + ctx = (CONTEXT *)((ULONG_PTR)context.Esp & ~15) - 1; + *ctx = context; + } + else + { + ctx = (CONTEXT *)((char *)NtCurrentTeb()->Tib.StackBase - 16) - 1; + init_thread_context( ctx, entry, arg, relay ); + } + ctx->ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; + LdrInitializeThunk( ctx, (void **)&ctx->Eax, 0, 0 ); + return ctx; +} + + +/*********************************************************************** + * signal_start_thread + */ +__ASM_GLOBAL_FUNC( signal_start_thread, + "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") + "pushl %esi\n\t" + __ASM_CFI(".cfi_rel_offset %esi,-8\n\t") + "pushl %edi\n\t" + __ASM_CFI(".cfi_rel_offset %edi,-12\n\t") + /* store exit frame */ + "movl %ebp,%fs:0x1f4\n\t" /* x86_thread_data()->exit_frame */ + /* switch to thread stack */ + "movl %fs:4,%eax\n\t" /* NtCurrentTeb()->StackBase */ + "leal -0x1000(%eax),%esp\n\t" + /* attach dlls */ + "pushl 20(%ebp)\n\t" /* relay */ + "pushl 16(%ebp)\n\t" /* suspend */ + "pushl 12(%ebp)\n\t" /* arg */ + "pushl 8(%ebp)\n\t" /* entry */ + "xorl %ebp,%ebp\n\t" + "call " __ASM_NAME("attach_thread") "\n\t" + "movl %eax,%esi\n\t" + "leal -12(%eax),%esp\n\t" + /* clear the stack */ + "andl $~0xfff,%eax\n\t" /* round down to page size */ + "movl %eax,(%esp)\n\t" + "call " __ASM_NAME("virtual_clear_thread_stack") "\n\t" + /* switch to the initial context */ + "movl %esi,(%esp)\n\t" + "call " __ASM_NAME("set_cpu_context") ) + + /*********************************************************************** * signal_exit_thread */ diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index abe4d6905e6..aec0228de02 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -650,6 +650,90 @@ void signal_init_thread( TEB *teb ) } +/*********************************************************************** + * init_thread_context + */ +static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay ) +{ + __asm__( "movw %%cs,%0" : "=m" (context->SegCs) ); + __asm__( "movw %%ss,%0" : "=m" (context->SegSs) ); + context->Rcx = (ULONG_PTR)entry; + context->Rdx = (ULONG_PTR)arg; + context->Rsp = (ULONG_PTR)NtCurrentTeb()->Tib.StackBase - 0x28; + context->Rip = (ULONG_PTR)relay; + context->EFlags = 0x200; + context->u.FltSave.ControlWord = 0x27f; + context->u.FltSave.MxCsr = context->MxCsr = 0x1f80; +} + + +/*********************************************************************** + * attach_thread + */ +PCONTEXT DECLSPEC_HIDDEN attach_thread( LPTHREAD_START_ROUTINE entry, void *arg, + BOOL suspend, void *relay ) +{ + CONTEXT *ctx; + + if (suspend) + { + CONTEXT context = { 0 }; + + context.ContextFlags = CONTEXT_ALL; + init_thread_context( &context, entry, arg, relay ); + wait_suspend( &context ); + ctx = (CONTEXT *)((ULONG_PTR)context.Rsp & ~15) - 1; + *ctx = context; + } + else + { + ctx = (CONTEXT *)((char *)NtCurrentTeb()->Tib.StackBase - 0x30) - 1; + init_thread_context( ctx, entry, arg, relay ); + } + ctx->ContextFlags = CONTEXT_FULL; + LdrInitializeThunk( ctx, (void **)&ctx->Rcx, 0, 0 ); + return ctx; +} + + +/*********************************************************************** + * signal_start_thread + */ +__ASM_GLOBAL_FUNC( signal_start_thread, + "subq $56,%rsp\n\t" + __ASM_SEH(".seh_stackalloc 56\n\t") + __ASM_SEH(".seh_endprologue\n\t") + __ASM_CFI(".cfi_adjust_cfa_offset 56\n\t") + "movq %rbp,48(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %rbp,48\n\t") + "movq %rbx,40(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %rbx,40\n\t") + "movq %r12,32(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %r12,32\n\t") + "movq %r13,24(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %r13,24\n\t") + "movq %r14,16(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %r14,16\n\t") + "movq %r15,8(%rsp)\n\t" + __ASM_CFI(".cfi_rel_offset %r15,8\n\t") + /* store exit frame */ + "movq %gs:0x30,%rax\n\t" + "movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */ + /* switch to thread stack */ + "movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */ + "leaq -0x1000(%rax),%rsp\n\t" + /* attach dlls */ + "call " __ASM_NAME("attach_thread") "\n\t" + "movq %rax,%rsp\n\t" + /* clear the stack */ + "andq $~0xfff,%rax\n\t" /* round down to page size */ + "movq %rax,%rdi\n\t" + "call " __ASM_NAME("virtual_clear_thread_stack") "\n\t" + /* switch to the initial context */ + "movq %rsp,%rdi\n\t" + "call " __ASM_NAME("set_cpu_context") ) + + /*********************************************************************** * signal_exit_thread */ diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 603ceaf6d27..7e18caeaebf 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -26,6 +26,7 @@ #include "wine/port.h" #include <assert.h> +#include <errno.h> #include <limits.h> #include <stdarg.h> #include <pthread.h> @@ -92,11 +93,24 @@ void CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy ) /*********************************************************************** - * init_thread + * start_thread */ -void CDECL init_thread( TEB *teb ) +void CDECL start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ) { + BOOL suspend; + signal_init_thread( teb ); + server_init_thread( entry, &suspend, NULL, NULL, NULL ); + signal_start_thread( entry, arg, suspend, relay, teb ); +} + + +/*********************************************************************** + * start_process + */ +void CDECL start_process( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ) +{ + signal_start_thread( entry, NtCurrentTeb()->Peb, suspend, relay, NtCurrentTeb() ); } @@ -131,6 +145,21 @@ void CDECL exit_process( int status ) } +/********************************************************************** + * wait_suspend + * + * Wait until the thread is no longer suspended. + */ +void wait_suspend( CONTEXT *context ) +{ + int saved_errno = errno; + + /* wait with 0 timeout, will only return once the thread is no longer suspended */ + server_select( NULL, 0, SELECT_INTERRUPTIBLE, 0, context, NULL, NULL ); + errno = saved_errno; +} + + /*********************************************************************** * set_thread_context */ diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 8562efb7dd4..dd94cde1cf1 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -50,6 +50,8 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void) return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch; } +void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR); + void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; @@ -104,7 +106,8 @@ extern void CDECL server_init_process_done(void) DECLSPEC_HIDDEN; extern size_t CDECL server_init_thread( void *entry_point, BOOL *suspend, unsigned int *cpus, BOOL *wow64, timeout_t *start_time ) DECLSPEC_HIDDEN; extern void CDECL init_threading( int *nb_threads, struct ldt_copy **ldt_copy ) DECLSPEC_HIDDEN; -extern void CDECL init_thread( TEB *teb ) DECLSPEC_HIDDEN; +extern void CDECL DECLSPEC_NORETURN start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ) DECLSPEC_HIDDEN; +extern void CDECL DECLSPEC_NORETURN start_process( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN; extern void CDECL DECLSPEC_NORETURN exit_process( int status ) DECLSPEC_HIDDEN; @@ -125,6 +128,7 @@ extern void start_server( BOOL debug ) DECLSPEC_HIDDEN; extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN; extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN; +extern void wait_suspend( CONTEXT *context ) DECLSPEC_HIDDEN; extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN; extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN; @@ -132,6 +136,8 @@ extern void signal_init_threading(void) DECLSPEC_HIDDEN; 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 DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, + BOOL suspend, void *relay, TEB *teb ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int) ) DECLSPEC_HIDDEN; #endif /* __NTDLL_UNIX_PRIVATE_H */ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 0346d0d9753..9e229c5f4d2 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2721,6 +2721,21 @@ done: } +/*********************************************************************** + * virtual_clear_thread_stack + * + * Clear the stack contents before calling the main entry point, some broken apps need that. + */ +void virtual_clear_thread_stack( void *stack_end ) +{ + void *stack = NtCurrentTeb()->Tib.StackLimit; + size_t size = (char *)stack_end - (char *)stack; + + wine_anon_mmap( stack, size, PROT_READ | PROT_WRITE, MAP_FIXED ); + if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EXEC ); +} + + /*********************************************************************** * virtual_handle_fault */ diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index fb755373f07..69581c23914 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 16 +#define NTDLL_UNIXLIB_VERSION 17 struct unix_funcs { @@ -112,7 +112,8 @@ struct unix_funcs /* thread/process functions */ void (CDECL *init_threading)( int *nb_threads, struct ldt_copy **ldt_copy ); - void (CDECL *init_thread)( TEB *teb ); + void (CDECL *start_thread)( PRTL_THREAD_START_ROUTINE entry, void *arg, void *relay, TEB *teb ); + void (CDECL *start_process)( PRTL_THREAD_START_ROUTINE entry, BOOL suspend, void *relay ); void (CDECL *abort_thread)( int status ); void (CDECL *exit_thread)( int status ); void (CDECL *exit_process)( int status ); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 709d2b26cdb..e277de16fe8 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -84,8 +84,6 @@ static SIZE_T signal_stack_align; #define ROUND_SIZE(addr,size) \ (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask) -static BOOL force_exec_prot; /* whether to force PROT_EXEC on all PROT_READ mmaps */ - /*********************************************************************** * get_vprot_flags * @@ -139,31 +137,6 @@ static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot, BOOL image } -/*********************************************************************** - * virtual_clear_thread_stack - * - * Clear the stack contents before calling the main entry point, some broken apps need that. - */ -void virtual_clear_thread_stack( void *stack_end ) -{ - void *stack = NtCurrentTeb()->Tib.StackLimit; - size_t size = (char *)stack_end - (char *)stack; - - wine_anon_mmap( stack, size, PROT_READ | PROT_WRITE, MAP_FIXED ); - if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EXEC ); -} - -/*********************************************************************** - * VIRTUAL_SetForceExec - * - * Whether to force exec prot on all views. - */ -void VIRTUAL_SetForceExec( BOOL enable ) -{ - force_exec_prot = enable; - unix_funcs->virtual_set_force_exec( enable ); -} - /********************************************************************** * RtlCreateUserStack (NTDLL.@) */ -- GitLab