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);
|
||||
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 );
|
||||
|
@ -1258,6 +1251,46 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
|
|||
"movne sp, r3\n\t"
|
||||
"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
|
||||
*
|
||||
|
|
|
@ -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) );
|
||||
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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"
|
||||
|
@ -4140,6 +4129,51 @@ __ASM_GLOBAL_FUNC( call_thread_exit_func,
|
|||
"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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue