server: Define a generic context structure instead of using the platform-specific version.
This commit is contained in:
parent
53929f1906
commit
5316dd011f
|
@ -149,14 +149,16 @@ void wait_suspend( CONTEXT *context )
|
||||||
{
|
{
|
||||||
LARGE_INTEGER timeout;
|
LARGE_INTEGER timeout;
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
|
||||||
/* store the context we got at suspend time */
|
/* store the context we got at suspend time */
|
||||||
SERVER_START_REQ( set_thread_context )
|
SERVER_START_REQ( set_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( GetCurrentThread() );
|
req->handle = wine_server_obj_handle( GetCurrentThread() );
|
||||||
req->flags = CONTEXT_FULL;
|
|
||||||
req->suspend = 1;
|
req->suspend = 1;
|
||||||
wine_server_add_data( req, context, sizeof(*context) );
|
wine_server_add_data( req, &server_context, sizeof(server_context) );
|
||||||
wine_server_call( req );
|
wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -169,13 +171,13 @@ void wait_suspend( CONTEXT *context )
|
||||||
SERVER_START_REQ( get_thread_context )
|
SERVER_START_REQ( get_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( GetCurrentThread() );
|
req->handle = wine_server_obj_handle( GetCurrentThread() );
|
||||||
req->flags = CONTEXT_FULL;
|
|
||||||
req->suspend = 1;
|
req->suspend = 1;
|
||||||
wine_server_set_reply( req, context, sizeof(*context) );
|
wine_server_set_reply( req, &server_context, sizeof(server_context) );
|
||||||
wine_server_call( req );
|
wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
context_from_server( context, &server_context );
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,16 +189,19 @@ void wait_suspend( CONTEXT *context )
|
||||||
*/
|
*/
|
||||||
static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context )
|
static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context )
|
||||||
{
|
{
|
||||||
int ret;
|
NTSTATUS ret;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
HANDLE handle = 0;
|
HANDLE handle = 0;
|
||||||
client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
|
client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
if (!NtCurrentTeb()->Peb->BeingDebugged) return 0; /* no debugger present */
|
if (!NtCurrentTeb()->Peb->BeingDebugged) return 0; /* no debugger present */
|
||||||
|
|
||||||
for (i = 0; i < min( rec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS ); i++)
|
for (i = 0; i < min( rec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS ); i++)
|
||||||
params[i] = rec->ExceptionInformation[i];
|
params[i] = rec->ExceptionInformation[i];
|
||||||
|
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
|
||||||
SERVER_START_REQ( queue_exception_event )
|
SERVER_START_REQ( queue_exception_event )
|
||||||
{
|
{
|
||||||
req->first = first_chance;
|
req->first = first_chance;
|
||||||
|
@ -206,7 +211,7 @@ static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTE
|
||||||
req->address = wine_server_client_ptr( rec->ExceptionAddress );
|
req->address = wine_server_client_ptr( rec->ExceptionAddress );
|
||||||
req->len = i * sizeof(params[0]);
|
req->len = i * sizeof(params[0]);
|
||||||
wine_server_add_data( req, params, req->len );
|
wine_server_add_data( req, params, req->len );
|
||||||
wine_server_add_data( req, context, sizeof(*context) );
|
wine_server_add_data( req, &server_context, sizeof(server_context) );
|
||||||
if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
|
if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -217,10 +222,11 @@ static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTE
|
||||||
SERVER_START_REQ( get_exception_status )
|
SERVER_START_REQ( get_exception_status )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
wine_server_set_reply( req, context, sizeof(*context) );
|
wine_server_set_reply( req, &server_context, sizeof(server_context) );
|
||||||
ret = wine_server_call( req );
|
ret = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
if (!ret) ret = context_from_server( context, &server_context );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ extern void wait_suspend( CONTEXT *context );
|
||||||
extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
|
extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
|
||||||
extern void set_cpu_context( const CONTEXT *context );
|
extern void set_cpu_context( const CONTEXT *context );
|
||||||
extern void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags );
|
extern void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags );
|
||||||
|
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from );
|
||||||
|
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from );
|
||||||
|
|
||||||
/* debug helpers */
|
/* debug helpers */
|
||||||
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
||||||
|
|
|
@ -55,6 +55,8 @@
|
||||||
# include <sys/sysctl.h>
|
# include <sys/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
#include "ntdll_misc.h"
|
#include "ntdll_misc.h"
|
||||||
|
@ -1064,6 +1066,148 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_to_server
|
||||||
|
*
|
||||||
|
* Convert a register context to the server format.
|
||||||
|
*/
|
||||||
|
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
||||||
|
{
|
||||||
|
DWORD flags = from->ContextFlags & ~CONTEXT_i386; /* get rid of CPU id */
|
||||||
|
|
||||||
|
memset( to, 0, sizeof(*to) );
|
||||||
|
to->cpu = CPU_x86;
|
||||||
|
|
||||||
|
if (flags & CONTEXT_CONTROL)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_CONTROL;
|
||||||
|
to->ctl.i386_regs.ebp = from->Ebp;
|
||||||
|
to->ctl.i386_regs.esp = from->Esp;
|
||||||
|
to->ctl.i386_regs.eip = from->Eip;
|
||||||
|
to->ctl.i386_regs.cs = from->SegCs;
|
||||||
|
to->ctl.i386_regs.ss = from->SegSs;
|
||||||
|
to->ctl.i386_regs.eflags = from->EFlags;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_INTEGER)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_INTEGER;
|
||||||
|
to->integer.i386_regs.eax = from->Eax;
|
||||||
|
to->integer.i386_regs.ebx = from->Ebx;
|
||||||
|
to->integer.i386_regs.ecx = from->Ecx;
|
||||||
|
to->integer.i386_regs.edx = from->Edx;
|
||||||
|
to->integer.i386_regs.esi = from->Esi;
|
||||||
|
to->integer.i386_regs.edi = from->Edi;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_SEGMENTS)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_SEGMENTS;
|
||||||
|
to->seg.i386_regs.ds = from->SegDs;
|
||||||
|
to->seg.i386_regs.es = from->SegEs;
|
||||||
|
to->seg.i386_regs.fs = from->SegFs;
|
||||||
|
to->seg.i386_regs.gs = from->SegGs;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_FLOATING_POINT;
|
||||||
|
to->fp.i386_regs.ctrl = from->FloatSave.ControlWord;
|
||||||
|
to->fp.i386_regs.status = from->FloatSave.StatusWord;
|
||||||
|
to->fp.i386_regs.tag = from->FloatSave.TagWord;
|
||||||
|
to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset;
|
||||||
|
to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector;
|
||||||
|
to->fp.i386_regs.data_off = from->FloatSave.DataOffset;
|
||||||
|
to->fp.i386_regs.data_sel = from->FloatSave.DataSelector;
|
||||||
|
to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState;
|
||||||
|
memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) );
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_DEBUG_REGISTERS)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
|
to->debug.i386_regs.dr0 = from->Dr0;
|
||||||
|
to->debug.i386_regs.dr1 = from->Dr1;
|
||||||
|
to->debug.i386_regs.dr2 = from->Dr2;
|
||||||
|
to->debug.i386_regs.dr3 = from->Dr3;
|
||||||
|
to->debug.i386_regs.dr6 = from->Dr6;
|
||||||
|
to->debug.i386_regs.dr7 = from->Dr7;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_EXTENDED_REGISTERS)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
|
||||||
|
memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_from_server
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* is_privileged_instr
|
* is_privileged_instr
|
||||||
*
|
*
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
# include <sys/signal.h>
|
# include <sys/signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
|
@ -298,9 +300,13 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
{
|
{
|
||||||
if (flags & CONTEXT_CONTROL)
|
if (flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
to->Msr = from->Msr;
|
to->Msr = from->Msr;
|
||||||
to->Ctr = from->Ctr;
|
to->Ctr = from->Ctr;
|
||||||
to->Iar = from->Iar;
|
to->Iar = from->Iar;
|
||||||
|
to->Lr = from->Lr;
|
||||||
|
to->Dar = from->Dar;
|
||||||
|
to->Dsisr = from->Dsisr;
|
||||||
|
to->Trap = from->Trap;
|
||||||
}
|
}
|
||||||
if (flags & CONTEXT_INTEGER)
|
if (flags & CONTEXT_INTEGER)
|
||||||
{
|
{
|
||||||
|
@ -378,6 +384,208 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_to_server
|
||||||
|
*
|
||||||
|
* Convert a register context to the server format.
|
||||||
|
*/
|
||||||
|
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
||||||
|
{
|
||||||
|
DWORD flags = from->ContextFlags; /* no CPU id? */
|
||||||
|
|
||||||
|
memset( to, 0, sizeof(*to) );
|
||||||
|
to->cpu = CPU_POWERPC;
|
||||||
|
|
||||||
|
if (flags & CONTEXT_CONTROL)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_CONTROL;
|
||||||
|
to->ctl.powerpc_regs.iar = from->Iar;
|
||||||
|
to->ctl.powerpc_regs.msr = from->Msr;
|
||||||
|
to->ctl.powerpc_regs.ctr = from->Ctr;
|
||||||
|
to->ctl.powerpc_regs.lr = from->Lr;
|
||||||
|
to->ctl.powerpc_regs.dar = from->Dar;
|
||||||
|
to->ctl.powerpc_regs.dsisr = from->Dsisr;
|
||||||
|
to->ctl.powerpc_regs.trap = from->Trap;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_INTEGER)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_INTEGER;
|
||||||
|
to->integer.powerpc_regs.gpr[0] = from->Gpr0;
|
||||||
|
to->integer.powerpc_regs.gpr[1] = from->Gpr1;
|
||||||
|
to->integer.powerpc_regs.gpr[2] = from->Gpr2;
|
||||||
|
to->integer.powerpc_regs.gpr[3] = from->Gpr3;
|
||||||
|
to->integer.powerpc_regs.gpr[4] = from->Gpr4;
|
||||||
|
to->integer.powerpc_regs.gpr[5] = from->Gpr5;
|
||||||
|
to->integer.powerpc_regs.gpr[6] = from->Gpr6;
|
||||||
|
to->integer.powerpc_regs.gpr[7] = from->Gpr7;
|
||||||
|
to->integer.powerpc_regs.gpr[8] = from->Gpr8;
|
||||||
|
to->integer.powerpc_regs.gpr[9] = from->Gpr9;
|
||||||
|
to->integer.powerpc_regs.gpr[10] = from->Gpr10;
|
||||||
|
to->integer.powerpc_regs.gpr[11] = from->Gpr11;
|
||||||
|
to->integer.powerpc_regs.gpr[12] = from->Gpr12;
|
||||||
|
to->integer.powerpc_regs.gpr[13] = from->Gpr13;
|
||||||
|
to->integer.powerpc_regs.gpr[14] = from->Gpr14;
|
||||||
|
to->integer.powerpc_regs.gpr[15] = from->Gpr15;
|
||||||
|
to->integer.powerpc_regs.gpr[16] = from->Gpr16;
|
||||||
|
to->integer.powerpc_regs.gpr[17] = from->Gpr17;
|
||||||
|
to->integer.powerpc_regs.gpr[18] = from->Gpr18;
|
||||||
|
to->integer.powerpc_regs.gpr[19] = from->Gpr19;
|
||||||
|
to->integer.powerpc_regs.gpr[20] = from->Gpr20;
|
||||||
|
to->integer.powerpc_regs.gpr[21] = from->Gpr21;
|
||||||
|
to->integer.powerpc_regs.gpr[22] = from->Gpr22;
|
||||||
|
to->integer.powerpc_regs.gpr[23] = from->Gpr23;
|
||||||
|
to->integer.powerpc_regs.gpr[24] = from->Gpr24;
|
||||||
|
to->integer.powerpc_regs.gpr[25] = from->Gpr25;
|
||||||
|
to->integer.powerpc_regs.gpr[26] = from->Gpr26;
|
||||||
|
to->integer.powerpc_regs.gpr[27] = from->Gpr27;
|
||||||
|
to->integer.powerpc_regs.gpr[28] = from->Gpr28;
|
||||||
|
to->integer.powerpc_regs.gpr[29] = from->Gpr29;
|
||||||
|
to->integer.powerpc_regs.gpr[30] = from->Gpr30;
|
||||||
|
to->integer.powerpc_regs.gpr[31] = from->Gpr31;
|
||||||
|
to->integer.powerpc_regs.xer = from->Xer;
|
||||||
|
to->integer.powerpc_regs.cr = from->Cr;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_FLOATING_POINT;
|
||||||
|
to->fp.powerpc_regs.fpr[0] = from->Fpr0;
|
||||||
|
to->fp.powerpc_regs.fpr[1] = from->Fpr1;
|
||||||
|
to->fp.powerpc_regs.fpr[2] = from->Fpr2;
|
||||||
|
to->fp.powerpc_regs.fpr[3] = from->Fpr3;
|
||||||
|
to->fp.powerpc_regs.fpr[4] = from->Fpr4;
|
||||||
|
to->fp.powerpc_regs.fpr[5] = from->Fpr5;
|
||||||
|
to->fp.powerpc_regs.fpr[6] = from->Fpr6;
|
||||||
|
to->fp.powerpc_regs.fpr[7] = from->Fpr7;
|
||||||
|
to->fp.powerpc_regs.fpr[8] = from->Fpr8;
|
||||||
|
to->fp.powerpc_regs.fpr[9] = from->Fpr9;
|
||||||
|
to->fp.powerpc_regs.fpr[10] = from->Fpr10;
|
||||||
|
to->fp.powerpc_regs.fpr[11] = from->Fpr11;
|
||||||
|
to->fp.powerpc_regs.fpr[12] = from->Fpr12;
|
||||||
|
to->fp.powerpc_regs.fpr[13] = from->Fpr13;
|
||||||
|
to->fp.powerpc_regs.fpr[14] = from->Fpr14;
|
||||||
|
to->fp.powerpc_regs.fpr[15] = from->Fpr15;
|
||||||
|
to->fp.powerpc_regs.fpr[16] = from->Fpr16;
|
||||||
|
to->fp.powerpc_regs.fpr[17] = from->Fpr17;
|
||||||
|
to->fp.powerpc_regs.fpr[18] = from->Fpr18;
|
||||||
|
to->fp.powerpc_regs.fpr[19] = from->Fpr19;
|
||||||
|
to->fp.powerpc_regs.fpr[20] = from->Fpr20;
|
||||||
|
to->fp.powerpc_regs.fpr[21] = from->Fpr21;
|
||||||
|
to->fp.powerpc_regs.fpr[22] = from->Fpr22;
|
||||||
|
to->fp.powerpc_regs.fpr[23] = from->Fpr23;
|
||||||
|
to->fp.powerpc_regs.fpr[24] = from->Fpr24;
|
||||||
|
to->fp.powerpc_regs.fpr[25] = from->Fpr25;
|
||||||
|
to->fp.powerpc_regs.fpr[26] = from->Fpr26;
|
||||||
|
to->fp.powerpc_regs.fpr[27] = from->Fpr27;
|
||||||
|
to->fp.powerpc_regs.fpr[28] = from->Fpr28;
|
||||||
|
to->fp.powerpc_regs.fpr[29] = from->Fpr29;
|
||||||
|
to->fp.powerpc_regs.fpr[30] = from->Fpr30;
|
||||||
|
to->fp.powerpc_regs.fpr[31] = from->Fpr31;
|
||||||
|
to->fp.powerpc_regs.fpscr = from->Fpscr;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_from_server
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_fpu_code
|
* get_fpu_code
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
@ -230,6 +232,136 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_to_server
|
||||||
|
*
|
||||||
|
* Convert a register context to the server format.
|
||||||
|
*/
|
||||||
|
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
||||||
|
{
|
||||||
|
DWORD flags = from->ContextFlags & ~CONTEXT_SPARC; /* get rid of CPU id */
|
||||||
|
|
||||||
|
memset( to, 0, sizeof(*to) );
|
||||||
|
to->cpu = CPU_SPARC;
|
||||||
|
|
||||||
|
if (flags & CONTEXT_CONTROL)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_CONTROL;
|
||||||
|
to->ctl.sparc_regs.psr = from->psr;
|
||||||
|
to->ctl.sparc_regs.pc = from->pc;
|
||||||
|
to->ctl.sparc_regs.npc = from->npc;
|
||||||
|
to->ctl.sparc_regs.y = from->y;
|
||||||
|
to->ctl.sparc_regs.wim = from->wim;
|
||||||
|
to->ctl.sparc_regs.tbr = from->tbr;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_INTEGER)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_INTEGER;
|
||||||
|
to->integer.sparc_regs.g[0] = from->g0;
|
||||||
|
to->integer.sparc_regs.g[1] = from->g1;
|
||||||
|
to->integer.sparc_regs.g[2] = from->g2;
|
||||||
|
to->integer.sparc_regs.g[3] = from->g3;
|
||||||
|
to->integer.sparc_regs.g[4] = from->g4;
|
||||||
|
to->integer.sparc_regs.g[5] = from->g5;
|
||||||
|
to->integer.sparc_regs.g[6] = from->g6;
|
||||||
|
to->integer.sparc_regs.g[7] = from->g7;
|
||||||
|
to->integer.sparc_regs.o[0] = from->o0;
|
||||||
|
to->integer.sparc_regs.o[1] = from->o1;
|
||||||
|
to->integer.sparc_regs.o[2] = from->o2;
|
||||||
|
to->integer.sparc_regs.o[3] = from->o3;
|
||||||
|
to->integer.sparc_regs.o[4] = from->o4;
|
||||||
|
to->integer.sparc_regs.o[5] = from->o5;
|
||||||
|
to->integer.sparc_regs.o[6] = from->o6;
|
||||||
|
to->integer.sparc_regs.o[7] = from->o7;
|
||||||
|
to->integer.sparc_regs.l[0] = from->l0;
|
||||||
|
to->integer.sparc_regs.l[1] = from->l1;
|
||||||
|
to->integer.sparc_regs.l[2] = from->l2;
|
||||||
|
to->integer.sparc_regs.l[3] = from->l3;
|
||||||
|
to->integer.sparc_regs.l[4] = from->l4;
|
||||||
|
to->integer.sparc_regs.l[5] = from->l5;
|
||||||
|
to->integer.sparc_regs.l[6] = from->l6;
|
||||||
|
to->integer.sparc_regs.l[7] = from->l7;
|
||||||
|
to->integer.sparc_regs.i[0] = from->i0;
|
||||||
|
to->integer.sparc_regs.i[1] = from->i1;
|
||||||
|
to->integer.sparc_regs.i[2] = from->i2;
|
||||||
|
to->integer.sparc_regs.i[3] = from->i3;
|
||||||
|
to->integer.sparc_regs.i[4] = from->i4;
|
||||||
|
to->integer.sparc_regs.i[5] = from->i5;
|
||||||
|
to->integer.sparc_regs.i[6] = from->i6;
|
||||||
|
to->integer.sparc_regs.i[7] = from->i7;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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_SPARC) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
to->ContextFlags = CONTEXT_SPARC;
|
||||||
|
if (from->flags & SERVER_CTX_CONTROL)
|
||||||
|
{
|
||||||
|
to->ContextFlags |= CONTEXT_CONTROL;
|
||||||
|
to->psr = from->ctl.sparc_regs.psr;
|
||||||
|
to->pc = from->ctl.sparc_regs.pc;
|
||||||
|
to->npc = from->ctl.sparc_regs.npc;
|
||||||
|
to->y = from->ctl.sparc_regs.y;
|
||||||
|
to->wim = from->ctl.sparc_regs.wim;
|
||||||
|
to->tbr = from->ctl.sparc_regs.tbr;
|
||||||
|
}
|
||||||
|
if (from->flags & SERVER_CTX_INTEGER)
|
||||||
|
{
|
||||||
|
to->ContextFlags |= CONTEXT_INTEGER;
|
||||||
|
to->g0 = from->integer.sparc_regs.g[0];
|
||||||
|
to->g1 = from->integer.sparc_regs.g[1];
|
||||||
|
to->g2 = from->integer.sparc_regs.g[2];
|
||||||
|
to->g3 = from->integer.sparc_regs.g[3];
|
||||||
|
to->g4 = from->integer.sparc_regs.g[4];
|
||||||
|
to->g5 = from->integer.sparc_regs.g[5];
|
||||||
|
to->g6 = from->integer.sparc_regs.g[6];
|
||||||
|
to->g7 = from->integer.sparc_regs.g[7];
|
||||||
|
to->o0 = from->integer.sparc_regs.o[0];
|
||||||
|
to->o1 = from->integer.sparc_regs.o[1];
|
||||||
|
to->o2 = from->integer.sparc_regs.o[2];
|
||||||
|
to->o3 = from->integer.sparc_regs.o[3];
|
||||||
|
to->o4 = from->integer.sparc_regs.o[4];
|
||||||
|
to->o5 = from->integer.sparc_regs.o[5];
|
||||||
|
to->o6 = from->integer.sparc_regs.o[6];
|
||||||
|
to->o7 = from->integer.sparc_regs.o[7];
|
||||||
|
to->l0 = from->integer.sparc_regs.l[0];
|
||||||
|
to->l1 = from->integer.sparc_regs.l[1];
|
||||||
|
to->l2 = from->integer.sparc_regs.l[2];
|
||||||
|
to->l3 = from->integer.sparc_regs.l[3];
|
||||||
|
to->l4 = from->integer.sparc_regs.l[4];
|
||||||
|
to->l5 = from->integer.sparc_regs.l[5];
|
||||||
|
to->l6 = from->integer.sparc_regs.l[6];
|
||||||
|
to->l7 = from->integer.sparc_regs.l[7];
|
||||||
|
to->i0 = from->integer.sparc_regs.i[0];
|
||||||
|
to->i1 = from->integer.sparc_regs.i[1];
|
||||||
|
to->i2 = from->integer.sparc_regs.i[2];
|
||||||
|
to->i3 = from->integer.sparc_regs.i[3];
|
||||||
|
to->i4 = from->integer.sparc_regs.i[4];
|
||||||
|
to->i5 = from->integer.sparc_regs.i[5];
|
||||||
|
to->i6 = from->integer.sparc_regs.i[6];
|
||||||
|
to->i7 = from->integer.sparc_regs.i[7];
|
||||||
|
}
|
||||||
|
if (from->flags & SERVER_CTX_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* segv_handler
|
* segv_handler
|
||||||
*
|
*
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NONAMELESSUNION
|
#define NONAMELESSUNION
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
|
@ -327,6 +329,141 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_to_server
|
||||||
|
*
|
||||||
|
* Convert a register context to the server format.
|
||||||
|
*/
|
||||||
|
NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
|
||||||
|
{
|
||||||
|
DWORD flags = from->ContextFlags & ~CONTEXT_AMD64; /* get rid of CPU id */
|
||||||
|
|
||||||
|
memset( to, 0, sizeof(*to) );
|
||||||
|
to->cpu = CPU_x86_64;
|
||||||
|
|
||||||
|
if (flags & CONTEXT_CONTROL)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_CONTROL;
|
||||||
|
to->ctl.x86_64_regs.rbp = from->Rbp;
|
||||||
|
to->ctl.x86_64_regs.rip = from->Rip;
|
||||||
|
to->ctl.x86_64_regs.rsp = from->Rsp;
|
||||||
|
to->ctl.x86_64_regs.cs = from->SegCs;
|
||||||
|
to->ctl.x86_64_regs.ss = from->SegSs;
|
||||||
|
to->ctl.x86_64_regs.flags = from->EFlags;
|
||||||
|
to->ctl.x86_64_regs.mxcsr = from->MxCsr;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_INTEGER)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_INTEGER;
|
||||||
|
to->integer.x86_64_regs.rax = from->Rax;
|
||||||
|
to->integer.x86_64_regs.rcx = from->Rcx;
|
||||||
|
to->integer.x86_64_regs.rdx = from->Rdx;
|
||||||
|
to->integer.x86_64_regs.rbx = from->Rbx;
|
||||||
|
to->integer.x86_64_regs.rsi = from->Rsi;
|
||||||
|
to->integer.x86_64_regs.rdi = from->Rdi;
|
||||||
|
to->integer.x86_64_regs.r8 = from->R8;
|
||||||
|
to->integer.x86_64_regs.r9 = from->R9;
|
||||||
|
to->integer.x86_64_regs.r10 = from->R10;
|
||||||
|
to->integer.x86_64_regs.r11 = from->R11;
|
||||||
|
to->integer.x86_64_regs.r12 = from->R12;
|
||||||
|
to->integer.x86_64_regs.r13 = from->R13;
|
||||||
|
to->integer.x86_64_regs.r14 = from->R14;
|
||||||
|
to->integer.x86_64_regs.r15 = from->R15;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_SEGMENTS)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_SEGMENTS;
|
||||||
|
to->seg.x86_64_regs.ds = from->SegDs;
|
||||||
|
to->seg.x86_64_regs.es = from->SegEs;
|
||||||
|
to->seg.x86_64_regs.fs = from->SegFs;
|
||||||
|
to->seg.x86_64_regs.gs = from->SegGs;
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_FLOATING_POINT;
|
||||||
|
memcpy( to->fp.x86_64_regs.fpregs, &from->u.FltSave, sizeof(to->fp.x86_64_regs.fpregs) );
|
||||||
|
}
|
||||||
|
if (flags & CONTEXT_DEBUG_REGISTERS)
|
||||||
|
{
|
||||||
|
to->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
|
to->debug.x86_64_regs.dr0 = from->Dr0;
|
||||||
|
to->debug.x86_64_regs.dr1 = from->Dr1;
|
||||||
|
to->debug.x86_64_regs.dr2 = from->Dr2;
|
||||||
|
to->debug.x86_64_regs.dr3 = from->Dr3;
|
||||||
|
to->debug.x86_64_regs.dr6 = from->Dr6;
|
||||||
|
to->debug.x86_64_regs.dr7 = from->Dr7;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* context_from_server
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
to->MxCsr = from->ctl.x86_64_regs.mxcsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) );
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* segv_handler
|
* segv_handler
|
||||||
*
|
*
|
||||||
|
|
|
@ -824,12 +824,15 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
|
|
||||||
if (!self)
|
if (!self)
|
||||||
{
|
{
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
|
context_to_server( &server_context, context );
|
||||||
|
|
||||||
SERVER_START_REQ( set_thread_context )
|
SERVER_START_REQ( set_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->flags = context->ContextFlags;
|
|
||||||
req->suspend = 0;
|
req->suspend = 0;
|
||||||
wine_server_add_data( req, context, sizeof(*context) );
|
wine_server_add_data( req, &server_context, sizeof(server_context) );
|
||||||
ret = wine_server_call( req );
|
ret = wine_server_call( req );
|
||||||
self = reply->self;
|
self = reply->self;
|
||||||
}
|
}
|
||||||
|
@ -844,9 +847,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
SERVER_START_REQ( set_thread_context )
|
SERVER_START_REQ( set_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->flags = context->ContextFlags;
|
|
||||||
req->suspend = 0;
|
req->suspend = 0;
|
||||||
wine_server_add_data( req, context, sizeof(*context) );
|
wine_server_add_data( req, &server_context, sizeof(server_context) );
|
||||||
ret = wine_server_call( req );
|
ret = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -871,6 +873,29 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* convert CPU-specific flags to generic server flags */
|
||||||
|
static inline unsigned int get_server_context_flags( DWORD flags )
|
||||||
|
{
|
||||||
|
unsigned int ret = 0;
|
||||||
|
|
||||||
|
flags &= ~0x3f; /* mask CPU id flags */
|
||||||
|
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
|
||||||
|
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
|
||||||
|
#ifdef CONTEXT_SEGMENTS
|
||||||
|
if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
|
||||||
|
#endif
|
||||||
|
#ifdef CONTEXT_FLOATING_POINT
|
||||||
|
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
|
||||||
|
#endif
|
||||||
|
#ifdef CONTEXT_DEBUG_REGISTERS
|
||||||
|
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
|
#endif
|
||||||
|
#ifdef CONTEXT_EXTENDED_REGISTERS
|
||||||
|
if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS;
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* NtGetContextThread (NTDLL.@)
|
* NtGetContextThread (NTDLL.@)
|
||||||
* ZwGetContextThread (NTDLL.@)
|
* ZwGetContextThread (NTDLL.@)
|
||||||
|
@ -878,7 +903,6 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
||||||
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||||
{
|
{
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
CONTEXT ctx;
|
|
||||||
DWORD dummy, i;
|
DWORD dummy, i;
|
||||||
DWORD needed_flags = context->ContextFlags;
|
DWORD needed_flags = context->ContextFlags;
|
||||||
BOOL self = (handle == GetCurrentThread());
|
BOOL self = (handle == GetCurrentThread());
|
||||||
|
@ -890,12 +914,15 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||||
|
|
||||||
if (!self)
|
if (!self)
|
||||||
{
|
{
|
||||||
|
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
|
||||||
|
context_t server_context;
|
||||||
|
|
||||||
SERVER_START_REQ( get_thread_context )
|
SERVER_START_REQ( get_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->flags = context->ContextFlags;
|
req->flags = server_flags;
|
||||||
req->suspend = 0;
|
req->suspend = 0;
|
||||||
wine_server_set_reply( req, &ctx, sizeof(ctx) );
|
wine_server_set_reply( req, &server_context, sizeof(server_context) );
|
||||||
ret = wine_server_call( req );
|
ret = wine_server_call( req );
|
||||||
self = reply->self;
|
self = reply->self;
|
||||||
}
|
}
|
||||||
|
@ -910,9 +937,9 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||||
SERVER_START_REQ( get_thread_context )
|
SERVER_START_REQ( get_thread_context )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
req->flags = context->ContextFlags;
|
req->flags = server_flags;
|
||||||
req->suspend = 0;
|
req->suspend = 0;
|
||||||
wine_server_set_reply( req, &ctx, sizeof(ctx) );
|
wine_server_set_reply( req, &server_context, sizeof(server_context) );
|
||||||
ret = wine_server_call( req );
|
ret = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -928,17 +955,19 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||||
}
|
}
|
||||||
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
|
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
if (!ret) ret = context_from_server( context, &server_context );
|
||||||
if (ret) return ret;
|
if (ret) return ret;
|
||||||
copy_context( context, &ctx, context->ContextFlags & ctx.ContextFlags );
|
needed_flags &= ~context->ContextFlags;
|
||||||
needed_flags &= ~ctx.ContextFlags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
if (needed_flags)
|
if (needed_flags)
|
||||||
{
|
{
|
||||||
|
CONTEXT ctx;
|
||||||
RtlCaptureContext( &ctx );
|
RtlCaptureContext( &ctx );
|
||||||
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
|
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
|
||||||
|
context->ContextFlags |= ctx.ContextFlags & needed_flags;
|
||||||
}
|
}
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
/* update the cached version of the debug registers */
|
/* update the cached version of the debug registers */
|
||||||
|
|
|
@ -135,6 +135,63 @@ enum cpu_type
|
||||||
typedef int cpu_type_t;
|
typedef int cpu_type_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cpu_type_t cpu;
|
||||||
|
unsigned int flags;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int eip, ebp, esp, eflags, cs, ss; } i386_regs;
|
||||||
|
struct { unsigned __int64 rip, rbp, rsp;
|
||||||
|
unsigned int cs, ss, flags, mxcsr; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 fir;
|
||||||
|
unsigned int psr; } alpha_regs;
|
||||||
|
struct { unsigned int iar, msr, ctr, lr, dar, dsisr, trap; } powerpc_regs;
|
||||||
|
struct { unsigned int psr, pc, npc, y, wim, tbr; } sparc_regs;
|
||||||
|
} ctl;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int eax, ebx, ecx, edx, esi, edi; } i386_regs;
|
||||||
|
struct { unsigned __int64 rax,rbx, rcx, rdx, rsi, rdi,
|
||||||
|
r8, r9, r10, r11, r12, r13, r14, r15; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 v0, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12,
|
||||||
|
s0, s1, s2, s3, s4, s5, s6, a0, a1, a2, a3, a4, a5, at; } alpha_regs;
|
||||||
|
struct { unsigned int gpr[32], cr, xer; } powerpc_regs;
|
||||||
|
struct { unsigned int g[8], o[8], l[8], i[8]; } sparc_regs;
|
||||||
|
} integer;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int ds, es, fs, gs; } i386_regs;
|
||||||
|
struct { unsigned int ds, es, fs, gs; } x86_64_regs;
|
||||||
|
} seg;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int ctrl, status, tag, err_off, err_sel, data_off, data_sel, cr0npx;
|
||||||
|
unsigned char regs[80]; } i386_regs;
|
||||||
|
struct { struct { unsigned __int64 low, high; } fpregs[32]; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 f[32], fpcr, softfpcr; } alpha_regs;
|
||||||
|
struct { double fpr[32], fpscr; } powerpc_regs;
|
||||||
|
} fp;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int dr0, dr1, dr2, dr3, dr6, dr7; } i386_regs;
|
||||||
|
struct { unsigned __int64 dr0, dr1, dr2, dr3, dr6, dr7; } x86_64_regs;
|
||||||
|
struct { unsigned int dr[8]; } powerpc_regs;
|
||||||
|
} debug;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char i386_regs[512];
|
||||||
|
} ext;
|
||||||
|
} context_t;
|
||||||
|
|
||||||
|
#define SERVER_CTX_CONTROL 0x01
|
||||||
|
#define SERVER_CTX_INTEGER 0x02
|
||||||
|
#define SERVER_CTX_SEGMENTS 0x04
|
||||||
|
#define SERVER_CTX_FLOATING_POINT 0x08
|
||||||
|
#define SERVER_CTX_DEBUG_REGISTERS 0x10
|
||||||
|
#define SERVER_CTX_EXTENDED_REGISTERS 0x20
|
||||||
|
|
||||||
|
|
||||||
struct send_fd
|
struct send_fd
|
||||||
{
|
{
|
||||||
thread_id_t tid;
|
thread_id_t tid;
|
||||||
|
@ -2356,7 +2413,6 @@ struct set_thread_context_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
obj_handle_t handle;
|
obj_handle_t handle;
|
||||||
unsigned int flags;
|
|
||||||
int suspend;
|
int suspend;
|
||||||
/* VARARG(context,context); */
|
/* VARARG(context,context); */
|
||||||
};
|
};
|
||||||
|
@ -5224,6 +5280,6 @@ union generic_reply
|
||||||
struct set_window_layered_info_reply set_window_layered_info_reply;
|
struct set_window_layered_info_reply set_window_layered_info_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 384
|
#define SERVER_PROTOCOL_VERSION 385
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -14,11 +14,6 @@ C_SRCS = \
|
||||||
clipboard.c \
|
clipboard.c \
|
||||||
completion.c \
|
completion.c \
|
||||||
console.c \
|
console.c \
|
||||||
context_alpha.c \
|
|
||||||
context_i386.c \
|
|
||||||
context_powerpc.c \
|
|
||||||
context_sparc.c \
|
|
||||||
context_x86_64.c \
|
|
||||||
debugger.c \
|
debugger.c \
|
||||||
device.c \
|
device.c \
|
||||||
directory.c \
|
directory.c \
|
||||||
|
|
|
@ -1,348 +0,0 @@
|
||||||
/*
|
|
||||||
* Alpha register context support
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 Vincent Béron
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __ALPHA__
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef HAVE_SYS_REG_H
|
|
||||||
# include <sys/reg.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_SYS_PTRACE_H
|
|
||||||
# include <sys/ptrace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "request.h"
|
|
||||||
|
|
||||||
#if 0 /* no longer used */
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_USER_H
|
|
||||||
# include <sys/user.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* user definitions from asm/user.h */
|
|
||||||
struct kernel_user_struct
|
|
||||||
{
|
|
||||||
unsigned long regs[EF_SIZE/8+32];
|
|
||||||
size_t u_tsize;
|
|
||||||
size_t u_dsize;
|
|
||||||
size_t u_ssize;
|
|
||||||
unsigned long start_code;
|
|
||||||
unsigned long start_data;
|
|
||||||
unsigned long start_stack;
|
|
||||||
long int signal;
|
|
||||||
struct regs * u_ar0;
|
|
||||||
unsigned long magic;
|
|
||||||
char u_comm[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* get thread context */
|
|
||||||
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
|
|
||||||
{
|
|
||||||
int pid = get_ptrace_pid(thread);
|
|
||||||
if (flags & CONTEXT_FULL)
|
|
||||||
{
|
|
||||||
struct kernel_user_struct regs;
|
|
||||||
if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error;
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
context->IntV0 = regs.regs[EF_V0];
|
|
||||||
context->IntT0 = regs.regs[EF_T0];
|
|
||||||
context->IntT1 = regs.regs[EF_T1];
|
|
||||||
context->IntT2 = regs.regs[EF_T2];
|
|
||||||
context->IntT3 = regs.regs[EF_T3];
|
|
||||||
context->IntT4 = regs.regs[EF_T4];
|
|
||||||
context->IntT5 = regs.regs[EF_T5];
|
|
||||||
context->IntT6 = regs.regs[EF_T6];
|
|
||||||
context->IntT7 = regs.regs[EF_T7];
|
|
||||||
context->IntS0 = regs.regs[EF_S0];
|
|
||||||
context->IntS1 = regs.regs[EF_S1];
|
|
||||||
context->IntS2 = regs.regs[EF_S2];
|
|
||||||
context->IntS3 = regs.regs[EF_S3];
|
|
||||||
context->IntS4 = regs.regs[EF_S4];
|
|
||||||
context->IntS5 = regs.regs[EF_S5];
|
|
||||||
context->IntFp = regs.regs[EF_S6];
|
|
||||||
context->IntA0 = regs.regs[EF_A0];
|
|
||||||
context->IntA1 = regs.regs[EF_A1];
|
|
||||||
context->IntA2 = regs.regs[EF_A2];
|
|
||||||
context->IntA3 = regs.regs[EF_A3];
|
|
||||||
context->IntA4 = regs.regs[EF_A4];
|
|
||||||
context->IntA5 = regs.regs[EF_A5];
|
|
||||||
context->IntT8 = regs.regs[EF_T8];
|
|
||||||
context->IntT9 = regs.regs[EF_T9];
|
|
||||||
context->IntT10 = regs.regs[EF_T10];
|
|
||||||
context->IntT11 = regs.regs[EF_T11];
|
|
||||||
context->IntT12 = regs.regs[EF_T12];
|
|
||||||
context->IntAt = regs.regs[EF_AT];
|
|
||||||
context->IntZero = 0;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
context->IntRa = regs.regs[EF_RA];
|
|
||||||
context->IntGp = regs.regs[EF_GP];
|
|
||||||
context->IntSp = regs.regs[EF_SP];
|
|
||||||
context->Fir = regs.regs[EF_PC];
|
|
||||||
context->Psr = regs.regs[EF_PS];
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
context->FltF0 = regs.regs[EF_SIZE/8+0];
|
|
||||||
context->FltF1 = regs.regs[EF_SIZE/8+1];
|
|
||||||
context->FltF2 = regs.regs[EF_SIZE/8+2];
|
|
||||||
context->FltF3 = regs.regs[EF_SIZE/8+3];
|
|
||||||
context->FltF4 = regs.regs[EF_SIZE/8+4];
|
|
||||||
context->FltF5 = regs.regs[EF_SIZE/8+5];
|
|
||||||
context->FltF6 = regs.regs[EF_SIZE/8+6];
|
|
||||||
context->FltF7 = regs.regs[EF_SIZE/8+7];
|
|
||||||
context->FltF8 = regs.regs[EF_SIZE/8+8];
|
|
||||||
context->FltF9 = regs.regs[EF_SIZE/8+9];
|
|
||||||
context->FltF10 = regs.regs[EF_SIZE/8+10];
|
|
||||||
context->FltF11 = regs.regs[EF_SIZE/8+11];
|
|
||||||
context->FltF12 = regs.regs[EF_SIZE/8+12];
|
|
||||||
context->FltF13 = regs.regs[EF_SIZE/8+13];
|
|
||||||
context->FltF14 = regs.regs[EF_SIZE/8+14];
|
|
||||||
context->FltF15 = regs.regs[EF_SIZE/8+15];
|
|
||||||
context->FltF16 = regs.regs[EF_SIZE/8+16];
|
|
||||||
context->FltF17 = regs.regs[EF_SIZE/8+17];
|
|
||||||
context->FltF18 = regs.regs[EF_SIZE/8+18];
|
|
||||||
context->FltF19 = regs.regs[EF_SIZE/8+19];
|
|
||||||
context->FltF20 = regs.regs[EF_SIZE/8+20];
|
|
||||||
context->FltF21 = regs.regs[EF_SIZE/8+21];
|
|
||||||
context->FltF22 = regs.regs[EF_SIZE/8+22];
|
|
||||||
context->FltF23 = regs.regs[EF_SIZE/8+23];
|
|
||||||
context->FltF24 = regs.regs[EF_SIZE/8+24];
|
|
||||||
context->FltF25 = regs.regs[EF_SIZE/8+25];
|
|
||||||
context->FltF26 = regs.regs[EF_SIZE/8+26];
|
|
||||||
context->FltF27 = regs.regs[EF_SIZE/8+27];
|
|
||||||
context->FltF28 = regs.regs[EF_SIZE/8+28];
|
|
||||||
context->FltF29 = regs.regs[EF_SIZE/8+29];
|
|
||||||
context->FltF30 = regs.regs[EF_SIZE/8+30];
|
|
||||||
context->FltF31 = 0;
|
|
||||||
context->Fpcr = regs.regs[EF_SIZE/8+31];
|
|
||||||
context->SoftFpcr = 0; /* FIXME */
|
|
||||||
}
|
|
||||||
context->ContextFlags |= flags & CONTEXT_FULL;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set a thread context */
|
|
||||||
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
int pid = get_ptrace_pid(thread);
|
|
||||||
if (flags & CONTEXT_FULL)
|
|
||||||
{
|
|
||||||
struct kernel_user_struct regs;
|
|
||||||
if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error;
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
regs.regs[EF_V0] = context->IntV0;
|
|
||||||
regs.regs[EF_T0] = context->IntT0;
|
|
||||||
regs.regs[EF_T1] = context->IntT1;
|
|
||||||
regs.regs[EF_T2] = context->IntT2;
|
|
||||||
regs.regs[EF_T3] = context->IntT3;
|
|
||||||
regs.regs[EF_T4] = context->IntT4;
|
|
||||||
regs.regs[EF_T5] = context->IntT5;
|
|
||||||
regs.regs[EF_T6] = context->IntT6;
|
|
||||||
regs.regs[EF_T7] = context->IntT7;
|
|
||||||
regs.regs[EF_S0] = context->IntS0;
|
|
||||||
regs.regs[EF_S1] = context->IntS1;
|
|
||||||
regs.regs[EF_S2] = context->IntS2;
|
|
||||||
regs.regs[EF_S3] = context->IntS3;
|
|
||||||
regs.regs[EF_S4] = context->IntS4;
|
|
||||||
regs.regs[EF_S5] = context->IntS5;
|
|
||||||
regs.regs[EF_S6] = context->IntFp;
|
|
||||||
regs.regs[EF_A0] = context->IntA0;
|
|
||||||
regs.regs[EF_A1] = context->IntA1;
|
|
||||||
regs.regs[EF_A2] = context->IntA2;
|
|
||||||
regs.regs[EF_A3] = context->IntA3;
|
|
||||||
regs.regs[EF_A4] = context->IntA4;
|
|
||||||
regs.regs[EF_A5] = context->IntA5;
|
|
||||||
regs.regs[EF_T8] = context->IntT8;
|
|
||||||
regs.regs[EF_T9] = context->IntT9;
|
|
||||||
regs.regs[EF_T10] = context->IntT10;
|
|
||||||
regs.regs[EF_T11] = context->IntT11;
|
|
||||||
regs.regs[EF_T12] = context->IntT12;
|
|
||||||
regs.regs[EF_AT] = context->IntAt;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
regs.regs[EF_RA] = context->IntRa;
|
|
||||||
regs.regs[EF_GP] = context->IntGp;
|
|
||||||
regs.regs[EF_SP] = context->IntSp;
|
|
||||||
regs.regs[EF_PC] = context->Fir;
|
|
||||||
regs.regs[EF_PS] = context->Psr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
regs.regs[EF_SIZE/8+0] = context->FltF0;
|
|
||||||
regs.regs[EF_SIZE/8+1] = context->FltF1;
|
|
||||||
regs.regs[EF_SIZE/8+2] = context->FltF2;
|
|
||||||
regs.regs[EF_SIZE/8+3] = context->FltF3;
|
|
||||||
regs.regs[EF_SIZE/8+4] = context->FltF4;
|
|
||||||
regs.regs[EF_SIZE/8+5] = context->FltF5;
|
|
||||||
regs.regs[EF_SIZE/8+6] = context->FltF6;
|
|
||||||
regs.regs[EF_SIZE/8+7] = context->FltF7;
|
|
||||||
regs.regs[EF_SIZE/8+8] = context->FltF8;
|
|
||||||
regs.regs[EF_SIZE/8+9] = context->FltF9;
|
|
||||||
regs.regs[EF_SIZE/8+10] = context->FltF10;
|
|
||||||
regs.regs[EF_SIZE/8+11] = context->FltF11;
|
|
||||||
regs.regs[EF_SIZE/8+12] = context->FltF12;
|
|
||||||
regs.regs[EF_SIZE/8+13] = context->FltF13;
|
|
||||||
regs.regs[EF_SIZE/8+14] = context->FltF14;
|
|
||||||
regs.regs[EF_SIZE/8+15] = context->FltF15;
|
|
||||||
regs.regs[EF_SIZE/8+16] = context->FltF16;
|
|
||||||
regs.regs[EF_SIZE/8+17] = context->FltF17;
|
|
||||||
regs.regs[EF_SIZE/8+18] = context->FltF18;
|
|
||||||
regs.regs[EF_SIZE/8+19] = context->FltF19;
|
|
||||||
regs.regs[EF_SIZE/8+20] = context->FltF20;
|
|
||||||
regs.regs[EF_SIZE/8+21] = context->FltF21;
|
|
||||||
regs.regs[EF_SIZE/8+22] = context->FltF22;
|
|
||||||
regs.regs[EF_SIZE/8+23] = context->FltF23;
|
|
||||||
regs.regs[EF_SIZE/8+24] = context->FltF24;
|
|
||||||
regs.regs[EF_SIZE/8+25] = context->FltF25;
|
|
||||||
regs.regs[EF_SIZE/8+26] = context->FltF26;
|
|
||||||
regs.regs[EF_SIZE/8+27] = context->FltF27;
|
|
||||||
regs.regs[EF_SIZE/8+28] = context->FltF28;
|
|
||||||
regs.regs[EF_SIZE/8+29] = context->FltF29;
|
|
||||||
regs.regs[EF_SIZE/8+30] = context->FltF30;
|
|
||||||
regs.regs[EF_SIZE/8+31] = context->Fpcr;
|
|
||||||
}
|
|
||||||
if (ptrace( PTRACE_SETREGS, pid, 0, ®s ) == -1) goto error;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
|
||||||
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
|
||||||
{
|
|
||||||
flags &= ~CONTEXT_ALPHA; /* get rid of CPU id */
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->IntRa = from->IntRa;
|
|
||||||
to->IntGp = from->IntGp;
|
|
||||||
to->IntSp = from->IntSp;
|
|
||||||
to->Fir = from->Fir;
|
|
||||||
to->Psr = from->Psr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->IntV0 = from->IntV0;
|
|
||||||
to->IntT0 = from->IntT0;
|
|
||||||
to->IntT1 = from->IntT1;
|
|
||||||
to->IntT2 = from->IntT2;
|
|
||||||
to->IntT3 = from->IntT3;
|
|
||||||
to->IntT4 = from->IntT4;
|
|
||||||
to->IntT5 = from->IntT5;
|
|
||||||
to->IntT6 = from->IntT6;
|
|
||||||
to->IntT7 = from->IntT7;
|
|
||||||
to->IntS0 = from->IntS0;
|
|
||||||
to->IntS1 = from->IntS1;
|
|
||||||
to->IntS2 = from->IntS2;
|
|
||||||
to->IntS3 = from->IntS3;
|
|
||||||
to->IntS4 = from->IntS4;
|
|
||||||
to->IntS5 = from->IntS5;
|
|
||||||
to->IntFp = from->IntFp;
|
|
||||||
to->IntA0 = from->IntA0;
|
|
||||||
to->IntA1 = from->IntA1;
|
|
||||||
to->IntA2 = from->IntA2;
|
|
||||||
to->IntA3 = from->IntA3;
|
|
||||||
to->IntA4 = from->IntA4;
|
|
||||||
to->IntA5 = from->IntA5;
|
|
||||||
to->IntT8 = from->IntT8;
|
|
||||||
to->IntT9 = from->IntT9;
|
|
||||||
to->IntT10 = from->IntT10;
|
|
||||||
to->IntT11 = from->IntT11;
|
|
||||||
to->IntT12 = from->IntT12;
|
|
||||||
to->IntAt = from->IntAt;
|
|
||||||
to->IntZero = from->IntZero;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
to->FltF0 = from->FltF0;
|
|
||||||
to->FltF1 = from->FltF1;
|
|
||||||
to->FltF2 = from->FltF2;
|
|
||||||
to->FltF3 = from->FltF3;
|
|
||||||
to->FltF4 = from->FltF4;
|
|
||||||
to->FltF5 = from->FltF5;
|
|
||||||
to->FltF6 = from->FltF6;
|
|
||||||
to->FltF7 = from->FltF7;
|
|
||||||
to->FltF8 = from->FltF8;
|
|
||||||
to->FltF9 = from->FltF9;
|
|
||||||
to->FltF10 = from->FltF10;
|
|
||||||
to->FltF11 = from->FltF11;
|
|
||||||
to->FltF12 = from->FltF12;
|
|
||||||
to->FltF13 = from->FltF13;
|
|
||||||
to->FltF14 = from->FltF14;
|
|
||||||
to->FltF15 = from->FltF15;
|
|
||||||
to->FltF16 = from->FltF16;
|
|
||||||
to->FltF17 = from->FltF17;
|
|
||||||
to->FltF18 = from->FltF18;
|
|
||||||
to->FltF19 = from->FltF19;
|
|
||||||
to->FltF20 = from->FltF20;
|
|
||||||
to->FltF21 = from->FltF21;
|
|
||||||
to->FltF22 = from->FltF22;
|
|
||||||
to->FltF23 = from->FltF23;
|
|
||||||
to->FltF24 = from->FltF24;
|
|
||||||
to->FltF25 = from->FltF25;
|
|
||||||
to->FltF26 = from->FltF26;
|
|
||||||
to->FltF27 = from->FltF27;
|
|
||||||
to->FltF28 = from->FltF28;
|
|
||||||
to->FltF29 = from->FltF29;
|
|
||||||
to->FltF30 = from->FltF30;
|
|
||||||
to->FltF31 = from->FltF31;
|
|
||||||
to->Fpcr = from->Fpcr;
|
|
||||||
to->SoftFpcr = from->SoftFpcr;
|
|
||||||
}
|
|
||||||
to->ContextFlags |= flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve the current instruction pointer of a context */
|
|
||||||
client_ptr_t get_context_ip( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
return 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 0; /* FIXME: implement client-side handling */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __ALPHA__ */
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* i386 register context support
|
|
||||||
*
|
|
||||||
* Copyright (C) 1999 Alexandre Julliard
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "windef.h"
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "request.h"
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
|
||||||
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
|
||||||
{
|
|
||||||
flags &= ~CONTEXT_i386; /* get rid of CPU id */
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->Ebp = from->Ebp;
|
|
||||||
to->Eip = from->Eip;
|
|
||||||
to->Esp = from->Esp;
|
|
||||||
to->SegCs = from->SegCs;
|
|
||||||
to->SegSs = from->SegSs;
|
|
||||||
to->EFlags = from->EFlags;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->Eax = from->Eax;
|
|
||||||
to->Ebx = from->Ebx;
|
|
||||||
to->Ecx = from->Ecx;
|
|
||||||
to->Edx = from->Edx;
|
|
||||||
to->Esi = from->Esi;
|
|
||||||
to->Edi = from->Edi;
|
|
||||||
}
|
|
||||||
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->FloatSave = from->FloatSave;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_EXTENDED_REGISTERS)
|
|
||||||
{
|
|
||||||
memcpy( to->ExtendedRegisters, from->ExtendedRegisters, sizeof(to->ExtendedRegisters) );
|
|
||||||
}
|
|
||||||
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 */
|
|
||||||
client_ptr_t get_context_ip( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
return context->Eip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return the context flag that contains the CPU id */
|
|
||||||
unsigned int get_context_cpu_flag(void)
|
|
||||||
{
|
|
||||||
return CONTEXT_i386;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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_i386);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __i386__ */
|
|
|
@ -1,286 +0,0 @@
|
||||||
/*
|
|
||||||
* PowerPC register context support
|
|
||||||
*
|
|
||||||
* Copyright (C) 2002 Marcus Meissner, SuSE Linux AG.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __powerpc__
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_SYS_REG_H
|
|
||||||
# include <sys/reg.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_SYS_PTRACE_H
|
|
||||||
# include <sys/ptrace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "windef.h"
|
|
||||||
|
|
||||||
#if 0 /* no longer used */
|
|
||||||
|
|
||||||
#ifndef PTRACE_PEEKUSER
|
|
||||||
# ifdef PT_READ_D
|
|
||||||
# define PTRACE_PEEKUSER PT_READ_D
|
|
||||||
# endif
|
|
||||||
#endif /* PTRACE_PEEKUSER */
|
|
||||||
|
|
||||||
#ifndef PTRACE_POKEUSER
|
|
||||||
# ifdef PT_WRITE_D
|
|
||||||
# define PTRACE_POKEUSER PT_WRITE_D
|
|
||||||
# endif
|
|
||||||
#endif /* PTRACE_POKEUSER */
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "request.h"
|
|
||||||
|
|
||||||
/* 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_INTEGER)
|
|
||||||
{
|
|
||||||
#define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
|
|
||||||
#define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
|
|
||||||
IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
|
|
||||||
IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
|
|
||||||
IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
|
|
||||||
IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
|
|
||||||
IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
|
|
||||||
#undef IREG
|
|
||||||
XREG(37,Xer);
|
|
||||||
XREG(38,Cr);
|
|
||||||
context->ContextFlags |= CONTEXT_INTEGER;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
XREG(32,Iar);
|
|
||||||
XREG(33,Msr);
|
|
||||||
XREG(35,Ctr);
|
|
||||||
XREG(36,Lr); /* 36 is LNK ... probably Lr ? */
|
|
||||||
context->ContextFlags |= CONTEXT_CONTROL;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
#define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
|
|
||||||
FREG(0);
|
|
||||||
FREG(1);
|
|
||||||
FREG(2);
|
|
||||||
FREG(3);
|
|
||||||
FREG(4);
|
|
||||||
FREG(5);
|
|
||||||
FREG(6);
|
|
||||||
FREG(7);
|
|
||||||
FREG(8);
|
|
||||||
FREG(9);
|
|
||||||
FREG(10);
|
|
||||||
FREG(11);
|
|
||||||
FREG(12);
|
|
||||||
FREG(13);
|
|
||||||
FREG(14);
|
|
||||||
FREG(15);
|
|
||||||
FREG(16);
|
|
||||||
FREG(17);
|
|
||||||
FREG(18);
|
|
||||||
FREG(19);
|
|
||||||
FREG(20);
|
|
||||||
FREG(21);
|
|
||||||
FREG(22);
|
|
||||||
FREG(23);
|
|
||||||
FREG(24);
|
|
||||||
FREG(25);
|
|
||||||
FREG(26);
|
|
||||||
FREG(27);
|
|
||||||
FREG(28);
|
|
||||||
FREG(29);
|
|
||||||
FREG(30);
|
|
||||||
FREG(31);
|
|
||||||
XREG((48+32*2),Fpscr);
|
|
||||||
context->ContextFlags |= CONTEXT_FLOATING_POINT;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
}
|
|
||||||
#undef XREG
|
|
||||||
#undef IREG
|
|
||||||
#undef FREG
|
|
||||||
|
|
||||||
#define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
|
|
||||||
#define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
|
|
||||||
#define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto 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)
|
|
||||||
{
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
|
|
||||||
IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
|
|
||||||
IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
|
|
||||||
IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
|
|
||||||
IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
|
|
||||||
XREG(37,Xer);
|
|
||||||
XREG(38,Cr);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
XREG(32,Iar);
|
|
||||||
XREG(33,Msr);
|
|
||||||
XREG(35,Ctr);
|
|
||||||
XREG(36,Lr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
FREG(0);
|
|
||||||
FREG(1);
|
|
||||||
FREG(2);
|
|
||||||
FREG(3);
|
|
||||||
FREG(4);
|
|
||||||
FREG(5);
|
|
||||||
FREG(6);
|
|
||||||
FREG(7);
|
|
||||||
FREG(8);
|
|
||||||
FREG(9);
|
|
||||||
FREG(10);
|
|
||||||
FREG(11);
|
|
||||||
FREG(12);
|
|
||||||
FREG(13);
|
|
||||||
FREG(14);
|
|
||||||
FREG(15);
|
|
||||||
FREG(16);
|
|
||||||
FREG(17);
|
|
||||||
FREG(18);
|
|
||||||
FREG(19);
|
|
||||||
FREG(20);
|
|
||||||
FREG(21);
|
|
||||||
FREG(22);
|
|
||||||
FREG(23);
|
|
||||||
FREG(24);
|
|
||||||
FREG(25);
|
|
||||||
FREG(26);
|
|
||||||
FREG(27);
|
|
||||||
FREG(28);
|
|
||||||
FREG(29);
|
|
||||||
FREG(30);
|
|
||||||
FREG(31);
|
|
||||||
#undef FREG
|
|
||||||
XREG((48+32*2),Fpscr);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
}
|
|
||||||
#undef XREG
|
|
||||||
#undef IREG
|
|
||||||
#undef FREG
|
|
||||||
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
#define IREG(x) to->Gpr##x = from->Gpr##x;
|
|
||||||
#define FREG(x) to->Fpr##x = from->Fpr##x;
|
|
||||||
#define CREG(x) to->x = from->x;
|
|
||||||
/* copy a context structure according to the flags */
|
|
||||||
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
|
||||||
{
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
CREG(Msr);
|
|
||||||
CREG(Ctr);
|
|
||||||
CREG(Iar);
|
|
||||||
to->ContextFlags |= CONTEXT_CONTROL;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
|
|
||||||
IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
|
|
||||||
IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
|
|
||||||
IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
|
|
||||||
IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
|
|
||||||
CREG(Xer);
|
|
||||||
CREG(Cr);
|
|
||||||
to->ContextFlags |= CONTEXT_INTEGER;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
FREG(0);
|
|
||||||
FREG(1);
|
|
||||||
FREG(2);
|
|
||||||
FREG(3);
|
|
||||||
FREG(4);
|
|
||||||
FREG(5);
|
|
||||||
FREG(6);
|
|
||||||
FREG(7);
|
|
||||||
FREG(8);
|
|
||||||
FREG(9);
|
|
||||||
FREG(10);
|
|
||||||
FREG(11);
|
|
||||||
FREG(12);
|
|
||||||
FREG(13);
|
|
||||||
FREG(14);
|
|
||||||
FREG(15);
|
|
||||||
FREG(16);
|
|
||||||
FREG(17);
|
|
||||||
FREG(18);
|
|
||||||
FREG(19);
|
|
||||||
FREG(20);
|
|
||||||
FREG(21);
|
|
||||||
FREG(22);
|
|
||||||
FREG(23);
|
|
||||||
FREG(24);
|
|
||||||
FREG(25);
|
|
||||||
FREG(26);
|
|
||||||
FREG(27);
|
|
||||||
FREG(28);
|
|
||||||
FREG(29);
|
|
||||||
FREG(30);
|
|
||||||
FREG(31);
|
|
||||||
CREG(Fpscr);
|
|
||||||
to->ContextFlags |= CONTEXT_FLOATING_POINT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve the current instruction pointer of a context */
|
|
||||||
client_ptr_t get_context_ip( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
return 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 0; /* FIXME: implement client-side handling */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __powerpc__ */
|
|
|
@ -1,184 +0,0 @@
|
||||||
/*
|
|
||||||
* Sparc register context support
|
|
||||||
*
|
|
||||||
* Copyright (C) 2000 Ulrich Weigand
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __sparc__
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef HAVE_SYS_REG_H
|
|
||||||
# include <sys/reg.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_SYS_PTRACE_H
|
|
||||||
# include <sys/ptrace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "windef.h"
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "request.h"
|
|
||||||
|
|
||||||
#if 0 /* no longer used */
|
|
||||||
|
|
||||||
#if 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, 0, (int) ®s ) == -1) goto error;
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
context->g0 = 0;
|
|
||||||
context->g1 = regs.r_g1;
|
|
||||||
context->g2 = regs.r_g2;
|
|
||||||
context->g3 = regs.r_g3;
|
|
||||||
context->g4 = regs.r_g4;
|
|
||||||
context->g5 = regs.r_g5;
|
|
||||||
context->g6 = regs.r_g6;
|
|
||||||
context->g7 = regs.r_g7;
|
|
||||||
|
|
||||||
context->o0 = regs.r_o0;
|
|
||||||
context->o1 = regs.r_o1;
|
|
||||||
context->o2 = regs.r_o2;
|
|
||||||
context->o3 = regs.r_o3;
|
|
||||||
context->o4 = regs.r_o4;
|
|
||||||
context->o5 = regs.r_o5;
|
|
||||||
context->o6 = regs.r_o6;
|
|
||||||
context->o7 = regs.r_o7;
|
|
||||||
|
|
||||||
/* FIXME: local and in registers */
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
context->psr = regs.r_psr;
|
|
||||||
context->pc = regs.r_pc;
|
|
||||||
context->npc = regs.r_npc;
|
|
||||||
context->y = regs.r_y;
|
|
||||||
context->wim = 0; /* FIXME */
|
|
||||||
context->tbr = 0; /* FIXME */
|
|
||||||
}
|
|
||||||
context |= flags & (CONTEXT_CONTROL|CONTEXT_INTEGER);
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
/* FIXME */
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* set a thread context */
|
|
||||||
static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context )
|
|
||||||
{
|
|
||||||
/* FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* __sun__ */
|
|
||||||
#error You must implement get/set_thread_context_ptrace for your platform
|
|
||||||
#endif /* __sun__ */
|
|
||||||
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
|
||||||
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
|
|
||||||
{
|
|
||||||
flags &= ~CONTEXT_SPARC; /* get rid of CPU id */
|
|
||||||
if (flags & CONTEXT_CONTROL)
|
|
||||||
{
|
|
||||||
to->psr = from->psr;
|
|
||||||
to->pc = from->pc;
|
|
||||||
to->npc = from->npc;
|
|
||||||
to->y = from->y;
|
|
||||||
to->wim = from->wim;
|
|
||||||
to->tbr = from->tbr;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_INTEGER)
|
|
||||||
{
|
|
||||||
to->g0 = from->g0;
|
|
||||||
to->g1 = from->g1;
|
|
||||||
to->g2 = from->g2;
|
|
||||||
to->g3 = from->g3;
|
|
||||||
to->g4 = from->g4;
|
|
||||||
to->g5 = from->g5;
|
|
||||||
to->g6 = from->g6;
|
|
||||||
to->g7 = from->g7;
|
|
||||||
to->o0 = from->o0;
|
|
||||||
to->o1 = from->o1;
|
|
||||||
to->o2 = from->o2;
|
|
||||||
to->o3 = from->o3;
|
|
||||||
to->o4 = from->o4;
|
|
||||||
to->o5 = from->o5;
|
|
||||||
to->o6 = from->o6;
|
|
||||||
to->o7 = from->o7;
|
|
||||||
to->l0 = from->l0;
|
|
||||||
to->l1 = from->l1;
|
|
||||||
to->l2 = from->l2;
|
|
||||||
to->l3 = from->l3;
|
|
||||||
to->l4 = from->l4;
|
|
||||||
to->l5 = from->l5;
|
|
||||||
to->l6 = from->l6;
|
|
||||||
to->l7 = from->l7;
|
|
||||||
to->i0 = from->i0;
|
|
||||||
to->i1 = from->i1;
|
|
||||||
to->i2 = from->i2;
|
|
||||||
to->i3 = from->i3;
|
|
||||||
to->i4 = from->i4;
|
|
||||||
to->i5 = from->i5;
|
|
||||||
to->i6 = from->i6;
|
|
||||||
to->i7 = from->i7;
|
|
||||||
}
|
|
||||||
if (flags & CONTEXT_FLOATING_POINT)
|
|
||||||
{
|
|
||||||
/* FIXME */
|
|
||||||
}
|
|
||||||
context |= flags & (CONTEXT_CONTROL|CONTEXT_INTEGER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve the current instruction pointer of a context */
|
|
||||||
client_ptr_t get_context_ip( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
return 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 0; /* FIXME: implement client-side handling */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __sparc__ */
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* x86-64 register context support
|
|
||||||
*
|
|
||||||
* Copyright (C) 1999, 2005 Alexandre Julliard
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define NONAMELESSUNION
|
|
||||||
#include "windef.h"
|
|
||||||
#include "winbase.h"
|
|
||||||
|
|
||||||
#include "file.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "request.h"
|
|
||||||
|
|
||||||
/* copy a context structure according to the flags */
|
|
||||||
void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int 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;
|
|
||||||
to->MxCsr = from->MxCsr;
|
|
||||||
}
|
|
||||||
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->u.FltSave = from->u.FltSave;
|
|
||||||
}
|
|
||||||
/* we don't bother copying the debug registers, since they */
|
|
||||||
/* always need to be accessed by ptrace anyway */
|
|
||||||
to->ContextFlags |= flags & ~CONTEXT_DEBUG_REGISTERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve the current instruction pointer of a context */
|
|
||||||
client_ptr_t get_context_ip( const CONTEXT *context )
|
|
||||||
{
|
|
||||||
return 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __x86_64__ */
|
|
|
@ -49,7 +49,7 @@ struct debug_event
|
||||||
enum debug_event_state state; /* event state */
|
enum debug_event_state state; /* event state */
|
||||||
int status; /* continuation status */
|
int status; /* continuation status */
|
||||||
debug_event_t data; /* event data */
|
debug_event_t data; /* event data */
|
||||||
CONTEXT context; /* register context */
|
context_t context; /* register context */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* debug context */
|
/* debug context */
|
||||||
|
@ -652,11 +652,11 @@ DECL_HANDLER(queue_exception_event)
|
||||||
|
|
||||||
if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data )))
|
if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data )))
|
||||||
{
|
{
|
||||||
const CONTEXT *context = (const CONTEXT *)((char *)get_req_data() + req->len);
|
const context_t *context = (const context_t *)((char *)get_req_data() + req->len);
|
||||||
data_size_t size = get_req_data_size() - req->len;
|
data_size_t size = get_req_data_size() - req->len;
|
||||||
|
|
||||||
memset( &event->context, 0, sizeof(event->context) );
|
memset( &event->context, 0, sizeof(event->context) );
|
||||||
memcpy( &event->context, context, size );
|
memcpy( &event->context, context, min( sizeof(event->context), size ) );
|
||||||
current->context = &event->context;
|
current->context = &event->context;
|
||||||
|
|
||||||
if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, 0 )))
|
if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, 0 )))
|
||||||
|
@ -682,7 +682,7 @@ DECL_HANDLER(get_exception_status)
|
||||||
{
|
{
|
||||||
if (current->context == &event->context)
|
if (current->context == &event->context)
|
||||||
{
|
{
|
||||||
data_size_t size = min( sizeof(CONTEXT), get_reply_max_size() );
|
data_size_t size = min( sizeof(context_t), get_reply_max_size() );
|
||||||
set_reply_data( &event->context, size );
|
set_reply_data( &event->context, size );
|
||||||
current->context = NULL;
|
current->context = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ void finish_process_tracing( struct process *process )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* retrieve the thread x86 registers */
|
/* retrieve the thread x86 registers */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
x86_debug_state32_t state;
|
x86_debug_state32_t state;
|
||||||
|
@ -169,7 +169,7 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
mach_port_t port, process_port = get_process_port( thread->process );
|
mach_port_t port, process_port = get_process_port( thread->process );
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (thread->unix_pid == -1 || !process_port ||
|
if (thread->unix_pid == -1 || !process_port ||
|
||||||
mach_port_extract_right( process_port, thread->unix_tid,
|
mach_port_extract_right( process_port, thread->unix_tid,
|
||||||
|
@ -183,28 +183,28 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
{
|
{
|
||||||
/* work around silly renaming of struct members in OS X 10.5 */
|
/* work around silly renaming of struct members in OS X 10.5 */
|
||||||
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32)
|
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32)
|
||||||
context->Dr0 = state.__dr0;
|
context->debug.i386_regs.dr0 = state.__dr0;
|
||||||
context->Dr1 = state.__dr1;
|
context->debug.i386_regs.dr1 = state.__dr1;
|
||||||
context->Dr2 = state.__dr2;
|
context->debug.i386_regs.dr2 = state.__dr2;
|
||||||
context->Dr3 = state.__dr3;
|
context->debug.i386_regs.dr3 = state.__dr3;
|
||||||
context->Dr6 = state.__dr6;
|
context->debug.i386_regs.dr6 = state.__dr6;
|
||||||
context->Dr7 = state.__dr7;
|
context->debug.i386_regs.dr7 = state.__dr7;
|
||||||
#else
|
#else
|
||||||
context->Dr0 = state.dr0;
|
context->debug.i386_regs.dr0 = state.dr0;
|
||||||
context->Dr1 = state.dr1;
|
context->debug.i386_regs.dr1 = state.dr1;
|
||||||
context->Dr2 = state.dr2;
|
context->debug.i386_regs.dr2 = state.dr2;
|
||||||
context->Dr3 = state.dr3;
|
context->debug.i386_regs.dr3 = state.dr3;
|
||||||
context->Dr6 = state.dr6;
|
context->debug.i386_regs.dr6 = state.dr6;
|
||||||
context->Dr7 = state.dr7;
|
context->debug.i386_regs.dr7 = state.dr7;
|
||||||
#endif
|
#endif
|
||||||
context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
context->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
}
|
}
|
||||||
mach_port_deallocate( mach_task_self(), port );
|
mach_port_deallocate( mach_task_self(), port );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 registers */
|
/* set the thread x86 registers */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
x86_debug_state32_t state;
|
x86_debug_state32_t state;
|
||||||
|
@ -213,7 +213,7 @@ void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned
|
||||||
mach_port_t port, process_port = get_process_port( thread->process );
|
mach_port_t port, process_port = get_process_port( thread->process );
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (thread->unix_pid == -1 || !process_port ||
|
if (thread->unix_pid == -1 || !process_port ||
|
||||||
mach_port_extract_right( process_port, thread->unix_tid,
|
mach_port_extract_right( process_port, thread->unix_tid,
|
||||||
|
@ -224,35 +224,28 @@ void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32)
|
#if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32)
|
||||||
state.__dr0 = context->Dr0;
|
state.__dr0 = context->debug.i386_regs.dr0;
|
||||||
state.__dr1 = context->Dr1;
|
state.__dr1 = context->debug.i386_regs.dr1;
|
||||||
state.__dr2 = context->Dr2;
|
state.__dr2 = context->debug.i386_regs.dr2;
|
||||||
state.__dr3 = context->Dr3;
|
state.__dr3 = context->debug.i386_regs.dr3;
|
||||||
state.__dr4 = 0;
|
state.__dr4 = 0;
|
||||||
state.__dr5 = 0;
|
state.__dr5 = 0;
|
||||||
state.__dr6 = context->Dr6;
|
state.__dr6 = context->debug.i386_regs.dr6;
|
||||||
state.__dr7 = context->Dr7;
|
state.__dr7 = context->debug.i386_regs.dr7;
|
||||||
#else
|
#else
|
||||||
state.dr0 = context->Dr0;
|
state.dr0 = context->debug.i386_regs.dr0;
|
||||||
state.dr1 = context->Dr1;
|
state.dr1 = context->debug.i386_regs.dr1;
|
||||||
state.dr2 = context->Dr2;
|
state.dr2 = context->debug.i386_regs.dr2;
|
||||||
state.dr3 = context->Dr3;
|
state.dr3 = context->debug.i386_regs.dr3;
|
||||||
state.dr4 = 0;
|
state.dr4 = 0;
|
||||||
state.dr5 = 0;
|
state.dr5 = 0;
|
||||||
state.dr6 = context->Dr6;
|
state.dr6 = context->debug.i386_regs.dr6;
|
||||||
state.dr7 = context->Dr7;
|
state.dr7 = context->debug.i386_regs.dr7;
|
||||||
#endif
|
#endif
|
||||||
if (!thread_set_state( port, x86_DEBUG_STATE32, (thread_state_t)&state, count ))
|
if (!thread_set_state( port, x86_DEBUG_STATE32, (thread_state_t)&state, count ))
|
||||||
{
|
{
|
||||||
if (thread->context) /* update the cached values */
|
if (thread->context) /* update the cached values */
|
||||||
{
|
thread->context->debug.i386_regs = context->debug.i386_regs;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mach_port_deallocate( mach_task_self(), port );
|
mach_port_deallocate( mach_task_self(), port );
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -200,20 +200,14 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* retrieve the thread registers */
|
/* retrieve the thread registers */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
/* all other regs are handled on the client side */
|
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
|
||||||
|
|
||||||
/* FIXME: get debug registers */
|
/* FIXME: get debug registers */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread registers */
|
/* set the thread registers */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
/* all other regs are handled on the client side */
|
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
|
||||||
|
|
||||||
/* FIXME: set debug registers */
|
/* FIXME: set debug registers */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,63 @@ enum cpu_type
|
||||||
};
|
};
|
||||||
typedef int cpu_type_t;
|
typedef int cpu_type_t;
|
||||||
|
|
||||||
|
/* context data */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cpu_type_t cpu; /* cpu type */
|
||||||
|
unsigned int flags; /* SERVER_CTX_* flags */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int eip, ebp, esp, eflags, cs, ss; } i386_regs;
|
||||||
|
struct { unsigned __int64 rip, rbp, rsp;
|
||||||
|
unsigned int cs, ss, flags, mxcsr; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 fir;
|
||||||
|
unsigned int psr; } alpha_regs;
|
||||||
|
struct { unsigned int iar, msr, ctr, lr, dar, dsisr, trap; } powerpc_regs;
|
||||||
|
struct { unsigned int psr, pc, npc, y, wim, tbr; } sparc_regs;
|
||||||
|
} ctl; /* selected by SERVER_CTX_CONTROL */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int eax, ebx, ecx, edx, esi, edi; } i386_regs;
|
||||||
|
struct { unsigned __int64 rax,rbx, rcx, rdx, rsi, rdi,
|
||||||
|
r8, r9, r10, r11, r12, r13, r14, r15; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 v0, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12,
|
||||||
|
s0, s1, s2, s3, s4, s5, s6, a0, a1, a2, a3, a4, a5, at; } alpha_regs;
|
||||||
|
struct { unsigned int gpr[32], cr, xer; } powerpc_regs;
|
||||||
|
struct { unsigned int g[8], o[8], l[8], i[8]; } sparc_regs;
|
||||||
|
} integer; /* selected by SERVER_CTX_INTEGER */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int ds, es, fs, gs; } i386_regs;
|
||||||
|
struct { unsigned int ds, es, fs, gs; } x86_64_regs;
|
||||||
|
} seg; /* selected by SERVER_CTX_SEGMENTS */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int ctrl, status, tag, err_off, err_sel, data_off, data_sel, cr0npx;
|
||||||
|
unsigned char regs[80]; } i386_regs;
|
||||||
|
struct { struct { unsigned __int64 low, high; } fpregs[32]; } x86_64_regs;
|
||||||
|
struct { unsigned __int64 f[32], fpcr, softfpcr; } alpha_regs;
|
||||||
|
struct { double fpr[32], fpscr; } powerpc_regs;
|
||||||
|
} fp; /* selected by SERVER_CTX_FLOATING_POINT */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct { unsigned int dr0, dr1, dr2, dr3, dr6, dr7; } i386_regs;
|
||||||
|
struct { unsigned __int64 dr0, dr1, dr2, dr3, dr6, dr7; } x86_64_regs;
|
||||||
|
struct { unsigned int dr[8]; } powerpc_regs;
|
||||||
|
} debug; /* selected by SERVER_CTX_DEBUG_REGISTERS */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char i386_regs[512];
|
||||||
|
} ext; /* selected by SERVER_CTX_EXTENDED_REGISTERS */
|
||||||
|
} context_t;
|
||||||
|
|
||||||
|
#define SERVER_CTX_CONTROL 0x01
|
||||||
|
#define SERVER_CTX_INTEGER 0x02
|
||||||
|
#define SERVER_CTX_SEGMENTS 0x04
|
||||||
|
#define SERVER_CTX_FLOATING_POINT 0x08
|
||||||
|
#define SERVER_CTX_DEBUG_REGISTERS 0x10
|
||||||
|
#define SERVER_CTX_EXTENDED_REGISTERS 0x20
|
||||||
|
|
||||||
/* structure used in sending an fd from client to server */
|
/* structure used in sending an fd from client to server */
|
||||||
struct send_fd
|
struct send_fd
|
||||||
{
|
{
|
||||||
|
@ -1732,7 +1789,6 @@ enum char_info_mode
|
||||||
/* Set the current context of a thread */
|
/* Set the current context of a thread */
|
||||||
@REQ(set_thread_context)
|
@REQ(set_thread_context)
|
||||||
obj_handle_t handle; /* thread handle */
|
obj_handle_t handle; /* thread handle */
|
||||||
unsigned int flags; /* context flags */
|
|
||||||
int suspend; /* if setting context during suspend */
|
int suspend; /* if setting context during suspend */
|
||||||
VARARG(context,context); /* thread context */
|
VARARG(context,context); /* thread context */
|
||||||
@REPLY
|
@REPLY
|
||||||
|
|
119
server/ptrace.c
119
server/ptrace.c
|
@ -527,13 +527,13 @@ void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
|
||||||
#define DR_OFFSET(dr) ((((struct user *)0)->u_debugreg) + (dr))
|
#define DR_OFFSET(dr) ((((struct user *)0)->u_debugreg) + (dr))
|
||||||
|
|
||||||
/* retrieve the thread x86 registers */
|
/* retrieve the thread x86 registers */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int i, pid = get_ptrace_tid(thread);
|
int i, pid = get_ptrace_tid(thread);
|
||||||
long data[8];
|
long data[8];
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (!suspend_for_ptrace( thread )) return;
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
|
@ -548,39 +548,39 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context->Dr0 = data[0];
|
context->debug.i386_regs.dr0 = data[0];
|
||||||
context->Dr1 = data[1];
|
context->debug.i386_regs.dr1 = data[1];
|
||||||
context->Dr2 = data[2];
|
context->debug.i386_regs.dr2 = data[2];
|
||||||
context->Dr3 = data[3];
|
context->debug.i386_regs.dr3 = data[3];
|
||||||
context->Dr6 = data[6];
|
context->debug.i386_regs.dr6 = data[6];
|
||||||
context->Dr7 = data[7];
|
context->debug.i386_regs.dr7 = data[7];
|
||||||
context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
context->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
done:
|
done:
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 registers */
|
/* set the thread x86 registers */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int pid = get_ptrace_tid( thread );
|
int pid = get_ptrace_tid( thread );
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (!suspend_for_ptrace( thread )) return;
|
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->debug.i386_regs.dr0 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr0 = context->Dr0;
|
if (thread->context) thread->context->debug.i386_regs.dr0 = context->debug.i386_regs.dr0;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.i386_regs.dr1 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr1 = context->Dr1;
|
if (thread->context) thread->context->debug.i386_regs.dr1 = context->debug.i386_regs.dr1;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->debug.i386_regs.dr2 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr2 = context->Dr2;
|
if (thread->context) thread->context->debug.i386_regs.dr2 = context->debug.i386_regs.dr2;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->debug.i386_regs.dr3 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr3 = context->Dr3;
|
if (thread->context) thread->context->debug.i386_regs.dr3 = context->debug.i386_regs.dr3;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->debug.i386_regs.dr6 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr6 = context->Dr6;
|
if (thread->context) thread->context->debug.i386_regs.dr6 = context->debug.i386_regs.dr6;
|
||||||
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error;
|
if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.i386_regs.dr7 ) == -1) goto error;
|
||||||
if (thread->context) thread->context->Dr7 = context->Dr7;
|
if (thread->context) thread->context->debug.i386_regs.dr7 = context->debug.i386_regs.dr7;
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
|
@ -594,13 +594,13 @@ void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
/* retrieve the thread x86 registers */
|
/* retrieve the thread x86 registers */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int pid = get_ptrace_tid(thread);
|
int pid = get_ptrace_tid(thread);
|
||||||
struct dbreg dbregs;
|
struct dbreg dbregs;
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (!suspend_for_ptrace( thread )) return;
|
if (!suspend_for_ptrace( thread )) return;
|
||||||
|
|
||||||
|
@ -609,78 +609,71 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
|
||||||
{
|
{
|
||||||
#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->debug.i386_regs.dr0 = DBREG_DRX((&dbregs), 0);
|
||||||
context->Dr1 = DBREG_DRX((&dbregs), 1);
|
context->debug.i386_regs.dr1 = DBREG_DRX((&dbregs), 1);
|
||||||
context->Dr2 = DBREG_DRX((&dbregs), 2);
|
context->debug.i386_regs.dr2 = DBREG_DRX((&dbregs), 2);
|
||||||
context->Dr3 = DBREG_DRX((&dbregs), 3);
|
context->debug.i386_regs.dr3 = DBREG_DRX((&dbregs), 3);
|
||||||
context->Dr6 = DBREG_DRX((&dbregs), 6);
|
context->debug.i386_regs.dr6 = DBREG_DRX((&dbregs), 6);
|
||||||
context->Dr7 = DBREG_DRX((&dbregs), 7);
|
context->debug.i386_regs.dr7 = DBREG_DRX((&dbregs), 7);
|
||||||
#else
|
#else
|
||||||
context->Dr0 = dbregs.dr0;
|
context->debug.i386_regs.dr0 = dbregs.dr0;
|
||||||
context->Dr1 = dbregs.dr1;
|
context->debug.i386_regs.dr1 = dbregs.dr1;
|
||||||
context->Dr2 = dbregs.dr2;
|
context->debug.i386_regs.dr2 = dbregs.dr2;
|
||||||
context->Dr3 = dbregs.dr3;
|
context->debug.i386_regs.dr3 = dbregs.dr3;
|
||||||
context->Dr6 = dbregs.dr6;
|
context->debug.i386_regs.dr6 = dbregs.dr6;
|
||||||
context->Dr7 = dbregs.dr7;
|
context->debug.i386_regs.dr7 = dbregs.dr7;
|
||||||
#endif
|
#endif
|
||||||
context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
|
context->flags |= SERVER_CTX_DEBUG_REGISTERS;
|
||||||
}
|
}
|
||||||
resume_after_ptrace( thread );
|
resume_after_ptrace( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 registers */
|
/* set the thread x86 registers */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
int pid = get_ptrace_tid(thread);
|
int pid = get_ptrace_tid(thread);
|
||||||
struct dbreg dbregs;
|
struct dbreg dbregs;
|
||||||
|
|
||||||
/* all other regs are handled on the client side */
|
/* all other regs are handled on the client side */
|
||||||
assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
|
assert( flags == SERVER_CTX_DEBUG_REGISTERS );
|
||||||
|
|
||||||
if (!suspend_for_ptrace( thread )) return;
|
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->debug.i386_regs.dr0;
|
||||||
DBREG_DRX((&dbregs), 1) = context->Dr1;
|
DBREG_DRX((&dbregs), 1) = context->debug.i386_regs.dr1;
|
||||||
DBREG_DRX((&dbregs), 2) = context->Dr2;
|
DBREG_DRX((&dbregs), 2) = context->debug.i386_regs.dr2;
|
||||||
DBREG_DRX((&dbregs), 3) = context->Dr3;
|
DBREG_DRX((&dbregs), 3) = context->debug.i386_regs.dr3;
|
||||||
DBREG_DRX((&dbregs), 4) = 0;
|
DBREG_DRX((&dbregs), 4) = 0;
|
||||||
DBREG_DRX((&dbregs), 5) = 0;
|
DBREG_DRX((&dbregs), 5) = 0;
|
||||||
DBREG_DRX((&dbregs), 6) = context->Dr6;
|
DBREG_DRX((&dbregs), 6) = context->debug.i386_regs.dr6;
|
||||||
DBREG_DRX((&dbregs), 7) = context->Dr7;
|
DBREG_DRX((&dbregs), 7) = context->debug.i386_regs.dr7;
|
||||||
#else
|
#else
|
||||||
dbregs.dr0 = context->Dr0;
|
dbregs.dr0 = context->debug.i386_regs.dr0;
|
||||||
dbregs.dr1 = context->Dr1;
|
dbregs.dr1 = context->debug.i386_regs.dr1;
|
||||||
dbregs.dr2 = context->Dr2;
|
dbregs.dr2 = context->debug.i386_regs.dr2;
|
||||||
dbregs.dr3 = context->Dr3;
|
dbregs.dr3 = context->debug.i386_regs.dr3;
|
||||||
dbregs.dr4 = 0;
|
dbregs.dr4 = 0;
|
||||||
dbregs.dr5 = 0;
|
dbregs.dr5 = 0;
|
||||||
dbregs.dr6 = context->Dr6;
|
dbregs.dr6 = context->debug.i386_regs.dr6;
|
||||||
dbregs.dr7 = context->Dr7;
|
dbregs.dr7 = context->debug.i386_regs.dr7;
|
||||||
#endif
|
#endif
|
||||||
if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
|
if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
|
||||||
else if (thread->context) /* update the cached values */
|
else if (thread->context)
|
||||||
{
|
thread->context->debug.i386_regs = context->debug.i386_regs; /* 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 );
|
resume_after_ptrace( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* linux || __FreeBSD__ */
|
#else /* linux || __FreeBSD__ */
|
||||||
|
|
||||||
/* retrieve the thread x86 registers */
|
/* retrieve the thread x86 registers */
|
||||||
void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
|
void get_thread_context( struct thread *thread, context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the thread x86 debug registers */
|
/* set the thread x86 debug registers */
|
||||||
void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
|
void set_thread_context( struct thread *thread, const context_t *context, unsigned int flags )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1212,8 +1212,7 @@ C_ASSERT( FIELD_OFFSET(struct get_thread_context_request, suspend) == 20 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_thread_context_reply, self) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct get_thread_context_reply, self) == 8 );
|
||||||
C_ASSERT( sizeof(struct get_thread_context_reply) == 16 );
|
C_ASSERT( sizeof(struct get_thread_context_reply) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, handle) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, flags) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, suspend) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, suspend) == 20 );
|
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_thread_context_reply, self) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct set_thread_context_reply, self) == 8 );
|
||||||
C_ASSERT( sizeof(struct set_thread_context_reply) == 16 );
|
C_ASSERT( sizeof(struct set_thread_context_reply) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_selector_entry_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_selector_entry_request, handle) == 12 );
|
||||||
|
|
|
@ -944,6 +944,34 @@ void kill_thread( struct thread *thread, int violent_death )
|
||||||
release_object( thread );
|
release_object( thread );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy parts of a context structure */
|
||||||
|
static void copy_context( context_t *to, const context_t *from, unsigned int flags )
|
||||||
|
{
|
||||||
|
assert( to->cpu == from->cpu );
|
||||||
|
to->flags |= flags;
|
||||||
|
if (flags & SERVER_CTX_CONTROL) to->ctl = from->ctl;
|
||||||
|
if (flags & SERVER_CTX_INTEGER) to->integer = from->integer;
|
||||||
|
if (flags & SERVER_CTX_SEGMENTS) to->seg = from->seg;
|
||||||
|
if (flags & SERVER_CTX_FLOATING_POINT) to->fp = from->fp;
|
||||||
|
if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug;
|
||||||
|
if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the context flags that correspond to system regs */
|
||||||
|
/* (system regs are the ones we can't access on the client side) */
|
||||||
|
static unsigned int get_context_system_regs( enum cpu_type cpu )
|
||||||
|
{
|
||||||
|
switch (cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86: return SERVER_CTX_DEBUG_REGISTERS;
|
||||||
|
case CPU_x86_64: return SERVER_CTX_DEBUG_REGISTERS;
|
||||||
|
case CPU_ALPHA: return 0;
|
||||||
|
case CPU_POWERPC: return 0;
|
||||||
|
case CPU_SPARC: return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* trigger a breakpoint event in a given thread */
|
/* trigger a breakpoint event in a given thread */
|
||||||
void break_thread( struct thread *thread )
|
void break_thread( struct thread *thread )
|
||||||
{
|
{
|
||||||
|
@ -955,7 +983,24 @@ void break_thread( struct thread *thread )
|
||||||
data.exception.first = 1;
|
data.exception.first = 1;
|
||||||
data.exception.exc_code = STATUS_BREAKPOINT;
|
data.exception.exc_code = STATUS_BREAKPOINT;
|
||||||
data.exception.flags = EXCEPTION_CONTINUABLE;
|
data.exception.flags = EXCEPTION_CONTINUABLE;
|
||||||
data.exception.address = get_context_ip( thread->context );
|
switch (thread->context->cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86:
|
||||||
|
data.exception.address = thread->context->ctl.i386_regs.eip;
|
||||||
|
break;
|
||||||
|
case CPU_x86_64:
|
||||||
|
data.exception.address = thread->context->ctl.x86_64_regs.rip;
|
||||||
|
break;
|
||||||
|
case CPU_ALPHA:
|
||||||
|
data.exception.address = thread->context->ctl.alpha_regs.fir;
|
||||||
|
break;
|
||||||
|
case CPU_POWERPC:
|
||||||
|
data.exception.address = thread->context->ctl.powerpc_regs.iar;
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
data.exception.address = thread->context->ctl.sparc_regs.pc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
|
generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
|
||||||
thread->debug_break = 0;
|
thread->debug_break = 0;
|
||||||
}
|
}
|
||||||
|
@ -1357,9 +1402,9 @@ DECL_HANDLER(get_apc_result)
|
||||||
DECL_HANDLER(get_thread_context)
|
DECL_HANDLER(get_thread_context)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
CONTEXT *context;
|
context_t *context;
|
||||||
|
|
||||||
if (get_reply_max_size() < sizeof(CONTEXT))
|
if (get_reply_max_size() < sizeof(context_t))
|
||||||
{
|
{
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
return;
|
return;
|
||||||
|
@ -1376,7 +1421,7 @@ DECL_HANDLER(get_thread_context)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (thread->context == thread->suspend_context) thread->context = NULL;
|
if (thread->context == thread->suspend_context) thread->context = NULL;
|
||||||
set_reply_data_ptr( thread->suspend_context, sizeof(CONTEXT) );
|
set_reply_data_ptr( thread->suspend_context, sizeof(context_t) );
|
||||||
thread->suspend_context = NULL;
|
thread->suspend_context = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1386,12 +1431,12 @@ 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 ((context = set_reply_data_size( sizeof(CONTEXT) )))
|
else if ((context = set_reply_data_size( sizeof(context_t) )))
|
||||||
{
|
{
|
||||||
unsigned int flags = get_context_system_regs( req->flags );
|
unsigned int flags = get_context_system_regs( thread->process->cpu );
|
||||||
|
|
||||||
memset( context, 0, sizeof(CONTEXT) );
|
memset( context, 0, sizeof(context_t) );
|
||||||
context->ContextFlags = get_context_cpu_flag();
|
context->cpu = thread->process->cpu;
|
||||||
if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
|
if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
|
||||||
if (flags) get_thread_context( thread, context, flags );
|
if (flags) get_thread_context( thread, context, flags );
|
||||||
}
|
}
|
||||||
|
@ -1403,8 +1448,9 @@ DECL_HANDLER(get_thread_context)
|
||||||
DECL_HANDLER(set_thread_context)
|
DECL_HANDLER(set_thread_context)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
|
const context_t *context = get_req_data();
|
||||||
|
|
||||||
if (get_req_data_size() < sizeof(CONTEXT))
|
if (get_req_data_size() < sizeof(context_t))
|
||||||
{
|
{
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
return;
|
return;
|
||||||
|
@ -1413,14 +1459,14 @@ DECL_HANDLER(set_thread_context)
|
||||||
|
|
||||||
if (req->suspend)
|
if (req->suspend)
|
||||||
{
|
{
|
||||||
if (thread != current || thread->context)
|
if (thread != current || thread->context || context->cpu != thread->process->cpu)
|
||||||
{
|
{
|
||||||
/* nested suspend or exception, shouldn't happen */
|
/* nested suspend or exception, shouldn't happen */
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
}
|
}
|
||||||
else if ((thread->suspend_context = mem_alloc( sizeof(CONTEXT) )))
|
else if ((thread->suspend_context = mem_alloc( sizeof(context_t) )))
|
||||||
{
|
{
|
||||||
memcpy( thread->suspend_context, get_req_data(), sizeof(CONTEXT) );
|
memcpy( thread->suspend_context, get_req_data(), sizeof(context_t) );
|
||||||
thread->context = thread->suspend_context;
|
thread->context = thread->suspend_context;
|
||||||
if (thread->debug_break) break_thread( thread );
|
if (thread->debug_break) break_thread( thread );
|
||||||
}
|
}
|
||||||
|
@ -1431,15 +1477,16 @@ DECL_HANDLER(set_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
|
else if (context->cpu == thread->process->cpu)
|
||||||
{
|
{
|
||||||
const CONTEXT *context = get_req_data();
|
unsigned int system_flags = get_context_system_regs(context->cpu) & context->flags;
|
||||||
unsigned int flags = get_context_system_regs( req->flags );
|
unsigned int client_flags = context->flags & ~system_flags;
|
||||||
|
|
||||||
if (flags) set_thread_context( thread, context, flags );
|
if (system_flags) set_thread_context( thread, context, system_flags );
|
||||||
if (thread->context && !get_error())
|
if (thread->context && !get_error()) copy_context( thread->context, context, client_flags );
|
||||||
copy_context( thread->context, context, req->flags & ~flags );
|
|
||||||
}
|
}
|
||||||
|
else set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
|
||||||
reply->self = (thread == current);
|
reply->self = (thread == current);
|
||||||
release_object( thread );
|
release_object( thread );
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ struct thread
|
||||||
int exit_code; /* thread exit code */
|
int exit_code; /* thread exit code */
|
||||||
int unix_pid; /* Unix pid of client */
|
int unix_pid; /* Unix pid of client */
|
||||||
int unix_tid; /* Unix tid of client */
|
int unix_tid; /* Unix tid of client */
|
||||||
CONTEXT *context; /* current context if in an exception handler */
|
context_t *context; /* current context if in an exception handler */
|
||||||
CONTEXT *suspend_context; /* current context if suspended */
|
context_t *suspend_context; /* current context if suspended */
|
||||||
client_ptr_t teb; /* TEB address (in client address space) */
|
client_ptr_t teb; /* TEB address (in client address space) */
|
||||||
affinity_t affinity; /* affinity mask */
|
affinity_t affinity; /* affinity mask */
|
||||||
int priority; /* priority level */
|
int priority; /* priority level */
|
||||||
|
@ -119,17 +119,11 @@ 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 client_ptr_t 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 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
|
extern void get_thread_context( struct thread *thread, context_t *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_t *context, unsigned int flags );
|
||||||
extern int send_thread_signal( struct thread *thread, int sig );
|
extern int send_thread_signal( struct thread *thread, int sig );
|
||||||
extern void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
|
extern void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
|
||||||
unsigned int *limit, unsigned char *flags );
|
unsigned int *limit, unsigned char *flags );
|
||||||
|
|
210
server/trace.c
210
server/trace.c
|
@ -298,33 +298,6 @@ static void dump_luid( const char *prefix, const luid_t *luid )
|
||||||
fprintf( stderr, "%s%d.%u", prefix, luid->high_part, luid->low_part );
|
fprintf( stderr, "%s%d.%u", prefix, luid->high_part, luid->low_part );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_context( const CONTEXT *context, data_size_t size )
|
|
||||||
{
|
|
||||||
CONTEXT ctx;
|
|
||||||
|
|
||||||
memset( &ctx, 0, sizeof(ctx) );
|
|
||||||
memcpy( &ctx, context, min( size, sizeof(CONTEXT) ));
|
|
||||||
#ifdef __i386__
|
|
||||||
fprintf( stderr, "{flags=%08x,eax=%08x,ebx=%08x,ecx=%08x,edx=%08x,esi=%08x,edi=%08x,"
|
|
||||||
"ebp=%08x,eip=%08x,esp=%08x,eflags=%08x,cs=%04x,ds=%04x,es=%04x,"
|
|
||||||
"fs=%04x,gs=%04x,dr0=%08x,dr1=%08x,dr2=%08x,dr3=%08x,dr6=%08x,dr7=%08x,",
|
|
||||||
ctx.ContextFlags, ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx,
|
|
||||||
ctx.Esi, ctx.Edi, ctx.Ebp, ctx.Eip, ctx.Esp, ctx.EFlags,
|
|
||||||
ctx.SegCs, ctx.SegDs, ctx.SegEs, ctx.SegFs, ctx.SegGs,
|
|
||||||
ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr6, ctx.Dr7 );
|
|
||||||
fprintf( stderr, "float=" );
|
|
||||||
dump_uints( (const int *)&ctx.FloatSave, sizeof(ctx.FloatSave) / sizeof(int) );
|
|
||||||
if (size > FIELD_OFFSET( CONTEXT, ExtendedRegisters ))
|
|
||||||
{
|
|
||||||
fprintf( stderr, ",extended=" );
|
|
||||||
dump_uints( (const int *)&ctx.ExtendedRegisters, sizeof(ctx.ExtendedRegisters) / sizeof(int) );
|
|
||||||
}
|
|
||||||
fprintf( stderr, "}" );
|
|
||||||
#else
|
|
||||||
dump_uints( (const int *)&ctx, sizeof(ctx) / sizeof(int) );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_varargs_ints( const char *prefix, data_size_t size )
|
static void dump_varargs_ints( const char *prefix, data_size_t size )
|
||||||
{
|
{
|
||||||
const int *data = cur_data;
|
const int *data = cur_data;
|
||||||
|
@ -428,14 +401,190 @@ static void dump_varargs_unicode_str( const char *prefix, data_size_t size )
|
||||||
|
|
||||||
static void dump_varargs_context( const char *prefix, data_size_t size )
|
static void dump_varargs_context( const char *prefix, data_size_t size )
|
||||||
{
|
{
|
||||||
|
const context_t *context = cur_data;
|
||||||
|
context_t ctx;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
{
|
{
|
||||||
fprintf( stderr, "%s{}", prefix );
|
fprintf( stderr, "%s{}", prefix );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf( stderr, "%s", prefix );
|
size = min( size, sizeof(ctx) );
|
||||||
dump_context( cur_data, size );
|
memset( &ctx, 0, sizeof(ctx) );
|
||||||
remove_data( min( size, sizeof(CONTEXT) ));
|
memcpy( &ctx, context, size );
|
||||||
|
|
||||||
|
fprintf( stderr,"%s{", prefix );
|
||||||
|
dump_cpu_type( "cpu=", &ctx.cpu );
|
||||||
|
switch (ctx.cpu)
|
||||||
|
{
|
||||||
|
case CPU_x86:
|
||||||
|
if (ctx.flags & SERVER_CTX_CONTROL)
|
||||||
|
fprintf( stderr, ",eip=%08x,esp=%08x,ebp=%08x,eflags=%08x,cs=%04x,ss=%04x",
|
||||||
|
ctx.ctl.i386_regs.eip, ctx.ctl.i386_regs.esp, ctx.ctl.i386_regs.ebp,
|
||||||
|
ctx.ctl.i386_regs.eflags, ctx.ctl.i386_regs.cs, ctx.ctl.i386_regs.ss );
|
||||||
|
if (ctx.flags & SERVER_CTX_SEGMENTS)
|
||||||
|
fprintf( stderr, ",ds=%04x,es=%04x,fs=%04x,gs=%04x",
|
||||||
|
ctx.seg.i386_regs.ds, ctx.seg.i386_regs.es,
|
||||||
|
ctx.seg.i386_regs.fs, ctx.seg.i386_regs.gs );
|
||||||
|
if (ctx.flags & SERVER_CTX_INTEGER)
|
||||||
|
fprintf( stderr, ",eax=%08x,ebx=%08x,ecx=%08x,edx=%08x,esi=%08x,edi=%08x",
|
||||||
|
ctx.integer.i386_regs.eax, ctx.integer.i386_regs.ebx, ctx.integer.i386_regs.ecx,
|
||||||
|
ctx.integer.i386_regs.edx, ctx.integer.i386_regs.esi, ctx.integer.i386_regs.edi );
|
||||||
|
if (ctx.flags & SERVER_CTX_DEBUG_REGISTERS)
|
||||||
|
fprintf( stderr, ",dr0=%08x,dr1=%08x,dr2=%08x,dr3=%08x,dr6=%08x,dr7=%08x",
|
||||||
|
ctx.debug.i386_regs.dr0, ctx.debug.i386_regs.dr1, ctx.debug.i386_regs.dr2,
|
||||||
|
ctx.debug.i386_regs.dr3, ctx.debug.i386_regs.dr6, ctx.debug.i386_regs.dr7 );
|
||||||
|
if (ctx.flags & SERVER_CTX_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
fprintf( stderr, "fp.ctrl=%08x,fp.status=%08x,fp.tag=%08x,fp.err_off=%08x,fp.err_sel=%08x",
|
||||||
|
ctx.fp.i386_regs.ctrl, ctx.fp.i386_regs.status, ctx.fp.i386_regs.tag,
|
||||||
|
ctx.fp.i386_regs.err_off, ctx.fp.i386_regs.err_sel );
|
||||||
|
fprintf( stderr, ",fp.data_off=%08x,fp.data_sel=%08x,fp.cr0npx=%08x",
|
||||||
|
ctx.fp.i386_regs.data_off, ctx.fp.i386_regs.data_sel, ctx.fp.i386_regs.cr0npx );
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
fprintf( stderr, ",fp.reg%u=%Lg", i, *(long double *)&ctx.fp.i386_regs.regs[10*i] );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_EXTENDED_REGISTERS)
|
||||||
|
{
|
||||||
|
fprintf( stderr, ",extended=" );
|
||||||
|
dump_uints( (const int *)ctx.ext.i386_regs, sizeof(ctx.ext.i386_regs) / sizeof(int) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_x86_64:
|
||||||
|
if (ctx.flags & SERVER_CTX_CONTROL)
|
||||||
|
{
|
||||||
|
dump_uint64( ",rip=", &ctx.ctl.x86_64_regs.rip );
|
||||||
|
dump_uint64( ",rbp=", &ctx.ctl.x86_64_regs.rbp );
|
||||||
|
dump_uint64( ",rsp=", &ctx.ctl.x86_64_regs.rsp );
|
||||||
|
fprintf( stderr, ",cs=%04x,ss=%04x,flags=%08x,mxcsr=%08x",
|
||||||
|
ctx.ctl.x86_64_regs.cs, ctx.ctl.x86_64_regs.ss,
|
||||||
|
ctx.ctl.x86_64_regs.flags, ctx.ctl.x86_64_regs.mxcsr );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_INTEGER)
|
||||||
|
{
|
||||||
|
dump_uint64( ",rax=", &ctx.integer.x86_64_regs.rax );
|
||||||
|
dump_uint64( ",rbx=", &ctx.integer.x86_64_regs.rbx );
|
||||||
|
dump_uint64( ",rcx=", &ctx.integer.x86_64_regs.rcx );
|
||||||
|
dump_uint64( ",rdx=", &ctx.integer.x86_64_regs.rdx );
|
||||||
|
dump_uint64( ",rsi=", &ctx.integer.x86_64_regs.rsi );
|
||||||
|
dump_uint64( ",rdi=", &ctx.integer.x86_64_regs.rdi );
|
||||||
|
dump_uint64( ",r8=", &ctx.integer.x86_64_regs.r8 );
|
||||||
|
dump_uint64( ",r9=", &ctx.integer.x86_64_regs.r9 );
|
||||||
|
dump_uint64( ",r10=", &ctx.integer.x86_64_regs.r10 );
|
||||||
|
dump_uint64( ",r11=", &ctx.integer.x86_64_regs.r11 );
|
||||||
|
dump_uint64( ",r12=", &ctx.integer.x86_64_regs.r12 );
|
||||||
|
dump_uint64( ",r13=", &ctx.integer.x86_64_regs.r13 );
|
||||||
|
dump_uint64( ",r14=", &ctx.integer.x86_64_regs.r14 );
|
||||||
|
dump_uint64( ",r15=", &ctx.integer.x86_64_regs.r15 );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_SEGMENTS)
|
||||||
|
fprintf( stderr, ",ds=%04x,es=%04x,fs=%04x,gs=%04x",
|
||||||
|
ctx.seg.x86_64_regs.ds, ctx.seg.x86_64_regs.es,
|
||||||
|
ctx.seg.x86_64_regs.fs, ctx.seg.x86_64_regs.gs );
|
||||||
|
if (ctx.flags & SERVER_CTX_DEBUG_REGISTERS)
|
||||||
|
{
|
||||||
|
dump_uint64( ",dr0=", &ctx.debug.x86_64_regs.dr0 );
|
||||||
|
dump_uint64( ",dr1=", &ctx.debug.x86_64_regs.dr1 );
|
||||||
|
dump_uint64( ",dr2=", &ctx.debug.x86_64_regs.dr2 );
|
||||||
|
dump_uint64( ",dr3=", &ctx.debug.x86_64_regs.dr3 );
|
||||||
|
dump_uint64( ",dr6=", &ctx.debug.x86_64_regs.dr6 );
|
||||||
|
dump_uint64( ",dr7=", &ctx.debug.x86_64_regs.dr7 );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
fprintf( stderr, ",fp%u=%08x%08x%08x%08x", i,
|
||||||
|
(unsigned int)(ctx.fp.x86_64_regs.fpregs[i].high >> 32),
|
||||||
|
(unsigned int)ctx.fp.x86_64_regs.fpregs[i].high,
|
||||||
|
(unsigned int)(ctx.fp.x86_64_regs.fpregs[i].low >> 32),
|
||||||
|
(unsigned int)ctx.fp.x86_64_regs.fpregs[i].low );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_ALPHA:
|
||||||
|
if (ctx.flags & SERVER_CTX_CONTROL)
|
||||||
|
{
|
||||||
|
dump_uint64( ",fir=", &ctx.ctl.alpha_regs.fir );
|
||||||
|
fprintf( stderr, ",psr=%08x", ctx.ctl.alpha_regs.psr );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_INTEGER)
|
||||||
|
{
|
||||||
|
dump_uint64( ",v0=", &ctx.integer.alpha_regs.v0 );
|
||||||
|
dump_uint64( ",t0=", &ctx.integer.alpha_regs.t0 );
|
||||||
|
dump_uint64( ",t1=", &ctx.integer.alpha_regs.t1 );
|
||||||
|
dump_uint64( ",t2=", &ctx.integer.alpha_regs.t2 );
|
||||||
|
dump_uint64( ",t3=", &ctx.integer.alpha_regs.t3 );
|
||||||
|
dump_uint64( ",t4=", &ctx.integer.alpha_regs.t4 );
|
||||||
|
dump_uint64( ",t5=", &ctx.integer.alpha_regs.t5 );
|
||||||
|
dump_uint64( ",t6=", &ctx.integer.alpha_regs.t6 );
|
||||||
|
dump_uint64( ",t7=", &ctx.integer.alpha_regs.t7 );
|
||||||
|
dump_uint64( ",t8=", &ctx.integer.alpha_regs.t8 );
|
||||||
|
dump_uint64( ",t9=", &ctx.integer.alpha_regs.t9 );
|
||||||
|
dump_uint64( ",t10=", &ctx.integer.alpha_regs.t10 );
|
||||||
|
dump_uint64( ",t11=", &ctx.integer.alpha_regs.t11 );
|
||||||
|
dump_uint64( ",t12=", &ctx.integer.alpha_regs.t12 );
|
||||||
|
dump_uint64( ",s0=", &ctx.integer.alpha_regs.s0 );
|
||||||
|
dump_uint64( ",s1=", &ctx.integer.alpha_regs.s1 );
|
||||||
|
dump_uint64( ",s2=", &ctx.integer.alpha_regs.s2 );
|
||||||
|
dump_uint64( ",s3=", &ctx.integer.alpha_regs.s3 );
|
||||||
|
dump_uint64( ",s4=", &ctx.integer.alpha_regs.s4 );
|
||||||
|
dump_uint64( ",s5=", &ctx.integer.alpha_regs.s5 );
|
||||||
|
dump_uint64( ",s6=", &ctx.integer.alpha_regs.s6 );
|
||||||
|
dump_uint64( ",a0=", &ctx.integer.alpha_regs.a0 );
|
||||||
|
dump_uint64( ",a1=", &ctx.integer.alpha_regs.a1 );
|
||||||
|
dump_uint64( ",a2=", &ctx.integer.alpha_regs.a2 );
|
||||||
|
dump_uint64( ",a3=", &ctx.integer.alpha_regs.a3 );
|
||||||
|
dump_uint64( ",a4=", &ctx.integer.alpha_regs.a4 );
|
||||||
|
dump_uint64( ",a5=", &ctx.integer.alpha_regs.a5 );
|
||||||
|
dump_uint64( ",at=", &ctx.integer.alpha_regs.at );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
fprintf( stderr, ",f%u", i );
|
||||||
|
dump_uint64( "=", &ctx.fp.alpha_regs.f[i] );
|
||||||
|
}
|
||||||
|
dump_uint64( ",fpcr=", &ctx.fp.alpha_regs.fpcr );
|
||||||
|
dump_uint64( ",softfpcr=", &ctx.fp.alpha_regs.softfpcr );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_POWERPC:
|
||||||
|
if (ctx.flags & SERVER_CTX_CONTROL)
|
||||||
|
fprintf( stderr, ",iar=%08x,msr=%08x,ctr=%08x,lr=%08x,dar=%08x,dsisr=%08x,trap=%08x",
|
||||||
|
ctx.ctl.powerpc_regs.iar, ctx.ctl.powerpc_regs.msr, ctx.ctl.powerpc_regs.ctr,
|
||||||
|
ctx.ctl.powerpc_regs.lr, ctx.ctl.powerpc_regs.dar, ctx.ctl.powerpc_regs.dsisr,
|
||||||
|
ctx.ctl.powerpc_regs.trap );
|
||||||
|
if (ctx.flags & SERVER_CTX_INTEGER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++) fprintf( stderr, ",gpr%u=%08x", i, ctx.integer.powerpc_regs.gpr[i] );
|
||||||
|
fprintf( stderr, ",cr=%08x,xer=%08x",
|
||||||
|
ctx.integer.powerpc_regs.cr, ctx.integer.powerpc_regs.xer );
|
||||||
|
}
|
||||||
|
if (ctx.flags & SERVER_CTX_DEBUG_REGISTERS)
|
||||||
|
for (i = 0; i < 8; i++) fprintf( stderr, ",dr%u=%08x", i, ctx.debug.powerpc_regs.dr[i] );
|
||||||
|
if (ctx.flags & SERVER_CTX_FLOATING_POINT)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++) fprintf( stderr, ",fpr%u=%g", i, ctx.fp.powerpc_regs.fpr[i] );
|
||||||
|
fprintf( stderr, ",fpscr=%g", ctx.fp.powerpc_regs.fpscr );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPU_SPARC:
|
||||||
|
if (ctx.flags & SERVER_CTX_CONTROL)
|
||||||
|
fprintf( stderr, ",psr=%08x,pc=%08x,npc=%08x,y=%08x,wim=%08x,tbr=%08x",
|
||||||
|
ctx.ctl.sparc_regs.psr, ctx.ctl.sparc_regs.pc, ctx.ctl.sparc_regs.npc,
|
||||||
|
ctx.ctl.sparc_regs.y, ctx.ctl.sparc_regs.wim, ctx.ctl.sparc_regs.tbr );
|
||||||
|
if (ctx.flags & SERVER_CTX_INTEGER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 8; i++) fprintf( stderr, ",g%u=%08x", i, ctx.integer.sparc_regs.g[i] );
|
||||||
|
for (i = 0; i < 8; i++) fprintf( stderr, ",o%u=%08x", i, ctx.integer.sparc_regs.o[i] );
|
||||||
|
for (i = 0; i < 8; i++) fprintf( stderr, ",l%u=%08x", i, ctx.integer.sparc_regs.l[i] );
|
||||||
|
for (i = 0; i < 8; i++) fprintf( stderr, ",i%u=%08x", i, ctx.integer.sparc_regs.i[i] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fputc( '}', stderr );
|
||||||
|
remove_data( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_varargs_debug_event( const char *prefix, data_size_t size )
|
static void dump_varargs_debug_event( const char *prefix, data_size_t size )
|
||||||
|
@ -2128,7 +2277,6 @@ static void dump_get_thread_context_reply( const struct get_thread_context_reply
|
||||||
static void dump_set_thread_context_request( const struct set_thread_context_request *req )
|
static void dump_set_thread_context_request( const struct set_thread_context_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%04x", req->handle );
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
fprintf( stderr, ", flags=%08x", req->flags );
|
|
||||||
fprintf( stderr, ", suspend=%d", req->suspend );
|
fprintf( stderr, ", suspend=%d", req->suspend );
|
||||||
dump_varargs_context( ", context=", cur_size );
|
dump_varargs_context( ", context=", cur_size );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue