--- memory/emulate.c Thu Jan 1 01:00:00 1970 +++ memory/emulate.c Thu May 9 17:35:27 2002 @@ -0,0 +1,53 @@ +/* + * Emulation of privileged memory + * + * Copyright 2002 Laurent Pinchart + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "windef.h" +#include "wingdi.h" +#include "wine/winuser16.h" +#include "module.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(virtual); + +#ifdef __i386__ + +/*********************************************************************** + * MEMORY_SharedUserData + * + * Handles exceptions for the SharedUserData access. + */ +BOOL MEMORY_SharedUserData( LPVOID arg, LPCVOID addr ) +{ + DWORD dwProtection; + BOOL ret; + + TRACE( "MEMORY_SharedUserData\n" ); + + ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READWRITE, &dwProtection ); + if ( ret ) + { + *(LPDWORD)0x7ffe0000 = 0x12345678; + ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READONLY, &dwProtection ); + } + + return ret; +} + +#endif /* __i386__ */ Index: dlls/ntdll/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/ntdll/Makefile.in,v retrieving revision 1.27 diff -u -r1.27 Makefile.in --- dlls/ntdll/Makefile.in 14 May 2002 20:55:01 -0000 1.27 +++ dlls/ntdll/Makefile.in 23 May 2002 18:54:33 -0000 @@ -32,6 +32,7 @@ $(TOPOBJDIR)/loader/ne/segment.c \ $(TOPOBJDIR)/memory/atom.c \ $(TOPOBJDIR)/memory/codepage.c \ + $(TOPOBJDIR)/memory/emulate.c \ $(TOPOBJDIR)/memory/environ.c \ $(TOPOBJDIR)/memory/global.c \ $(TOPOBJDIR)/memory/heap.c \ Index: dlls/ntdll/signal_i386.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/signal_i386.c,v retrieving revision 1.35 diff -u -r1.35 signal_i386.c --- dlls/ntdll/signal_i386.c 16 May 2002 20:32:16 -0000 1.35 +++ dlls/ntdll/signal_i386.c 23 May 2002 18:54:40 -0000 @@ -679,6 +679,7 @@ { EXCEPTION_RECORD rec; DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION; + DWORD priv_instr_code = EXCEPTION_PRIV_INSTRUCTION; #ifdef CR2_sig /* we want the page-fault case to be fast */ @@ -708,8 +709,8 @@ case T_SEGNPFLT: /* Segment not present exception */ case T_PROTFLT: /* General protection fault */ case T_UNKNOWN: /* Unknown fault code */ - if (INSTR_EmulateInstruction( context )) return; - rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; + if (INSTR_EmulateInstruction( context, &priv_instr_code )) return; + rec.ExceptionCode = priv_instr_code; break; case T_PAGEFLT: /* Page fault */ #ifdef CR2_sig Index: include/miscemu.h =================================================================== RCS file: /home/wine/wine/include/miscemu.h,v retrieving revision 1.46 diff -u -r1.46 miscemu.h --- include/miscemu.h 10 Mar 2002 00:02:34 -0000 1.46 +++ include/miscemu.h 23 May 2002 18:54:49 -0000 @@ -167,7 +167,7 @@ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ /* memory/instr.c */ -extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context ); +extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context, DWORD *exception_code ); /* msdos/interrupts.c */ typedef void (WINAPI *INTPROC)(CONTEXT86*); Index: include/wine/server_protocol.h =================================================================== RCS file: /home/wine/wine/include/wine/server_protocol.h,v retrieving revision 1.35 diff -u -r1.35 server_protocol.h --- include/wine/server_protocol.h 25 Apr 2002 22:58:59 -0000 1.35 +++ include/wine/server_protocol.h 23 May 2002 18:54:56 -0000 @@ -296,6 +296,7 @@ struct init_process_done_reply { struct reply_header __header; + int suspended; int debugged; }; @@ -3198,6 +3199,6 @@ struct get_window_properties_reply get_window_properties_reply; }; -#define SERVER_PROTOCOL_VERSION 79 +#define SERVER_PROTOCOL_VERSION 80 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ Index: memory/instr.c =================================================================== RCS file: /home/wine/wine/memory/instr.c,v retrieving revision 1.15 diff -u -r1.15 instr.c --- memory/instr.c 11 May 2002 23:01:12 -0000 1.15 +++ memory/instr.c 23 May 2002 18:54:58 -0000 @@ -396,7 +396,7 @@ * * Emulate a privileged instruction. Returns TRUE if emulation successful. */ -BOOL INSTR_EmulateInstruction( CONTEXT86 *context ) +BOOL INSTR_EmulateInstruction( CONTEXT86 *context, DWORD *exception_code ) { int prefix, segprefix, prefixlen, len, repX, long_op, long_addr; SEGPTR gpHandler; @@ -686,7 +686,9 @@ case 0xcd: /* int */ if (long_op) { - ERR("int xx from 32-bit code is not supported.\n"); + ERR("int 0x%02x from 32-bit code is not supported.\n", instr[1]); + if (instr[1] == 0x01) + *exception_code = EXCEPTION_ACCESS_VIOLATION; break; /* Unable to emulate it */ } else Index: scheduler/process.c =================================================================== RCS file: /home/wine/wine/scheduler/process.c,v retrieving revision 1.182 diff -u -r1.182 process.c --- scheduler/process.c 22 May 2002 21:32:50 -0000 1.182 +++ scheduler/process.c 23 May 2002 18:55:04 -0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include "wine/server.h" #include "options.h" #include "wine/debug.h" +#include "global.h" WINE_DEFAULT_DEBUG_CHANNEL(process); WINE_DECLARE_DEBUG_CHANNEL(relay); @@ -126,6 +128,9 @@ /* scheduler/pthread.c */ extern void PTHREAD_init_done(void); +/* memory/emulate.c */ +extern BOOL MEMORY_SharedUserData(LPVOID, LPCVOID); + extern BOOL MAIN_MainInit(void); typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 ); @@ -416,6 +421,20 @@ SetStdHandle( STD_ERROR_HANDLE, current_startupinfo.hStdError ); } + /* Reserves a PAGE_NOACCESS at 0x7ffe0000. That page is used as shared + * memory between kernel space and user space (see SharedUserData in + * ntddk.h). It looks like it is at 0xffdf0000 on NT5. That is still to + * be checked. + */ + if ( VirtualAlloc( (LPVOID)0x7ffe0000, 0x10000, MEM_RESERVE|MEM_COMMIT, PAGE_NOACCESS ) == (LPCVOID)0x07ffe0000 ) + { + VIRTUAL_SetFaultHandler( (LPCVOID)0x7ffe0000, MEMORY_SharedUserData, 0 ); + } + else + { + WARN( "Unable to map SharedUserData, SafeDisc protection won't be supported\n" ); + } + /* Now we can use the pthreads routines */ PTHREAD_init_done(); @@ -440,7 +459,7 @@ */ static void start_process(void) { - int debugged, console_app; + int suspended, debugged, console_app; LPTHREAD_START_ROUTINE entry; WINE_MODREF *wm; HFILE main_file = main_exe_file; @@ -481,7 +500,8 @@ req->gui = !console_app; wine_server_add_data( req, main_exe_name, strlen(main_exe_name) ); wine_server_call( req ); - debugged = reply->debugged; + suspended = reply->suspended; + debugged = reply->debugged; } SERVER_END_REQ; @@ -513,6 +533,8 @@ PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 ); /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */ if (console_app) PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 ); + + if (suspended) raise( SIGSTOP ); if (TRACE_ON(relay)) DPRINTF( "%08lx:Starting process %s (entryproc=%p)\n", Index: server/process.c =================================================================== RCS file: /home/wine/wine/server/process.c,v retrieving revision 1.83 diff -u -r1.83 process.c --- server/process.c 26 Apr 2002 19:05:18 -0000 1.83 +++ server/process.c 23 May 2002 18:55:07 -0000 @@ -382,6 +382,14 @@ } +/* signal the parent that a process init is finished */ +void process_init_done( struct process *process ) +{ + set_event( process->init_event ); + release_object( process->init_event ); + process->init_event = NULL; +} + /* get a process from an id (and increment the refcount) */ struct process *get_process_from_id( void *id ) { @@ -896,13 +904,27 @@ if ((process->exe.namelen = get_req_data_size())) process->exe.filename = memdup( get_req_data(), process->exe.namelen ); - generate_startup_debug_events( current->process, req->entry ); - set_event( process->init_event ); - release_object( process->init_event ); - process->init_event = NULL; + generate_startup_debug_events( process, req->entry ); if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 ); - if (current->suspend + current->process->suspend > 0) stop_thread( current ); - reply->debugged = (current->process->debugger != 0); + + reply->suspended = 0; + reply->debugged = (current->process->debugger != 0); + if (current->suspend + current->process->suspend > 0) + { + /* temporarily clear the init event so that ptrace functions work */ + struct event *init_event = process->init_event; + process->init_event = NULL; + stop_thread( current ); + process->init_event = init_event; + + if (current->attached) + { + reply->suspended = 1; + continue_thread( current ); /* it will suspend itself */ + return; + } + } + process_init_done( process ); } /* open a handle to a process */ Index: server/process.h =================================================================== RCS file: /home/wine/wine/server/process.h,v retrieving revision 1.27 diff -u -r1.27 process.h --- server/process.h 22 Mar 2002 00:21:23 -0000 1.27 +++ server/process.h 23 May 2002 18:55:07 -0000 @@ -90,6 +90,7 @@ extern struct thread *create_process( int fd ); extern struct process *get_process_from_id( void *id ); extern struct process *get_process_from_handle( handle_t handle, unsigned int access ); +extern void process_init_done( struct process *process ); extern int process_set_debugger( struct process *process, struct thread *thread ); extern int debugger_detach( struct process* process, struct thread* debugger ); Index: server/protocol.def =================================================================== RCS file: /home/wine/wine/server/protocol.def,v retrieving revision 1.36 diff -u -r1.36 protocol.def --- server/protocol.def 25 Apr 2002 22:58:59 -0000 1.36 +++ server/protocol.def 23 May 2002 18:55:12 -0000 @@ -276,6 +276,7 @@ int gui; /* is it a GUI process? */ VARARG(filename,string); /* file name of main exe */ @REPLY + int suspended; /* created suspended? */ int debugged; /* being debugged? */ @END Index: server/ptrace.c =================================================================== RCS file: /home/wine/wine/server/ptrace.c,v retrieving revision 1.14 diff -u -r1.14 ptrace.c --- server/ptrace.c 10 Mar 2002 00:18:36 -0000 1.14 +++ server/ptrace.c 23 May 2002 18:55:13 -0000 @@ -79,7 +79,12 @@ switch(sig) { case SIGSTOP: /* continue at once if not suspended */ - if (thread && (thread->process->suspend + thread->suspend)) break; + if (thread && (thread->process->suspend + thread->suspend)) + { + /* check if this was the self-suspend upon process init */ + if (thread->process->init_event) process_init_done( thread->process ); + break; + } /* fall through */ default: /* ignore other signals for now */ if (thread && get_thread_single_step( thread )) Index: server/trace.c =================================================================== RCS file: /home/wine/wine/server/trace.c,v retrieving revision 1.132 diff -u -r1.132 trace.c --- server/trace.c 26 Apr 2002 19:05:18 -0000 1.132 +++ server/trace.c 23 May 2002 18:55:20 -0000 @@ -441,6 +441,7 @@ static void dump_init_process_done_reply( const struct init_process_done_reply *req ) { + fprintf( stderr, " suspended=%d,", req->suspended ); fprintf( stderr, " debugged=%d", req->debugged ); }