From 7c32b2dd9368137eca3cf0202360bbe0db62efbf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 2 Jun 2020 14:05:42 +0200 Subject: [PATCH] ntdll: Move NtGetContextThread() implementation to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/ntdll_misc.h | 1 - dlls/ntdll/signal_arm.c | 142 ------------------ dlls/ntdll/signal_arm64.c | 130 ----------------- dlls/ntdll/signal_i386.c | 171 ++-------------------- dlls/ntdll/signal_powerpc.c | 241 ------------------------------- dlls/ntdll/signal_x86_64.c | 195 ------------------------- dlls/ntdll/thread.c | 12 ++ dlls/ntdll/unix/loader.c | 1 + dlls/ntdll/unix/signal_arm.c | 88 +++++++++++ dlls/ntdll/unix/signal_arm64.c | 86 +++++++++++ dlls/ntdll/unix/signal_i386.c | 150 +++++++++++++++++++ dlls/ntdll/unix/signal_powerpc.c | 141 ++++++++++++++++++ dlls/ntdll/unix/signal_x86_64.c | 128 ++++++++++++++++ dlls/ntdll/unix/thread.c | 40 +++++ dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unixlib.h | 3 +- 16 files changed, 660 insertions(+), 870 deletions(-) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 901377425fa..e9a3230e814 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -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 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 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 get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN; extern LONG WINAPI call_unhandled_exception_filter( PEXCEPTION_POINTERS eptr ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 2e4730d8591..b4b434e4442 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -296,148 +296,6 @@ __ASM_GLOBAL_FUNC( set_cpu_context, "pop {pc}" ) -/*********************************************************************** - * get_server_context_flags - * - * Convert CPU-specific flags to generic server flags - */ -static unsigned int get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - flags &= ~CONTEXT_ARM; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - return ret; -} - - -/*********************************************************************** - * copy_context - * - * Copy a register context according to the flags. - */ -static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) -{ - flags &= ~CONTEXT_ARM; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) - { - to->Sp = from->Sp; - to->Lr = from->Lr; - to->Pc = from->Pc; - to->Cpsr = from->Cpsr; - } - if (flags & CONTEXT_INTEGER) - { - to->R0 = from->R0; - to->R1 = from->R1; - to->R2 = from->R2; - to->R3 = from->R3; - to->R4 = from->R4; - to->R5 = from->R5; - to->R6 = from->R6; - to->R7 = from->R7; - to->R8 = from->R8; - to->R9 = from->R9; - to->R10 = from->R10; - to->R11 = from->R11; - to->R12 = from->R12; - } - if (flags & CONTEXT_FLOATING_POINT) - { - to->Fpscr = from->Fpscr; - memcpy( to->u.D, from->u.D, sizeof(to->u.D) ); - } -} - - -/*********************************************************************** - * context_from_server - * - * Convert a register context from the server format. - */ -NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) -{ - DWORD i; - - if (from->cpu != CPU_ARM) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = CONTEXT_ARM; - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= CONTEXT_CONTROL; - to->Sp = from->ctl.arm_regs.sp; - to->Lr = from->ctl.arm_regs.lr; - to->Pc = from->ctl.arm_regs.pc; - to->Cpsr = from->ctl.arm_regs.cpsr; - } - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= CONTEXT_INTEGER; - to->R0 = from->integer.arm_regs.r[0]; - to->R1 = from->integer.arm_regs.r[1]; - to->R2 = from->integer.arm_regs.r[2]; - to->R3 = from->integer.arm_regs.r[3]; - to->R4 = from->integer.arm_regs.r[4]; - to->R5 = from->integer.arm_regs.r[5]; - to->R6 = from->integer.arm_regs.r[6]; - to->R7 = from->integer.arm_regs.r[7]; - to->R8 = from->integer.arm_regs.r[8]; - to->R9 = from->integer.arm_regs.r[9]; - to->R10 = from->integer.arm_regs.r[10]; - to->R11 = from->integer.arm_regs.r[11]; - to->R12 = from->integer.arm_regs.r[12]; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= CONTEXT_FLOATING_POINT; - for (i = 0; i < 32; i++) to->u.D[i] = from->fp.arm_regs.d[i]; - to->Fpscr = from->fp.arm_regs.fpscr; - } - if (from->flags & SERVER_CTX_DEBUG_REGISTERS) - { - to->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - for (i = 0; i < ARM_MAX_BREAKPOINTS; i++) to->Bvr[i] = from->debug.arm_regs.bvr[i]; - for (i = 0; i < ARM_MAX_BREAKPOINTS; i++) to->Bcr[i] = from->debug.arm_regs.bcr[i]; - for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm_regs.wvr[i]; - for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm_regs.wcr[i]; - } - return STATUS_SUCCESS; -} - -/*********************************************************************** - * NtGetContextThread (NTDLL.@) - * ZwGetContextThread (NTDLL.@) - */ -NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) -{ - NTSTATUS ret; - DWORD needed_flags = context->ContextFlags; - BOOL self = (handle == GetCurrentThread()); - - if (!self) - { - context_t server_context; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if ((ret = context_from_server( context, &server_context ))) return ret; - needed_flags &= ~context->ContextFlags; - } - - if (self && needed_flags) - { - CONTEXT ctx; - RtlCaptureContext( &ctx ); - copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); - context->ContextFlags |= ctx.ContextFlags & needed_flags; - } - return STATUS_SUCCESS; -} - - extern void raise_func_trampoline_thumb( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func ); __ASM_GLOBAL_FUNC( raise_func_trampoline_thumb, ".thumb\n\t" diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 7831b581b7b..f15c9126287 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -308,136 +308,6 @@ static void set_cpu_context( const CONTEXT *context ) raise( SIGUSR2 ); } -/*********************************************************************** - * get_server_context_flags - * - * Convert CPU-specific flags to generic server flags - */ -static unsigned int get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - flags &= ~CONTEXT_ARM64; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - return ret; -} - -/*********************************************************************** - * copy_context - * - * Copy a register context according to the flags. - */ -static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) -{ - flags &= ~CONTEXT_ARM64; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) - { - to->u.s.Fp = from->u.s.Fp; - to->u.s.Lr = from->u.s.Lr; - to->Sp = from->Sp; - to->Pc = from->Pc; - to->Cpsr = from->Cpsr; - } - if (flags & CONTEXT_INTEGER) - { - memcpy( to->u.X, from->u.X, sizeof(to->u.X) ); - } - if (flags & CONTEXT_FLOATING_POINT) - { - memcpy( to->V, from->V, sizeof(to->V) ); - to->Fpcr = from->Fpcr; - to->Fpsr = from->Fpsr; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - memcpy( to->Bcr, from->Bcr, sizeof(to->Bcr) ); - memcpy( to->Bvr, from->Bvr, sizeof(to->Bvr) ); - memcpy( to->Wcr, from->Wcr, sizeof(to->Wcr) ); - memcpy( to->Wvr, from->Wvr, sizeof(to->Wvr) ); - } -} - -/*********************************************************************** - * context_from_server - * - * Convert a register context from the server format. - */ -NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) -{ - DWORD i; - - if (from->cpu != CPU_ARM64) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = CONTEXT_ARM64; - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= CONTEXT_CONTROL; - to->u.s.Fp = from->integer.arm64_regs.x[29]; - to->u.s.Lr = from->integer.arm64_regs.x[30]; - to->Sp = from->ctl.arm64_regs.sp; - to->Pc = from->ctl.arm64_regs.pc; - to->Cpsr = from->ctl.arm64_regs.pstate; - } - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= CONTEXT_INTEGER; - for (i = 0; i <= 28; i++) to->u.X[i] = from->integer.arm64_regs.x[i]; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= CONTEXT_FLOATING_POINT; - for (i = 0; i < 32; i++) - { - to->V[i].s.Low = from->fp.arm64_regs.q[i].low; - to->V[i].s.High = from->fp.arm64_regs.q[i].high; - } - to->Fpcr = from->fp.arm64_regs.fpcr; - to->Fpsr = from->fp.arm64_regs.fpsr; - } - if (from->flags & SERVER_CTX_DEBUG_REGISTERS) - { - to->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) to->Bcr[i] = from->debug.arm64_regs.bcr[i]; - for (i = 0; i < ARM64_MAX_BREAKPOINTS; i++) to->Bvr[i] = from->debug.arm64_regs.bvr[i]; - for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm64_regs.wcr[i]; - for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm64_regs.wvr[i]; - } - return STATUS_SUCCESS; -} - -/*********************************************************************** - * NtGetContextThread (NTDLL.@) - * ZwGetContextThread (NTDLL.@) - */ -NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) -{ - NTSTATUS ret; - DWORD needed_flags = context->ContextFlags; - BOOL self = (handle == GetCurrentThread()); - - if (!self) - { - context_t server_context; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if ((ret = context_from_server( context, &server_context ))) return ret; - needed_flags &= ~context->ContextFlags; - } - - if (self && needed_flags) - { - CONTEXT ctx; - RtlCaptureContext( &ctx ); - copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); - context->ContextFlags |= ctx.ContextFlags & needed_flags; - } - return STATUS_SUCCESS; -} - /*********************************************************************** * libunwind_virtual_unwind diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 83eca0bf2b9..9ad4ce6a355 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -1251,96 +1251,6 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) } -/*********************************************************************** - * get_server_context_flags - * - * Convert CPU-specific flags to generic server flags - */ -static unsigned int get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - flags &= ~CONTEXT_i386; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; - if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; - return ret; -} - - -/*********************************************************************** - * context_from_server - * - * Convert a register context from the server format. - */ -NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) -{ - if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = CONTEXT_i386; - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= CONTEXT_CONTROL; - to->Ebp = from->ctl.i386_regs.ebp; - to->Esp = from->ctl.i386_regs.esp; - to->Eip = from->ctl.i386_regs.eip; - to->SegCs = from->ctl.i386_regs.cs; - to->SegSs = from->ctl.i386_regs.ss; - to->EFlags = from->ctl.i386_regs.eflags; - } - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= CONTEXT_INTEGER; - to->Eax = from->integer.i386_regs.eax; - to->Ebx = from->integer.i386_regs.ebx; - to->Ecx = from->integer.i386_regs.ecx; - to->Edx = from->integer.i386_regs.edx; - to->Esi = from->integer.i386_regs.esi; - to->Edi = from->integer.i386_regs.edi; - } - if (from->flags & SERVER_CTX_SEGMENTS) - { - to->ContextFlags |= CONTEXT_SEGMENTS; - to->SegDs = from->seg.i386_regs.ds; - to->SegEs = from->seg.i386_regs.es; - to->SegFs = from->seg.i386_regs.fs; - to->SegGs = from->seg.i386_regs.gs; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= CONTEXT_FLOATING_POINT; - to->FloatSave.ControlWord = from->fp.i386_regs.ctrl; - to->FloatSave.StatusWord = from->fp.i386_regs.status; - to->FloatSave.TagWord = from->fp.i386_regs.tag; - to->FloatSave.ErrorOffset = from->fp.i386_regs.err_off; - to->FloatSave.ErrorSelector = from->fp.i386_regs.err_sel; - to->FloatSave.DataOffset = from->fp.i386_regs.data_off; - to->FloatSave.DataSelector = from->fp.i386_regs.data_sel; - to->FloatSave.Cr0NpxState = from->fp.i386_regs.cr0npx; - memcpy( to->FloatSave.RegisterArea, from->fp.i386_regs.regs, sizeof(to->FloatSave.RegisterArea) ); - } - if (from->flags & SERVER_CTX_DEBUG_REGISTERS) - { - to->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - to->Dr0 = from->debug.i386_regs.dr0; - to->Dr1 = from->debug.i386_regs.dr1; - to->Dr2 = from->debug.i386_regs.dr2; - to->Dr3 = from->debug.i386_regs.dr3; - to->Dr6 = from->debug.i386_regs.dr6; - to->Dr7 = from->debug.i386_regs.dr7; - } - if (from->flags & SERVER_CTX_EXTENDED_REGISTERS) - { - to->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; - memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); - } - return STATUS_SUCCESS; -} - - /*********************************************************************** * NtGetContextThread (NTDLL.@) * ZwGetContextThread (NTDLL.@) @@ -1352,82 +1262,23 @@ NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi, DWORD ebp, DWORD retaddr, HANDLE handle, CONTEXT *context ) { - NTSTATUS ret; DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386; - BOOL self = (handle == GetCurrentThread()); - /* debug registers require a server call */ - if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE; - - if (!self) + /* preset the registers that we got from the asm wrapper */ + if (needed_flags & CONTEXT_INTEGER) { - context_t server_context; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if ((ret = context_from_server( context, &server_context ))) return ret; - needed_flags &= ~context->ContextFlags; + context->Ebx = ebx; + context->Esi = esi; + context->Edi = edi; } - - if (self) + if (needed_flags & CONTEXT_CONTROL) { - if (needed_flags & CONTEXT_INTEGER) - { - context->Eax = 0; - context->Ebx = ebx; - context->Ecx = 0; - context->Edx = 0; - context->Esi = esi; - context->Edi = edi; - context->ContextFlags |= CONTEXT_INTEGER; - } - if (needed_flags & CONTEXT_CONTROL) - { - context->Ebp = ebp; - context->Esp = (DWORD)&retaddr; - context->Eip = *(&edi - 1); - context->SegCs = get_cs(); - context->SegSs = get_ds(); - context->EFlags = eflags; - context->ContextFlags |= CONTEXT_CONTROL; - } - if (needed_flags & CONTEXT_SEGMENTS) - { - context->SegDs = get_ds(); - context->SegEs = get_ds(); - context->SegFs = get_fs(); - context->SegGs = get_gs(); - context->ContextFlags |= CONTEXT_SEGMENTS; - } - if (needed_flags & CONTEXT_FLOATING_POINT) save_fpu( context ); - if (needed_flags & CONTEXT_EXTENDED_REGISTERS) save_fpux( context ); - /* FIXME: xstate */ - /* update the cached version of the debug registers */ - if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) - { - 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; - } + context->Ebp = ebp; + context->Esp = (DWORD)&retaddr; + context->Eip = *(&edi - 1); + context->EFlags = eflags; } - - if (context->ContextFlags & (CONTEXT_INTEGER & ~CONTEXT_i386)) - TRACE( "%p: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n", handle, - context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi ); - if (context->ContextFlags & (CONTEXT_CONTROL & ~CONTEXT_i386)) - TRACE( "%p: ebp=%08x esp=%08x eip=%08x cs=%04x ss=%04x flags=%08x\n", handle, - context->Ebp, context->Esp, context->Eip, context->SegCs, context->SegSs, context->EFlags ); - if (context->ContextFlags & (CONTEXT_SEGMENTS & ~CONTEXT_i386)) - TRACE( "%p: ds=%04x es=%04x fs=%04x gs=%04x\n", handle, - context->SegDs, context->SegEs, context->SegFs, context->SegGs ); - if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) - TRACE( "%p: dr0=%08x dr1=%08x dr2=%08x dr3=%08x dr6=%08x dr7=%08x\n", handle, - context->Dr0, context->Dr1, context->Dr2, context->Dr3, context->Dr6, context->Dr7 ); - - return STATUS_SUCCESS; + return unix_funcs->NtGetContextThread( handle, context ); } __ASM_STDCALL_FUNC( NtGetContextThread, 8, "pushl %ebp\n\t" diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index b41f22f2b3c..fa1c4d21103 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -260,247 +260,6 @@ void WINAPI RtlCaptureContext( CONTEXT *context ) } -/*********************************************************************** - * get_server_context_flags - * - * Convert CPU-specific flags to generic server flags - */ -static unsigned int get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - return ret; -} - - -/*********************************************************************** - * copy_context - * - * Copy a register context according to the flags. - */ -static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) -{ - if (flags & CONTEXT_CONTROL) - { - to->Msr = from->Msr; - to->Ctr = from->Ctr; - to->Iar = from->Iar; - to->Lr = from->Lr; - to->Dar = from->Dar; - to->Dsisr = from->Dsisr; - to->Trap = from->Trap; - } - if (flags & CONTEXT_INTEGER) - { - to->Gpr0 = from->Gpr0; - to->Gpr1 = from->Gpr1; - to->Gpr2 = from->Gpr2; - to->Gpr3 = from->Gpr3; - to->Gpr4 = from->Gpr4; - to->Gpr5 = from->Gpr5; - to->Gpr6 = from->Gpr6; - to->Gpr7 = from->Gpr7; - to->Gpr8 = from->Gpr8; - to->Gpr9 = from->Gpr9; - to->Gpr10 = from->Gpr10; - to->Gpr11 = from->Gpr11; - to->Gpr12 = from->Gpr12; - to->Gpr13 = from->Gpr13; - to->Gpr14 = from->Gpr14; - to->Gpr15 = from->Gpr15; - to->Gpr16 = from->Gpr16; - to->Gpr17 = from->Gpr17; - to->Gpr18 = from->Gpr18; - to->Gpr19 = from->Gpr19; - to->Gpr20 = from->Gpr20; - to->Gpr21 = from->Gpr21; - to->Gpr22 = from->Gpr22; - to->Gpr23 = from->Gpr23; - to->Gpr24 = from->Gpr24; - to->Gpr25 = from->Gpr25; - to->Gpr26 = from->Gpr26; - to->Gpr27 = from->Gpr27; - to->Gpr28 = from->Gpr28; - to->Gpr29 = from->Gpr29; - to->Gpr30 = from->Gpr30; - to->Gpr31 = from->Gpr31; - to->Xer = from->Xer; - to->Cr = from->Cr; - } - if (flags & CONTEXT_FLOATING_POINT) - { - to->Fpr0 = from->Fpr0; - to->Fpr1 = from->Fpr1; - to->Fpr2 = from->Fpr2; - to->Fpr3 = from->Fpr3; - to->Fpr4 = from->Fpr4; - to->Fpr5 = from->Fpr5; - to->Fpr6 = from->Fpr6; - to->Fpr7 = from->Fpr7; - to->Fpr8 = from->Fpr8; - to->Fpr9 = from->Fpr9; - to->Fpr10 = from->Fpr10; - to->Fpr11 = from->Fpr11; - to->Fpr12 = from->Fpr12; - to->Fpr13 = from->Fpr13; - to->Fpr14 = from->Fpr14; - to->Fpr15 = from->Fpr15; - to->Fpr16 = from->Fpr16; - to->Fpr17 = from->Fpr17; - to->Fpr18 = from->Fpr18; - to->Fpr19 = from->Fpr19; - to->Fpr20 = from->Fpr20; - to->Fpr21 = from->Fpr21; - to->Fpr22 = from->Fpr22; - to->Fpr23 = from->Fpr23; - to->Fpr24 = from->Fpr24; - to->Fpr25 = from->Fpr25; - to->Fpr26 = from->Fpr26; - to->Fpr27 = from->Fpr27; - to->Fpr28 = from->Fpr28; - to->Fpr29 = from->Fpr29; - to->Fpr30 = from->Fpr30; - to->Fpr31 = from->Fpr31; - to->Fpscr = from->Fpscr; - } -} - - -/*********************************************************************** - * context_from_server - * - * Convert a register context from the server format. - */ -NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) -{ - if (from->cpu != CPU_POWERPC) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = 0; /* no CPU id? */ - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= CONTEXT_CONTROL; - to->Msr = from->ctl.powerpc_regs.msr; - to->Ctr = from->ctl.powerpc_regs.ctr; - to->Iar = from->ctl.powerpc_regs.iar; - to->Lr = from->ctl.powerpc_regs.lr; - to->Dar = from->ctl.powerpc_regs.dar; - to->Dsisr = from->ctl.powerpc_regs.dsisr; - to->Trap = from->ctl.powerpc_regs.trap; - } - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= CONTEXT_INTEGER; - to->Gpr0 = from->integer.powerpc_regs.gpr[0]; - to->Gpr1 = from->integer.powerpc_regs.gpr[1]; - to->Gpr2 = from->integer.powerpc_regs.gpr[2]; - to->Gpr3 = from->integer.powerpc_regs.gpr[3]; - to->Gpr4 = from->integer.powerpc_regs.gpr[4]; - to->Gpr5 = from->integer.powerpc_regs.gpr[5]; - to->Gpr6 = from->integer.powerpc_regs.gpr[6]; - to->Gpr7 = from->integer.powerpc_regs.gpr[7]; - to->Gpr8 = from->integer.powerpc_regs.gpr[8]; - to->Gpr9 = from->integer.powerpc_regs.gpr[9]; - to->Gpr10 = from->integer.powerpc_regs.gpr[10]; - to->Gpr11 = from->integer.powerpc_regs.gpr[11]; - to->Gpr12 = from->integer.powerpc_regs.gpr[12]; - to->Gpr13 = from->integer.powerpc_regs.gpr[13]; - to->Gpr14 = from->integer.powerpc_regs.gpr[14]; - to->Gpr15 = from->integer.powerpc_regs.gpr[15]; - to->Gpr16 = from->integer.powerpc_regs.gpr[16]; - to->Gpr17 = from->integer.powerpc_regs.gpr[17]; - to->Gpr18 = from->integer.powerpc_regs.gpr[18]; - to->Gpr19 = from->integer.powerpc_regs.gpr[19]; - to->Gpr20 = from->integer.powerpc_regs.gpr[20]; - to->Gpr21 = from->integer.powerpc_regs.gpr[21]; - to->Gpr22 = from->integer.powerpc_regs.gpr[22]; - to->Gpr23 = from->integer.powerpc_regs.gpr[23]; - to->Gpr24 = from->integer.powerpc_regs.gpr[24]; - to->Gpr25 = from->integer.powerpc_regs.gpr[25]; - to->Gpr26 = from->integer.powerpc_regs.gpr[26]; - to->Gpr27 = from->integer.powerpc_regs.gpr[27]; - to->Gpr28 = from->integer.powerpc_regs.gpr[28]; - to->Gpr29 = from->integer.powerpc_regs.gpr[29]; - to->Gpr30 = from->integer.powerpc_regs.gpr[30]; - to->Gpr31 = from->integer.powerpc_regs.gpr[31]; - to->Xer = from->integer.powerpc_regs.xer; - to->Cr = from->integer.powerpc_regs.cr; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= CONTEXT_FLOATING_POINT; - to->Fpr0 = from->fp.powerpc_regs.fpr[0]; - to->Fpr1 = from->fp.powerpc_regs.fpr[1]; - to->Fpr2 = from->fp.powerpc_regs.fpr[2]; - to->Fpr3 = from->fp.powerpc_regs.fpr[3]; - to->Fpr4 = from->fp.powerpc_regs.fpr[4]; - to->Fpr5 = from->fp.powerpc_regs.fpr[5]; - to->Fpr6 = from->fp.powerpc_regs.fpr[6]; - to->Fpr7 = from->fp.powerpc_regs.fpr[7]; - to->Fpr8 = from->fp.powerpc_regs.fpr[8]; - to->Fpr9 = from->fp.powerpc_regs.fpr[9]; - to->Fpr10 = from->fp.powerpc_regs.fpr[10]; - to->Fpr11 = from->fp.powerpc_regs.fpr[11]; - to->Fpr12 = from->fp.powerpc_regs.fpr[12]; - to->Fpr13 = from->fp.powerpc_regs.fpr[13]; - to->Fpr14 = from->fp.powerpc_regs.fpr[14]; - to->Fpr15 = from->fp.powerpc_regs.fpr[15]; - to->Fpr16 = from->fp.powerpc_regs.fpr[16]; - to->Fpr17 = from->fp.powerpc_regs.fpr[17]; - to->Fpr18 = from->fp.powerpc_regs.fpr[18]; - to->Fpr19 = from->fp.powerpc_regs.fpr[19]; - to->Fpr20 = from->fp.powerpc_regs.fpr[20]; - to->Fpr21 = from->fp.powerpc_regs.fpr[21]; - to->Fpr22 = from->fp.powerpc_regs.fpr[22]; - to->Fpr23 = from->fp.powerpc_regs.fpr[23]; - to->Fpr24 = from->fp.powerpc_regs.fpr[24]; - to->Fpr25 = from->fp.powerpc_regs.fpr[25]; - to->Fpr26 = from->fp.powerpc_regs.fpr[26]; - to->Fpr27 = from->fp.powerpc_regs.fpr[27]; - to->Fpr28 = from->fp.powerpc_regs.fpr[28]; - to->Fpr29 = from->fp.powerpc_regs.fpr[29]; - to->Fpr30 = from->fp.powerpc_regs.fpr[30]; - to->Fpr31 = from->fp.powerpc_regs.fpr[31]; - to->Fpscr = from->fp.powerpc_regs.fpscr; - } - return STATUS_SUCCESS; -} - - -/*********************************************************************** - * NtGetContextThread (NTDLL.@) - * ZwGetContextThread (NTDLL.@) - */ -NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) -{ - NTSTATUS ret; - DWORD needed_flags = context->ContextFlags; - BOOL self = (handle == GetCurrentThread()); - - if (!self) - { - context_t server_context; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if ((ret = context_from_server( context, &server_context ))) return ret; - needed_flags &= ~context->ContextFlags; - } - - if (self && needed_flags) - { - CONTEXT ctx; - RtlCaptureContext( &ctx ); - copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); - context->ContextFlags |= ctx.ContextFlags & needed_flags; - } - return STATUS_SUCCESS; -} - - /********************************************************************** * call_stack_handlers * diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 794f10bbc6b..cb9c04c1bfd 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1889,201 +1889,6 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) } -/*********************************************************************** - * get_server_context_flags - * - * Convert CPU-specific flags to generic server flags - */ -static unsigned int get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - flags &= ~CONTEXT_AMD64; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; - if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - return ret; -} - - -/*********************************************************************** - * copy_context - * - * Copy a register context according to the flags. - */ -static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) -{ - flags &= ~CONTEXT_AMD64; /* get rid of CPU id */ - if (flags & CONTEXT_CONTROL) - { - to->Rbp = from->Rbp; - to->Rip = from->Rip; - to->Rsp = from->Rsp; - to->SegCs = from->SegCs; - to->SegSs = from->SegSs; - to->EFlags = from->EFlags; - } - if (flags & CONTEXT_INTEGER) - { - to->Rax = from->Rax; - to->Rcx = from->Rcx; - to->Rdx = from->Rdx; - to->Rbx = from->Rbx; - to->Rsi = from->Rsi; - to->Rdi = from->Rdi; - to->R8 = from->R8; - to->R9 = from->R9; - to->R10 = from->R10; - to->R11 = from->R11; - to->R12 = from->R12; - to->R13 = from->R13; - to->R14 = from->R14; - to->R15 = from->R15; - } - if (flags & CONTEXT_SEGMENTS) - { - to->SegDs = from->SegDs; - to->SegEs = from->SegEs; - to->SegFs = from->SegFs; - to->SegGs = from->SegGs; - } - if (flags & CONTEXT_FLOATING_POINT) - { - to->MxCsr = from->MxCsr; - to->u.FltSave = from->u.FltSave; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - to->Dr0 = from->Dr0; - to->Dr1 = from->Dr1; - to->Dr2 = from->Dr2; - to->Dr3 = from->Dr3; - to->Dr6 = from->Dr6; - to->Dr7 = from->Dr7; - } -} - - -/*********************************************************************** - * context_from_server - * - * Convert a register context from the server format. - */ -NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) -{ - if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = CONTEXT_AMD64; - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= CONTEXT_CONTROL; - to->Rbp = from->ctl.x86_64_regs.rbp; - to->Rip = from->ctl.x86_64_regs.rip; - to->Rsp = from->ctl.x86_64_regs.rsp; - to->SegCs = from->ctl.x86_64_regs.cs; - to->SegSs = from->ctl.x86_64_regs.ss; - to->EFlags = from->ctl.x86_64_regs.flags; - } - - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= CONTEXT_INTEGER; - to->Rax = from->integer.x86_64_regs.rax; - to->Rcx = from->integer.x86_64_regs.rcx; - to->Rdx = from->integer.x86_64_regs.rdx; - to->Rbx = from->integer.x86_64_regs.rbx; - to->Rsi = from->integer.x86_64_regs.rsi; - to->Rdi = from->integer.x86_64_regs.rdi; - to->R8 = from->integer.x86_64_regs.r8; - to->R9 = from->integer.x86_64_regs.r9; - to->R10 = from->integer.x86_64_regs.r10; - to->R11 = from->integer.x86_64_regs.r11; - to->R12 = from->integer.x86_64_regs.r12; - to->R13 = from->integer.x86_64_regs.r13; - to->R14 = from->integer.x86_64_regs.r14; - to->R15 = from->integer.x86_64_regs.r15; - } - if (from->flags & SERVER_CTX_SEGMENTS) - { - to->ContextFlags |= CONTEXT_SEGMENTS; - to->SegDs = from->seg.x86_64_regs.ds; - to->SegEs = from->seg.x86_64_regs.es; - to->SegFs = from->seg.x86_64_regs.fs; - to->SegGs = from->seg.x86_64_regs.gs; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= CONTEXT_FLOATING_POINT; - memcpy( &to->u.FltSave, from->fp.x86_64_regs.fpregs, sizeof(from->fp.x86_64_regs.fpregs) ); - to->MxCsr = to->u.FltSave.MxCsr; - } - if (from->flags & SERVER_CTX_DEBUG_REGISTERS) - { - to->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - to->Dr0 = from->debug.x86_64_regs.dr0; - to->Dr1 = from->debug.x86_64_regs.dr1; - to->Dr2 = from->debug.x86_64_regs.dr2; - to->Dr3 = from->debug.x86_64_regs.dr3; - to->Dr6 = from->debug.x86_64_regs.dr6; - to->Dr7 = from->debug.x86_64_regs.dr7; - } - return STATUS_SUCCESS; -} - - -/*********************************************************************** - * NtGetContextThread (NTDLL.@) - * ZwGetContextThread (NTDLL.@) - */ -NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) -{ - NTSTATUS ret; - DWORD needed_flags; - BOOL self = (handle == GetCurrentThread()); - - if (!context) return STATUS_INVALID_PARAMETER; - - needed_flags = context->ContextFlags; - - /* debug registers require a server call */ - if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE; - - if (!self) - { - context_t server_context; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if ((ret = context_from_server( context, &server_context ))) return ret; - needed_flags &= ~context->ContextFlags; - } - - if (self) - { - if (needed_flags) - { - CONTEXT ctx; - RtlCaptureContext( &ctx ); - copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); - context->ContextFlags |= ctx.ContextFlags & needed_flags; - } - /* update the cached version of the debug registers */ - if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) - { - 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; - } - } - return STATUS_SUCCESS; -} - - /*********************************************************************** * wow64_get_server_context_flags */ diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index d22a9bcaae5..e58b18e4bf6 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -777,6 +777,18 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +#ifndef __i386__ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + return unix_funcs->NtGetContextThread( handle, context ); +} +#endif + + /****************************************************************************** * NtSetLdtEntries (NTDLL.@) * ZwSetLdtEntries (NTDLL.@) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 0d078991022..e0b126bc8ea 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -986,6 +986,7 @@ static struct unix_funcs unix_funcs = NtClose, NtCurrentTeb, NtDuplicateObject, + NtGetContextThread, NtSetContextThread, NtSetLdtEntries, get_main_args, diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 8f464763b86..8228f3f92a2 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -90,6 +90,63 @@ __ASM_GLOBAL_FUNC( set_cpu_context, "pop {pc}" ) +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= ~CONTEXT_ARM; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + return ret; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + flags &= ~CONTEXT_ARM; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) + { + to->Sp = from->Sp; + to->Lr = from->Lr; + to->Pc = from->Pc; + to->Cpsr = from->Cpsr; + } + if (flags & CONTEXT_INTEGER) + { + to->R0 = from->R0; + to->R1 = from->R1; + to->R2 = from->R2; + to->R3 = from->R3; + to->R4 = from->R4; + to->R5 = from->R5; + to->R6 = from->R6; + to->R7 = from->R7; + to->R8 = from->R8; + to->R9 = from->R9; + to->R10 = from->R10; + to->R11 = from->R11; + to->R12 = from->R12; + } + if (flags & CONTEXT_FLOATING_POINT) + { + to->Fpscr = from->Fpscr; + memcpy( to->u.D, from->u.D, sizeof(to->u.D) ); + } +} + + /*********************************************************************** * context_to_server * @@ -217,6 +274,37 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags = context->ContextFlags; + BOOL self = (handle == GetCurrentThread()); + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self && needed_flags) + { + CONTEXT ctx; + RtlCaptureContext( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; + } + return STATUS_SUCCESS; +} + + /********************************************************************** * get_thread_ldt_entry */ diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 97c1295a3cd..ca47481b194 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -99,6 +99,61 @@ static void set_cpu_context( const CONTEXT *context ) raise( SIGUSR2 ); } + +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= ~CONTEXT_ARM64; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + return ret; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + flags &= ~CONTEXT_ARM64; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) + { + to->u.s.Fp = from->u.s.Fp; + to->u.s.Lr = from->u.s.Lr; + to->Sp = from->Sp; + to->Pc = from->Pc; + to->Cpsr = from->Cpsr; + } + if (flags & CONTEXT_INTEGER) + { + memcpy( to->u.X, from->u.X, sizeof(to->u.X) ); + } + if (flags & CONTEXT_FLOATING_POINT) + { + memcpy( to->V, from->V, sizeof(to->V) ); + to->Fpcr = from->Fpcr; + to->Fpsr = from->Fpsr; + } + if (flags & CONTEXT_DEBUG_REGISTERS) + { + memcpy( to->Bcr, from->Bcr, sizeof(to->Bcr) ); + memcpy( to->Bvr, from->Bvr, sizeof(to->Bvr) ); + memcpy( to->Wcr, from->Wcr, sizeof(to->Wcr) ); + memcpy( to->Wvr, from->Wvr, sizeof(to->Wvr) ); + } +} + + /*********************************************************************** * context_to_server * @@ -220,6 +275,37 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags = context->ContextFlags; + BOOL self = (handle == GetCurrentThread()); + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self && needed_flags) + { + CONTEXT ctx; + RtlCaptureContext( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; + } + return STATUS_SUCCESS; +} + + /********************************************************************** * get_thread_ldt_entry */ diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 6bdb9339eb7..8902be00cd1 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -201,6 +201,53 @@ static inline int is_gdt_sel( WORD sel ) } +/*********************************************************************** + * save_fpu + * + * Save the thread FPU context. + */ +static inline void save_fpu( CONTEXT *context ) +{ + struct + { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + } + float_status; + + context->ContextFlags |= CONTEXT_FLOATING_POINT; + __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) ); + + /* Reset unmasked exceptions status to avoid firing an exception. */ + memcpy(&float_status, &context->FloatSave, sizeof(float_status)); + float_status.StatusWord &= float_status.ControlWord | 0xffffff80; + + __asm__ __volatile__( "fldenv %0" : : "m" (float_status) ); +} + + +/*********************************************************************** + * save_fpux + * + * Save the thread FPU extended context. + */ +static inline void save_fpux( 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); + + context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; + __asm__ __volatile__( "fxsave %0" : "=m" (*state) ); + memcpy( context->ExtendedRegisters, state, sizeof(*state) ); +} + + /*********************************************************************** * restore_fpu * @@ -329,6 +376,26 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) } +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= ~CONTEXT_i386; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; + return ret; +} + + /*********************************************************************** * context_to_server * @@ -501,6 +568,89 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + * + * Note: we use a small assembly wrapper to save the necessary registers + * in case we are fetching the context of the current thread. + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386; + BOOL self = (handle == GetCurrentThread()); + + /* debug registers require a server call */ + if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE; + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self) + { + if (needed_flags & CONTEXT_INTEGER) + { + context->Eax = 0; + context->Ecx = 0; + context->Edx = 0; + /* other registers already set from asm wrapper */ + context->ContextFlags |= CONTEXT_INTEGER; + } + if (needed_flags & CONTEXT_CONTROL) + { + context->SegCs = get_cs(); + context->SegSs = get_ds(); + /* other registers already set from asm wrapper */ + context->ContextFlags |= CONTEXT_CONTROL; + } + if (needed_flags & CONTEXT_SEGMENTS) + { + context->SegDs = get_ds(); + context->SegEs = get_ds(); + context->SegFs = get_fs(); + context->SegGs = get_gs(); + context->ContextFlags |= CONTEXT_SEGMENTS; + } + if (needed_flags & CONTEXT_FLOATING_POINT) save_fpu( context ); + if (needed_flags & CONTEXT_EXTENDED_REGISTERS) save_fpux( context ); + /* FIXME: xstate */ + /* update the cached version of the debug registers */ + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) + { + 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 (context->ContextFlags & (CONTEXT_INTEGER & ~CONTEXT_i386)) + TRACE( "%p: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n", handle, + context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi ); + if (context->ContextFlags & (CONTEXT_CONTROL & ~CONTEXT_i386)) + TRACE( "%p: ebp=%08x esp=%08x eip=%08x cs=%04x ss=%04x flags=%08x\n", handle, + context->Ebp, context->Esp, context->Eip, context->SegCs, context->SegSs, context->EFlags ); + if (context->ContextFlags & (CONTEXT_SEGMENTS & ~CONTEXT_i386)) + TRACE( "%p: ds=%04x es=%04x fs=%04x gs=%04x\n", handle, + context->SegDs, context->SegEs, context->SegFs, context->SegGs ); + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) + TRACE( "%p: dr0=%08x dr1=%08x dr2=%08x dr3=%08x dr6=%08x dr7=%08x\n", handle, + context->Dr0, context->Dr1, context->Dr2, context->Dr3, context->Dr6, context->Dr7 ); + + return STATUS_SUCCESS; +} + + /*********************************************************************** * LDT support */ diff --git a/dlls/ntdll/unix/signal_powerpc.c b/dlls/ntdll/unix/signal_powerpc.c index 940bcf4eed0..fefb3a99135 100644 --- a/dlls/ntdll/unix/signal_powerpc.c +++ b/dlls/ntdll/unix/signal_powerpc.c @@ -77,6 +77,116 @@ static void set_cpu_context( const CONTEXT *context ) } +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + return ret; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + if (flags & CONTEXT_CONTROL) + { + to->Msr = from->Msr; + to->Ctr = from->Ctr; + to->Iar = from->Iar; + to->Lr = from->Lr; + to->Dar = from->Dar; + to->Dsisr = from->Dsisr; + to->Trap = from->Trap; + } + if (flags & CONTEXT_INTEGER) + { + to->Gpr0 = from->Gpr0; + to->Gpr1 = from->Gpr1; + to->Gpr2 = from->Gpr2; + to->Gpr3 = from->Gpr3; + to->Gpr4 = from->Gpr4; + to->Gpr5 = from->Gpr5; + to->Gpr6 = from->Gpr6; + to->Gpr7 = from->Gpr7; + to->Gpr8 = from->Gpr8; + to->Gpr9 = from->Gpr9; + to->Gpr10 = from->Gpr10; + to->Gpr11 = from->Gpr11; + to->Gpr12 = from->Gpr12; + to->Gpr13 = from->Gpr13; + to->Gpr14 = from->Gpr14; + to->Gpr15 = from->Gpr15; + to->Gpr16 = from->Gpr16; + to->Gpr17 = from->Gpr17; + to->Gpr18 = from->Gpr18; + to->Gpr19 = from->Gpr19; + to->Gpr20 = from->Gpr20; + to->Gpr21 = from->Gpr21; + to->Gpr22 = from->Gpr22; + to->Gpr23 = from->Gpr23; + to->Gpr24 = from->Gpr24; + to->Gpr25 = from->Gpr25; + to->Gpr26 = from->Gpr26; + to->Gpr27 = from->Gpr27; + to->Gpr28 = from->Gpr28; + to->Gpr29 = from->Gpr29; + to->Gpr30 = from->Gpr30; + to->Gpr31 = from->Gpr31; + to->Xer = from->Xer; + to->Cr = from->Cr; + } + if (flags & CONTEXT_FLOATING_POINT) + { + to->Fpr0 = from->Fpr0; + to->Fpr1 = from->Fpr1; + to->Fpr2 = from->Fpr2; + to->Fpr3 = from->Fpr3; + to->Fpr4 = from->Fpr4; + to->Fpr5 = from->Fpr5; + to->Fpr6 = from->Fpr6; + to->Fpr7 = from->Fpr7; + to->Fpr8 = from->Fpr8; + to->Fpr9 = from->Fpr9; + to->Fpr10 = from->Fpr10; + to->Fpr11 = from->Fpr11; + to->Fpr12 = from->Fpr12; + to->Fpr13 = from->Fpr13; + to->Fpr14 = from->Fpr14; + to->Fpr15 = from->Fpr15; + to->Fpr16 = from->Fpr16; + to->Fpr17 = from->Fpr17; + to->Fpr18 = from->Fpr18; + to->Fpr19 = from->Fpr19; + to->Fpr20 = from->Fpr20; + to->Fpr21 = from->Fpr21; + to->Fpr22 = from->Fpr22; + to->Fpr23 = from->Fpr23; + to->Fpr24 = from->Fpr24; + to->Fpr25 = from->Fpr25; + to->Fpr26 = from->Fpr26; + to->Fpr27 = from->Fpr27; + to->Fpr28 = from->Fpr28; + to->Fpr29 = from->Fpr29; + to->Fpr30 = from->Fpr30; + to->Fpr31 = from->Fpr31; + to->Fpscr = from->Fpscr; + } +} + + /*********************************************************************** * context_to_server * @@ -296,6 +406,37 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags = context->ContextFlags; + BOOL self = (handle == GetCurrentThread()); + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self && needed_flags) + { + CONTEXT ctx; + RtlCaptureContext( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; + } + return STATUS_SUCCESS; +} + + /********************************************************************** * get_thread_ldt_entry */ diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index b1d796bcc4b..abe4d6905e6 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -219,6 +219,83 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) } +/*********************************************************************** + * get_server_context_flags + * + * Convert CPU-specific flags to generic server flags + */ +static unsigned int get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= ~CONTEXT_AMD64; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; + if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + return ret; +} + + +/*********************************************************************** + * copy_context + * + * Copy a register context according to the flags. + */ +static void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) +{ + flags &= ~CONTEXT_AMD64; /* get rid of CPU id */ + if (flags & CONTEXT_CONTROL) + { + to->Rbp = from->Rbp; + to->Rip = from->Rip; + to->Rsp = from->Rsp; + to->SegCs = from->SegCs; + to->SegSs = from->SegSs; + to->EFlags = from->EFlags; + } + if (flags & CONTEXT_INTEGER) + { + to->Rax = from->Rax; + to->Rcx = from->Rcx; + to->Rdx = from->Rdx; + to->Rbx = from->Rbx; + to->Rsi = from->Rsi; + to->Rdi = from->Rdi; + to->R8 = from->R8; + to->R9 = from->R9; + to->R10 = from->R10; + to->R11 = from->R11; + to->R12 = from->R12; + to->R13 = from->R13; + to->R14 = from->R14; + to->R15 = from->R15; + } + if (flags & CONTEXT_SEGMENTS) + { + to->SegDs = from->SegDs; + to->SegEs = from->SegEs; + to->SegFs = from->SegFs; + to->SegGs = from->SegGs; + } + if (flags & CONTEXT_FLOATING_POINT) + { + to->MxCsr = from->MxCsr; + to->u.FltSave = from->u.FltSave; + } + if (flags & CONTEXT_DEBUG_REGISTERS) + { + to->Dr0 = from->Dr0; + to->Dr1 = from->Dr1; + to->Dr2 = from->Dr2; + to->Dr3 = from->Dr3; + to->Dr6 = from->Dr6; + to->Dr7 = from->Dr7; + } +} + + /*********************************************************************** * context_to_server * @@ -382,6 +459,57 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) } +/*********************************************************************** + * NtGetContextThread (NTDLL.@) + * ZwGetContextThread (NTDLL.@) + */ +NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) +{ + NTSTATUS ret; + DWORD needed_flags; + BOOL self = (handle == GetCurrentThread()); + + if (!context) return STATUS_INVALID_PARAMETER; + + needed_flags = context->ContextFlags; + + /* debug registers require a server call */ + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE; + + if (!self) + { + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + + if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; + if ((ret = context_from_server( context, &server_context ))) return ret; + needed_flags &= ~context->ContextFlags; + } + + if (self) + { + if (needed_flags) + { + CONTEXT ctx; + RtlCaptureContext( &ctx ); + copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; + } + /* update the cached version of the debug registers */ + if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) + { + 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; + } + } + return STATUS_SUCCESS; +} + + /********************************************************************** * get_thread_ldt_entry */ diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 2fca3037871..6343e3e3b70 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -168,3 +168,43 @@ NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self return ret; } + + +/*********************************************************************** + * get_thread_context + */ +NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) +{ + NTSTATUS ret; + + SERVER_START_REQ( get_thread_context ) + { + req->handle = wine_server_obj_handle( handle ); + req->flags = flags; + wine_server_set_reply( req, context, sizeof(*context) ); + ret = wine_server_call( req ); + *self = reply->self; + handle = wine_server_ptr_handle( reply->handle ); + } + SERVER_END_REQ; + + if (ret == STATUS_PENDING) + { + LARGE_INTEGER timeout; + timeout.QuadPart = -1000000; + if (NtWaitForSingleObject( handle, FALSE, &timeout )) + { + NtClose( handle ); + return STATUS_ACCESS_DENIED; + } + SERVER_START_REQ( get_thread_context ) + { + req->handle = wine_server_obj_handle( handle ); + req->flags = flags; + wine_server_set_reply( req, context, sizeof(*context) ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + } + return ret; +} diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 14453955923..0c653d29bd6 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -104,6 +104,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_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 get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN; extern void signal_init_threading(void) DECLSPEC_HIDDEN; extern NTSTATUS signal_alloc_thread( TEB *teb ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index b87123efd06..a6d8725f176 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -27,7 +27,7 @@ struct ldt_copy; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 14 +#define NTDLL_UNIXLIB_VERSION 15 struct unix_funcs { @@ -37,6 +37,7 @@ struct unix_funcs NTSTATUS (WINAPI *NtDuplicateObject)( HANDLE source_process, HANDLE source, HANDLE dest_process, HANDLE *dest, ACCESS_MASK access, ULONG attributes, ULONG options ); + NTSTATUS (WINAPI *NtGetContextThread)( HANDLE handle, CONTEXT *context ); NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context ); NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 );