ntdll: Use NtContinue() to set the thread initial context.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-06 15:41:24 +02:00
parent 7f28a1c521
commit 20c91c5e80
5 changed files with 69 additions and 115 deletions

View File

@ -3819,7 +3819,6 @@ PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
*/
void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknown3, ULONG_PTR unknown4 )
{
static const LARGE_INTEGER zero;
static int attach_done;
int i;
NTSTATUS status;
@ -3898,8 +3897,6 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknow
}
RtlLeaveCriticalSection( &loader_section );
NtDelayExecution( TRUE, &zero );
}

View File

@ -422,8 +422,9 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
"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 r1, #1\n\t"
"mov r0, sp\n\t"
"b " __ASM_NAME("set_cpu_context") )
"b " __ASM_NAME("NtContinue") )
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );

View File

@ -88,18 +88,6 @@ static inline struct arm64_thread_data *arm64_thread_data(void)
}
/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
*/
static void set_cpu_context( const CONTEXT *context )
{
InterlockedExchangePointer( (void **)&arm64_thread_data()->context, (void *)context );
raise( SIGUSR2 );
}
/***********************************************************************
* get_server_context_flags
*
@ -261,8 +249,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
NTSTATUS ret = STATUS_SUCCESS;
BOOL self = (handle == GetCurrentThread());
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_ARM64)))
self = FALSE;
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_ARM64))) self = FALSE;
if (!self)
{
@ -270,7 +257,11 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
}
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
if (self && ret == STATUS_SUCCESS)
{
InterlockedExchangePointer( (void **)&arm64_thread_data()->context, (void *)context );
raise( SIGUSR2 );
}
return ret;
}
@ -451,26 +442,8 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
"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" )
"mov x1, #1\n\t"
"b " __ASM_NAME("NtContinue") )
extern void DECLSPEC_NORETURN call_thread_exit_func( int status, void (*func)(int), TEB *teb );

View File

@ -336,46 +336,6 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
"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) 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 );
}
}
}
/***********************************************************************
* get_server_context_flags
*
@ -545,10 +505,11 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret = STATUS_SUCCESS;
DWORD flags = context->ContextFlags & ~CONTEXT_i386;
BOOL self = (handle == GetCurrentThread());
/* debug registers require a server call */
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
if (self && (flags & CONTEXT_DEBUG_REGISTERS))
self = (x86_thread_data()->dr0 == context->Dr0 &&
x86_thread_data()->dr1 == context->Dr1 &&
x86_thread_data()->dr2 == context->Dr2 &&
@ -561,9 +522,37 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
context_t server_context;
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
if (ret || !self) return ret;
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 (self && ret == STATUS_SUCCESS) set_cpu_context( context );
if (flags & CONTEXT_EXTENDED_REGISTERS) restore_fpux( context );
else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context );
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 );
}
}
return ret;
}
@ -1044,8 +1033,9 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
"movl %eax,(%esp)\n\t"
"call " __ASM_NAME("virtual_clear_thread_stack") "\n\t"
/* switch to the initial context */
"movl $1,4(%esp)\n\t"
"movl %esi,(%esp)\n\t"
"call " __ASM_NAME("set_cpu_context") )
"call " __ASM_NAME("NtContinue") )
/***********************************************************************

View File

@ -191,34 +191,6 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
"iretq" );
/***********************************************************************
* 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_AMD64;
if (flags & CONTEXT_DEBUG_REGISTERS)
{
amd64_thread_data()->dr0 = context->Dr0;
amd64_thread_data()->dr1 = context->Dr1;
amd64_thread_data()->dr2 = context->Dr2;
amd64_thread_data()->dr3 = context->Dr3;
amd64_thread_data()->dr6 = context->Dr6;
amd64_thread_data()->dr7 = context->Dr7;
}
if (flags & CONTEXT_FULL)
{
if (!(flags & CONTEXT_CONTROL))
FIXME( "setting partial context (%x) not supported\n", flags );
else
set_full_cpu_context( context );
}
}
/***********************************************************************
* get_server_context_flags
*
@ -437,10 +409,11 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret = STATUS_SUCCESS;
DWORD flags = context->ContextFlags & ~CONTEXT_AMD64;
BOOL self = (handle == GetCurrentThread());
/* debug registers require a server call */
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)))
if (self && (flags & CONTEXT_DEBUG_REGISTERS))
self = (amd64_thread_data()->dr0 == context->Dr0 &&
amd64_thread_data()->dr1 == context->Dr1 &&
amd64_thread_data()->dr2 == context->Dr2 &&
@ -451,10 +424,28 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
if (!self)
{
context_t server_context;
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
if (ret || !self) return ret;
if (flags & CONTEXT_DEBUG_REGISTERS)
{
amd64_thread_data()->dr0 = context->Dr0;
amd64_thread_data()->dr1 = context->Dr1;
amd64_thread_data()->dr2 = context->Dr2;
amd64_thread_data()->dr3 = context->Dr3;
amd64_thread_data()->dr6 = context->Dr6;
amd64_thread_data()->dr7 = context->Dr7;
}
}
if (flags & CONTEXT_FULL)
{
if (!(flags & CONTEXT_CONTROL))
FIXME( "setting partial context (%x) not supported\n", flags );
else
set_full_cpu_context( context );
}
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
}
@ -724,14 +715,16 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
"leaq -0x1000(%rax),%rsp\n\t"
/* attach dlls */
"call " __ASM_NAME("attach_thread") "\n\t"
"movq %rax,%rsp\n\t"
"movq %rax,%rbx\n\t"
"leaq -32(%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") )
"movl $1,%edx\n\t"
"movq %rbx,%rcx\n\t"
"call " __ASM_NAME("NtContinue") )
/***********************************************************************