From f6cb551d7f65c2098607a80d95302afb829d4df9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 20 Apr 2006 17:46:16 +0200 Subject: [PATCH] server: Remove some no longer needed ptrace code to set registers. Also make sure the debug registers are properly copied to the context when set. --- server/context_i386.c | 505 +++++++++--------------------------------- 1 file changed, 107 insertions(+), 398 deletions(-) diff --git a/server/context_i386.c b/server/context_i386.c index 0a3a3291b7d..5247478fbec 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -58,19 +58,6 @@ # endif #endif -#ifndef PTRACE_GETREGS -#define PTRACE_GETREGS PT_GETREGS -#endif -#ifndef PTRACE_GETFPREGS -#define PTRACE_GETFPREGS PT_GETFPREGS -#endif -#ifndef PTRACE_SETREGS -#define PTRACE_SETREGS PT_SETREGS -#endif -#ifndef PTRACE_SETFPREGS -#define PTRACE_SETFPREGS PT_SETFPREGS -#endif - #ifdef PT_GETDBREGS #define PTRACE_GETDBREGS PT_GETDBREGS #endif @@ -84,18 +71,6 @@ # include #endif -/* user_regs definitions from asm/user.h */ -struct kernel_user_regs_struct -{ - long ebx, ecx, edx, esi, edi, ebp, eax; - unsigned short ds, __ds, es, __es; - unsigned short fs, __fs, gs, __gs; - long orig_eax, eip; - unsigned short cs, __cs; - long eflags, esp; - unsigned short ss, __ss; -}; - /* debug register offset in struct user */ #define DR_OFFSET(dr) ((int)((((struct user *)0)->u_debugreg) + (dr))) @@ -114,390 +89,122 @@ static inline int get_debug_reg( int pid, int num, DWORD *data ) return 0; } -/* retrieve a thread context */ -static void get_thread_context_ptrace( struct thread *thread, unsigned int flags, CONTEXT *context ) +/* retrieve the thread x86 debug registers */ +static int get_thread_debug_regs( struct thread *thread, CONTEXT *context ) { int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct kernel_user_regs_struct regs; - if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; - if (flags & CONTEXT_INTEGER) - { - context->Eax = regs.eax; - context->Ebx = regs.ebx; - context->Ecx = regs.ecx; - context->Edx = regs.edx; - context->Esi = regs.esi; - context->Edi = regs.edi; - } - if (flags & CONTEXT_CONTROL) - { - context->Ebp = regs.ebp; - context->Esp = regs.esp; - context->Eip = regs.eip; - context->SegCs = regs.cs; - context->SegSs = regs.ss; - context->EFlags = regs.eflags; - } - if (flags & CONTEXT_SEGMENTS) - { - context->SegDs = regs.ds; - context->SegEs = regs.es; - context->SegFs = regs.fs; - context->SegGs = regs.gs; - } - context->ContextFlags |= flags & CONTEXT_FULL; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - if (get_debug_reg( pid, 0, &context->Dr0 ) == -1) goto error; - if (get_debug_reg( pid, 1, &context->Dr1 ) == -1) goto error; - if (get_debug_reg( pid, 2, &context->Dr2 ) == -1) goto error; - if (get_debug_reg( pid, 3, &context->Dr3 ) == -1) goto error; - if (get_debug_reg( pid, 6, &context->Dr6 ) == -1) goto error; - if (get_debug_reg( pid, 7, &context->Dr7 ) == -1) goto error; - context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_GETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error; - context->FloatSave.Cr0NpxState = 0; /* FIXME */ - context->ContextFlags |= CONTEXT_FLOATING_POINT; - } - return; + + if (get_debug_reg( pid, 0, &context->Dr0 ) == -1) goto error; + if (get_debug_reg( pid, 1, &context->Dr1 ) == -1) goto error; + if (get_debug_reg( pid, 2, &context->Dr2 ) == -1) goto error; + if (get_debug_reg( pid, 3, &context->Dr3 ) == -1) goto error; + if (get_debug_reg( pid, 6, &context->Dr6 ) == -1) goto error; + if (get_debug_reg( pid, 7, &context->Dr7 ) == -1) goto error; + return 1; error: file_set_error(); + return 0; } - -/* set a thread context */ -static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context ) +/* set the thread x86 debug registers */ +static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context ) { int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct kernel_user_regs_struct regs; - /* need to preserve some registers (at a minimum orig_eax must always be preserved) */ - if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; - - if (flags & CONTEXT_INTEGER) - { - regs.eax = context->Eax; - regs.ebx = context->Ebx; - regs.ecx = context->Ecx; - regs.edx = context->Edx; - regs.esi = context->Esi; - regs.edi = context->Edi; - } - if (flags & CONTEXT_CONTROL) - { - regs.ebp = context->Ebp; - regs.esp = context->Esp; - regs.eip = context->Eip; - regs.cs = context->SegCs; - regs.ss = context->SegSs; - regs.eflags = context->EFlags; - } - if (flags & CONTEXT_SEGMENTS) - { - regs.ds = context->SegDs; - regs.es = context->SegEs; - regs.fs = context->SegFs; - regs.gs = context->SegGs; - } - if (ptrace( PTRACE_SETREGS, pid, 0, ®s ) == -1) goto error; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error; - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_SETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error; - } - return; - error: - file_set_error(); -} - -#elif defined(__sun) || defined(__sun__) - -/* retrieve a thread context */ -static void get_thread_context_ptrace( struct thread *thread, unsigned int flags, CONTEXT *context ) -{ - int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct regs regs; - if (ptrace( PTRACE_GETREGS, pid, (int) ®s, 0 ) == -1) goto error; - if (flags & CONTEXT_INTEGER) - { - context->Eax = regs.r_eax; - context->Ebx = regs.r_ebx; - context->Ecx = regs.r_ecx; - context->Edx = regs.r_edx; - context->Esi = regs.r_esi; - context->Edi = regs.r_edi; - } - if (flags & CONTEXT_CONTROL) - { - context->Ebp = regs.r_ebp; - context->Esp = regs.r_esp; - context->Eip = regs.r_eip; - context->SegCs = regs.r_cs & 0xffff; - context->SegSs = regs.r_ss & 0xffff; - context->EFlags = regs.r_efl; - } - if (flags & CONTEXT_SEGMENTS) - { - context->SegDs = regs.r_ds & 0xffff; - context->SegEs = regs.r_es & 0xffff; - context->SegFs = regs.r_fs & 0xffff; - context->SegGs = regs.r_gs & 0xffff; - } - context->ContextFlags |= flags & CONTEXT_FULL; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - /* FIXME: How is this done on Solaris? */ - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_GETFPREGS, pid, (int) &context->FloatSave, 0 ) == -1) goto error; - context->FloatSave.Cr0NpxState = 0; /* FIXME */ - context->ContextFlags |= CONTEXT_FLOATING_POINT; - } - return; - error: - file_set_error(); -} - - -/* set a thread context */ -static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context ) -{ - int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct regs regs; - if (((flags | CONTEXT_i386) & CONTEXT_FULL) != CONTEXT_FULL) - { - /* need to preserve some registers */ - if (ptrace( PTRACE_GETREGS, pid, (int) ®s, 0 ) == -1) goto error; - } - if (flags & CONTEXT_INTEGER) - { - regs.r_eax = context->Eax; - regs.r_ebx = context->Ebx; - regs.r_ecx = context->Ecx; - regs.r_edx = context->Edx; - regs.r_esi = context->Esi; - regs.r_edi = context->Edi; - } - if (flags & CONTEXT_CONTROL) - { - regs.r_ebp = context->Ebp; - regs.r_esp = context->Esp; - regs.r_eip = context->Eip; - regs.r_cs = context->SegCs; - regs.r_ss = context->SegSs; - regs.r_efl = context->EFlags; - } - if (flags & CONTEXT_SEGMENTS) - { - regs.r_ds = context->SegDs; - regs.r_es = context->SegEs; - regs.r_fs = context->SegFs; - regs.r_gs = context->SegGs; - } - if (ptrace( PTRACE_SETREGS, pid, (int) ®s, 0 ) == -1) goto error; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { - /* FIXME: How is this done on Solaris? */ - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_SETFPREGS, pid, (int) &context->FloatSave, 0 ) == -1) goto error; - } - return; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error; + return 1; error: file_set_error(); + return 0; } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) #include -/* retrieve a thread context */ -static void get_thread_context_ptrace( struct thread *thread, unsigned int flags, CONTEXT *context ) +/* retrieve the thread x86 debug registers */ +static int get_thread_debug_regs( struct thread *thread, CONTEXT *context ) { - int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct reg regs; - if (ptrace( PTRACE_GETREGS, pid, (caddr_t) ®s, 0 ) == -1) goto error; - if (flags & CONTEXT_INTEGER) - { - context->Eax = regs.r_eax; - context->Ebx = regs.r_ebx; - context->Ecx = regs.r_ecx; - context->Edx = regs.r_edx; - context->Esi = regs.r_esi; - context->Edi = regs.r_edi; - } - if (flags & CONTEXT_CONTROL) - { - context->Ebp = regs.r_ebp; - context->Esp = regs.r_esp; - context->Eip = regs.r_eip; - context->SegCs = regs.r_cs & 0xffff; - context->SegSs = regs.r_ss & 0xffff; - context->EFlags = regs.r_eflags; - } - if (flags & CONTEXT_SEGMENTS) - { - context->SegDs = regs.r_ds & 0xffff; - context->SegEs = regs.r_es & 0xffff; - context->SegFs = regs.r_fs & 0xffff; - context->SegGs = regs.r_gs & 0xffff; - } - context->ContextFlags |= flags & CONTEXT_FULL; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { #ifdef PTRACE_GETDBREGS - struct dbreg dbregs; - if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) - goto error; -#ifdef DBREG_DRX - /* needed for FreeBSD, the structure fields have changed under 5.x */ - context->Dr0 = DBREG_DRX((&dbregs), 0); - context->Dr1 = DBREG_DRX((&dbregs), 1); - context->Dr2 = DBREG_DRX((&dbregs), 2); - context->Dr3 = DBREG_DRX((&dbregs), 3); - context->Dr6 = DBREG_DRX((&dbregs), 6); - context->Dr7 = DBREG_DRX((&dbregs), 7); -#else - context->Dr0 = dbregs.dr0; - context->Dr1 = dbregs.dr1; - context->Dr2 = dbregs.dr2; - context->Dr3 = dbregs.dr3; - context->Dr6 = dbregs.dr6; - context->Dr7 = dbregs.dr7; -#endif - context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; -#endif - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_GETFPREGS, pid, (caddr_t) &context->FloatSave, 0 ) == -1) goto error; - context->FloatSave.Cr0NpxState = 0; /* FIXME */ - context->ContextFlags |= CONTEXT_FLOATING_POINT; - } - return; - error: - file_set_error(); -} - - -/* set a thread context */ -static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context ) -{ int pid = get_ptrace_pid(thread); - if (flags & CONTEXT_FULL) - { - struct reg regs; - if (((flags | CONTEXT_i386) & CONTEXT_FULL) != CONTEXT_FULL) - { - /* need to preserve some registers */ - if (ptrace( PTRACE_GETREGS, pid, (caddr_t) ®s, 0 ) == -1) goto error; - } - if (flags & CONTEXT_INTEGER) - { - regs.r_eax = context->Eax; - regs.r_ebx = context->Ebx; - regs.r_ecx = context->Ecx; - regs.r_edx = context->Edx; - regs.r_esi = context->Esi; - regs.r_edi = context->Edi; - } - if (flags & CONTEXT_CONTROL) - { - regs.r_ebp = context->Ebp; - regs.r_esp = context->Esp; - regs.r_eip = context->Eip; - regs.r_cs = context->SegCs; - regs.r_ss = context->SegSs; - regs.r_eflags = context->EFlags; - } - if (flags & CONTEXT_SEGMENTS) - { - regs.r_ds = context->SegDs; - regs.r_es = context->SegEs; - regs.r_fs = context->SegFs; - regs.r_gs = context->SegGs; - } - if (ptrace( PTRACE_SETREGS, pid, (caddr_t) ®s, 0 ) == -1) goto error; - } - if (flags & CONTEXT_DEBUG_REGISTERS) - { -#ifdef PTRACE_SETDBREGS - struct dbreg dbregs; + + struct dbreg dbregs; + if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) + goto error; #ifdef DBREG_DRX - /* needed for FreeBSD, the structure fields have changed under 5.x */ - DBREG_DRX((&dbregs), 0) = context->Dr0; - DBREG_DRX((&dbregs), 1) = context->Dr1; - DBREG_DRX((&dbregs), 2) = context->Dr2; - DBREG_DRX((&dbregs), 3) = context->Dr3; - DBREG_DRX((&dbregs), 4) = 0; - DBREG_DRX((&dbregs), 5) = 0; - DBREG_DRX((&dbregs), 6) = context->Dr6; - DBREG_DRX((&dbregs), 7) = context->Dr7; + /* needed for FreeBSD, the structure fields have changed under 5.x */ + context->Dr0 = DBREG_DRX((&dbregs), 0); + context->Dr1 = DBREG_DRX((&dbregs), 1); + context->Dr2 = DBREG_DRX((&dbregs), 2); + context->Dr3 = DBREG_DRX((&dbregs), 3); + context->Dr6 = DBREG_DRX((&dbregs), 6); + context->Dr7 = DBREG_DRX((&dbregs), 7); #else - dbregs.dr0 = context->Dr0; - dbregs.dr1 = context->Dr1; - dbregs.dr2 = context->Dr2; - dbregs.dr3 = context->Dr3; - dbregs.dr4 = 0; - dbregs.dr5 = 0; - dbregs.dr6 = context->Dr6; - dbregs.dr7 = context->Dr7; + context->Dr0 = dbregs.dr0; + context->Dr1 = dbregs.dr1; + context->Dr2 = dbregs.dr2; + context->Dr3 = dbregs.dr3; + context->Dr6 = dbregs.dr6; + context->Dr7 = dbregs.dr7; #endif - if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) - goto error; -#endif - } - if (flags & CONTEXT_FLOATING_POINT) - { - /* we can use context->FloatSave directly as it is using the */ - /* correct structure (the same as fsave/frstor) */ - if (ptrace( PTRACE_SETFPREGS, pid, (caddr_t) &context->FloatSave, 0 ) == -1) goto error; - } - return; + return 1; error: file_set_error(); +#endif + return 0; } -#else /* linux || __sun__ || __FreeBSD__ */ -#error You must implement get/set_thread_context_ptrace for your platform -#endif /* linux || __sun__ || __FreeBSD__ */ +/* set the thread x86 debug registers */ +static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context ) +{ +#ifdef PTRACE_SETDBREGS + int pid = get_ptrace_pid(thread); + struct dbreg dbregs; +#ifdef DBREG_DRX + /* needed for FreeBSD, the structure fields have changed under 5.x */ + DBREG_DRX((&dbregs), 0) = context->Dr0; + DBREG_DRX((&dbregs), 1) = context->Dr1; + DBREG_DRX((&dbregs), 2) = context->Dr2; + DBREG_DRX((&dbregs), 3) = context->Dr3; + DBREG_DRX((&dbregs), 4) = 0; + DBREG_DRX((&dbregs), 5) = 0; + DBREG_DRX((&dbregs), 6) = context->Dr6; + DBREG_DRX((&dbregs), 7) = context->Dr7; +#else + dbregs.dr0 = context->Dr0; + dbregs.dr1 = context->Dr1; + dbregs.dr2 = context->Dr2; + dbregs.dr3 = context->Dr3; + dbregs.dr4 = 0; + dbregs.dr5 = 0; + dbregs.dr6 = context->Dr6; + dbregs.dr7 = context->Dr7; +#endif + if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) != -1) return 1; + file_set_error(); +#endif + return 0; +} + +#else /* linux || __FreeBSD__ */ + +/* retrieve the thread x86 debug registers */ +static int get_thread_debug_regs( struct thread *thread, CONTEXT *context ) +{ + return 0; +} + +/* set the thread x86 debug registers */ +static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context ) +{ + return 0; +} + +#endif /* linux || __FreeBSD__ */ /* copy a context structure according to the flags */ @@ -532,9 +239,16 @@ static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) { to->FloatSave = from->FloatSave; } - /* we don't bother copying the debug registers, since they */ - /* always need to be accessed by ptrace anyway */ - to->ContextFlags |= flags & ~CONTEXT_DEBUG_REGISTERS; + 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; + } + to->ContextFlags |= flags; } /* retrieve the current instruction pointer of a context */ @@ -550,13 +264,11 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f flags &= ~CONTEXT_i386; /* get rid of CPU id */ if (thread->context) /* thread is inside an exception event or suspended */ - copy_context( context, thread->context, flags ); + copy_context( context, thread->context, flags & ~CONTEXT_DEBUG_REGISTERS ); - flags &= CONTEXT_DEBUG_REGISTERS; - - if (flags && suspend_for_ptrace( thread )) + if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread )) { - get_thread_context_ptrace( thread, flags, context ); + if (get_thread_debug_regs( thread, context )) context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; resume_after_ptrace( thread ); } } @@ -566,16 +278,13 @@ void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned { flags &= ~CONTEXT_i386; /* get rid of CPU id */ - if (thread->context) /* thread is inside an exception event or suspended */ - copy_context( thread->context, context, flags ); - - flags &= CONTEXT_DEBUG_REGISTERS; /* the other registers are handled on the client side */ - - if (flags && suspend_for_ptrace( thread )) + if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread )) { - set_thread_context_ptrace( thread, flags, context ); + if (!set_thread_debug_regs( thread, context )) flags &= ~CONTEXT_DEBUG_REGISTERS; resume_after_ptrace( thread ); } + + if (thread->context) copy_context( thread->context, context, flags ); } #endif /* __i386__ */