ntdll: Store the context on the thread stack after the initial suspend.
The initial stack pointer may have been modified during suspend. Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3e80093410
commit
a83532d8dd
|
@ -3059,11 +3059,11 @@ static void test_SuspendProcessNewThread(void)
|
||||||
ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
|
ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
|
||||||
ok(!ret, "IAT entry resolved prematurely\n");
|
ok(!ret, "IAT entry resolved prematurely\n");
|
||||||
|
|
||||||
ctx.ContextFlags = CONTEXT_FULL;
|
ctx.ContextFlags = CONTEXT_ALL;
|
||||||
ret = GetThreadContext( thread_handle, &ctx );
|
ret = GetThreadContext( thread_handle, &ctx );
|
||||||
ok( ret, "Failed retrieving remote thread context (%d)\n", GetLastError() );
|
ok( ret, "Failed retrieving remote thread context (%d)\n", GetLastError() );
|
||||||
|
ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %x\n", ctx.ContextFlags );
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags );
|
|
||||||
ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
|
ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
|
||||||
ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
|
ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
|
||||||
ok( ctx.Rcx == (ULONG_PTR)exit_thread_ptr, "wrong rcx %lx/%p\n", ctx.Rcx, exit_thread_ptr );
|
ok( ctx.Rcx == (ULONG_PTR)exit_thread_ptr, "wrong rcx %lx/%p\n", ctx.Rcx, exit_thread_ptr );
|
||||||
|
@ -3080,8 +3080,10 @@ static void test_SuspendProcessNewThread(void)
|
||||||
ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
|
ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
|
||||||
ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
|
ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
|
||||||
ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
|
ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
|
||||||
|
ok( ctx.EFlags == 0x200, "wrong flags %08x\n", ctx.EFlags );
|
||||||
|
ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08x\n", ctx.MxCsr );
|
||||||
|
ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
|
||||||
#else
|
#else
|
||||||
ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags );
|
|
||||||
ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
|
ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
|
||||||
if (!ctx.Ebp) /* winxp is completely different */
|
if (!ctx.Ebp) /* winxp is completely different */
|
||||||
{
|
{
|
||||||
|
@ -3094,6 +3096,9 @@ static void test_SuspendProcessNewThread(void)
|
||||||
ok( ctx.Ebx == 0x1234, "wrong ebx %08x\n", ctx.Ebx );
|
ok( ctx.Ebx == 0x1234, "wrong ebx %08x\n", ctx.Ebx );
|
||||||
ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
|
ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
|
||||||
"esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
|
"esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
|
||||||
|
ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08x\n", ctx.EFlags );
|
||||||
|
ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FloatSave.ControlWord );
|
||||||
|
ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ResumeThread( thread_handle );
|
ResumeThread( thread_handle );
|
||||||
|
@ -3193,9 +3198,10 @@ static void test_SuspendProcessState(void)
|
||||||
ok(server_pipe_handle != INVALID_HANDLE_VALUE, "Failed to create communication pipe (%d)\n", GetLastError());
|
ok(server_pipe_handle != INVALID_HANDLE_VALUE, "Failed to create communication pipe (%d)\n", GetLastError());
|
||||||
|
|
||||||
/* Set up the remote process environment */
|
/* Set up the remote process environment */
|
||||||
ctx.ContextFlags = CONTEXT_FULL;
|
ctx.ContextFlags = CONTEXT_ALL;
|
||||||
ret = GetThreadContext(pi.hThread, &ctx);
|
ret = GetThreadContext(pi.hThread, &ctx);
|
||||||
ok(ret, "Failed retrieving remote thread context (%d)\n", GetLastError());
|
ok(ret, "Failed retrieving remote thread context (%d)\n", GetLastError());
|
||||||
|
ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %x\n", ctx.ContextFlags );
|
||||||
|
|
||||||
remote_pipe_params = VirtualAllocEx(pi.hProcess, NULL, sizeof(pipe_params), MEM_COMMIT, PAGE_READWRITE);
|
remote_pipe_params = VirtualAllocEx(pi.hProcess, NULL, sizeof(pipe_params), MEM_COMMIT, PAGE_READWRITE);
|
||||||
ok(remote_pipe_params != NULL, "Failed allocating memory in remote process (%d)\n", GetLastError());
|
ok(remote_pipe_params != NULL, "Failed allocating memory in remote process (%d)\n", GetLastError());
|
||||||
|
@ -3210,7 +3216,6 @@ static void test_SuspendProcessState(void)
|
||||||
ok(ret, "Failed to write to remote process memory (%d)\n", GetLastError());
|
ok(ret, "Failed to write to remote process memory (%d)\n", GetLastError());
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags );
|
|
||||||
ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
|
ok( !ctx.Rax, "rax is not zero %lx\n", ctx.Rax );
|
||||||
ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
|
ok( !ctx.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
|
||||||
ok( !ctx.Rsi, "rsi is not zero %lx\n", ctx.Rsi );
|
ok( !ctx.Rsi, "rsi is not zero %lx\n", ctx.Rsi );
|
||||||
|
@ -3225,6 +3230,9 @@ static void test_SuspendProcessState(void)
|
||||||
ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
|
ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
|
||||||
ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
|
ok( !ctx.R15, "r15 is not zero %lx\n", ctx.R15 );
|
||||||
ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
|
ok( !((ctx.Rsp + 0x28) & 0xfff), "rsp is not at top of stack page %lx\n", ctx.Rsp );
|
||||||
|
ok( ctx.EFlags == 0x200, "wrong flags %08x\n", ctx.EFlags );
|
||||||
|
ok( ctx.MxCsr == 0x1f80, "wrong mxcsr %08x\n", ctx.MxCsr );
|
||||||
|
ok( ctx.FltSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FltSave.ControlWord );
|
||||||
entry_ptr = (void *)ctx.Rcx;
|
entry_ptr = (void *)ctx.Rcx;
|
||||||
peb_ptr = (void *)ctx.Rdx;
|
peb_ptr = (void *)ctx.Rdx;
|
||||||
|
|
||||||
|
@ -3242,7 +3250,6 @@ static void test_SuspendProcessState(void)
|
||||||
ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Rsp, &rop_chain, sizeof(rop_chain), NULL);
|
ret = WriteProcessMemory(pi.hProcess, (void *)ctx.Rsp, &rop_chain, sizeof(rop_chain), NULL);
|
||||||
ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError());
|
ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError());
|
||||||
#else
|
#else
|
||||||
ok( ctx.ContextFlags == CONTEXT_FULL, "wrong flags %x\n", ctx.ContextFlags );
|
|
||||||
ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
|
ok( !ctx.Ebp || broken(ctx.Ebp), /* winxp */ "ebp is not zero %08x\n", ctx.Ebp );
|
||||||
if (!ctx.Ebp) /* winxp is completely different */
|
if (!ctx.Ebp) /* winxp is completely different */
|
||||||
{
|
{
|
||||||
|
@ -3253,6 +3260,9 @@ static void test_SuspendProcessState(void)
|
||||||
}
|
}
|
||||||
ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
|
ok( !((ctx.Esp + 0x10) & 0xfff) || broken( !((ctx.Esp + 4) & 0xfff) ), /* winxp, w2k3 */
|
||||||
"esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
|
"esp is not at top of stack page or properly aligned: %08x\n", ctx.Esp );
|
||||||
|
ok( (ctx.EFlags & ~2) == 0x200, "wrong flags %08x\n", ctx.EFlags );
|
||||||
|
ok( (WORD)ctx.FloatSave.ControlWord == 0x27f, "wrong control %08x\n", ctx.FloatSave.ControlWord );
|
||||||
|
ok( *(WORD *)ctx.ExtendedRegisters == 0x27f, "wrong control %08x\n", *(WORD *)ctx.ExtendedRegisters );
|
||||||
entry_ptr = (void *)ctx.Eax;
|
entry_ptr = (void *)ctx.Eax;
|
||||||
peb_ptr = (void *)ctx.Ebx;
|
peb_ptr = (void *)ctx.Ebx;
|
||||||
|
|
||||||
|
|
|
@ -1228,24 +1228,17 @@ __ASM_GLOBAL_FUNC( start_thread,
|
||||||
/* store exit frame */
|
/* store exit frame */
|
||||||
"ldr r4, [sp, #40]\n\t" /* teb */
|
"ldr r4, [sp, #40]\n\t" /* teb */
|
||||||
"str sp, [r4, #0x1d4]\n\t" /* teb->SystemReserved2 */
|
"str sp, [r4, #0x1d4]\n\t" /* teb->SystemReserved2 */
|
||||||
/* build initial context on thread stack */
|
|
||||||
"ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */
|
|
||||||
"sub r5, r4, #0x1a0\n\t" /* sizeof(CONTEXT) */
|
|
||||||
"mov ip, #0x0200000\n\t" /* CONTEXT_ARM */
|
|
||||||
"add ip, #0x3\n\t" /* CONTEXT_FULL */
|
|
||||||
"str ip, [r5]\n\t" /* context->ContextFlags */
|
|
||||||
"str r0, [r5, #0x4]\n\t" /* context->R0 = entry */
|
|
||||||
"str r1, [r5, #0x8]\n\t" /* context->R1 = arg */
|
|
||||||
"str r4, [r5, #0x38]\n\t" /* context->Sp = stack */
|
|
||||||
"str r3, [r5, #0x40]\n\t" /* context->Pc = relay */
|
|
||||||
/* switch to thread stack */
|
/* switch to thread stack */
|
||||||
"mov sp, r5\n\t"
|
"ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */
|
||||||
|
"sub sp, r4, #0x1000\n\t"
|
||||||
/* attach dlls */
|
/* attach dlls */
|
||||||
"mov r0, r5\n\t" /* context */
|
"bl " __ASM_NAME("attach_thread") "\n\t"
|
||||||
"mov r1, r2\n\t" /* suspend */
|
"mov sp, r0\n\t"
|
||||||
"bl " __ASM_NAME("attach_dlls") "\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 */
|
/* switch to the initial context */
|
||||||
"mov r0, r5\n\t"
|
"mov r0, sp\n\t"
|
||||||
"b " __ASM_NAME("set_cpu_context") )
|
"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 );
|
||||||
|
@ -1258,6 +1251,46 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
|
||||||
"movne sp, r3\n\t"
|
"movne sp, r3\n\t"
|
||||||
"blx r1" )
|
"blx r1" )
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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;
|
||||||
|
attach_dlls( ctx, FALSE );
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* signal_start_thread
|
||||||
*
|
*
|
||||||
|
|
|
@ -2865,39 +2865,24 @@ __ASM_GLOBAL_FUNC( start_thread,
|
||||||
__ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
|
__ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
|
||||||
/* store exit frame */
|
/* store exit frame */
|
||||||
"movl %ebp,%fs:0x1f4\n\t" /* x86_thread_data()->exit_frame */
|
"movl %ebp,%fs:0x1f4\n\t" /* x86_thread_data()->exit_frame */
|
||||||
/* build initial context on thread stack */
|
|
||||||
"movl %fs:4,%eax\n\t" /* NtCurrentTeb()->StackBase */
|
|
||||||
"leal -0x2dc(%eax),%esi\n\t" /* sizeof(context) + 16 */
|
|
||||||
"movl $0x10007,(%esi)\n\t" /* context->ContextFlags = CONTEXT_FULL */
|
|
||||||
"movw %cs,0xbc(%esi)\n\t" /* context->SegCs */
|
|
||||||
"movw %ds,0x98(%esi)\n\t" /* context->SegDs */
|
|
||||||
"movw %es,0x94(%esi)\n\t" /* context->SegEs */
|
|
||||||
"movw %fs,0x90(%esi)\n\t" /* context->SegFs */
|
|
||||||
"movw %gs,0x8c(%esi)\n\t" /* context->SegGs */
|
|
||||||
"movw %ss,0xc8(%esi)\n\t" /* context->SegSs */
|
|
||||||
"movl 8(%ebp),%eax\n\t"
|
|
||||||
"movl %eax,0xb0(%esi)\n\t" /* context->Eax = entry */
|
|
||||||
"movl 12(%ebp),%eax\n\t"
|
|
||||||
"movl %eax,0xa4(%esi)\n\t" /* context->Ebx = arg */
|
|
||||||
"movl 20(%ebp),%eax\n\t"
|
|
||||||
"movl %eax,0xb8(%esi)\n\t" /* context->Eip = relay */
|
|
||||||
"leal 0x2cc(%esi),%eax\n\t"
|
|
||||||
"movl %eax,0xc4(%esi)\n\t" /* context->Esp */
|
|
||||||
/* switch to thread stack */
|
/* switch to thread stack */
|
||||||
"leal -12(%esi),%esp\n\t"
|
"movl %fs:4,%eax\n\t" /* NtCurrentTeb()->StackBase */
|
||||||
|
"leal -0x1000(%eax),%esp\n\t"
|
||||||
/* attach dlls */
|
/* attach dlls */
|
||||||
|
"pushl 20(%ebp)\n\t" /* relay */
|
||||||
"pushl 16(%ebp)\n\t" /* suspend */
|
"pushl 16(%ebp)\n\t" /* suspend */
|
||||||
"pushl %esi\n\t" /* context */
|
"pushl 12(%ebp)\n\t" /* arg */
|
||||||
|
"pushl 8(%ebp)\n\t" /* entry */
|
||||||
"xorl %ebp,%ebp\n\t"
|
"xorl %ebp,%ebp\n\t"
|
||||||
"call " __ASM_NAME("attach_dlls") "\n\t"
|
"call " __ASM_NAME("attach_thread") "\n\t"
|
||||||
"addl $20,%esp\n\t"
|
"movl %eax,%esi\n\t"
|
||||||
|
"leal -12(%eax),%esp\n\t"
|
||||||
/* clear the stack */
|
/* clear the stack */
|
||||||
"leal -0xd24(%esi),%eax\n\t" /* round down to page size */
|
"andl $~0xfff,%eax\n\t" /* round down to page size */
|
||||||
"pushl %eax\n\t"
|
"movl %eax,(%esp)\n\t"
|
||||||
"call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
|
"call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
|
||||||
/* switch to the initial context */
|
/* switch to the initial context */
|
||||||
"movl %esi,(%esp)\n\t"
|
"movl %esi,(%esp)\n\t"
|
||||||
"movl $0x10007,(%esi)\n\t" /* context->ContextFlags = CONTEXT_FULL */
|
|
||||||
"call " __ASM_NAME("set_cpu_context") )
|
"call " __ASM_NAME("set_cpu_context") )
|
||||||
|
|
||||||
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int) );
|
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int) );
|
||||||
|
@ -2967,6 +2952,55 @@ void DECLSPEC_HIDDEN call_thread_func( LPTHREAD_START_ROUTINE entry, void *arg )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* init_thread_context
|
||||||
|
*/
|
||||||
|
static void init_thread_context( CONTEXT *context, LPTHREAD_START_ROUTINE entry, void *arg, void *relay )
|
||||||
|
{
|
||||||
|
context->SegCs = wine_get_cs();
|
||||||
|
context->SegDs = wine_get_ds();
|
||||||
|
context->SegEs = wine_get_es();
|
||||||
|
context->SegFs = wine_get_fs();
|
||||||
|
context->SegGs = wine_get_gs();
|
||||||
|
context->SegSs = wine_get_ss();
|
||||||
|
context->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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;
|
||||||
|
attach_dlls( ctx, FALSE );
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* signal_start_thread
|
||||||
*
|
*
|
||||||
|
|
|
@ -4094,26 +4094,15 @@ __ASM_GLOBAL_FUNC( start_thread,
|
||||||
/* store exit frame */
|
/* store exit frame */
|
||||||
"movq %gs:0x30,%rax\n\t"
|
"movq %gs:0x30,%rax\n\t"
|
||||||
"movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */
|
"movq %rsp,0x330(%rax)\n\t" /* amd64_thread_data()->exit_frame */
|
||||||
/* build initial context on thread stack */
|
|
||||||
"movq 8(%rax),%r8\n\t" /* NtCurrentTeb()->Tib.StackBase */
|
|
||||||
"leaq -0x500(%r8),%r10\n\t" /* sizeof(context) + 0x30 for function params */
|
|
||||||
"movq $0x001000b,0x30(%r10)\n\t" /* context->ContextFlags = CONTEXT_FULL */
|
|
||||||
"movw %cs,0x38(%r10)\n\t" /* context->SegCs */
|
|
||||||
"movw %ss,0x42(%r10)\n\t" /* context->SegSs */
|
|
||||||
"movq %rdi,0x80(%r10)\n\t" /* context->Rcx = entry */
|
|
||||||
"movq %rsi,0x88(%r10)\n\t" /* context->Rdx = arg */
|
|
||||||
"leaq -0x28(%r8),%rax\n\t"
|
|
||||||
"movq %rax,0x98(%r10)\n\t" /* context->Rsp */
|
|
||||||
"movq %rcx,0xf8(%r10)\n\t" /* context->Rip = relay */
|
|
||||||
"fxsave 0x100(%r10)\n\t" /* context->FtlSave */
|
|
||||||
/* switch to thread stack */
|
/* switch to thread stack */
|
||||||
"movq %r10,%rsp\n\t"
|
"movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */
|
||||||
|
"leaq -0x1000(%rax),%rsp\n\t"
|
||||||
/* attach dlls */
|
/* attach dlls */
|
||||||
"movq %r10,%rdi\n\t" /* context */
|
"call " __ASM_NAME("attach_thread") "\n\t"
|
||||||
"movq %rdx,%rsi\n\t" /* suspend */
|
"movq %rax,%rsp\n\t"
|
||||||
"call " __ASM_NAME("attach_dlls") "\n\t"
|
|
||||||
/* clear the stack */
|
/* clear the stack */
|
||||||
"leaq -0xb00(%rsp),%rdi\n\t" /* round down to page size */
|
"andq $~0xfff,%rax\n\t" /* round down to page size */
|
||||||
|
"movq %rax,%rdi\n\t"
|
||||||
"call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
|
"call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
|
||||||
/* switch to the initial context */
|
/* switch to the initial context */
|
||||||
"movq %rsp,%rdi\n\t"
|
"movq %rsp,%rdi\n\t"
|
||||||
|
@ -4140,6 +4129,51 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
|
||||||
"call *%rsi" )
|
"call *%rsi" )
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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) );
|
||||||
|
__asm__( "fxsave %0" : "=m" (context->u.FltSave) );
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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;
|
||||||
|
attach_dlls( ctx, FALSE );
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal_start_thread
|
* signal_start_thread
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue