forked from Mirrors/wine-wine
server: Moved some common bits of get/set_thread_context to thread.c.
parent
e040e6c4f8
commit
86d4688171
|
@ -239,8 +239,9 @@ static void set_thread_context( struct thread *thread, unsigned int flags, const
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
/* copy a context structure according to the flags */
|
||||||
static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
||||||
{
|
{
|
||||||
|
flags &= ~CONTEXT_ALPHA; /* get rid of CPU id */
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
to->IntRa = from->IntRa;
|
to->IntRa = from->IntRa;
|
||||||
|
@ -327,17 +328,23 @@ void *get_context_ip( const CONTEXT *context )
|
||||||
return (void *)context->Fir;
|
return (void *)context->Fir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the context flag that contains the CPU id */
|
||||||
|
unsigned int get_context_cpu_flag(void)
|
||||||
|
{
|
||||||
|
return CONTEXT_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return only the context flags that correspond to system regs */
|
||||||
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
unsigned int get_context_system_regs( unsigned int flags )
|
||||||
|
{
|
||||||
|
return flags & ~CONTEXT_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve the thread context */
|
/* retrieve the thread context */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
context->ContextFlags |= CONTEXT_ALPHA;
|
if (suspend_for_ptrace( thread ))
|
||||||
flags &= ~CONTEXT_ALPHA; /* get rid of CPU id */
|
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( context, thread->context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
get_thread_context_ptrace( thread, flags, context );
|
get_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
@ -347,13 +354,7 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
/* set the thread context */
|
/* set the thread context */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
flags &= ~CONTEXT_ALPHA; /* get rid of CPU id */
|
if (suspend_for_ptrace( thread ))
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( thread->context, context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
set_thread_context_ptrace( thread, flags, context );
|
set_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
|
|
@ -89,81 +89,111 @@ static inline int get_debug_reg( int pid, int num, DWORD *data )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* retrieve the thread x86 debug registers */
|
/* retrieve the thread x86 registers */
|
||||||
static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int pid = get_ptrace_pid(thread);
|
int pid = get_ptrace_pid(thread);
|
||||||
|
|
||||||
|
/* all other regs are handled on the client side */
|
||||||
|
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
||||||
|
|
||||||
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
if (get_debug_reg( pid, 0, &context->Dr0 ) == -1) goto error;
|
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, 1, &context->Dr1 ) == -1) goto error;
|
||||||
if (get_debug_reg( pid, 2, &context->Dr2 ) == -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, 3, &context->Dr3 ) == -1) goto error;
|
||||||
if (get_debug_reg( pid, 6, &context->Dr6 ) == -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;
|
if (get_debug_reg( pid, 7, &context->Dr7 ) == -1) goto error;
|
||||||
return 1;
|
context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
||||||
|
resume_after_ptrace( thread );
|
||||||
|
return;
|
||||||
error:
|
error:
|
||||||
file_set_error();
|
file_set_error();
|
||||||
return 0;
|
resume_after_ptrace( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 debug registers */
|
/* set the thread x86 registers */
|
||||||
static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int pid = get_ptrace_pid(thread);
|
int pid = get_ptrace_pid( thread );
|
||||||
|
|
||||||
|
/* all other regs are handled on the client side */
|
||||||
|
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
||||||
|
|
||||||
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error;
|
||||||
|
if (thread->context) thread->context->Dr0 = context->Dr0;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error;
|
||||||
|
if (thread->context) thread->context->Dr1 = context->Dr1;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error;
|
||||||
|
if (thread->context) thread->context->Dr2 = context->Dr2;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error;
|
||||||
|
if (thread->context) thread->context->Dr3 = context->Dr3;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error;
|
||||||
|
if (thread->context) thread->context->Dr6 = context->Dr6;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error;
|
||||||
return 1;
|
if (thread->context) thread->context->Dr7 = context->Dr7;
|
||||||
|
resume_after_ptrace( thread );
|
||||||
|
return;
|
||||||
error:
|
error:
|
||||||
file_set_error();
|
file_set_error();
|
||||||
return 0;
|
resume_after_ptrace( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
/* retrieve the thread x86 debug registers */
|
/* retrieve the thread x86 registers */
|
||||||
static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
#ifdef PTRACE_GETDBREGS
|
#ifdef PTRACE_GETDBREGS
|
||||||
int pid = get_ptrace_pid(thread);
|
int pid = get_ptrace_pid(thread);
|
||||||
|
|
||||||
struct dbreg dbregs;
|
struct dbreg dbregs;
|
||||||
if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1)
|
|
||||||
goto error;
|
/* all other regs are handled on the client side */
|
||||||
|
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
||||||
|
|
||||||
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
|
if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
|
||||||
|
else
|
||||||
|
{
|
||||||
#ifdef DBREG_DRX
|
#ifdef DBREG_DRX
|
||||||
/* needed for FreeBSD, the structure fields have changed under 5.x */
|
/* needed for FreeBSD, the structure fields have changed under 5.x */
|
||||||
context->Dr0 = DBREG_DRX((&dbregs), 0);
|
context->Dr0 = DBREG_DRX((&dbregs), 0);
|
||||||
context->Dr1 = DBREG_DRX((&dbregs), 1);
|
context->Dr1 = DBREG_DRX((&dbregs), 1);
|
||||||
context->Dr2 = DBREG_DRX((&dbregs), 2);
|
context->Dr2 = DBREG_DRX((&dbregs), 2);
|
||||||
context->Dr3 = DBREG_DRX((&dbregs), 3);
|
context->Dr3 = DBREG_DRX((&dbregs), 3);
|
||||||
context->Dr6 = DBREG_DRX((&dbregs), 6);
|
context->Dr6 = DBREG_DRX((&dbregs), 6);
|
||||||
context->Dr7 = DBREG_DRX((&dbregs), 7);
|
context->Dr7 = DBREG_DRX((&dbregs), 7);
|
||||||
#else
|
#else
|
||||||
context->Dr0 = dbregs.dr0;
|
context->Dr0 = dbregs.dr0;
|
||||||
context->Dr1 = dbregs.dr1;
|
context->Dr1 = dbregs.dr1;
|
||||||
context->Dr2 = dbregs.dr2;
|
context->Dr2 = dbregs.dr2;
|
||||||
context->Dr3 = dbregs.dr3;
|
context->Dr3 = dbregs.dr3;
|
||||||
context->Dr6 = dbregs.dr6;
|
context->Dr6 = dbregs.dr6;
|
||||||
context->Dr7 = dbregs.dr7;
|
context->Dr7 = dbregs.dr7;
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
||||||
error:
|
}
|
||||||
file_set_error();
|
resume_after_ptrace( thread );
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 debug registers */
|
/* set the thread x86 registers */
|
||||||
static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
#ifdef PTRACE_SETDBREGS
|
#ifdef PTRACE_SETDBREGS
|
||||||
int pid = get_ptrace_pid(thread);
|
int pid = get_ptrace_pid(thread);
|
||||||
struct dbreg dbregs;
|
struct dbreg dbregs;
|
||||||
|
|
||||||
|
/* all other regs are handled on the client side */
|
||||||
|
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
||||||
|
|
||||||
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
#ifdef DBREG_DRX
|
#ifdef DBREG_DRX
|
||||||
/* needed for FreeBSD, the structure fields have changed under 5.x */
|
/* needed for FreeBSD, the structure fields have changed under 5.x */
|
||||||
DBREG_DRX((&dbregs), 0) = context->Dr0;
|
DBREG_DRX((&dbregs), 0) = context->Dr0;
|
||||||
|
@ -184,32 +214,39 @@ static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context
|
||||||
dbregs.dr6 = context->Dr6;
|
dbregs.dr6 = context->Dr6;
|
||||||
dbregs.dr7 = context->Dr7;
|
dbregs.dr7 = context->Dr7;
|
||||||
#endif
|
#endif
|
||||||
if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) != -1) return 1;
|
if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
|
||||||
file_set_error();
|
else if (thread->context) /* update the cached values */
|
||||||
|
{
|
||||||
|
thread->context->Dr0 = context->Dr0;
|
||||||
|
thread->context->Dr1 = context->Dr1;
|
||||||
|
thread->context->Dr2 = context->Dr2;
|
||||||
|
thread->context->Dr3 = context->Dr3;
|
||||||
|
thread->context->Dr6 = context->Dr6;
|
||||||
|
thread->context->Dr7 = context->Dr7;
|
||||||
|
}
|
||||||
|
resume_after_ptrace( thread );
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* linux || __FreeBSD__ */
|
#else /* linux || __FreeBSD__ */
|
||||||
|
|
||||||
/* retrieve the thread x86 debug registers */
|
/* retrieve the thread x86 registers */
|
||||||
static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 debug registers */
|
/* set the thread x86 debug registers */
|
||||||
static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* linux || __FreeBSD__ */
|
#endif /* linux || __FreeBSD__ */
|
||||||
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
/* copy a context structure according to the flags */
|
||||||
static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
||||||
{
|
{
|
||||||
|
flags &= ~CONTEXT_i386; /* get rid of CPU id */
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
to->Ebp = from->Ebp;
|
to->Ebp = from->Ebp;
|
||||||
|
@ -257,34 +294,17 @@ void *get_context_ip( const CONTEXT *context )
|
||||||
return (void *)context->Eip;
|
return (void *)context->Eip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* retrieve the thread context */
|
/* return the context flag that contains the CPU id */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
unsigned int get_context_cpu_flag(void)
|
||||||
{
|
{
|
||||||
context->ContextFlags |= CONTEXT_i386;
|
return CONTEXT_i386;
|
||||||
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 & ~CONTEXT_DEBUG_REGISTERS );
|
|
||||||
|
|
||||||
if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread ))
|
|
||||||
{
|
|
||||||
if (get_thread_debug_regs( thread, context )) context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
|
||||||
resume_after_ptrace( thread );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread context */
|
/* return only the context flags that correspond to system regs */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
unsigned int get_context_system_regs( unsigned int flags )
|
||||||
{
|
{
|
||||||
flags &= ~CONTEXT_i386; /* get rid of CPU id */
|
return flags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386);
|
||||||
|
|
||||||
if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread ))
|
|
||||||
{
|
|
||||||
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__ */
|
#endif /* __i386__ */
|
||||||
|
|
|
@ -201,7 +201,7 @@ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags
|
||||||
#define FREG(x) to->Fpr##x = from->Fpr##x;
|
#define FREG(x) to->Fpr##x = from->Fpr##x;
|
||||||
#define CREG(x) to->x = from->x;
|
#define CREG(x) to->x = from->x;
|
||||||
/* copy a context structure according to the flags */
|
/* copy a context structure according to the flags */
|
||||||
static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
||||||
{
|
{
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
|
@ -266,14 +266,23 @@ void *get_context_ip( const CONTEXT *context )
|
||||||
return (void *)context->Iar;
|
return (void *)context->Iar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the context flag that contains the CPU id */
|
||||||
|
unsigned int get_context_cpu_flag(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return only the context flags that correspond to system regs */
|
||||||
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
unsigned int get_context_system_regs( unsigned int flags )
|
||||||
|
{
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve the thread context */
|
/* retrieve the thread context */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
if (suspend_for_ptrace( thread ))
|
||||||
{
|
|
||||||
copy_context( context, thread->context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
get_thread_context_ptrace( thread, flags, context );
|
get_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
@ -283,11 +292,7 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
/* set the thread context */
|
/* set the thread context */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
if (suspend_for_ptrace( thread ))
|
||||||
{
|
|
||||||
copy_context( thread->context, context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
set_thread_context_ptrace( thread, flags, context );
|
set_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
|
|
@ -106,8 +106,9 @@ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags
|
||||||
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
/* copy a context structure according to the flags */
|
||||||
static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
||||||
{
|
{
|
||||||
|
flags &= ~CONTEXT_SPARC; /* get rid of CPU id */
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
to->psr = from->psr;
|
to->psr = from->psr;
|
||||||
|
@ -165,17 +166,23 @@ void *get_context_ip( const CONTEXT *context )
|
||||||
return (void *)context->pc;
|
return (void *)context->pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the context flag that contains the CPU id */
|
||||||
|
unsigned int get_context_cpu_flag(void)
|
||||||
|
{
|
||||||
|
return CONTEXT_SPARC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return only the context flags that correspond to system regs */
|
||||||
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
unsigned int get_context_system_regs( unsigned int flags )
|
||||||
|
{
|
||||||
|
return flags & ~CONTEXT_SPARC;
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve the thread context */
|
/* retrieve the thread context */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
context->ContextFlags |= CONTEXT_SPARC;
|
if (suspend_for_ptrace( thread ))
|
||||||
flags &= ~CONTEXT_SPARC; /* get rid of CPU id */
|
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( context, thread->context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
get_thread_context_ptrace( thread, flags, context );
|
get_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
@ -185,13 +192,7 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
/* set the thread context */
|
/* set the thread context */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
flags &= ~CONTEXT_SPARC; /* get rid of CPU id */
|
if (suspend_for_ptrace( thread ))
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( thread->context, context, flags );
|
|
||||||
}
|
|
||||||
else if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
set_thread_context_ptrace( thread, flags, context );
|
set_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
|
|
@ -203,8 +203,9 @@ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags
|
||||||
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
/* copy a context structure according to the flags */
|
||||||
static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
||||||
{
|
{
|
||||||
|
flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
to->Rbp = from->Rbp;
|
to->Rbp = from->Rbp;
|
||||||
|
@ -254,19 +255,23 @@ void *get_context_ip( const CONTEXT *context )
|
||||||
return (void *)context->Rip;
|
return (void *)context->Rip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the context flag that contains the CPU id */
|
||||||
|
unsigned int get_context_cpu_flag(void)
|
||||||
|
{
|
||||||
|
return CONTEXT_AMD64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return only the context flags that correspond to system regs */
|
||||||
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
unsigned int get_context_system_regs( unsigned int flags )
|
||||||
|
{
|
||||||
|
return flags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64);
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve the thread context */
|
/* retrieve the thread context */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
context->ContextFlags |= CONTEXT_AMD64;
|
if (suspend_for_ptrace( thread ))
|
||||||
flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
|
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( context, thread->context, flags );
|
|
||||||
flags &= CONTEXT_DEBUG_REGISTERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
get_thread_context_ptrace( thread, flags, context );
|
get_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
@ -276,15 +281,7 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
/* set the thread context */
|
/* set the thread context */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
|
if (suspend_for_ptrace( thread ))
|
||||||
|
|
||||||
if (thread->context) /* thread is inside an exception event or suspended */
|
|
||||||
{
|
|
||||||
copy_context( thread->context, context, flags );
|
|
||||||
flags &= CONTEXT_DEBUG_REGISTERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags && suspend_for_ptrace( thread ))
|
|
||||||
{
|
{
|
||||||
set_thread_context_ptrace( thread, flags, context );
|
set_thread_context_ptrace( thread, flags, context );
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
|
|
|
@ -1043,7 +1043,7 @@ DECL_HANDLER(get_apc)
|
||||||
DECL_HANDLER(get_thread_context)
|
DECL_HANDLER(get_thread_context)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
void *data;
|
CONTEXT *context;
|
||||||
|
|
||||||
if (get_reply_max_size() < sizeof(CONTEXT))
|
if (get_reply_max_size() < sizeof(CONTEXT))
|
||||||
{
|
{
|
||||||
|
@ -1072,10 +1072,14 @@ DECL_HANDLER(get_thread_context)
|
||||||
if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
|
if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
|
||||||
else set_error( STATUS_PENDING );
|
else set_error( STATUS_PENDING );
|
||||||
}
|
}
|
||||||
else if ((data = set_reply_data_size( sizeof(CONTEXT) )))
|
else if ((context = set_reply_data_size( sizeof(CONTEXT) )))
|
||||||
{
|
{
|
||||||
memset( data, 0, sizeof(CONTEXT) );
|
unsigned int flags = get_context_system_regs( req->flags );
|
||||||
get_thread_context( thread, data, req->flags );
|
|
||||||
|
memset( context, 0, sizeof(CONTEXT) );
|
||||||
|
context->ContextFlags = get_context_cpu_flag();
|
||||||
|
if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
|
||||||
|
if (flags) get_thread_context( thread, context, flags );
|
||||||
}
|
}
|
||||||
reply->self = (thread == current);
|
reply->self = (thread == current);
|
||||||
release_object( thread );
|
release_object( thread );
|
||||||
|
@ -1115,7 +1119,12 @@ DECL_HANDLER(set_thread_context)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_thread_context( thread, get_req_data(), req->flags );
|
const CONTEXT *context = get_req_data();
|
||||||
|
unsigned int flags = get_context_system_regs( req->flags );
|
||||||
|
|
||||||
|
if (flags) set_thread_context( thread, context, flags );
|
||||||
|
if (thread->context && !get_error())
|
||||||
|
copy_context( thread->context, context, req->flags & ~flags );
|
||||||
}
|
}
|
||||||
reply->self = (thread == current);
|
reply->self = (thread == current);
|
||||||
release_object( thread );
|
release_object( thread );
|
||||||
|
|
|
@ -119,13 +119,18 @@ extern int thread_get_inflight_fd( struct thread *thread, int client );
|
||||||
extern struct thread_snapshot *thread_snap( int *count );
|
extern struct thread_snapshot *thread_snap( int *count );
|
||||||
extern struct token *thread_get_impersonation_token( struct thread *thread );
|
extern struct token *thread_get_impersonation_token( struct thread *thread );
|
||||||
|
|
||||||
|
/* CPU context functions */
|
||||||
|
extern void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags );
|
||||||
|
extern void *get_context_ip( const CONTEXT *context );
|
||||||
|
extern unsigned int get_context_cpu_flag(void);
|
||||||
|
extern unsigned int get_context_system_regs( unsigned int flags );
|
||||||
|
|
||||||
/* ptrace functions */
|
/* ptrace functions */
|
||||||
|
|
||||||
extern void sigchld_callback(void);
|
extern void sigchld_callback(void);
|
||||||
extern int get_ptrace_pid( struct thread *thread );
|
extern int get_ptrace_pid( struct thread *thread );
|
||||||
extern int suspend_for_ptrace( struct thread *thread );
|
extern int suspend_for_ptrace( struct thread *thread );
|
||||||
extern void resume_after_ptrace( struct thread *thread );
|
extern void resume_after_ptrace( struct thread *thread );
|
||||||
extern void *get_context_ip( const CONTEXT *context );
|
|
||||||
extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
|
extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
|
||||||
extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
|
extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
|
||||||
extern int send_thread_signal( struct thread *thread, int sig );
|
extern int send_thread_signal( struct thread *thread, int sig );
|
||||||
|
|
Loading…
Reference in New Issue