ntdll: Move NtSetContextThread() implementation to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b4310a19e9
commit
ac90898f72
|
@ -62,7 +62,6 @@ extern void wait_suspend( CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context ) DECLSPEC_HIDDEN;
|
extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||||
extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) DECLSPEC_HIDDEN;
|
extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||||
extern void DECLSPEC_NORETURN raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ) DECLSPEC_HIDDEN;
|
extern void DECLSPEC_NORETURN raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
|
|
||||||
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
|
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
|
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
|
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -353,61 +353,6 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* context_to_server
|
|
||||||
*
|
|
||||||
* Convert a register context to the server format.
|
|
||||||
*/
|
|
||||||
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
|
||||||
{
|
|
||||||
DWORD i, flags = from->ContextFlags & ~CONTEXT_ARM; /* get rid of CPU id */
|
|
||||||
|
|
||||||
memset( to, 0, sizeof(*to) );
|
|
||||||
to->cpu = CPU_ARM;
|
|
||||||
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_CONTROL;
|
|
||||||
to->ctl.arm_regs.sp = from->Sp;
|
|
||||||
to->ctl.arm_regs.lr = from->Lr;
|
|
||||||
to->ctl.arm_regs.pc = from->Pc;
|
|
||||||
to->ctl.arm_regs.cpsr = from->Cpsr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_INTEGER;
|
|
||||||
to->integer.arm_regs.r[0] = from->R0;
|
|
||||||
to->integer.arm_regs.r[1] = from->R1;
|
|
||||||
to->integer.arm_regs.r[2] = from->R2;
|
|
||||||
to->integer.arm_regs.r[3] = from->R3;
|
|
||||||
to->integer.arm_regs.r[4] = from->R4;
|
|
||||||
to->integer.arm_regs.r[5] = from->R5;
|
|
||||||
to->integer.arm_regs.r[6] = from->R6;
|
|
||||||
to->integer.arm_regs.r[7] = from->R7;
|
|
||||||
to->integer.arm_regs.r[8] = from->R8;
|
|
||||||
to->integer.arm_regs.r[9] = from->R9;
|
|
||||||
to->integer.arm_regs.r[10] = from->R10;
|
|
||||||
to->integer.arm_regs.r[11] = from->R11;
|
|
||||||
to->integer.arm_regs.r[12] = from->R12;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_FLOATING_POINT;
|
|
||||||
for (i = 0; i < 32; i++) to->fp.arm_regs.d[i] = from->u.D[i];
|
|
||||||
to->fp.arm_regs.fpscr = from->Fpscr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
|
||||||
for (i = 0; i < ARM_MAX_BREAKPOINTS; i++) to->debug.arm_regs.bvr[i] = from->Bvr[i];
|
|
||||||
for (i = 0; i < ARM_MAX_BREAKPOINTS; i++) to->debug.arm_regs.bcr[i] = from->Bcr[i];
|
|
||||||
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wvr[i] = from->Wvr[i];
|
|
||||||
for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wcr[i] = from->Wcr[i];
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_from_server
|
* context_from_server
|
||||||
*
|
*
|
||||||
|
@ -462,23 +407,6 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NtSetContextThread (NTDLL.@)
|
|
||||||
* ZwSetContextThread (NTDLL.@)
|
|
||||||
*/
|
|
||||||
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
BOOL self;
|
|
||||||
context_t server_context;
|
|
||||||
|
|
||||||
context_to_server( &server_context, context );
|
|
||||||
ret = set_thread_context( handle, &server_context, &self );
|
|
||||||
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
|
|
@ -360,55 +360,6 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* context_to_server
|
|
||||||
*
|
|
||||||
* Convert a register context to the server format.
|
|
||||||
*/
|
|
||||||
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
|
||||||
{
|
|
||||||
DWORD i, flags = from->ContextFlags & ~CONTEXT_ARM64; /* get rid of CPU id */
|
|
||||||
|
|
||||||
memset( to, 0, sizeof(*to) );
|
|
||||||
to->cpu = CPU_ARM64;
|
|
||||||
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_CONTROL;
|
|
||||||
to->integer.arm64_regs.x[29] = from->u.s.Fp;
|
|
||||||
to->integer.arm64_regs.x[30] = from->u.s.Lr;
|
|
||||||
to->ctl.arm64_regs.sp = from->Sp;
|
|
||||||
to->ctl.arm64_regs.pc = from->Pc;
|
|
||||||
to->ctl.arm64_regs.pstate = from->Cpsr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_INTEGER;
|
|
||||||
for (i = 0; i <= 28; i++) to->integer.arm64_regs.x[i] = from->u.X[i];
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_FLOATING_POINT;
|
|
||||||
for (i = 0; i < 32; i++)
|
|
||||||
{
|
|
||||||
to->fp.arm64_regs.q[i].low = from->V[i].s.Low;
|
|
||||||
to->fp.arm64_regs.q[i].high = from->V[i].s.High;
|
|
||||||
}
|
|
||||||
to->fp.arm64_regs.fpcr = from->Fpcr;
|
|
||||||
to->fp.arm64_regs.fpsr = from->Fpsr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
|
||||||
for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) to->debug.arm64_regs.bcr[i] = from->Bcr[i];
|
|
||||||
for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) to->debug.arm64_regs.bvr[i] = from->Bvr[i];
|
|
||||||
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wcr[i] = from->Wcr[i];
|
|
||||||
for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wvr[i] = from->Wvr[i];
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_from_server
|
* context_from_server
|
||||||
*
|
*
|
||||||
|
@ -457,29 +408,6 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NtSetContextThread (NTDLL.@)
|
|
||||||
* ZwSetContextThread (NTDLL.@)
|
|
||||||
*/
|
|
||||||
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_t server_context;
|
|
||||||
context_to_server( &server_context, context );
|
|
||||||
ret = set_thread_context( handle, &server_context, &self );
|
|
||||||
}
|
|
||||||
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
|
|
@ -1271,78 +1271,6 @@ static unsigned int get_server_context_flags( DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* context_to_server
|
|
||||||
*
|
|
||||||
* Convert a register context to the server format.
|
|
||||||
*/
|
|
||||||
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
|
||||||
{
|
|
||||||
DWORD flags = from->ContextFlags & ~CONTEXT_i386; /* get rid of CPU id */
|
|
||||||
|
|
||||||
memset( to, 0, sizeof(*to) );
|
|
||||||
to->cpu = CPU_x86;
|
|
||||||
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_CONTROL;
|
|
||||||
to->ctl.i386_regs.ebp = from->Ebp;
|
|
||||||
to->ctl.i386_regs.esp = from->Esp;
|
|
||||||
to->ctl.i386_regs.eip = from->Eip;
|
|
||||||
to->ctl.i386_regs.cs = from->SegCs;
|
|
||||||
to->ctl.i386_regs.ss = from->SegSs;
|
|
||||||
to->ctl.i386_regs.eflags = from->EFlags;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_INTEGER;
|
|
||||||
to->integer.i386_regs.eax = from->Eax;
|
|
||||||
to->integer.i386_regs.ebx = from->Ebx;
|
|
||||||
to->integer.i386_regs.ecx = from->Ecx;
|
|
||||||
to->integer.i386_regs.edx = from->Edx;
|
|
||||||
to->integer.i386_regs.esi = from->Esi;
|
|
||||||
to->integer.i386_regs.edi = from->Edi;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_SEGMENTS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_SEGMENTS;
|
|
||||||
to->seg.i386_regs.ds = from->SegDs;
|
|
||||||
to->seg.i386_regs.es = from->SegEs;
|
|
||||||
to->seg.i386_regs.fs = from->SegFs;
|
|
||||||
to->seg.i386_regs.gs = from->SegGs;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_FLOATING_POINT;
|
|
||||||
to->fp.i386_regs.ctrl = from->FloatSave.ControlWord;
|
|
||||||
to->fp.i386_regs.status = from->FloatSave.StatusWord;
|
|
||||||
to->fp.i386_regs.tag = from->FloatSave.TagWord;
|
|
||||||
to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset;
|
|
||||||
to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector;
|
|
||||||
to->fp.i386_regs.data_off = from->FloatSave.DataOffset;
|
|
||||||
to->fp.i386_regs.data_sel = from->FloatSave.DataSelector;
|
|
||||||
to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState;
|
|
||||||
memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) );
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
|
||||||
to->debug.i386_regs.dr0 = from->Dr0;
|
|
||||||
to->debug.i386_regs.dr1 = from->Dr1;
|
|
||||||
to->debug.i386_regs.dr2 = from->Dr2;
|
|
||||||
to->debug.i386_regs.dr3 = from->Dr3;
|
|
||||||
to->debug.i386_regs.dr6 = from->Dr6;
|
|
||||||
to->debug.i386_regs.dr7 = from->Dr7;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_EXTENDED_REGISTERS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
|
|
||||||
memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_from_server
|
* context_from_server
|
||||||
*
|
*
|
||||||
|
@ -1413,36 +1341,6 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NtSetContextThread (NTDLL.@)
|
|
||||||
* ZwSetContextThread (NTDLL.@)
|
|
||||||
*/
|
|
||||||
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
|
||||||
BOOL self = (handle == GetCurrentThread());
|
|
||||||
|
|
||||||
/* debug registers require a server call */
|
|
||||||
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
|
|
||||||
self = (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)
|
|
||||||
{
|
|
||||||
context_t server_context;
|
|
||||||
context_to_server( &server_context, context );
|
|
||||||
ret = set_thread_context( handle, &server_context, &self );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
|
|
@ -260,17 +260,6 @@ void WINAPI RtlCaptureContext( CONTEXT *context )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* set_cpu_context
|
|
||||||
*
|
|
||||||
* Set the new CPU context.
|
|
||||||
*/
|
|
||||||
static void set_cpu_context( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
FIXME("not implemented\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* get_server_context_flags
|
* get_server_context_flags
|
||||||
*
|
*
|
||||||
|
@ -381,108 +370,6 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* context_to_server
|
|
||||||
*
|
|
||||||
* Convert a register context to the server format.
|
|
||||||
*/
|
|
||||||
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
|
||||||
{
|
|
||||||
DWORD flags = from->ContextFlags; /* no CPU id? */
|
|
||||||
|
|
||||||
memset( to, 0, sizeof(*to) );
|
|
||||||
to->cpu = CPU_POWERPC;
|
|
||||||
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_CONTROL;
|
|
||||||
to->ctl.powerpc_regs.iar = from->Iar;
|
|
||||||
to->ctl.powerpc_regs.msr = from->Msr;
|
|
||||||
to->ctl.powerpc_regs.ctr = from->Ctr;
|
|
||||||
to->ctl.powerpc_regs.lr = from->Lr;
|
|
||||||
to->ctl.powerpc_regs.dar = from->Dar;
|
|
||||||
to->ctl.powerpc_regs.dsisr = from->Dsisr;
|
|
||||||
to->ctl.powerpc_regs.trap = from->Trap;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_INTEGER;
|
|
||||||
to->integer.powerpc_regs.gpr[0] = from->Gpr0;
|
|
||||||
to->integer.powerpc_regs.gpr[1] = from->Gpr1;
|
|
||||||
to->integer.powerpc_regs.gpr[2] = from->Gpr2;
|
|
||||||
to->integer.powerpc_regs.gpr[3] = from->Gpr3;
|
|
||||||
to->integer.powerpc_regs.gpr[4] = from->Gpr4;
|
|
||||||
to->integer.powerpc_regs.gpr[5] = from->Gpr5;
|
|
||||||
to->integer.powerpc_regs.gpr[6] = from->Gpr6;
|
|
||||||
to->integer.powerpc_regs.gpr[7] = from->Gpr7;
|
|
||||||
to->integer.powerpc_regs.gpr[8] = from->Gpr8;
|
|
||||||
to->integer.powerpc_regs.gpr[9] = from->Gpr9;
|
|
||||||
to->integer.powerpc_regs.gpr[10] = from->Gpr10;
|
|
||||||
to->integer.powerpc_regs.gpr[11] = from->Gpr11;
|
|
||||||
to->integer.powerpc_regs.gpr[12] = from->Gpr12;
|
|
||||||
to->integer.powerpc_regs.gpr[13] = from->Gpr13;
|
|
||||||
to->integer.powerpc_regs.gpr[14] = from->Gpr14;
|
|
||||||
to->integer.powerpc_regs.gpr[15] = from->Gpr15;
|
|
||||||
to->integer.powerpc_regs.gpr[16] = from->Gpr16;
|
|
||||||
to->integer.powerpc_regs.gpr[17] = from->Gpr17;
|
|
||||||
to->integer.powerpc_regs.gpr[18] = from->Gpr18;
|
|
||||||
to->integer.powerpc_regs.gpr[19] = from->Gpr19;
|
|
||||||
to->integer.powerpc_regs.gpr[20] = from->Gpr20;
|
|
||||||
to->integer.powerpc_regs.gpr[21] = from->Gpr21;
|
|
||||||
to->integer.powerpc_regs.gpr[22] = from->Gpr22;
|
|
||||||
to->integer.powerpc_regs.gpr[23] = from->Gpr23;
|
|
||||||
to->integer.powerpc_regs.gpr[24] = from->Gpr24;
|
|
||||||
to->integer.powerpc_regs.gpr[25] = from->Gpr25;
|
|
||||||
to->integer.powerpc_regs.gpr[26] = from->Gpr26;
|
|
||||||
to->integer.powerpc_regs.gpr[27] = from->Gpr27;
|
|
||||||
to->integer.powerpc_regs.gpr[28] = from->Gpr28;
|
|
||||||
to->integer.powerpc_regs.gpr[29] = from->Gpr29;
|
|
||||||
to->integer.powerpc_regs.gpr[30] = from->Gpr30;
|
|
||||||
to->integer.powerpc_regs.gpr[31] = from->Gpr31;
|
|
||||||
to->integer.powerpc_regs.xer = from->Xer;
|
|
||||||
to->integer.powerpc_regs.cr = from->Cr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_FLOATING_POINT;
|
|
||||||
to->fp.powerpc_regs.fpr[0] = from->Fpr0;
|
|
||||||
to->fp.powerpc_regs.fpr[1] = from->Fpr1;
|
|
||||||
to->fp.powerpc_regs.fpr[2] = from->Fpr2;
|
|
||||||
to->fp.powerpc_regs.fpr[3] = from->Fpr3;
|
|
||||||
to->fp.powerpc_regs.fpr[4] = from->Fpr4;
|
|
||||||
to->fp.powerpc_regs.fpr[5] = from->Fpr5;
|
|
||||||
to->fp.powerpc_regs.fpr[6] = from->Fpr6;
|
|
||||||
to->fp.powerpc_regs.fpr[7] = from->Fpr7;
|
|
||||||
to->fp.powerpc_regs.fpr[8] = from->Fpr8;
|
|
||||||
to->fp.powerpc_regs.fpr[9] = from->Fpr9;
|
|
||||||
to->fp.powerpc_regs.fpr[10] = from->Fpr10;
|
|
||||||
to->fp.powerpc_regs.fpr[11] = from->Fpr11;
|
|
||||||
to->fp.powerpc_regs.fpr[12] = from->Fpr12;
|
|
||||||
to->fp.powerpc_regs.fpr[13] = from->Fpr13;
|
|
||||||
to->fp.powerpc_regs.fpr[14] = from->Fpr14;
|
|
||||||
to->fp.powerpc_regs.fpr[15] = from->Fpr15;
|
|
||||||
to->fp.powerpc_regs.fpr[16] = from->Fpr16;
|
|
||||||
to->fp.powerpc_regs.fpr[17] = from->Fpr17;
|
|
||||||
to->fp.powerpc_regs.fpr[18] = from->Fpr18;
|
|
||||||
to->fp.powerpc_regs.fpr[19] = from->Fpr19;
|
|
||||||
to->fp.powerpc_regs.fpr[20] = from->Fpr20;
|
|
||||||
to->fp.powerpc_regs.fpr[21] = from->Fpr21;
|
|
||||||
to->fp.powerpc_regs.fpr[22] = from->Fpr22;
|
|
||||||
to->fp.powerpc_regs.fpr[23] = from->Fpr23;
|
|
||||||
to->fp.powerpc_regs.fpr[24] = from->Fpr24;
|
|
||||||
to->fp.powerpc_regs.fpr[25] = from->Fpr25;
|
|
||||||
to->fp.powerpc_regs.fpr[26] = from->Fpr26;
|
|
||||||
to->fp.powerpc_regs.fpr[27] = from->Fpr27;
|
|
||||||
to->fp.powerpc_regs.fpr[28] = from->Fpr28;
|
|
||||||
to->fp.powerpc_regs.fpr[29] = from->Fpr29;
|
|
||||||
to->fp.powerpc_regs.fpr[30] = from->Fpr30;
|
|
||||||
to->fp.powerpc_regs.fpr[31] = from->Fpr31;
|
|
||||||
to->fp.powerpc_regs.fpscr = from->Fpscr;
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_from_server
|
* context_from_server
|
||||||
*
|
*
|
||||||
|
@ -583,23 +470,6 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NtSetContextThread (NTDLL.@)
|
|
||||||
* ZwSetContextThread (NTDLL.@)
|
|
||||||
*/
|
|
||||||
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
NTSTATUS ret;
|
|
||||||
BOOL self;
|
|
||||||
context_t server_context;
|
|
||||||
|
|
||||||
context_to_server( &server_context, context );
|
|
||||||
ret = set_thread_context( handle, &server_context, &self );
|
|
||||||
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
|
|
@ -1966,73 +1966,6 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* context_to_server
|
|
||||||
*
|
|
||||||
* Convert a register context to the server format.
|
|
||||||
*/
|
|
||||||
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
|
||||||
{
|
|
||||||
DWORD flags = from->ContextFlags & ~CONTEXT_AMD64; /* get rid of CPU id */
|
|
||||||
|
|
||||||
memset( to, 0, sizeof(*to) );
|
|
||||||
to->cpu = CPU_x86_64;
|
|
||||||
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_CONTROL;
|
|
||||||
to->ctl.x86_64_regs.rbp = from->Rbp;
|
|
||||||
to->ctl.x86_64_regs.rip = from->Rip;
|
|
||||||
to->ctl.x86_64_regs.rsp = from->Rsp;
|
|
||||||
to->ctl.x86_64_regs.cs = from->SegCs;
|
|
||||||
to->ctl.x86_64_regs.ss = from->SegSs;
|
|
||||||
to->ctl.x86_64_regs.flags = from->EFlags;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_INTEGER;
|
|
||||||
to->integer.x86_64_regs.rax = from->Rax;
|
|
||||||
to->integer.x86_64_regs.rcx = from->Rcx;
|
|
||||||
to->integer.x86_64_regs.rdx = from->Rdx;
|
|
||||||
to->integer.x86_64_regs.rbx = from->Rbx;
|
|
||||||
to->integer.x86_64_regs.rsi = from->Rsi;
|
|
||||||
to->integer.x86_64_regs.rdi = from->Rdi;
|
|
||||||
to->integer.x86_64_regs.r8 = from->R8;
|
|
||||||
to->integer.x86_64_regs.r9 = from->R9;
|
|
||||||
to->integer.x86_64_regs.r10 = from->R10;
|
|
||||||
to->integer.x86_64_regs.r11 = from->R11;
|
|
||||||
to->integer.x86_64_regs.r12 = from->R12;
|
|
||||||
to->integer.x86_64_regs.r13 = from->R13;
|
|
||||||
to->integer.x86_64_regs.r14 = from->R14;
|
|
||||||
to->integer.x86_64_regs.r15 = from->R15;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_SEGMENTS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_SEGMENTS;
|
|
||||||
to->seg.x86_64_regs.ds = from->SegDs;
|
|
||||||
to->seg.x86_64_regs.es = from->SegEs;
|
|
||||||
to->seg.x86_64_regs.fs = from->SegFs;
|
|
||||||
to->seg.x86_64_regs.gs = from->SegGs;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_FLOATING_POINT;
|
|
||||||
memcpy( to->fp.x86_64_regs.fpregs, &from->u.FltSave, sizeof(to->fp.x86_64_regs.fpregs) );
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_DEBUG_REGISTERS)
|
|
||||||
{
|
|
||||||
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
|
||||||
to->debug.x86_64_regs.dr0 = from->Dr0;
|
|
||||||
to->debug.x86_64_regs.dr1 = from->Dr1;
|
|
||||||
to->debug.x86_64_regs.dr2 = from->Dr2;
|
|
||||||
to->debug.x86_64_regs.dr3 = from->Dr3;
|
|
||||||
to->debug.x86_64_regs.dr6 = from->Dr6;
|
|
||||||
to->debug.x86_64_regs.dr7 = from->Dr7;
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_from_server
|
* context_from_server
|
||||||
*
|
*
|
||||||
|
@ -2100,35 +2033,6 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* NtSetContextThread (NTDLL.@)
|
|
||||||
* ZwSetContextThread (NTDLL.@)
|
|
||||||
*/
|
|
||||||
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
NTSTATUS ret = STATUS_SUCCESS;
|
|
||||||
BOOL self = (handle == GetCurrentThread());
|
|
||||||
|
|
||||||
/* debug registers require a server call */
|
|
||||||
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)))
|
|
||||||
self = (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 (!self)
|
|
||||||
{
|
|
||||||
context_t server_context;
|
|
||||||
context_to_server( &server_context, context );
|
|
||||||
ret = set_thread_context( handle, &server_context, &self );
|
|
||||||
}
|
|
||||||
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
|
|
@ -767,6 +767,16 @@ NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int fla
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
{
|
||||||
|
return unix_funcs->NtSetContextThread( handle, context );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtSetLdtEntries (NTDLL.@)
|
* NtSetLdtEntries (NTDLL.@)
|
||||||
* ZwSetLdtEntries (NTDLL.@)
|
* ZwSetLdtEntries (NTDLL.@)
|
||||||
|
|
|
@ -986,6 +986,7 @@ static struct unix_funcs unix_funcs =
|
||||||
NtClose,
|
NtClose,
|
||||||
NtCurrentTeb,
|
NtCurrentTeb,
|
||||||
NtDuplicateObject,
|
NtDuplicateObject,
|
||||||
|
NtSetContextThread,
|
||||||
NtSetLdtEntries,
|
NtSetLdtEntries,
|
||||||
get_main_args,
|
get_main_args,
|
||||||
get_paths,
|
get_paths,
|
||||||
|
|
|
@ -69,6 +69,27 @@
|
||||||
static pthread_key_t teb_key;
|
static pthread_key_t teb_key;
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* set_cpu_context
|
||||||
|
*
|
||||||
|
* Set the new CPU context.
|
||||||
|
*/
|
||||||
|
void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context );
|
||||||
|
__ASM_GLOBAL_FUNC( set_cpu_context,
|
||||||
|
".arm\n\t"
|
||||||
|
"ldr r2, [r0, #0x44]\n\t" /* context->Cpsr */
|
||||||
|
"tst r2, #0x20\n\t" /* thumb? */
|
||||||
|
"ldr r1, [r0, #0x40]\n\t" /* context->Pc */
|
||||||
|
"orrne r1, r1, #1\n\t" /* Adjust PC according to thumb */
|
||||||
|
"biceq r1, r1, #1\n\t" /* Adjust PC according to arm */
|
||||||
|
"msr CPSR_f, r2\n\t"
|
||||||
|
"ldr lr, [r0, #0x3c]\n\t" /* context->Lr */
|
||||||
|
"ldr sp, [r0, #0x38]\n\t" /* context->Sp */
|
||||||
|
"push {r1}\n\t"
|
||||||
|
"ldmib r0, {r0-r12}\n\t" /* context->R0..R12 */
|
||||||
|
"pop {pc}" )
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_to_server
|
* context_to_server
|
||||||
*
|
*
|
||||||
|
@ -179,6 +200,23 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
BOOL self;
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
ret = set_thread_context( handle, &server_context, &self );
|
||||||
|
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_thread_ldt_entry
|
* get_thread_ldt_entry
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,6 +73,31 @@ static pthread_key_t teb_key;
|
||||||
|
|
||||||
static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
|
static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
|
||||||
|
|
||||||
|
struct arm64_thread_data
|
||||||
|
{
|
||||||
|
void *exit_frame; /* exit frame pointer */
|
||||||
|
CONTEXT *context; /* context to set with SIGUSR2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
C_ASSERT( sizeof(struct arm64_thread_data) <= sizeof(((TEB *)0)->SystemReserved2) );
|
||||||
|
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct arm64_thread_data, exit_frame ) == 0x300 );
|
||||||
|
|
||||||
|
static inline struct arm64_thread_data *arm64_thread_data(void)
|
||||||
|
{
|
||||||
|
return (struct arm64_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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 );
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_to_server
|
* context_to_server
|
||||||
|
@ -172,6 +197,29 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
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_t server_context;
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
ret = set_thread_context( handle, &server_context, &self );
|
||||||
|
}
|
||||||
|
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_thread_ldt_entry
|
* get_thread_ldt_entry
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -61,6 +61,34 @@
|
||||||
#include "unix_private.h"
|
#include "unix_private.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||||
|
|
||||||
|
/* not defined for x86, so copy the x86_64 definition */
|
||||||
|
typedef struct DECLSPEC_ALIGN(16) _M128A
|
||||||
|
{
|
||||||
|
ULONGLONG Low;
|
||||||
|
LONGLONG High;
|
||||||
|
} M128A;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORD ControlWord;
|
||||||
|
WORD StatusWord;
|
||||||
|
BYTE TagWord;
|
||||||
|
BYTE Reserved1;
|
||||||
|
WORD ErrorOpcode;
|
||||||
|
DWORD ErrorOffset;
|
||||||
|
WORD ErrorSelector;
|
||||||
|
WORD Reserved2;
|
||||||
|
DWORD DataOffset;
|
||||||
|
WORD DataSelector;
|
||||||
|
WORD Reserved3;
|
||||||
|
DWORD MxCsr;
|
||||||
|
DWORD MxCsr_Mask;
|
||||||
|
M128A FloatRegisters[8];
|
||||||
|
M128A XmmRegisters[16];
|
||||||
|
BYTE Reserved4[96];
|
||||||
|
} XMM_SAVE_AREA32;
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal context platform-specific definitions
|
* signal context platform-specific definitions
|
||||||
|
@ -152,6 +180,11 @@ struct x86_thread_data
|
||||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||||
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
|
||||||
|
|
||||||
|
static inline struct x86_thread_data *x86_thread_data(void)
|
||||||
|
{
|
||||||
|
return (struct x86_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||||
|
}
|
||||||
|
|
||||||
static inline WORD get_cs(void) { WORD res; __asm__( "movw %%cs,%0" : "=r" (res) ); return res; }
|
static inline WORD get_cs(void) { WORD res; __asm__( "movw %%cs,%0" : "=r" (res) ); return res; }
|
||||||
static inline WORD get_ds(void) { WORD res; __asm__( "movw %%ds,%0" : "=r" (res) ); return res; }
|
static inline WORD get_ds(void) { WORD res; __asm__( "movw %%ds,%0" : "=r" (res) ); return res; }
|
||||||
static inline WORD get_fs(void) { WORD res; __asm__( "movw %%fs,%0" : "=r" (res) ); return res; }
|
static inline WORD get_fs(void) { WORD res; __asm__( "movw %%fs,%0" : "=r" (res) ); return res; }
|
||||||
|
@ -168,6 +201,134 @@ static inline int is_gdt_sel( WORD sel )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* restore_fpu
|
||||||
|
*
|
||||||
|
* Restore the FPU context to a sigcontext.
|
||||||
|
*/
|
||||||
|
static inline void restore_fpu( const CONTEXT *context )
|
||||||
|
{
|
||||||
|
FLOATING_SAVE_AREA float_status = context->FloatSave;
|
||||||
|
/* reset the current interrupt status */
|
||||||
|
float_status.StatusWord &= float_status.ControlWord | 0xffffff80;
|
||||||
|
__asm__ __volatile__( "frstor %0; fwait" : : "m" (float_status) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* restore_fpux
|
||||||
|
*
|
||||||
|
* Restore the FPU extended context to a sigcontext.
|
||||||
|
*/
|
||||||
|
static inline void restore_fpux( const CONTEXT *context )
|
||||||
|
{
|
||||||
|
/* we have to enforce alignment by hand */
|
||||||
|
char buffer[sizeof(XMM_SAVE_AREA32) + 16];
|
||||||
|
XMM_SAVE_AREA32 *state = (XMM_SAVE_AREA32 *)(((ULONG_PTR)buffer + 15) & ~15);
|
||||||
|
|
||||||
|
memcpy( state, context->ExtendedRegisters, sizeof(*state) );
|
||||||
|
/* reset the current interrupt status */
|
||||||
|
state->StatusWord &= state->ControlWord | 0xff80;
|
||||||
|
__asm__ __volatile__( "fxrstor %0" : : "m" (*state) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* set_full_cpu_context
|
||||||
|
*
|
||||||
|
* Set the new CPU context.
|
||||||
|
*/
|
||||||
|
extern void set_full_cpu_context( const CONTEXT *context );
|
||||||
|
__ASM_GLOBAL_FUNC( set_full_cpu_context,
|
||||||
|
"movl 4(%esp),%ecx\n\t"
|
||||||
|
"movw 0x8c(%ecx),%gs\n\t" /* SegGs */
|
||||||
|
"movw 0x90(%ecx),%fs\n\t" /* SegFs */
|
||||||
|
"movw 0x94(%ecx),%es\n\t" /* SegEs */
|
||||||
|
"movl 0x9c(%ecx),%edi\n\t" /* Edi */
|
||||||
|
"movl 0xa0(%ecx),%esi\n\t" /* Esi */
|
||||||
|
"movl 0xa4(%ecx),%ebx\n\t" /* Ebx */
|
||||||
|
"movl 0xb4(%ecx),%ebp\n\t" /* Ebp */
|
||||||
|
"movw %ss,%ax\n\t"
|
||||||
|
"cmpw 0xc8(%ecx),%ax\n\t" /* SegSs */
|
||||||
|
"jne 1f\n\t"
|
||||||
|
/* As soon as we have switched stacks the context structure could
|
||||||
|
* be invalid (when signal handlers are executed for example). Copy
|
||||||
|
* values on the target stack before changing ESP. */
|
||||||
|
"movl 0xc4(%ecx),%eax\n\t" /* Esp */
|
||||||
|
"leal -4*4(%eax),%eax\n\t"
|
||||||
|
"movl 0xc0(%ecx),%edx\n\t" /* EFlags */
|
||||||
|
"movl %edx,3*4(%eax)\n\t"
|
||||||
|
"movl 0xbc(%ecx),%edx\n\t" /* SegCs */
|
||||||
|
"movl %edx,2*4(%eax)\n\t"
|
||||||
|
"movl 0xb8(%ecx),%edx\n\t" /* Eip */
|
||||||
|
"movl %edx,1*4(%eax)\n\t"
|
||||||
|
"movl 0xb0(%ecx),%edx\n\t" /* Eax */
|
||||||
|
"movl %edx,0*4(%eax)\n\t"
|
||||||
|
"pushl 0x98(%ecx)\n\t" /* SegDs */
|
||||||
|
"movl 0xa8(%ecx),%edx\n\t" /* Edx */
|
||||||
|
"movl 0xac(%ecx),%ecx\n\t" /* Ecx */
|
||||||
|
"popl %ds\n\t"
|
||||||
|
"movl %eax,%esp\n\t"
|
||||||
|
"popl %eax\n\t"
|
||||||
|
"iret\n"
|
||||||
|
/* Restore the context when the stack segment changes. We can't use
|
||||||
|
* the same code as above because we do not know if the stack segment
|
||||||
|
* is 16 or 32 bit, and 'movl' will throw an exception when we try to
|
||||||
|
* access memory above the limit. */
|
||||||
|
"1:\n\t"
|
||||||
|
"movl 0xa8(%ecx),%edx\n\t" /* Edx */
|
||||||
|
"movl 0xb0(%ecx),%eax\n\t" /* Eax */
|
||||||
|
"movw 0xc8(%ecx),%ss\n\t" /* SegSs */
|
||||||
|
"movl 0xc4(%ecx),%esp\n\t" /* Esp */
|
||||||
|
"pushl 0xc0(%ecx)\n\t" /* EFlags */
|
||||||
|
"pushl 0xbc(%ecx)\n\t" /* SegCs */
|
||||||
|
"pushl 0xb8(%ecx)\n\t" /* Eip */
|
||||||
|
"pushl 0x98(%ecx)\n\t" /* SegDs */
|
||||||
|
"movl 0xac(%ecx),%ecx\n\t" /* Ecx */
|
||||||
|
"popl %ds\n\t"
|
||||||
|
"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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_to_server
|
* context_to_server
|
||||||
*
|
*
|
||||||
|
@ -310,6 +471,36 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
{
|
||||||
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
BOOL self = (handle == GetCurrentThread());
|
||||||
|
|
||||||
|
/* debug registers require a server call */
|
||||||
|
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
|
||||||
|
self = (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)
|
||||||
|
{
|
||||||
|
context_t server_context;
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
ret = set_thread_context( handle, &server_context, &self );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* LDT support
|
* LDT support
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -66,6 +66,17 @@
|
||||||
static pthread_key_t teb_key;
|
static pthread_key_t teb_key;
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* set_cpu_context
|
||||||
|
*
|
||||||
|
* Set the new CPU context.
|
||||||
|
*/
|
||||||
|
static void set_cpu_context( const CONTEXT *context )
|
||||||
|
{
|
||||||
|
FIXME("not implemented\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_to_server
|
* context_to_server
|
||||||
*
|
*
|
||||||
|
@ -268,6 +279,23 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
BOOL self;
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
ret = set_thread_context( handle, &server_context, &self );
|
||||||
|
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_thread_ldt_entry
|
* get_thread_ldt_entry
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -76,6 +76,8 @@
|
||||||
#include "unix_private.h"
|
#include "unix_private.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* signal context platform-specific definitions
|
* signal context platform-specific definitions
|
||||||
*/
|
*/
|
||||||
|
@ -112,6 +114,110 @@ enum i386_trap_code
|
||||||
|
|
||||||
static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
|
static const size_t teb_size = 0x2000; /* we reserve two pages for the TEB */
|
||||||
|
|
||||||
|
struct amd64_thread_data
|
||||||
|
{
|
||||||
|
DWORD_PTR dr0; /* debug registers */
|
||||||
|
DWORD_PTR dr1;
|
||||||
|
DWORD_PTR dr2;
|
||||||
|
DWORD_PTR dr3;
|
||||||
|
DWORD_PTR dr6;
|
||||||
|
DWORD_PTR dr7;
|
||||||
|
void *exit_frame; /* exit frame pointer */
|
||||||
|
};
|
||||||
|
|
||||||
|
C_ASSERT( sizeof(struct amd64_thread_data) <= sizeof(((TEB *)0)->SystemReserved2) );
|
||||||
|
C_ASSERT( offsetof( TEB, SystemReserved2 ) + offsetof( struct amd64_thread_data, exit_frame ) == 0x330 );
|
||||||
|
|
||||||
|
static inline struct amd64_thread_data *amd64_thread_data(void)
|
||||||
|
{
|
||||||
|
return (struct amd64_thread_data *)NtCurrentTeb()->SystemReserved2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* set_full_cpu_context
|
||||||
|
*
|
||||||
|
* Set the new CPU context.
|
||||||
|
*/
|
||||||
|
extern void set_full_cpu_context( const CONTEXT *context );
|
||||||
|
__ASM_GLOBAL_FUNC( set_full_cpu_context,
|
||||||
|
"subq $40,%rsp\n\t"
|
||||||
|
__ASM_SEH(".seh_stackalloc 0x40\n\t")
|
||||||
|
__ASM_SEH(".seh_endprologue\n\t")
|
||||||
|
__ASM_CFI(".cfi_adjust_cfa_offset 40\n\t")
|
||||||
|
"ldmxcsr 0x34(%rdi)\n\t" /* context->MxCsr */
|
||||||
|
"movw 0x38(%rdi),%ax\n\t" /* context->SegCs */
|
||||||
|
"movq %rax,8(%rsp)\n\t"
|
||||||
|
"movw 0x42(%rdi),%ax\n\t" /* context->SegSs */
|
||||||
|
"movq %rax,32(%rsp)\n\t"
|
||||||
|
"movq 0x44(%rdi),%rax\n\t" /* context->Eflags */
|
||||||
|
"movq %rax,16(%rsp)\n\t"
|
||||||
|
"movq 0x80(%rdi),%rcx\n\t" /* context->Rcx */
|
||||||
|
"movq 0x88(%rdi),%rdx\n\t" /* context->Rdx */
|
||||||
|
"movq 0x90(%rdi),%rbx\n\t" /* context->Rbx */
|
||||||
|
"movq 0x98(%rdi),%rax\n\t" /* context->Rsp */
|
||||||
|
"movq %rax,24(%rsp)\n\t"
|
||||||
|
"movq 0xa0(%rdi),%rbp\n\t" /* context->Rbp */
|
||||||
|
"movq 0xa8(%rdi),%rsi\n\t" /* context->Rsi */
|
||||||
|
"movq 0xb8(%rdi),%r8\n\t" /* context->R8 */
|
||||||
|
"movq 0xc0(%rdi),%r9\n\t" /* context->R9 */
|
||||||
|
"movq 0xc8(%rdi),%r10\n\t" /* context->R10 */
|
||||||
|
"movq 0xd0(%rdi),%r11\n\t" /* context->R11 */
|
||||||
|
"movq 0xd8(%rdi),%r12\n\t" /* context->R12 */
|
||||||
|
"movq 0xe0(%rdi),%r13\n\t" /* context->R13 */
|
||||||
|
"movq 0xe8(%rdi),%r14\n\t" /* context->R14 */
|
||||||
|
"movq 0xf0(%rdi),%r15\n\t" /* context->R15 */
|
||||||
|
"movq 0xf8(%rdi),%rax\n\t" /* context->Rip */
|
||||||
|
"movq %rax,(%rsp)\n\t"
|
||||||
|
"fxrstor 0x100(%rdi)\n\t" /* context->FtlSave */
|
||||||
|
"movdqa 0x1a0(%rdi),%xmm0\n\t" /* context->Xmm0 */
|
||||||
|
"movdqa 0x1b0(%rdi),%xmm1\n\t" /* context->Xmm1 */
|
||||||
|
"movdqa 0x1c0(%rdi),%xmm2\n\t" /* context->Xmm2 */
|
||||||
|
"movdqa 0x1d0(%rdi),%xmm3\n\t" /* context->Xmm3 */
|
||||||
|
"movdqa 0x1e0(%rdi),%xmm4\n\t" /* context->Xmm4 */
|
||||||
|
"movdqa 0x1f0(%rdi),%xmm5\n\t" /* context->Xmm5 */
|
||||||
|
"movdqa 0x200(%rdi),%xmm6\n\t" /* context->Xmm6 */
|
||||||
|
"movdqa 0x210(%rdi),%xmm7\n\t" /* context->Xmm7 */
|
||||||
|
"movdqa 0x220(%rdi),%xmm8\n\t" /* context->Xmm8 */
|
||||||
|
"movdqa 0x230(%rdi),%xmm9\n\t" /* context->Xmm9 */
|
||||||
|
"movdqa 0x240(%rdi),%xmm10\n\t" /* context->Xmm10 */
|
||||||
|
"movdqa 0x250(%rdi),%xmm11\n\t" /* context->Xmm11 */
|
||||||
|
"movdqa 0x260(%rdi),%xmm12\n\t" /* context->Xmm12 */
|
||||||
|
"movdqa 0x270(%rdi),%xmm13\n\t" /* context->Xmm13 */
|
||||||
|
"movdqa 0x280(%rdi),%xmm14\n\t" /* context->Xmm14 */
|
||||||
|
"movdqa 0x290(%rdi),%xmm15\n\t" /* context->Xmm15 */
|
||||||
|
"movq 0x78(%rdi),%rax\n\t" /* context->Rax */
|
||||||
|
"movq 0xb0(%rdi),%rdi\n\t" /* context->Rdi */
|
||||||
|
"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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* context_to_server
|
* context_to_server
|
||||||
|
@ -247,6 +353,35 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* NtSetContextThread (NTDLL.@)
|
||||||
|
* ZwSetContextThread (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
{
|
||||||
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
|
BOOL self = (handle == GetCurrentThread());
|
||||||
|
|
||||||
|
/* debug registers require a server call */
|
||||||
|
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)))
|
||||||
|
self = (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 (!self)
|
||||||
|
{
|
||||||
|
context_t server_context;
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
ret = set_thread_context( handle, &server_context, &self );
|
||||||
|
}
|
||||||
|
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_thread_ldt_entry
|
* get_thread_ldt_entry
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -148,3 +148,23 @@ void CDECL exit_process( int status )
|
||||||
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
|
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
|
||||||
signal_exit_thread( get_unix_exit_code( status ), exit );
|
signal_exit_thread( get_unix_exit_code( status ), exit );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* set_thread_context
|
||||||
|
*/
|
||||||
|
NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self )
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
|
||||||
|
SERVER_START_REQ( set_thread_context )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
wine_server_add_data( req, context, sizeof(*context) );
|
||||||
|
ret = wine_server_call( req );
|
||||||
|
*self = reply->self;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -103,6 +103,7 @@ extern void start_server( BOOL debug ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
|
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
|
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
|
||||||
|
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
extern void signal_init_threading(void) DECLSPEC_HIDDEN;
|
extern void signal_init_threading(void) DECLSPEC_HIDDEN;
|
||||||
extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
struct ldt_copy;
|
struct ldt_copy;
|
||||||
|
|
||||||
/* increment this when you change the function table */
|
/* increment this when you change the function table */
|
||||||
#define NTDLL_UNIXLIB_VERSION 13
|
#define NTDLL_UNIXLIB_VERSION 14
|
||||||
|
|
||||||
struct unix_funcs
|
struct unix_funcs
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,7 @@ struct unix_funcs
|
||||||
NTSTATUS (WINAPI *NtDuplicateObject)( HANDLE source_process, HANDLE source,
|
NTSTATUS (WINAPI *NtDuplicateObject)( HANDLE source_process, HANDLE source,
|
||||||
HANDLE dest_process, HANDLE *dest,
|
HANDLE dest_process, HANDLE *dest,
|
||||||
ACCESS_MASK access, ULONG attributes, ULONG options );
|
ACCESS_MASK access, ULONG attributes, ULONG options );
|
||||||
|
NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context );
|
||||||
NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 );
|
NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 );
|
||||||
|
|
||||||
/* environment functions */
|
/* environment functions */
|
||||||
|
|
Loading…
Reference in New Issue