diff --git a/dlls/kernel32/debugger.c b/dlls/kernel32/debugger.c index a6e1bbb72b3..6e7b4b1a4db 100644 --- a/dlls/kernel32/debugger.c +++ b/dlls/kernel32/debugger.c @@ -50,7 +50,7 @@ BOOL WINAPI WaitForDebugEvent( DWORD timeout) { BOOL ret; - DWORD res; + DWORD i, res; for (;;) { @@ -74,8 +74,14 @@ BOOL WINAPI WaitForDebugEvent( switch(data.code) { case EXCEPTION_DEBUG_EVENT: - event->u.Exception.ExceptionRecord = data.exception.record; - event->u.Exception.dwFirstChance = data.exception.first; + event->u.Exception.dwFirstChance = data.exception.first; + event->u.Exception.ExceptionRecord.ExceptionCode = data.exception.exc_code; + event->u.Exception.ExceptionRecord.ExceptionFlags = data.exception.flags; + event->u.Exception.ExceptionRecord.ExceptionRecord = wine_server_get_ptr( data.exception.record ); + event->u.Exception.ExceptionRecord.ExceptionAddress = wine_server_get_ptr( data.exception.address ); + event->u.Exception.ExceptionRecord.NumberParameters = data.exception.nb_params; + for (i = 0; i < data.exception.nb_params; i++) + event->u.Exception.ExceptionRecord.ExceptionInformation[i] = data.exception.params[i]; break; case CREATE_THREAD_DEBUG_EVENT: event->u.CreateThread.hThread = wine_server_ptr_handle( data.create_thread.handle ); diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index d948f84a6ba..c1c53c37be6 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -188,15 +188,25 @@ void wait_suspend( CONTEXT *context ) static NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context ) { int ret; + DWORD i; HANDLE handle = 0; + client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS]; 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]; + SERVER_START_REQ( queue_exception_event ) { req->first = first_chance; + req->code = rec->ExceptionCode; + req->flags = rec->ExceptionFlags; + req->record = wine_server_client_ptr( rec->ExceptionRecord ); + 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, rec, sizeof(*rec) ); if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 4c8ddf37aa7..de80fc2908b 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -61,7 +61,13 @@ typedef union { int code; int first; - EXCEPTION_RECORD record; + unsigned int exc_code; + unsigned int flags; + client_ptr_t record; + client_ptr_t address; + int nb_params; + int __pad; + client_ptr_t params[15]; } exception; struct { @@ -1851,8 +1857,14 @@ struct wait_debug_event_reply struct queue_exception_event_request { struct request_header __header; - int first; - /* VARARG(record,exc_event); */ + int first; + unsigned int code; + unsigned int flags; + client_ptr_t record; + client_ptr_t address; + data_size_t len; + /* VARARG(params,uints64,len); */ + /* VARARG(context,context); */ }; struct queue_exception_event_reply { @@ -5058,6 +5070,6 @@ union generic_reply struct set_window_layered_info_reply set_window_layered_info_reply; }; -#define SERVER_PROTOCOL_VERSION 379 +#define SERVER_PROTOCOL_VERSION 380 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/context_alpha.c b/server/context_alpha.c index 29bd73e3850..3aed4f80d8f 100644 --- a/server/context_alpha.c +++ b/server/context_alpha.c @@ -327,9 +327,9 @@ void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) } /* retrieve the current instruction pointer of a context */ -void *get_context_ip( const CONTEXT *context ) +client_ptr_t get_context_ip( const CONTEXT *context ) { - return (void *)context->Fir; + return context->Fir; } /* return the context flag that contains the CPU id */ diff --git a/server/context_i386.c b/server/context_i386.c index 57709fe0491..458b04f316e 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -83,9 +83,9 @@ void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) } /* retrieve the current instruction pointer of a context */ -void *get_context_ip( const CONTEXT *context ) +client_ptr_t get_context_ip( const CONTEXT *context ) { - return (void *)context->Eip; + return context->Eip; } /* return the context flag that contains the CPU id */ diff --git a/server/context_powerpc.c b/server/context_powerpc.c index 5ce63648cd1..9825a4a9fb9 100644 --- a/server/context_powerpc.c +++ b/server/context_powerpc.c @@ -265,9 +265,9 @@ void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) } /* retrieve the current instruction pointer of a context */ -void *get_context_ip( const CONTEXT *context ) +client_ptr_t get_context_ip( const CONTEXT *context ) { - return (void *)context->Iar; + return context->Iar; } /* return the context flag that contains the CPU id */ diff --git a/server/context_sparc.c b/server/context_sparc.c index 5d70271d0e2..b94d917d53f 100644 --- a/server/context_sparc.c +++ b/server/context_sparc.c @@ -163,9 +163,9 @@ void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) } /* retrieve the current instruction pointer of a context */ -void *get_context_ip( const CONTEXT *context ) +client_ptr_t get_context_ip( const CONTEXT *context ) { - return (void *)context->pc; + return context->pc; } /* return the context flag that contains the CPU id */ diff --git a/server/context_x86_64.c b/server/context_x86_64.c index e45cbc0e251..264c549e20b 100644 --- a/server/context_x86_64.c +++ b/server/context_x86_64.c @@ -83,9 +83,9 @@ void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ) } /* retrieve the current instruction pointer of a context */ -void *get_context_ip( const CONTEXT *context ) +client_ptr_t get_context_ip( const CONTEXT *context ) { - return (void *)context->Rip; + return context->Rip; } /* return the context flag that contains the CPU id */ diff --git a/server/debugger.c b/server/debugger.c index 3201d887b17..9399cb302d8 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -116,6 +116,7 @@ static int fill_exception_event( struct debug_event *event, const void *arg ) { const debug_event_t *data = arg; event->data.exception = data->exception; + event->data.exception.nb_params = min( event->data.exception.nb_params, EXCEPTION_MAXIMUM_PARAMETERS ); return 1; } @@ -375,8 +376,7 @@ static int continue_debug_event( struct process *process, struct thread *thread, } /* alloc a debug event for a debugger */ -static struct debug_event *alloc_debug_event( struct thread *thread, int code, - const void *arg, const CONTEXT *context ) +static struct debug_event *alloc_debug_event( struct thread *thread, int code, const void *arg ) { struct thread *debugger = thread->process->debugger; struct debug_event *event; @@ -399,11 +399,6 @@ static struct debug_event *alloc_debug_event( struct thread *thread, int code, return NULL; } event->data.code = code; - if (context) - { - memcpy( &event->context, context, sizeof(event->context) ); - thread->context = &event->context; - } return event; } @@ -412,7 +407,7 @@ void generate_debug_event( struct thread *thread, int code, const void *arg ) { if (thread->process->debugger) { - struct debug_event *event = alloc_debug_event( thread, code, arg, NULL ); + struct debug_event *event = alloc_debug_event( thread, code, arg ); if (event) { link_event( event ); @@ -638,18 +633,32 @@ DECL_HANDLER(queue_exception_event) { debug_event_t data; struct debug_event *event; - const CONTEXT *context = get_req_data(); - const EXCEPTION_RECORD *rec = (const EXCEPTION_RECORD *)(context + 1); - if (get_req_data_size() < sizeof(*rec) + sizeof(*context)) + if ((req->len % sizeof(client_ptr_t)) != 0 || + req->len > get_req_data_size() || + req->len > EXCEPTION_MAXIMUM_PARAMETERS * sizeof(client_ptr_t)) { set_error( STATUS_INVALID_PARAMETER ); return; } - data.exception.record = *rec; - data.exception.first = req->first; - if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data, context ))) + memset( &data, 0, sizeof(data) ); + data.exception.first = req->first; + data.exception.exc_code = req->code; + data.exception.flags = req->flags; + data.exception.record = req->record; + data.exception.address = req->address; + data.exception.nb_params = req->len / sizeof(client_ptr_t); + memcpy( data.exception.params, get_req_data(), req->len ); + + if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data ))) { + const CONTEXT *context = (const CONTEXT *)((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 ); + current->context = &event->context; + if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, 0 ))) { link_event( event ); diff --git a/server/protocol.def b/server/protocol.def index d13ea520f9f..6d6be5bdc5c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -75,9 +75,15 @@ typedef union int code; /* event code */ struct { - int code; /* EXCEPTION_DEBUG_EVENT */ - int first; /* first chance exception? */ - EXCEPTION_RECORD record; /* exception record */ + int code; /* EXCEPTION_DEBUG_EVENT */ + int first; /* first chance exception? */ + unsigned int exc_code; /* exception code */ + unsigned int flags; /* exception flags */ + client_ptr_t record; /* exception record */ + client_ptr_t address; /* exception address */ + int nb_params; /* number of parameters */ + int __pad; + client_ptr_t params[15]; /* parameters */ } exception; struct { @@ -1450,8 +1456,14 @@ enum char_info_mode /* Queue an exception event */ @REQ(queue_exception_event) - int first; /* first chance exception? */ - VARARG(record,exc_event); /* thread context followed by exception record */ + int first; /* first chance exception? */ + unsigned int code; /* exception code */ + unsigned int flags; /* exception flags */ + client_ptr_t record; /* exception record */ + client_ptr_t address; /* exception address */ + data_size_t len; /* size of parameters */ + VARARG(params,uints64,len);/* exception parameters */ + VARARG(context,context); /* thread context */ @REPLY obj_handle_t handle; /* handle to the queued event */ @END diff --git a/server/thread.c b/server/thread.c index 6b58785009f..397ad9b695d 100644 --- a/server/thread.c +++ b/server/thread.c @@ -936,12 +936,11 @@ void break_thread( struct thread *thread ) assert( thread->context ); - data.exception.record.ExceptionCode = STATUS_BREAKPOINT; - data.exception.record.ExceptionFlags = EXCEPTION_CONTINUABLE; - data.exception.record.ExceptionRecord = NULL; - data.exception.record.ExceptionAddress = get_context_ip( thread->context ); - data.exception.record.NumberParameters = 0; - data.exception.first = 1; + memset( &data, 0, sizeof(data) ); + data.exception.first = 1; + data.exception.exc_code = STATUS_BREAKPOINT; + data.exception.flags = EXCEPTION_CONTINUABLE; + data.exception.address = get_context_ip( thread->context ); generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data ); thread->debug_break = 0; } diff --git a/server/thread.h b/server/thread.h index e28249988c1..1815f0b1ff8 100644 --- a/server/thread.h +++ b/server/thread.h @@ -121,7 +121,7 @@ extern struct token *thread_get_impersonation_token( struct thread *thread ); /* CPU context functions */ extern void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags ); -extern void *get_context_ip( const CONTEXT *context ); +extern 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 ); diff --git a/server/trace.c b/server/trace.c index e9af47b4041..e30517d67f6 100644 --- a/server/trace.c +++ b/server/trace.c @@ -351,20 +351,6 @@ static void dump_context( const CONTEXT *context, data_size_t size ) #endif } -static void dump_exc_record( const EXCEPTION_RECORD *rec ) -{ - unsigned int i; - fprintf( stderr, "{code=%x,flags=%x,rec=%p,addr=%p,params={", - rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionRecord, - rec->ExceptionAddress ); - for (i = 0; i < min(rec->NumberParameters,EXCEPTION_MAXIMUM_PARAMETERS); i++) - { - if (i) fputc( ',', stderr ); - fprintf( stderr, "%lx", rec->ExceptionInformation[i] ); - } - fputc( '}', stderr ); -} - static void dump_varargs_ints( data_size_t size ) { const int *data = cur_data; @@ -380,6 +366,21 @@ static void dump_varargs_ints( data_size_t size ) remove_data( size ); } +static void dump_varargs_uints64( data_size_t size ) +{ + const unsigned __int64 *data = cur_data; + data_size_t len = size / sizeof(*data); + + fputc( '{', stderr ); + while (len > 0) + { + dump_uint64( data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + remove_data( size ); +} + static void dump_varargs_apc_result( data_size_t size ) { const apc_result_t *result = cur_data; @@ -462,97 +463,92 @@ static void dump_varargs_context( data_size_t size ) remove_data( min( size, sizeof(CONTEXT) )); } -static void dump_varargs_exc_event( data_size_t size ) -{ - const CONTEXT *ptr = cur_data; - - if (!size) - { - fprintf( stderr, "{}" ); - return; - } - fprintf( stderr, "{context=" ); - dump_context( ptr, size ); - if (size > sizeof(CONTEXT)) - { - fprintf( stderr, ",rec=" ); - dump_exc_record( (const EXCEPTION_RECORD *)(ptr + 1) ); - } - fputc( '}', stderr ); - remove_data( size ); -} - static void dump_varargs_debug_event( data_size_t size ) { - const debug_event_t *event = cur_data; + debug_event_t event; + unsigned int i; if (!size) { fprintf( stderr, "{}" ); return; } - switch(event->code) + size = min( size, sizeof(event) ); + memset( &event, 0, sizeof(event) ); + memcpy( &event, cur_data, size ); + + switch(event.code) { case EXCEPTION_DEBUG_EVENT: - fprintf( stderr, "{exception," ); - dump_exc_record( &event->exception.record ); - fprintf( stderr, ",first=%d}", event->exception.first ); + fprintf( stderr, "{exception,first=%d,exc_code=%08x,flags=%08x,record=", + event.exception.first, event.exception.exc_code, event.exception.flags ); + dump_uint64( &event.exception.record ); + fprintf( stderr, ",address=" ); + dump_uint64( &event.exception.address ); + fprintf( stderr, ",params={" ); + event.exception.nb_params = min( event.exception.nb_params, EXCEPTION_MAXIMUM_PARAMETERS ); + for (i = 0; i < event.exception.nb_params; i++) + { + dump_uint64( &event.exception.params[i] ); + if (i < event.exception.nb_params) fputc( ',', stderr ); + } + fprintf( stderr, "}}" ); break; case CREATE_THREAD_DEBUG_EVENT: - fprintf( stderr, "{create_thread,thread=%04x,teb=", event->create_thread.handle ); - dump_uint64( &event->create_thread.teb ); + fprintf( stderr, "{create_thread,thread=%04x,teb=", event.create_thread.handle ); + dump_uint64( &event.create_thread.teb ); fprintf( stderr, ",start=" ); - dump_uint64( &event->create_thread.start ); + dump_uint64( &event.create_thread.start ); fputc( '}', stderr ); break; case CREATE_PROCESS_DEBUG_EVENT: fprintf( stderr, "{create_process,file=%04x,process=%04x,thread=%04x,base=", - event->create_process.file, event->create_process.process, - event->create_process.thread ); - dump_uint64( &event->create_process.base ); + event.create_process.file, event.create_process.process, + event.create_process.thread ); + dump_uint64( &event.create_process.base ); fprintf( stderr, ",offset=%d,size=%d,teb=", - event->create_process.dbg_offset, event->create_process.dbg_size ); - dump_uint64( &event->create_process.teb ); + event.create_process.dbg_offset, event.create_process.dbg_size ); + dump_uint64( &event.create_process.teb ); fprintf( stderr, ",start=" ); - dump_uint64( &event->create_process.start ); + dump_uint64( &event.create_process.start ); fprintf( stderr, ",name=" ); - dump_uint64( &event->create_process.name ); - fprintf( stderr, ",unicode=%d}", event->create_process.unicode ); + dump_uint64( &event.create_process.name ); + fprintf( stderr, ",unicode=%d}", event.create_process.unicode ); break; case EXIT_THREAD_DEBUG_EVENT: - fprintf( stderr, "{exit_thread,code=%d}", event->exit.exit_code ); + fprintf( stderr, "{exit_thread,code=%d}", event.exit.exit_code ); break; case EXIT_PROCESS_DEBUG_EVENT: - fprintf( stderr, "{exit_process,code=%d}", event->exit.exit_code ); + fprintf( stderr, "{exit_process,code=%d}", event.exit.exit_code ); break; case LOAD_DLL_DEBUG_EVENT: - fprintf( stderr, "{load_dll,file=%04x,base", event->load_dll.handle ); - dump_uint64( &event->load_dll.base ); + fprintf( stderr, "{load_dll,file=%04x,base", event.load_dll.handle ); + dump_uint64( &event.load_dll.base ); fprintf( stderr, ",offset=%d,size=%d,name=", - event->load_dll.dbg_offset, event->load_dll.dbg_size ); - dump_uint64( &event->load_dll.name ); - fprintf( stderr, ",unicode=%d}", event->load_dll.unicode ); + event.load_dll.dbg_offset, event.load_dll.dbg_size ); + dump_uint64( &event.load_dll.name ); + fprintf( stderr, ",unicode=%d}", event.load_dll.unicode ); break; case UNLOAD_DLL_DEBUG_EVENT: fputs( "{unload_dll,base=", stderr ); - dump_uint64( &event->unload_dll.base ); + dump_uint64( &event.unload_dll.base ); fputc( '}', stderr ); break; case OUTPUT_DEBUG_STRING_EVENT: fprintf( stderr, "{output_string,string=" ); - dump_uint64( &event->output_string.string ); + dump_uint64( &event.output_string.string ); fprintf( stderr, ",unicode=%d,len=%u}", - event->output_string.unicode, event->output_string.length ); + event.output_string.unicode, event.output_string.length ); break; case RIP_EVENT: fprintf( stderr, "{rip,err=%d,type=%d}", - event->rip_info.error, event->rip_info.type ); + event.rip_info.error, event.rip_info.type ); break; case 0: /* zero is the code returned on timeouts */ fprintf( stderr, "{}" ); break; default: - fprintf( stderr, "{code=??? (%d)}", event->code ); + fprintf( stderr, "{code=??? (%d)}", event.code ); break; } remove_data( size ); @@ -1975,8 +1971,20 @@ static void dump_wait_debug_event_reply( const struct wait_debug_event_reply *re static void dump_queue_exception_event_request( const struct queue_exception_event_request *req ) { fprintf( stderr, " first=%d,", req->first ); + fprintf( stderr, " code=%08x,", req->code ); + fprintf( stderr, " flags=%08x,", req->flags ); fprintf( stderr, " record=" ); - dump_varargs_exc_event( cur_size ); + dump_uint64( &req->record ); + fprintf( stderr, "," ); + fprintf( stderr, " address=" ); + dump_uint64( &req->address ); + fprintf( stderr, "," ); + fprintf( stderr, " len=%u,", req->len ); + fprintf( stderr, " params=" ); + dump_varargs_uints64( min(cur_size,req->len) ); + fputc( ',', stderr ); + fprintf( stderr, " context=" ); + dump_varargs_context( cur_size ); } static void dump_queue_exception_event_reply( const struct queue_exception_event_reply *req )