ntdll: Use NtContinue() to set the thread initial context.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7f28a1c521
commit
20c91c5e80
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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") )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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") )
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue