Commit a83532d8 authored by Alexandre Julliard's avatar Alexandre Julliard

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: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 3e800934
......@@ -3059,11 +3059,11 @@ static void test_SuspendProcessNewThread(void)
ret = are_imports_resolved(pi.hProcess, exe_base, &nt_header);
ok(!ret, "IAT entry resolved prematurely\n");
ctx.ContextFlags = CONTEXT_FULL;
ctx.ContextFlags = CONTEXT_ALL;
ret = GetThreadContext( thread_handle, &ctx );
ok( ret, "Failed retrieving remote thread context (%d)\n", GetLastError() );
ok( ctx.ContextFlags == CONTEXT_ALL, "wrong flags %x\n", ctx.ContextFlags );
#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.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 );
......@@ -3080,8 +3080,10 @@ static void test_SuspendProcessNewThread(void)
ok( !ctx.R14, "r14 is not zero %lx\n", ctx.R14 );
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.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
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 );
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.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 );
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
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());
/* Set up the remote process environment */
ctx.ContextFlags = CONTEXT_FULL;
ctx.ContextFlags = CONTEXT_ALL;
ret = GetThreadContext(pi.hThread, &ctx);
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);
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());
#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.Rbx, "rbx is not zero %lx\n", ctx.Rbx );
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.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.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;
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);
ok(ret, "Failed to write to remote process thread stack (%d)\n", GetLastError());
#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 );
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 */
"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;
peb_ptr = (void *)ctx.Ebx;
......
......@@ -1228,24 +1228,17 @@ __ASM_GLOBAL_FUNC( start_thread,
/* store exit frame */
"ldr r4, [sp, #40]\n\t" /* teb */
"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 */
"mov sp, r5\n\t"
"ldr r4, [r4, #4]\n\t" /* teb->Tib.StackBase */
"sub sp, r4, #0x1000\n\t"
/* attach dlls */
"mov r0, r5\n\t" /* context */
"mov r1, r2\n\t" /* suspend */
"bl " __ASM_NAME("attach_dlls") "\n\t"
"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, r5\n\t"
"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 );
......@@ -1259,6 +1252,46 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
"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
*
* Thread startup sequence:
......
......@@ -2865,39 +2865,24 @@ __ASM_GLOBAL_FUNC( start_thread,
__ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
/* store 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 */
"leal -12(%esi),%esp\n\t"
"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 %esi\n\t" /* context */
"pushl 12(%ebp)\n\t" /* arg */
"pushl 8(%ebp)\n\t" /* entry */
"xorl %ebp,%ebp\n\t"
"call " __ASM_NAME("attach_dlls") "\n\t"
"addl $20,%esp\n\t"
"call " __ASM_NAME("attach_thread") "\n\t"
"movl %eax,%esi\n\t"
"leal -12(%eax),%esp\n\t"
/* clear the stack */
"leal -0xd24(%esi),%eax\n\t" /* round down to page size */
"pushl %eax\n\t"
"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"
"movl $0x10007,(%esi)\n\t" /* context->ContextFlags = CONTEXT_FULL */
"call " __ASM_NAME("set_cpu_context") )
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int) );
......@@ -2968,6 +2953,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
*
* Thread startup sequence:
......
......@@ -4094,26 +4094,15 @@ __ASM_GLOBAL_FUNC( start_thread,
/* store exit frame */
"movq %gs:0x30,%rax\n\t"
"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 */
"movq %r10,%rsp\n\t"
"movq 8(%rax),%rax\n\t" /* NtCurrentTeb()->Tib.StackBase */
"leaq -0x1000(%rax),%rsp\n\t"
/* attach dlls */
"movq %r10,%rdi\n\t" /* context */
"movq %rdx,%rsi\n\t" /* suspend */
"call " __ASM_NAME("attach_dlls") "\n\t"
"call " __ASM_NAME("attach_thread") "\n\t"
"movq %rax,%rsp\n\t"
/* 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"
/* switch to the initial context */
"movq %rsp,%rdi\n\t"
......@@ -4141,6 +4130,51 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
/***********************************************************************
* 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
*
* Thread startup sequence:
......
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