From 5316dd011f15ca488ccfa69b5873b075407fe238 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 8 Apr 2009 19:38:02 +0200 Subject: [PATCH] server: Define a generic context structure instead of using the platform-specific version. --- dlls/ntdll/exception.c | 20 +- dlls/ntdll/ntdll_misc.h | 2 + dlls/ntdll/signal_i386.c | 144 ++++++++++++++ dlls/ntdll/signal_powerpc.c | 214 +++++++++++++++++++- dlls/ntdll/signal_sparc.c | 132 +++++++++++++ dlls/ntdll/signal_x86_64.c | 137 +++++++++++++ dlls/ntdll/thread.c | 51 +++-- include/wine/server_protocol.h | 60 +++++- server/Makefile.in | 5 - server/context_alpha.c | 348 --------------------------------- server/context_i386.c | 104 ---------- server/context_powerpc.c | 286 --------------------------- server/context_sparc.c | 184 ----------------- server/context_x86_64.c | 104 ---------- server/debugger.c | 8 +- server/mach.c | 67 +++---- server/procfs.c | 10 +- server/protocol.def | 58 +++++- server/ptrace.c | 119 ++++++----- server/request.h | 3 +- server/thread.c | 83 ++++++-- server/thread.h | 14 +- server/trace.c | 210 +++++++++++++++++--- 23 files changed, 1135 insertions(+), 1228 deletions(-) delete mode 100644 server/context_alpha.c delete mode 100644 server/context_i386.c delete mode 100644 server/context_powerpc.c delete mode 100644 server/context_sparc.c delete mode 100644 server/context_x86_64.c diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index f7ae9475d20..5399c40bffc 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -149,14 +149,16 @@ void wait_suspend( CONTEXT *context ) { LARGE_INTEGER timeout; int saved_errno = errno; + context_t server_context; + + context_to_server( &server_context, context ); /* store the context we got at suspend time */ SERVER_START_REQ( set_thread_context ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); - req->flags = CONTEXT_FULL; 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 ); } SERVER_END_REQ; @@ -169,13 +171,13 @@ void wait_suspend( CONTEXT *context ) SERVER_START_REQ( get_thread_context ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); - req->flags = CONTEXT_FULL; 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 ); } SERVER_END_REQ; + context_from_server( context, &server_context ); 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 ) { - int ret; + NTSTATUS ret; DWORD i; HANDLE handle = 0; client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS]; + context_t server_context; if (!NtCurrentTeb()->Peb->BeingDebugged) return 0; /* no debugger present */ for (i = 0; i < min( rec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS ); i++) params[i] = rec->ExceptionInformation[i]; + context_to_server( &server_context, context ); + SERVER_START_REQ( queue_exception_event ) { 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->len = i * sizeof(params[0]); 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 ); } 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 ) { 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 ); } SERVER_END_REQ; + if (!ret) ret = context_from_server( context, &server_context ); return ret; } diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 542607add95..61622b1c162 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -44,6 +44,8 @@ extern void wait_suspend( CONTEXT *context ); extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT ); extern void set_cpu_context( const CONTEXT *context ); 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 */ extern LPCSTR debugstr_us( const UNICODE_STRING *str ); diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 502195f1c22..6bec6973096 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -55,6 +55,8 @@ # include #endif +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "wine/library.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 * diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 2a758bfe6ce..4941e434d1f 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -51,6 +51,8 @@ # include #endif +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" #include "wine/library.h" @@ -298,9 +300,13 @@ void copy_context( CONTEXT *to, const CONTEXT *from, DWORD flags ) { if (flags & CONTEXT_CONTROL) { - to->Msr = from->Msr; - to->Ctr = from->Ctr; - to->Iar = from->Iar; + to->Msr = from->Msr; + to->Ctr = from->Ctr; + to->Iar = from->Iar; + to->Lr = from->Lr; + to->Dar = from->Dar; + to->Dsisr = from->Dsisr; + to->Trap = from->Trap; } if (flags & CONTEXT_INTEGER) { @@ -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 * diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c index b1d2cabe80f..e1bd991eba2 100644 --- a/dlls/ntdll/signal_sparc.c +++ b/dlls/ntdll/signal_sparc.c @@ -33,6 +33,8 @@ #include #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winternl.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 * diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7daa916e20c..7a0defa68d6 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -40,6 +40,8 @@ #endif #define NONAMELESSUNION +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winternl.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 * diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 190dfdc67f3..1a5017ebb6e 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -824,12 +824,15 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) if (!self) { + context_t server_context; + + context_to_server( &server_context, context ); + SERVER_START_REQ( set_thread_context ) { req->handle = wine_server_obj_handle( handle ); - req->flags = context->ContextFlags; 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 ); self = reply->self; } @@ -844,9 +847,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) SERVER_START_REQ( set_thread_context ) { req->handle = wine_server_obj_handle( handle ); - req->flags = context->ContextFlags; 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 ); } 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.@) * ZwGetContextThread (NTDLL.@) @@ -878,7 +903,6 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) { NTSTATUS ret; - CONTEXT ctx; DWORD dummy, i; DWORD needed_flags = context->ContextFlags; BOOL self = (handle == GetCurrentThread()); @@ -890,12 +914,15 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) if (!self) { + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + context_t server_context; + SERVER_START_REQ( get_thread_context ) { req->handle = wine_server_obj_handle( handle ); - req->flags = context->ContextFlags; + req->flags = server_flags; 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 ); self = reply->self; } @@ -910,9 +937,9 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) SERVER_START_REQ( get_thread_context ) { req->handle = wine_server_obj_handle( handle ); - req->flags = context->ContextFlags; + req->flags = server_flags; 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 ); } SERVER_END_REQ; @@ -928,17 +955,19 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) } if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED; } + if (!ret) ret = context_from_server( context, &server_context ); if (ret) return ret; - copy_context( context, &ctx, context->ContextFlags & ctx.ContextFlags ); - needed_flags &= ~ctx.ContextFlags; + needed_flags &= ~context->ContextFlags; } if (self) { if (needed_flags) { + CONTEXT ctx; RtlCaptureContext( &ctx ); copy_context( context, &ctx, ctx.ContextFlags & needed_flags ); + context->ContextFlags |= ctx.ContextFlags & needed_flags; } #ifdef __i386__ /* update the cached version of the debug registers */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 06eb4ae3f17..31ef863261c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -135,6 +135,63 @@ enum cpu_type 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 { thread_id_t tid; @@ -2356,7 +2413,6 @@ struct set_thread_context_request { struct request_header __header; obj_handle_t handle; - unsigned int flags; int suspend; /* VARARG(context,context); */ }; @@ -5224,6 +5280,6 @@ union generic_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 */ diff --git a/server/Makefile.in b/server/Makefile.in index 044c0c177ce..828d7b0b50c 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -14,11 +14,6 @@ C_SRCS = \ clipboard.c \ completion.c \ console.c \ - context_alpha.c \ - context_i386.c \ - context_powerpc.c \ - context_sparc.c \ - context_x86_64.c \ debugger.c \ device.c \ directory.c \ diff --git a/server/context_alpha.c b/server/context_alpha.c deleted file mode 100644 index 3aed4f80d8f..00000000000 --- a/server/context_alpha.c +++ /dev/null @@ -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 -#include -#ifdef HAVE_SYS_REG_H -# include -#endif -#include -#include -#ifdef HAVE_SYS_PTRACE_H -# include -#endif - -#include "file.h" -#include "thread.h" -#include "request.h" - -#if 0 /* no longer used */ - -#ifdef HAVE_SYS_USER_H -# include -#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__ */ diff --git a/server/context_i386.c b/server/context_i386.c deleted file mode 100644 index 458b04f316e..00000000000 --- a/server/context_i386.c +++ /dev/null @@ -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 -#include -#include -#include - -#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__ */ diff --git a/server/context_powerpc.c b/server/context_powerpc.c deleted file mode 100644 index 9825a4a9fb9..00000000000 --- a/server/context_powerpc.c +++ /dev/null @@ -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 -#include -#include -#ifdef HAVE_SYS_REG_H -# include -#endif -#include -#include -#ifdef HAVE_SYS_PTRACE_H -# include -#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__ */ diff --git a/server/context_sparc.c b/server/context_sparc.c deleted file mode 100644 index b94d917d53f..00000000000 --- a/server/context_sparc.c +++ /dev/null @@ -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 -#include -#include -#ifdef HAVE_SYS_REG_H -# include -#endif -#include -#include -#ifdef HAVE_SYS_PTRACE_H -# include -#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__ */ diff --git a/server/context_x86_64.c b/server/context_x86_64.c deleted file mode 100644 index 264c549e20b..00000000000 --- a/server/context_x86_64.c +++ /dev/null @@ -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 -#include -#include -#include - -#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__ */ diff --git a/server/debugger.c b/server/debugger.c index 9399cb302d8..c01ab459187 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -49,7 +49,7 @@ struct debug_event enum debug_event_state state; /* event state */ int status; /* continuation status */ debug_event_t data; /* event data */ - CONTEXT context; /* register context */ + context_t context; /* register context */ }; /* debug context */ @@ -652,11 +652,11 @@ DECL_HANDLER(queue_exception_event) 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; 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; if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, 0 ))) @@ -682,7 +682,7 @@ DECL_HANDLER(get_exception_status) { 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 ); current->context = NULL; } diff --git a/server/mach.c b/server/mach.c index fcc87a3830b..f9490f3f0de 100644 --- a/server/mach.c +++ b/server/mach.c @@ -160,7 +160,7 @@ void finish_process_tracing( struct process *process ) } /* 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__ 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 ); /* 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 || 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 */ #if __DARWIN_UNIX03 && defined(_STRUCT_X86_DEBUG_STATE32) - context->Dr0 = state.__dr0; - context->Dr1 = state.__dr1; - context->Dr2 = state.__dr2; - context->Dr3 = state.__dr3; - context->Dr6 = state.__dr6; - context->Dr7 = state.__dr7; + context->debug.i386_regs.dr0 = state.__dr0; + context->debug.i386_regs.dr1 = state.__dr1; + context->debug.i386_regs.dr2 = state.__dr2; + context->debug.i386_regs.dr3 = state.__dr3; + context->debug.i386_regs.dr6 = state.__dr6; + context->debug.i386_regs.dr7 = state.__dr7; #else - context->Dr0 = state.dr0; - context->Dr1 = state.dr1; - context->Dr2 = state.dr2; - context->Dr3 = state.dr3; - context->Dr6 = state.dr6; - context->Dr7 = state.dr7; + context->debug.i386_regs.dr0 = state.dr0; + context->debug.i386_regs.dr1 = state.dr1; + context->debug.i386_regs.dr2 = state.dr2; + context->debug.i386_regs.dr3 = state.dr3; + context->debug.i386_regs.dr6 = state.dr6; + context->debug.i386_regs.dr7 = state.dr7; #endif - context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; + context->flags |= SERVER_CTX_DEBUG_REGISTERS; } mach_port_deallocate( mach_task_self(), port ); #endif } /* 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__ 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 ); /* 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 || 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) - state.__dr0 = context->Dr0; - state.__dr1 = context->Dr1; - state.__dr2 = context->Dr2; - state.__dr3 = context->Dr3; + state.__dr0 = context->debug.i386_regs.dr0; + state.__dr1 = context->debug.i386_regs.dr1; + state.__dr2 = context->debug.i386_regs.dr2; + state.__dr3 = context->debug.i386_regs.dr3; state.__dr4 = 0; state.__dr5 = 0; - state.__dr6 = context->Dr6; - state.__dr7 = context->Dr7; + state.__dr6 = context->debug.i386_regs.dr6; + state.__dr7 = context->debug.i386_regs.dr7; #else - state.dr0 = context->Dr0; - state.dr1 = context->Dr1; - state.dr2 = context->Dr2; - state.dr3 = context->Dr3; + state.dr0 = context->debug.i386_regs.dr0; + state.dr1 = context->debug.i386_regs.dr1; + state.dr2 = context->debug.i386_regs.dr2; + state.dr3 = context->debug.i386_regs.dr3; state.dr4 = 0; state.dr5 = 0; - state.dr6 = context->Dr6; - state.dr7 = context->Dr7; + state.dr6 = context->debug.i386_regs.dr6; + state.dr7 = context->debug.i386_regs.dr7; #endif if (!thread_set_state( port, x86_DEBUG_STATE32, (thread_state_t)&state, count )) { if (thread->context) /* update the cached values */ - { - thread->context->Dr0 = context->Dr0; - thread->context->Dr1 = context->Dr1; - thread->context->Dr2 = context->Dr2; - thread->context->Dr3 = context->Dr3; - thread->context->Dr6 = context->Dr6; - thread->context->Dr7 = context->Dr7; - } + thread->context->debug.i386_regs = context->debug.i386_regs; } mach_port_deallocate( mach_task_self(), port ); #endif diff --git a/server/procfs.c b/server/procfs.c index 5978bbc801c..3b74e14f6ea 100644 --- a/server/procfs.c +++ b/server/procfs.c @@ -200,20 +200,14 @@ error: } /* 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 */ } /* 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 */ } diff --git a/server/protocol.def b/server/protocol.def index 0f7e7de15d2..004f4c9d51a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -150,6 +150,63 @@ enum cpu_type }; 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 */ struct send_fd { @@ -1732,7 +1789,6 @@ enum char_info_mode /* Set the current context of a thread */ @REQ(set_thread_context) obj_handle_t handle; /* thread handle */ - unsigned int flags; /* context flags */ int suspend; /* if setting context during suspend */ VARARG(context,context); /* thread context */ @REPLY diff --git a/server/ptrace.c b/server/ptrace.c index b446de9aaac..72e2b441760 100644 --- a/server/ptrace.c +++ b/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)) /* 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); long data[8]; /* 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; @@ -548,39 +548,39 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f goto done; } } - context->Dr0 = data[0]; - context->Dr1 = data[1]; - context->Dr2 = data[2]; - context->Dr3 = data[3]; - context->Dr6 = data[6]; - context->Dr7 = data[7]; - context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; + context->debug.i386_regs.dr0 = data[0]; + context->debug.i386_regs.dr1 = data[1]; + context->debug.i386_regs.dr2 = data[2]; + context->debug.i386_regs.dr3 = data[3]; + context->debug.i386_regs.dr6 = data[6]; + context->debug.i386_regs.dr7 = data[7]; + context->flags |= SERVER_CTX_DEBUG_REGISTERS; done: resume_after_ptrace( thread ); } /* 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 ); /* 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 (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error; - if (thread->context) thread->context->Dr0 = context->Dr0; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error; - if (thread->context) thread->context->Dr1 = context->Dr1; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error; - if (thread->context) thread->context->Dr2 = context->Dr2; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error; - if (thread->context) thread->context->Dr3 = context->Dr3; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error; - if (thread->context) thread->context->Dr6 = context->Dr6; - if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error; - if (thread->context) thread->context->Dr7 = context->Dr7; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->debug.i386_regs.dr0 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr0 = context->debug.i386_regs.dr0; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->debug.i386_regs.dr1 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr1 = context->debug.i386_regs.dr1; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->debug.i386_regs.dr2 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr2 = context->debug.i386_regs.dr2; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->debug.i386_regs.dr3 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr3 = context->debug.i386_regs.dr3; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->debug.i386_regs.dr6 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr6 = context->debug.i386_regs.dr6; + if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->debug.i386_regs.dr7 ) == -1) goto error; + if (thread->context) thread->context->debug.i386_regs.dr7 = context->debug.i386_regs.dr7; resume_after_ptrace( thread ); return; error: @@ -594,13 +594,13 @@ void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned #include /* 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); struct dbreg dbregs; /* 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; @@ -609,78 +609,71 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f { #ifdef DBREG_DRX /* needed for FreeBSD, the structure fields have changed under 5.x */ - context->Dr0 = DBREG_DRX((&dbregs), 0); - context->Dr1 = DBREG_DRX((&dbregs), 1); - context->Dr2 = DBREG_DRX((&dbregs), 2); - context->Dr3 = DBREG_DRX((&dbregs), 3); - context->Dr6 = DBREG_DRX((&dbregs), 6); - context->Dr7 = DBREG_DRX((&dbregs), 7); + context->debug.i386_regs.dr0 = DBREG_DRX((&dbregs), 0); + context->debug.i386_regs.dr1 = DBREG_DRX((&dbregs), 1); + context->debug.i386_regs.dr2 = DBREG_DRX((&dbregs), 2); + context->debug.i386_regs.dr3 = DBREG_DRX((&dbregs), 3); + context->debug.i386_regs.dr6 = DBREG_DRX((&dbregs), 6); + context->debug.i386_regs.dr7 = DBREG_DRX((&dbregs), 7); #else - context->Dr0 = dbregs.dr0; - context->Dr1 = dbregs.dr1; - context->Dr2 = dbregs.dr2; - context->Dr3 = dbregs.dr3; - context->Dr6 = dbregs.dr6; - context->Dr7 = dbregs.dr7; + context->debug.i386_regs.dr0 = dbregs.dr0; + context->debug.i386_regs.dr1 = dbregs.dr1; + context->debug.i386_regs.dr2 = dbregs.dr2; + context->debug.i386_regs.dr3 = dbregs.dr3; + context->debug.i386_regs.dr6 = dbregs.dr6; + context->debug.i386_regs.dr7 = dbregs.dr7; #endif - context->ContextFlags |= CONTEXT_DEBUG_REGISTERS; + context->flags |= SERVER_CTX_DEBUG_REGISTERS; } resume_after_ptrace( thread ); } /* 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); struct dbreg dbregs; /* 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; #ifdef DBREG_DRX /* needed for FreeBSD, the structure fields have changed under 5.x */ - DBREG_DRX((&dbregs), 0) = context->Dr0; - DBREG_DRX((&dbregs), 1) = context->Dr1; - DBREG_DRX((&dbregs), 2) = context->Dr2; - DBREG_DRX((&dbregs), 3) = context->Dr3; + DBREG_DRX((&dbregs), 0) = context->debug.i386_regs.dr0; + DBREG_DRX((&dbregs), 1) = context->debug.i386_regs.dr1; + DBREG_DRX((&dbregs), 2) = context->debug.i386_regs.dr2; + DBREG_DRX((&dbregs), 3) = context->debug.i386_regs.dr3; DBREG_DRX((&dbregs), 4) = 0; DBREG_DRX((&dbregs), 5) = 0; - DBREG_DRX((&dbregs), 6) = context->Dr6; - DBREG_DRX((&dbregs), 7) = context->Dr7; + DBREG_DRX((&dbregs), 6) = context->debug.i386_regs.dr6; + DBREG_DRX((&dbregs), 7) = context->debug.i386_regs.dr7; #else - dbregs.dr0 = context->Dr0; - dbregs.dr1 = context->Dr1; - dbregs.dr2 = context->Dr2; - dbregs.dr3 = context->Dr3; + dbregs.dr0 = context->debug.i386_regs.dr0; + dbregs.dr1 = context->debug.i386_regs.dr1; + dbregs.dr2 = context->debug.i386_regs.dr2; + dbregs.dr3 = context->debug.i386_regs.dr3; dbregs.dr4 = 0; dbregs.dr5 = 0; - dbregs.dr6 = context->Dr6; - dbregs.dr7 = context->Dr7; + dbregs.dr6 = context->debug.i386_regs.dr6; + dbregs.dr7 = context->debug.i386_regs.dr7; #endif if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error(); - else if (thread->context) /* update the cached values */ - { - thread->context->Dr0 = context->Dr0; - thread->context->Dr1 = context->Dr1; - thread->context->Dr2 = context->Dr2; - thread->context->Dr3 = context->Dr3; - thread->context->Dr6 = context->Dr6; - thread->context->Dr7 = context->Dr7; - } + else if (thread->context) + thread->context->debug.i386_regs = context->debug.i386_regs; /* update the cached values */ resume_after_ptrace( thread ); } #else /* linux || __FreeBSD__ */ /* 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 */ -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 ) { } diff --git a/server/request.h b/server/request.h index 3984ab136ea..f0ebcbabcf4 100644 --- a/server/request.h +++ b/server/request.h @@ -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( 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, flags) == 16 ); -C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, suspend) == 20 ); +C_ASSERT( FIELD_OFFSET(struct set_thread_context_request, suspend) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_thread_context_reply, self) == 8 ); C_ASSERT( sizeof(struct set_thread_context_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_selector_entry_request, handle) == 12 ); diff --git a/server/thread.c b/server/thread.c index 5520d6876c3..6ce59c89e06 100644 --- a/server/thread.c +++ b/server/thread.c @@ -944,6 +944,34 @@ void kill_thread( struct thread *thread, int violent_death ) 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 */ void break_thread( struct thread *thread ) { @@ -955,7 +983,24 @@ void break_thread( struct thread *thread ) data.exception.first = 1; data.exception.exc_code = STATUS_BREAKPOINT; 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 ); thread->debug_break = 0; } @@ -1357,9 +1402,9 @@ DECL_HANDLER(get_apc_result) DECL_HANDLER(get_thread_context) { 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 ); return; @@ -1376,7 +1421,7 @@ DECL_HANDLER(get_thread_context) else { 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; } } @@ -1386,12 +1431,12 @@ DECL_HANDLER(get_thread_context) if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED ); 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) ); - context->ContextFlags = get_context_cpu_flag(); + memset( context, 0, sizeof(context_t) ); + context->cpu = thread->process->cpu; if (thread->context) copy_context( context, thread->context, req->flags & ~flags ); if (flags) get_thread_context( thread, context, flags ); } @@ -1403,8 +1448,9 @@ DECL_HANDLER(get_thread_context) DECL_HANDLER(set_thread_context) { 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 ); return; @@ -1413,14 +1459,14 @@ DECL_HANDLER(set_thread_context) 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 */ 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; 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 ); else set_error( STATUS_PENDING ); } - else + else if (context->cpu == thread->process->cpu) { - const CONTEXT *context = get_req_data(); - unsigned int flags = get_context_system_regs( req->flags ); + unsigned int system_flags = get_context_system_regs(context->cpu) & context->flags; + unsigned int client_flags = context->flags & ~system_flags; - if (flags) set_thread_context( thread, context, flags ); - if (thread->context && !get_error()) - copy_context( thread->context, context, req->flags & ~flags ); + if (system_flags) set_thread_context( thread, context, system_flags ); + if (thread->context && !get_error()) copy_context( thread->context, context, client_flags ); } + else set_error( STATUS_INVALID_PARAMETER ); + reply->self = (thread == current); release_object( thread ); } diff --git a/server/thread.h b/server/thread.h index 2e334700803..b6c1cf589e5 100644 --- a/server/thread.h +++ b/server/thread.h @@ -76,8 +76,8 @@ struct thread int exit_code; /* thread exit code */ int unix_pid; /* Unix pid of client */ int unix_tid; /* Unix tid of client */ - CONTEXT *context; /* current context if in an exception handler */ - CONTEXT *suspend_context; /* current context if suspended */ + context_t *context; /* current context if in an exception handler */ + context_t *suspend_context; /* current context if suspended */ client_ptr_t teb; /* TEB address (in client address space) */ affinity_t affinity; /* affinity mask */ 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 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 */ extern void sigchld_callback(void); -extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags ); -extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags ); +extern void get_thread_context( struct thread *thread, context_t *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 void get_selector_entry( struct thread *thread, int entry, unsigned int *base, unsigned int *limit, unsigned char *flags ); diff --git a/server/trace.c b/server/trace.c index 88ea5e51470..4a7bfa54b87 100644 --- a/server/trace.c +++ b/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 ); } -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 ) { 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 ) { + const context_t *context = cur_data; + context_t ctx; + unsigned int i; + if (!size) { fprintf( stderr, "%s{}", prefix ); return; } - fprintf( stderr, "%s", prefix ); - dump_context( cur_data, size ); - remove_data( min( size, sizeof(CONTEXT) )); + size = min( size, sizeof(ctx) ); + memset( &ctx, 0, sizeof(ctx) ); + 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 ) @@ -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 ) { fprintf( stderr, " handle=%04x", req->handle ); - fprintf( stderr, ", flags=%08x", req->flags ); fprintf( stderr, ", suspend=%d", req->suspend ); dump_varargs_context( ", context=", cur_size ); }