Commit be0eb9c9 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Move the thread startup code to the Unix library.

parent 11217ee6
...@@ -78,8 +78,6 @@ extern LPCSTR debugstr_ObjectAttributes(const OBJECT_ATTRIBUTES *oa) DECLSPEC_HI ...@@ -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_size DECLSPEC_HIDDEN;
extern SIZE_T signal_stack_mask DECLSPEC_HIDDEN; extern SIZE_T signal_stack_mask DECLSPEC_HIDDEN;
extern void signal_init_process(void) 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 version_init(void) DECLSPEC_HIDDEN;
extern void debug_init(void) DECLSPEC_HIDDEN; extern void debug_init(void) DECLSPEC_HIDDEN;
extern TEB *thread_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 ...@@ -175,30 +173,6 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S
UINT disposition ) DECLSPEC_HIDDEN; UINT disposition ) DECLSPEC_HIDDEN;
/* virtual memory */ /* 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, extern void virtual_fill_image_information( const pe_image_info_t *pe_info,
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN;
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
......
...@@ -734,7 +734,7 @@ NTSTATUS WINAPI NtSetInformationProcess( ...@@ -734,7 +734,7 @@ NTSTATUS WINAPI NtSetInformationProcess(
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
execute_flags = *(ULONG *)ProcessInformation; execute_flags = *(ULONG *)ProcessInformation;
VIRTUAL_SetForceExec( enable ); unix_funcs->virtual_set_force_exec( enable );
} }
break; break;
......
...@@ -299,5 +299,5 @@ void server_init_process_done(void) ...@@ -299,5 +299,5 @@ void server_init_process_done(void)
SERVER_END_REQ; SERVER_END_REQ;
assert( !status ); assert( !status );
signal_start_process( entry, suspend ); unix_funcs->start_process( entry, suspend, kernel32_start_process );
} }
...@@ -61,7 +61,6 @@ ...@@ -61,7 +61,6 @@
#include "winnt.h" #include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
/*********************************************************************** /***********************************************************************
* signal context platform-specific definitions * signal context platform-specific definitions
...@@ -867,111 +866,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ...@@ -867,111 +866,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
return 0; 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.@) * DbgBreakPoint (NTDLL.@)
*/ */
......
...@@ -64,7 +64,6 @@ ...@@ -64,7 +64,6 @@
#include "winnt.h" #include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */ /* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
struct MSVCRT_JUMP_BUFFER struct MSVCRT_JUMP_BUFFER
...@@ -1880,149 +1879,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ...@@ -1880,149 +1879,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
return 0; 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.@) * DbgBreakPoint (NTDLL.@)
*/ */
......
...@@ -58,7 +58,6 @@ ...@@ -58,7 +58,6 @@
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
/*********************************************************************** /***********************************************************************
* signal context platform-specific definitions * signal context platform-specific definitions
...@@ -720,95 +719,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ...@@ -720,95 +719,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
return 0; 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.@) * DbgBreakPoint (NTDLL.@)
*/ */
......
...@@ -75,7 +75,6 @@ ...@@ -75,7 +75,6 @@
#endif #endif
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
typedef struct _SCOPE_TABLE typedef struct _SCOPE_TABLE
{ {
...@@ -3661,135 +3660,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, ...@@ -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.@) * DbgBreakPoint (NTDLL.@)
*/ */
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "wine/exception.h" #include "wine/exception.h"
WINE_DEFAULT_DEBUG_CHANNEL(thread); WINE_DEFAULT_DEBUG_CHANNEL(thread);
WINE_DECLARE_DEBUG_CHANNEL(relay);
#ifndef PTHREAD_STACK_MIN #ifndef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 16384 #define PTHREAD_STACK_MIN 16384
...@@ -336,13 +337,79 @@ void WINAPI RtlExitUserThread( ULONG status ) ...@@ -336,13 +337,79 @@ 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 * start_thread
* *
* Startup routine for a newly created thread. * Startup routine for a newly created thread.
*/ */
static void start_thread( struct startup_info *info ) static void start_thread( struct startup_info *info )
{ {
BOOL suspend;
TEB *teb = info->teb; TEB *teb = info->teb;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
struct debug_info debug_info; struct debug_info debug_info;
...@@ -350,10 +417,7 @@ static void start_thread( struct startup_info *info ) ...@@ -350,10 +417,7 @@ static void start_thread( struct startup_info *info )
debug_info.str_pos = debug_info.out_pos = 0; debug_info.str_pos = debug_info.out_pos = 0;
thread_data->debug_info = &debug_info; thread_data->debug_info = &debug_info;
thread_data->pthread_id = pthread_self(); thread_data->pthread_id = pthread_self();
unix_funcs->start_thread( info->entry_point, info->entry_arg, call_thread_entry_point, teb );
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 );
} }
......
...@@ -1035,7 +1035,8 @@ static struct unix_funcs unix_funcs = ...@@ -1035,7 +1035,8 @@ static struct unix_funcs unix_funcs =
virtual_release_address_space, virtual_release_address_space,
virtual_set_large_address_space, virtual_set_large_address_space,
init_threading, init_threading,
init_thread, start_thread,
start_process,
abort_thread, abort_thread,
exit_thread, exit_thread,
exit_process, exit_process,
......
...@@ -363,6 +363,69 @@ void signal_init_thread( TEB *teb ) ...@@ -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 ); extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );
__ASM_GLOBAL_FUNC( call_thread_exit_func, __ASM_GLOBAL_FUNC( call_thread_exit_func,
".arm\n\t" ".arm\n\t"
......
...@@ -370,6 +370,109 @@ void signal_init_thread( TEB *teb ) ...@@ -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 ); extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );
__ASM_GLOBAL_FUNC( call_thread_exit_func, __ASM_GLOBAL_FUNC( call_thread_exit_func,
"stp x29, x30, [sp,#-16]!\n\t" "stp x29, x30, [sp,#-16]!\n\t"
......
...@@ -961,6 +961,94 @@ void signal_init_thread( TEB *teb ) ...@@ -961,6 +961,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 * signal_exit_thread
*/ */
__ASM_GLOBAL_FUNC( signal_exit_thread, __ASM_GLOBAL_FUNC( signal_exit_thread,
......
...@@ -651,6 +651,90 @@ void signal_init_thread( TEB *teb ) ...@@ -651,6 +651,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 * signal_exit_thread
*/ */
__ASM_GLOBAL_FUNC( signal_exit_thread, __ASM_GLOBAL_FUNC( signal_exit_thread,
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "wine/port.h" #include "wine/port.h"
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <pthread.h> #include <pthread.h>
...@@ -92,11 +93,24 @@ void CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy ) ...@@ -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 ); 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 ) ...@@ -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 * set_thread_context
*/ */
......
...@@ -50,6 +50,8 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void) ...@@ -50,6 +50,8 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch; 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_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
void CDECL mmap_remove_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; 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; ...@@ -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, extern size_t CDECL server_init_thread( void *entry_point, BOOL *suspend, unsigned int *cpus,
BOOL *wow64, timeout_t *start_time ) DECLSPEC_HIDDEN; 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_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 abort_thread( int status ) DECLSPEC_HIDDEN;
extern void CDECL DECLSPEC_NORETURN exit_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; extern void CDECL DECLSPEC_NORETURN exit_process( int status ) DECLSPEC_HIDDEN;
...@@ -125,6 +128,7 @@ extern void start_server( BOOL debug ) 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_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *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 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; 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; ...@@ -132,6 +136,8 @@ extern void signal_init_threading(void) DECLSPEC_HIDDEN;
extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN; extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN;
extern void signal_free_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_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; extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int) ) DECLSPEC_HIDDEN;
#endif /* __NTDLL_UNIX_PRIVATE_H */ #endif /* __NTDLL_UNIX_PRIVATE_H */
...@@ -2722,6 +2722,21 @@ done: ...@@ -2722,6 +2722,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 * virtual_handle_fault
*/ */
NTSTATUS CDECL virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) NTSTATUS CDECL virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
......
...@@ -28,7 +28,7 @@ struct ldt_copy; ...@@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr; struct msghdr;
/* increment this when you change the function table */ /* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 16 #define NTDLL_UNIXLIB_VERSION 17
struct unix_funcs struct unix_funcs
{ {
...@@ -112,7 +112,8 @@ struct unix_funcs ...@@ -112,7 +112,8 @@ struct unix_funcs
/* thread/process functions */ /* thread/process functions */
void (CDECL *init_threading)( int *nb_threads, struct ldt_copy **ldt_copy ); 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 *abort_thread)( int status );
void (CDECL *exit_thread)( int status ); void (CDECL *exit_thread)( int status );
void (CDECL *exit_process)( int status ); void (CDECL *exit_process)( int status );
......
...@@ -84,8 +84,6 @@ static SIZE_T signal_stack_align; ...@@ -84,8 +84,6 @@ static SIZE_T signal_stack_align;
#define ROUND_SIZE(addr,size) \ #define ROUND_SIZE(addr,size) \
(((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask) (((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 * get_vprot_flags
* *
...@@ -139,31 +137,6 @@ static NTSTATUS get_vprot_flags( DWORD protect, unsigned int *vprot, BOOL image ...@@ -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.@) * RtlCreateUserStack (NTDLL.@)
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment