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

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-03 16:32:02 +02:00
parent 11217ee628
commit be0eb9c92e
19 changed files with 467 additions and 812 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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