[Fwd: WineDbg: adding a GDB remote proxy (part I)]

Eric Pouech eric.pouech at wanadoo.fr
Wed Jul 10 01:37:42 CDT 2002


this time with the patch
A+

-------- Original Message --------
Subject: WineDbg: adding a GDB remote proxy (part I)
Date: Tue, 09 Jul 2002 22:58:42 +0200
From: Eric Pouech <eric.pouech at wanadoo.fr>
Reply-To: wine-devel at winehq.com
To: Wine Patches <wine-patches at winehq.com>

before being able to add the GDB remote proxy code to winedbg, we need
first to have some internal restructuration
basically, winedbg had two nested loops:
- the outter one was in charge of the Win32 debug events
- the inner one was in charge of the parsing of commands

in order to incorporate the gdb proxy, we need to swap those two loops.
this first patch takes care of that. the second one will actually add
the gdb proxy code

Alexandre, those two patches are not really independant... wine (in fact
winedbg) will not compile if only the first is applied... but I thought
it was easier to set it that way

A+
-------------- next part --------------
Name:          wdbg_loop
ChangeLog:     inverted inner loops (Win32 debug event handling / WineDbg command line parser)
License:       X11
GenDate:       2002/07/09 20:32:34 UTC
ModifiedFiles: debugger-merge/break.c debugger-merge/dbg.y debugger-merge/debugger.h debugger-merge/hash.c debugger-merge/source.c debugger-merge/winedbg.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/break.c,v
retrieving revision 1.33
diff -u -u -r1.33 break.c
--- debugger-merge/break.c	2 Jun 2002 21:20:22 -0000	1.33
+++ debugger-merge/break.c	9 Jul 2002 17:51:03 -0000
@@ -836,8 +836,8 @@
      */
     if (mode != EXEC_CONT && mode != EXEC_FINISH)
     {
-	DEBUG_FindNearestSymbol( addr, TRUE, NULL, 0, &syminfo.list);
-	if( syminfo.list.sourcefile != NULL )
+	DEBUG_FindNearestSymbol(addr, TRUE, NULL, 0, &syminfo.list);
+	if (syminfo.list.sourcefile != NULL)
 	{
 	    DEBUG_List(&syminfo.list, NULL, 0);
 	}
Index: debugger-merge/dbg.y
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/dbg.y,v
retrieving revision 1.57
diff -u -u -r1.57 dbg.y
--- debugger-merge/dbg.y	2 Jun 2002 21:36:08 -0000	1.57
+++ debugger-merge/dbg.y	8 Jun 2002 07:38:23 -0000
@@ -105,30 +105,21 @@
     ;
 
 command:
-      tQUIT tEOL		{ DEBUG_ExitMode = EXIT_QUIT; return 1; }
+      tQUIT tEOL		{ /*DEBUG_Quit();*/ return 1; }
     | tHELP tEOL                { DEBUG_Help(); }
     | tHELP tINFO tEOL          { DEBUG_HelpInfo(); }
-    | tCONT tEOL                { DEBUG_CurrThread->exec_count = 1;
-				  DEBUG_CurrThread->exec_mode = EXEC_CONT; return 1; }
-    | tPASS tEOL                { DEBUG_ExitMode = EXIT_PASS; return 1; }
-    | tCONT tNUM tEOL         	{ DEBUG_CurrThread->exec_count = $2;
-				  DEBUG_CurrThread->exec_mode = EXEC_CONT; return 1; }
-    | tSTEP tEOL               	{ DEBUG_CurrThread->exec_count = 1;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEP_INSTR; return 1; }
-    | tNEXT tEOL                { DEBUG_CurrThread->exec_count = 1;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEP_OVER; return 1; }
-    | tSTEP tNUM tEOL           { DEBUG_CurrThread->exec_count = $2;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEP_INSTR; return 1; }
-    | tNEXT tNUM tEOL           { DEBUG_CurrThread->exec_count = $2;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEP_OVER; return 1; }
-    | tSTEPI tEOL               { DEBUG_CurrThread->exec_count = 1;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEPI_INSTR; return 1; }
-    | tNEXTI tEOL               { DEBUG_CurrThread->exec_count = 1;
-				  DEBUG_CurrThread->exec_mode = EXEC_STEPI_OVER; return 1; }
-    | tSTEPI tNUM tEOL          { DEBUG_CurrThread->exec_count = $2;
-			 	  DEBUG_CurrThread->exec_mode = EXEC_STEPI_INSTR; return 1; }
-    | tNEXTI tNUM tEOL          { DEBUG_CurrThread->exec_count = $2;
-                                  DEBUG_CurrThread->exec_mode = EXEC_STEPI_OVER; return 1; }
+    | tPASS tEOL                { DEBUG_WaitNextException(DBG_EXCEPTION_NOT_HANDLED, 0, 0); }
+    | tCONT tEOL                { DEBUG_WaitNextException(DBG_CONTINUE, 1,  EXEC_CONT); }
+    | tCONT tNUM tEOL         	{ DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_CONT); }
+    | tSTEP tEOL               	{ DEBUG_WaitNextException(DBG_CONTINUE, 1,  EXEC_STEP_INSTR); }
+    | tSTEP tNUM tEOL           { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEP_INSTR); }
+    | tNEXT tEOL                { DEBUG_WaitNextException(DBG_CONTINUE, 1,  EXEC_STEP_OVER); }
+    | tNEXT tNUM tEOL           { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEP_OVER); }
+    | tSTEPI tEOL               { DEBUG_WaitNextException(DBG_CONTINUE, 1,  EXEC_STEPI_INSTR); }
+    | tSTEPI tNUM tEOL          { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEPI_INSTR); }
+    | tNEXTI tEOL               { DEBUG_WaitNextException(DBG_CONTINUE, 1,  EXEC_STEPI_OVER); }
+    | tNEXTI tNUM tEOL          { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEPI_OVER); }
+    | tFINISH tEOL	       	{ DEBUG_WaitNextException(DBG_CONTINUE, 0,  EXEC_FINISH); }
     | tABORT tEOL              	{ kill(getpid(), SIGABRT); }
     | tMODE tNUM tEOL          	{ mode_command($2); }
     | tMODE tVM86 tEOL         	{ DEBUG_CurrThread->dbg_mode = MODE_VM86; }
@@ -142,8 +133,6 @@
     | tDOWN tEOL	       	{ DEBUG_SetFrame( curr_frame - 1 );  }
     | tDOWN tNUM tEOL	       	{ DEBUG_SetFrame( curr_frame - $2 ); }
     | tFRAME tNUM tEOL         	{ DEBUG_SetFrame( $2 ); }
-    | tFINISH tEOL	       	{ DEBUG_CurrThread->exec_count = 0;
-				  DEBUG_CurrThread->exec_mode = EXEC_FINISH; return 1; }
     | tSHOW tDIR tEOL	       	{ DEBUG_ShowDir(); }
     | tDIR pathname tEOL       	{ DEBUG_AddPath( $2 ); }
     | tDIR tEOL		       	{ DEBUG_NukePath(); }
@@ -158,8 +147,8 @@
     | tCOND tNUM expr tEOL	{ DEBUG_AddBPCondition($2, $3); }
     | tSYMBOLFILE pathname tEOL	{ DEBUG_ReadSymbolTable($2); }
     | tWHATIS expr_addr tEOL	{ DEBUG_PrintType(&$2); DEBUG_FreeExprMem(); }
-    | tATTACH tNUM tEOL		{ if (DEBUG_Attach($2, FALSE)) return 1; }
-    | tDETACH tEOL              { DEBUG_ExitMode = EXIT_DETACH; return 1; }
+    | tATTACH tNUM tEOL		{ DEBUG_Attach($2, FALSE); }
+    | tDETACH tEOL              { return DEBUG_Detach(); /* FIXME: we shouldn't return, but since we cannot simply clean the symbol table, exit debugger for now */ }
     | list_command
     | disassemble_command
     | set_command
@@ -415,6 +404,7 @@
       break;
    default:
       DEBUG_Printf(DBG_CHN_MESG, "Exception %lx\n", GetExceptionCode());
+      DEBUG_ExternalDebugger();
       break;
    }
 
@@ -433,8 +423,6 @@
     yydebug = 0;
 #endif
     yyin = stdin;
-
-    DEBUG_ExitMode = EXIT_CONTINUE;
 
     ret_ok = FALSE;
     do {
Index: debugger-merge/debugger.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/debugger.h,v
retrieving revision 1.35
diff -u -u -r1.35 debugger.h
--- debugger-merge/debugger.h	13 Jun 2002 21:37:07 -0000	1.35
+++ debugger-merge/debugger.h	9 Jul 2002 19:47:43 -0000
@@ -241,7 +241,7 @@
 extern	DWORD		DEBUG_CurrTid;
 extern	DWORD		DEBUG_CurrPid;
 extern  CONTEXT		DEBUG_context;
-extern  BOOL		DEBUG_interactiveP;
+extern  BOOL		DEBUG_InteractiveP;
 extern  enum exit_mode  DEBUG_ExitMode;
 
 #define DEBUG_READ_MEM(addr, buf, len) \
@@ -516,21 +516,30 @@
 #define DBG_CHN_WARN	4
 #define DBG_CHN_FIXME	8
 #define DBG_CHN_TRACE	16
-extern void	DEBUG_OutputA(int chn, const char* buffer, int len);
-extern void	DEBUG_OutputW(int chn, const WCHAR* buffer, int len);
+extern void	        DEBUG_OutputA(int chn, const char* buffer, int len);
+extern void	        DEBUG_OutputW(int chn, const WCHAR* buffer, int len);
 #ifdef __GNUC__
-extern int	DEBUG_Printf(int chn, const char* format, ...) __attribute__((format (printf,2,3)));
+extern int	        DEBUG_Printf(int chn, const char* format, ...) __attribute__((format (printf,2,3)));
 #else
-extern int	DEBUG_Printf(int chn, const char* format, ...);
+extern int	        DEBUG_Printf(int chn, const char* format, ...);
 #endif
 extern DBG_INTVAR*	DEBUG_GetIntVar(const char*);
-extern BOOL DEBUG_Attach(DWORD pid, BOOL cofe);
-extern BOOL DEBUG_Detach(void);
-extern void DEBUG_Run(const char* args);
+extern BOOL             DEBUG_Attach(DWORD pid, BOOL cofe);
+extern BOOL             DEBUG_Detach(void);
+extern void             DEBUG_Run(const char* args);
+extern DBG_PROCESS*	DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName);
 extern DBG_PROCESS* 	DEBUG_GetProcess(DWORD pid);
+extern void             DEBUG_DelProcess(DBG_PROCESS* p);
+extern DBG_THREAD*	DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, HANDLE h, LPVOID start, LPVOID teb);
 extern DBG_THREAD* 	DEBUG_GetThread(DBG_PROCESS* p, DWORD tid);
+extern void             DEBUG_DelThread(DBG_THREAD* t);
+extern BOOL             DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr);
+extern BOOL             DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr);
+extern void             DEBUG_WaitNextException(DWORD cont, int count, int mode);
 extern int curr_frame;
-extern int automatic_mode;
+
+/* gdbproxy.c */
+extern BOOL DEBUG_GdbRemote(unsigned int);
 
 /* Choose your allocator! */
 #if 1
Index: debugger-merge/hash.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/hash.c,v
retrieving revision 1.30
diff -u -u -r1.30 hash.c
--- debugger-merge/hash.c	31 May 2002 23:06:46 -0000	1.30
+++ debugger-merge/hash.c	5 Jun 2002 20:29:23 -0000
@@ -399,7 +399,7 @@
 
    if (num == 0) {
       return FALSE;
-   } else if (!DEBUG_interactiveP || num == 1) {
+   } else if (!DEBUG_InteractiveP || num == 1) {
       i = 0;
    } else {
       char	buffer[256];
Index: debugger-merge/source.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/source.c,v
retrieving revision 1.22
diff -u -u -r1.22 source.c
--- debugger-merge/source.c	13 Jun 2002 21:37:07 -0000	1.22
+++ debugger-merge/source.c	23 Jun 2002 07:36:20 -0000
@@ -196,7 +196,7 @@
 
 	  if( sl == NULL )
 	    {
-                if (!automatic_mode)
+                if (DEBUG_InteractiveP)
                 {
                     char zbuf[256];
                     /*
Index: debugger-merge/winedbg.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/winedbg.c,v
retrieving revision 1.58
diff -u -u -r1.58 winedbg.c
--- debugger-merge/winedbg.c	13 Jun 2002 21:37:07 -0000	1.58
+++ debugger-merge/winedbg.c	9 Jul 2002 20:26:18 -0000
@@ -39,13 +39,13 @@
 DWORD		DEBUG_CurrTid;
 DWORD		DEBUG_CurrPid;
 CONTEXT		DEBUG_context;
-BOOL		DEBUG_interactiveP = FALSE;
-enum exit_mode  DEBUG_ExitMode = EXIT_CONTINUE;
+BOOL		DEBUG_InteractiveP = FALSE;
 int 		curr_frame = 0;
-int automatic_mode = 0;
 static char*	DEBUG_LastCmdLine = NULL;
 
 static DBG_PROCESS* DEBUG_ProcessList = NULL;
+static enum {none_mode = 0, winedbg_mode, automatic_mode, gdb_mode} local_mode;
+
 DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
 
 void	DEBUG_OutputA(int chn, const char* buffer, int len)
@@ -142,13 +142,6 @@
     return NULL;
 }
 
-static WINE_EXCEPTION_FILTER(wine_dbg)
-{
-    DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg: Exception (%lx) inside debugger, continuing...\n", GetExceptionCode());
-    DEBUG_ExternalDebugger();
-    return EXCEPTION_EXECUTE_HANDLER;
-}
-
 DBG_PROCESS*	DEBUG_GetProcess(DWORD pid)
 {
     DBG_PROCESS*	p;
@@ -158,11 +151,25 @@
     return p;
 }
 
-static	DBG_PROCESS*	DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
+DBG_PROCESS*	DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
 {
-    DBG_PROCESS*	p = DBG_alloc(sizeof(DBG_PROCESS));
-    if (!p)
-	return NULL;
+    DBG_PROCESS*	p;
+
+    if ((p = DEBUG_GetProcess(pid)))
+    {
+        if (p->handle != 0)
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Process (%lu) is already defined\n", pid);
+        }
+        else
+        {
+            p->handle = h;
+            p->imageName = imageName ? DBG_strdup(imageName) : NULL;
+        }
+        return p;
+    }
+
+    if (!(p = DBG_alloc(sizeof(DBG_PROCESS)))) return NULL;
     p->handle = h;
     p->pid = pid;
     p->imageName = imageName ? DBG_strdup(imageName) : NULL;
@@ -183,16 +190,12 @@
     return p;
 }
 
-static	void			DEBUG_DelThread(DBG_THREAD* p);
-
-static	void			DEBUG_DelProcess(DBG_PROCESS* p)
+void DEBUG_DelProcess(DBG_PROCESS* p)
 {
     int	i;
 
-    if (p->threads != NULL) {
-	DEBUG_Printf(DBG_CHN_ERR, "Shouldn't happen\n");
-	while (p->threads) DEBUG_DelThread(p->threads);
-    }
+    while (p->threads) DEBUG_DelThread(p->threads);
+
     for (i = 0; i < p->num_delayed_bp; i++) {
 	DBG_free(p->delayed_bp[i].name);
     }
@@ -209,14 +212,14 @@
 {
 }
 
-static BOOL DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr)
+BOOL DEBUG_ProcessGetString(char* buffer, int size, HANDLE hp, LPSTR addr)
 {
     DWORD sz;
     *(WCHAR*)buffer = 0;
     return (addr && ReadProcessMemory(hp, addr, buffer, size, &sz));
 }
 
-static BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr)
+BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LPVOID addr)
 {
     LPVOID	ad;
     DWORD	sz;
@@ -235,13 +238,14 @@
 {
     DBG_THREAD*	t;
 
+    if (!p) return NULL;
     for (t = p->threads; t; t = t->next)
 	if (t->tid == tid) break;
     return t;
 }
 
-static	DBG_THREAD*	DEBUG_AddThread(DBG_PROCESS* p, DWORD tid,
-					HANDLE h, LPVOID start, LPVOID teb)
+DBG_THREAD*	DEBUG_AddThread(DBG_PROCESS* p, DWORD tid,
+                                HANDLE h, LPVOID start, LPVOID teb)
 {
     DBG_THREAD*	t = DBG_alloc(sizeof(DBG_THREAD));
     if (!t)
@@ -287,7 +291,7 @@
     }
 }
 
-static	void			DEBUG_DelThread(DBG_THREAD* t)
+void			DEBUG_DelThread(DBG_THREAD* t)
 {
     if (t->prev) t->prev->next = t->next;
     if (t->next) t->next->prev = t->prev;
@@ -336,7 +340,8 @@
     DEBUG_GetCurrentAddress(&addr);
     DEBUG_SuspendExecution();
 
-    if (!is_debug) {
+    if (!is_debug) 
+    {
         if (!addr.seg)
             DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off);
         else
@@ -425,7 +430,7 @@
 	DEBUG_CurrThread->exec_count = 0;
 }
 
-static	void DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force)
+static	BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force)
 {
     BOOL             is_debug = FALSE;
     THREADNAME_INFO *pThreadName;
@@ -433,8 +438,6 @@
 
     assert(DEBUG_CurrThread);
 
-    DEBUG_ExitMode = EXIT_CONTINUE;
-
     switch (rec->ExceptionCode)
     {
     case EXCEPTION_BREAKPOINT:
@@ -453,14 +456,13 @@
             DEBUG_Printf (DBG_CHN_MESG,
                           "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
                           pThread->tid, pThread->name);
-        return;
+        return FALSE;
     }
 
     if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance))
     {
         /* pass exception to program except for debug exceptions */
-        if (!is_debug) DEBUG_ExitMode = EXIT_PASS;
-        return;
+        return FALSE;
     }
 
     if (!is_debug)
@@ -518,7 +520,7 @@
 	    if (!DBG_IVAR(BreakOnCritSectTimeOut))
 	    {
 		DEBUG_Printf(DBG_CHN_MESG, "\n");
-		return;
+		return FALSE;
 	    }
             break;
         case EXCEPTION_WINE_STUB:
@@ -547,351 +549,341 @@
         }
     }
 
-#if 0
-    DEBUG_Printf(DBG_CHN_TRACE,
-		 "Entering debugger 	PC=%lx EFL=%08lx mode=%d count=%d\n",
-#ifdef __i386__
-		 DEBUG_context.Eip, DEBUG_context.EFlags,
-#else
-		 0L, 0L,
-#endif
-		 DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
-#endif
-
-    if (automatic_mode)
+    if (local_mode == automatic_mode)
     {
         DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode);
-        DEBUG_ExitMode = EXIT_QUIT;
-        return;  /* terminate execution */
+        DEBUG_ExceptionEpilog();
+        return TRUE;  /* terminate execution */
     }
 
-    if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) {
-	DEBUG_interactiveP = TRUE;
-	for (;;)
-        {
-            DEBUG_Parser();
-            if (DEBUG_ExitMode == EXIT_QUIT || DEBUG_ExitMode == EXIT_DETACH)
-                break;
-	    if (DEBUG_ValidateRegisters()) {
-		if (DEBUG_ExitMode == EXIT_CONTINUE || first_chance)
-		    break;
-		DEBUG_Printf(DBG_CHN_MESG, "Cannot pass on last chance exception. You must use cont\n");
-	    }
-	}
-	DEBUG_interactiveP = FALSE;
+    if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) 
+    {
+	DEBUG_InteractiveP = TRUE;
+        return TRUE;
     }
     DEBUG_ExceptionEpilog();
 
-#if 0
-    DEBUG_Printf(DBG_CHN_TRACE,
-		 "Exiting debugger 	PC=%lx EFL=%08lx mode=%d count=%d\n",
-#ifdef __i386__
-		 DEBUG_context.Eip, DEBUG_context.EFlags,
-#else
-		 0L, 0L,
-#endif
-		 DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
-#endif
+    return FALSE;
 }
 
-static	void	DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
+static	BOOL	DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
 {
     char		buffer[256];
+    BOOL                ret = FALSE;
 
     DEBUG_CurrPid = de->dwProcessId;
     DEBUG_CurrTid = de->dwThreadId;
 
-    DEBUG_ExitMode = EXIT_CONTINUE;
-    __TRY {
-	if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
-	    DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
-	else
-	    DEBUG_CurrThread = NULL;
-
-	switch (de->dwDebugEventCode) {
-	case EXCEPTION_DEBUG_EVENT:
-	    if (!DEBUG_CurrThread) {
-		DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
-			     de->dwProcessId, de->dwThreadId);
-		break;
-	    }
+    if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
+        DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
+    else
+        DEBUG_CurrThread = NULL;
 
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n",
-			 de->dwProcessId, de->dwThreadId,
-			 de->u.Exception.ExceptionRecord.ExceptionCode);
-
-	    if (DEBUG_CurrProcess->continue_on_first_exception) {
-		DEBUG_CurrProcess->continue_on_first_exception = FALSE;
-		if (!DBG_IVAR(BreakOnAttach)) {
-		    break;
-		}
-	    }
+    switch (de->dwDebugEventCode) 
+    {
+    case EXCEPTION_DEBUG_EVENT:
+        if (!DEBUG_CurrThread) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n",
+                         de->dwProcessId, de->dwThreadId);
+            break;
+        }
+
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n",
+                     de->dwProcessId, de->dwThreadId,
+                     de->u.Exception.ExceptionRecord.ExceptionCode);
 
-	    DEBUG_context.ContextFlags =  CONTEXT_CONTROL
-                                        | CONTEXT_INTEGER
+        if (DEBUG_CurrProcess->continue_on_first_exception) 
+        {
+            DEBUG_CurrProcess->continue_on_first_exception = FALSE;
+            if (!DBG_IVAR(BreakOnAttach)) break;
+        }
+        
+        DEBUG_context.ContextFlags =  CONTEXT_CONTROL
+                                    | CONTEXT_INTEGER
 #ifdef CONTEXT_SEGMENTS
-	                                | CONTEXT_SEGMENTS
+                                    | CONTEXT_SEGMENTS
 #endif
 #ifdef CONTEXT_DEBUG_REGISTERS
-		                        | CONTEXT_DEBUG_REGISTERS
+	                            | CONTEXT_DEBUG_REGISTERS
 #endif
-					;
-
-	    if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
-		DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
-		break;
-	    }
-
-	    DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
-                                  de->u.Exception.dwFirstChance,
-                                  DEBUG_CurrThread->wait_for_first_exception);
-	    if (DEBUG_CurrThread) {
-		DEBUG_CurrThread->wait_for_first_exception = 0;
-		SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
-	    }
-	    break;
+                                    ;
 
-	case CREATE_THREAD_DEBUG_EVENT:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId,
-			 (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
-
-	    if (DEBUG_CurrProcess == NULL) {
-		DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
-		break;
-	    }
-	    if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) {
-		DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
-		break;
-	    }
+        if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) 
+        {
+            DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
+            break;
+        }
 
-	    DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
-					       de->dwThreadId,
-					       de->u.CreateThread.hThread,
-					       de->u.CreateThread.lpStartAddress,
-					       de->u.CreateThread.lpThreadLocalBase);
-	    if (!DEBUG_CurrThread) {
-		DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
-		break;
-	    }
-	    DEBUG_InitCurrThread();
-	    break;
+        ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
+                                    de->u.Exception.dwFirstChance,
+                                    DEBUG_CurrThread->wait_for_first_exception);
+        if (DEBUG_CurrThread) 
+        {
+            DEBUG_CurrThread->wait_for_first_exception = 0;
+            SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
+        }
+        break;
 
-	case CREATE_PROCESS_DEBUG_EVENT:
-	    DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
-                                           de->u.CreateProcessInfo.hProcess,
-                                           de->u.CreateProcessInfo.lpImageName);
-
-	    /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
-			 de->dwProcessId, de->dwThreadId,
-			 buffer, de->u.CreateProcessInfo.lpImageName,
-			 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
-			 de->u.CreateProcessInfo.dwDebugInfoFileOffset,
-			 de->u.CreateProcessInfo.nDebugInfoSize);
-
-	    if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) {
-		if (DEBUG_CurrProcess->handle) {
-		    DEBUG_Printf(DBG_CHN_ERR, "Skipping already defined process\n");
-		    break;
-		}
-		DEBUG_CurrProcess->handle = de->u.CreateProcessInfo.hProcess;
-		if (DEBUG_CurrProcess->imageName == NULL)
-		    DEBUG_CurrProcess->imageName = DBG_strdup(buffer[0] ? buffer : "<Debugged Process>");
+    case CREATE_THREAD_DEBUG_EVENT:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId,
+                     (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
 
-	    } else {
-		DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
-						     de->u.CreateProcessInfo.hProcess,
-						     buffer[0] ? buffer : "<Debugged Process>");
-		if (DEBUG_CurrProcess == NULL) {
-		    DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
-		    break;
-		}
-	    }
+        if (DEBUG_CurrProcess == NULL) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
+            break;
+        }
+        if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL) 
+        {
+            DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
+            break;
+        }
 
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n",
-			 de->dwProcessId, de->dwThreadId,
-			 (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
-
-	    DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
-					       de->dwThreadId,
-					       de->u.CreateProcessInfo.hThread,
-					       de->u.CreateProcessInfo.lpStartAddress,
-					       de->u.CreateProcessInfo.lpThreadLocalBase);
-	    if (!DEBUG_CurrThread) {
-		DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
-		break;
-	    }
+        DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
+                                           de->dwThreadId,
+                                           de->u.CreateThread.hThread,
+                                           de->u.CreateThread.lpStartAddress,
+                                           de->u.CreateThread.lpThreadLocalBase);
+        if (!DEBUG_CurrThread) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
+            break;
+        }
+        DEBUG_InitCurrThread();
+        break;
 
-	    DEBUG_InitCurrProcess();
-	    DEBUG_InitCurrThread();
+    case CREATE_PROCESS_DEBUG_EVENT:
+        DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
+                                       de->u.CreateProcessInfo.hProcess,
+                                       de->u.CreateProcessInfo.lpImageName);
+
+        /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
+                     de->dwProcessId, de->dwThreadId,
+                     buffer, de->u.CreateProcessInfo.lpImageName,
+                     (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
+                     de->u.CreateProcessInfo.dwDebugInfoFileOffset,
+                     de->u.CreateProcessInfo.nDebugInfoSize);
+
+        DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
+                                             de->u.CreateProcessInfo.hProcess,
+                                             buffer[0] ? buffer : "<Debugged Process>");
+        if (DEBUG_CurrProcess == NULL) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Couldn't create process\n");
+            break;
+        }
 
-            /* module is either PE, NE or ELF module (for WineLib), but all
-             * are loaded with wine, so load its symbols, then the main module
-             */
-            do
-            {
-                char*   ptr = getenv("WINELOADER");
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n",
+                     de->dwProcessId, de->dwThreadId,
+                     (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
+
+        DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
+                                           de->dwThreadId,
+                                           de->u.CreateProcessInfo.hThread,
+                                           de->u.CreateProcessInfo.lpStartAddress,
+                                           de->u.CreateProcessInfo.lpThreadLocalBase);
+        if (!DEBUG_CurrThread) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
+            break;
+        }
 
-                if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR)
-                    DEBUG_ReadExecutableDbgInfo( "wine" );
-            } while (0);
+        DEBUG_InitCurrProcess();
+        DEBUG_InitCurrThread();
 
-	    DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
-			       (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
+        /* module is either PE, NE or ELF module (for WineLib), but all
+         * are loaded with wine, so load its symbols, then the main module
+         */
+        do
+        {
+            char*   ptr = getenv("WINELOADER");
 
-	    break;
+            if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR)
+                DEBUG_ReadExecutableDbgInfo( "wine" );
+        } while (0);
 
-	case EXIT_THREAD_DEBUG_EVENT:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n",
-			 de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
+        DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
+                           (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
 
-	    if (DEBUG_CurrThread == NULL) {
-		DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
-		break;
-	    }
-	    /* FIXME: remove break point set on thread startup */
-	    DEBUG_DelThread(DEBUG_CurrThread);
-	    break;
-
-	case EXIT_PROCESS_DEBUG_EVENT:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n",
-			 de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
-
-	    if (DEBUG_CurrProcess == NULL) {
-		DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
-		break;
-	    }
-	    /* just in case */
-	    DEBUG_SetBreakpoints(FALSE);
-	    /* kill last thread */
-	    DEBUG_DelThread(DEBUG_CurrProcess->threads);
-	    DEBUG_DelProcess(DEBUG_CurrProcess);
-
-	    DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
-	    break;
-
-	case LOAD_DLL_DEBUG_EVENT:
-	    if (DEBUG_CurrThread == NULL) {
-		DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
-		break;
-	    }
-	    DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
-                                           DEBUG_CurrThread->process->handle,
-                                           de->u.LoadDll.lpImageName);
-
-	    /* FIXME unicode: de->u.LoadDll.fUnicode */
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
-			 de->dwProcessId, de->dwThreadId,
-			 buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
-			 de->u.LoadDll.dwDebugInfoFileOffset,
-			 de->u.LoadDll.nDebugInfoSize);
-	    _strupr(buffer);
-	    DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, (DWORD)de->u.LoadDll.lpBaseOfDll);
-	    DEBUG_CheckDelayedBP();
-	    if (DBG_IVAR(BreakOnDllLoad)) {
-		DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n",
-			     buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
-		DEBUG_Parser();
-	    }
-	    break;
+        break;
 
-	case UNLOAD_DLL_DEBUG_EVENT:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId,
-			 (unsigned long)de->u.UnloadDll.lpBaseOfDll);
-	    break;
-
-	case OUTPUT_DEBUG_STRING_EVENT:
-	    if (DEBUG_CurrThread == NULL) {
-		DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
-		break;
-	    }
+    case EXIT_THREAD_DEBUG_EVENT:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n",
+                     de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode);
 
-	    DEBUG_ProcessGetString(buffer, sizeof(buffer),
-				   DEBUG_CurrThread->process->handle,
-				   de->u.DebugString.lpDebugStringData);
-
-	    /* FIXME unicode de->u.DebugString.fUnicode ? */
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n",
-			 de->dwProcessId, de->dwThreadId, buffer);
-	    break;
-
-	case RIP_EVENT:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n",
-			 de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
-			 de->u.RipInfo.dwType);
-	    break;
-
-	default:
-	    DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n",
-			 de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
-	}
+        if (DEBUG_CurrThread == NULL) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
+            break;
+        }
+        /* FIXME: remove break point set on thread startup */
+        DEBUG_DelThread(DEBUG_CurrThread);
+        break;
 
-    } __EXCEPT(wine_dbg) {
-	DEBUG_ExitMode = EXIT_CONTINUE;
-    }
-    __ENDTRY;
-}
+    case EXIT_PROCESS_DEBUG_EVENT:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n",
+                     de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
 
-static	DWORD	DEBUG_MainLoop(void)
-{
-    DEBUG_EVENT		de;
+        if (DEBUG_CurrProcess == NULL) 
+        {
+            DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
+            break;
+        }
+        /* just in case */
+        DEBUG_SetBreakpoints(FALSE);
+        /* kill last thread */
+        DEBUG_DelThread(DEBUG_CurrProcess->threads);
+        DEBUG_DelProcess(DEBUG_CurrProcess);
 
-    DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
+        DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
+        break;
 
-    while (DEBUG_ExitMode == EXIT_CONTINUE)
-    {
-	/* wait until we get at least one loaded process */
-	while (!DEBUG_ProcessList)
+    case LOAD_DLL_DEBUG_EVENT:
+        if (DEBUG_CurrThread == NULL) 
         {
-            DEBUG_Parser();
-            if (DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_QUIT) break;
+            DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
+            break;
         }
-	if (DEBUG_ExitMode != EXIT_CONTINUE) break;
-
-	while ((DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_PASS) &&
-               DEBUG_ProcessList &&
-               WaitForDebugEvent(&de, INFINITE))
+        DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
+                                       DEBUG_CurrThread->process->handle,
+                                       de->u.LoadDll.lpImageName);
+
+        /* FIXME unicode: de->u.LoadDll.fUnicode */
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
+                     de->dwProcessId, de->dwThreadId,
+                     buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
+                     de->u.LoadDll.dwDebugInfoFileOffset,
+                     de->u.LoadDll.nDebugInfoSize);
+        _strupr(buffer);
+        DEBUG_LoadModule32(buffer, de->u.LoadDll.hFile, (DWORD)de->u.LoadDll.lpBaseOfDll);
+        DEBUG_CheckDelayedBP();
+        if (DBG_IVAR(BreakOnDllLoad)) 
         {
-	    DEBUG_HandleDebugEvent(&de);
-	    ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
-                               (DEBUG_ExitMode == EXIT_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE);
-	}
-        if (DEBUG_ExitMode == EXIT_DETACH && DEBUG_Detach())
+            DEBUG_Printf(DBG_CHN_MESG, "Stopping on DLL %s loading at %08lx\n",
+                         buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll);
+            ret = TRUE;
+        }
+        break;
+
+    case UNLOAD_DLL_DEBUG_EVENT:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId,
+                     (unsigned long)de->u.UnloadDll.lpBaseOfDll);
+        break;
+
+    case OUTPUT_DEBUG_STRING_EVENT:
+        if (DEBUG_CurrThread == NULL) 
         {
-            /* DEBUG_ExitMode = EXIT_CONTINUE; */
-            /* FIXME: as we don't have a simple way to zero out the process symbol table
-             * we simply quit the debugger on detach...
-             */
-            DEBUG_ExitMode = EXIT_QUIT;
+            DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
+            break;
         }
+
+        DEBUG_ProcessGetString(buffer, sizeof(buffer),
+                               DEBUG_CurrThread->process->handle,
+                               de->u.DebugString.lpDebugStringData);
+
+        /* FIXME unicode de->u.DebugString.fUnicode ? */
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n",
+                     de->dwProcessId, de->dwThreadId, buffer);
+        break;
+
+    case RIP_EVENT:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n",
+                     de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
+                     de->u.RipInfo.dwType);
+        break;
+
+    default:
+        DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n",
+                     de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
     }
 
-    DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
+    return ret;
+}
 
-    return 0;
+static void                     DEBUG_ResumeDebuggee(DWORD cont)
+{
+    DEBUG_ExceptionEpilog();
+#if 1
+    DEBUG_Printf(DBG_CHN_TRACE,
+                 "Exiting debugger      PC=%lx EFL=%08lx mode=%d count=%d\n",
+#ifdef __i386__
+                 DEBUG_context.Eip, DEBUG_context.EFlags,
+#else
+                 0L, 0L,
+#endif
+                 DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
+#endif
+    DEBUG_InteractiveP = FALSE;
+    if (DEBUG_CurrThread)
+    {
+        if (!SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context))
+            DEBUG_Printf(DBG_CHN_MESG, "Cannot set ctx on %lu\n", DEBUG_CurrTid);
+        DEBUG_CurrThread->wait_for_first_exception = 0;
+    }
+    if (!ContinueDebugEvent(DEBUG_CurrPid, DEBUG_CurrTid, cont))
+        DEBUG_Printf(DBG_CHN_MESG, "Cannot continue on %lu (%lu)\n",
+                     DEBUG_CurrTid, cont);
 }
 
-static DWORD DEBUG_AutoMode(void)
+void                            DEBUG_WaitNextException(DWORD cont, int count, int mode)
 {
-    DEBUG_EVENT de;
+    DEBUG_EVENT         de;
 
-    DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
+    if (cont == DBG_CONTINUE)
+    {
+        DEBUG_CurrThread->exec_count = count;
+        DEBUG_CurrThread->exec_mode = mode;
+    }
+    DEBUG_ResumeDebuggee(cont);
 
-    while ((DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_PASS) &&
-           DEBUG_ProcessList &&
-           WaitForDebugEvent(&de, INFINITE))
+    while (DEBUG_CurrProcess && WaitForDebugEvent(&de, INFINITE))
     {
-        DEBUG_HandleDebugEvent(&de);
-        ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
-                           (DEBUG_ExitMode == EXIT_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE);
+        if (DEBUG_HandleDebugEvent(&de)) break;
+        ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
     }
-    /* print some extra information */
-    DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
-    DEBUG_WalkModules();
-    DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
-    DEBUG_WalkThreads();
+    if (!DEBUG_CurrProcess) return;
+    DEBUG_InteractiveP = TRUE;
+#if 1
+    DEBUG_Printf(DBG_CHN_TRACE,
+                 "Entering debugger     PC=%lx EFL=%08lx mode=%d count=%d\n",
+#ifdef __i386__
+                 DEBUG_context.Eip, DEBUG_context.EFlags,
+#else
+                 0L, 0L,
+#endif
+                 DEBUG_CurrThread->exec_mode, DEBUG_CurrThread->exec_count);
+#endif
+}
+
+static	DWORD	DEBUG_MainLoop(void)
+{
+    DEBUG_EVENT		de;
+
+    DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting on pid %lx\n", DEBUG_CurrPid);
 
+    /* wait for first exception */
+    while (WaitForDebugEvent(&de, INFINITE))
+    {
+        if (DEBUG_HandleDebugEvent(&de)) break;
+        ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
+    }
+    if (local_mode == automatic_mode)
+    {
+        /* print some extra information */
+        DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
+        DEBUG_WalkModules();
+        DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
+        DEBUG_WalkThreads();
+    }
+    else
+    {
+        DEBUG_InteractiveP = TRUE;
+        DEBUG_Parser();
+    }
     DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
+
     return 0;
 }
 
@@ -905,8 +897,13 @@
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = SW_SHOWNORMAL;
 
+    /* FIXME: shouldn't need the CREATE_NEW_CONSOLE, but as usual CUI:s need it
+     * while GUI:s don't
+     */
     if (!CreateProcess(NULL, cmdLine, NULL, NULL,
-		       FALSE, DEBUG_PROCESS|DETACHED_PROCESS, NULL, NULL, &startup, &info)) {
+		       FALSE, DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS|CREATE_NEW_CONSOLE,
+                       NULL, NULL, &startup, &info)) 
+    {
 	DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
 	return FALSE;
     }
@@ -980,13 +977,16 @@
     SetConsoleCtrlHandler(DEBUG_CtrlCHandler, TRUE);
 }
 
+static int DEBUG_Usage(void)
+{
+    DEBUG_Printf(DBG_CHN_MESG, "Usage: winedbg [--debugmsg dbgoptions] [--auto] [--gdb] cmdline\n" );
+    return 1;
+}
+
 int main(int argc, char** argv)
 {
     DWORD	retv = 0;
-
-    /* Initialize the type handling stuff. */
-    DEBUG_InitTypes();
-    DEBUG_InitCVDataTypes();
+    unsigned    gdb_flags = 0;
 
     /* Initialize internal vars (types must have been initialized before) */
     if (!DEBUG_IntVarsRW(TRUE)) return -1;
@@ -996,14 +996,33 @@
     {
         if (!strcmp( argv[1], "--auto" ))
         {
-            automatic_mode = 1;
+            if (local_mode != none_mode) return DEBUG_Usage();
+            local_mode = automatic_mode;
             /* force some internal variables */
             DBG_IVAR(UseXTerm) = 0;
             DBG_IVAR(BreakOnDllLoad) = 0;
             DBG_IVAR(ConChannelMask) = 0;
             DBG_IVAR(StdChannelMask) = DBG_CHN_MESG;
-            argc--;
-            argv++;
+            argc--; argv++;
+            continue;
+        }
+        if (!strcmp( argv[1], "--gdb" ))
+        {
+            if (local_mode != none_mode) return DEBUG_Usage();
+            local_mode = gdb_mode;
+            argc--; argv++; 
+            continue;
+        }
+        if (strcmp( argv[1], "--no-start") == 0 && local_mode == gdb_mode)
+        {
+            gdb_flags |= 1;
+            argc--; argv++; /* as we don't use argv[0] */
+            continue;
+        }
+        if (strcmp(argv[1], "--with-xterm") == 0 && local_mode == gdb_mode)
+        {
+            gdb_flags |= 2;
+            argc--; argv++; /* as we don't use argv[0] */
             continue;
         }
         if (!strcmp( argv[1], "--debugmsg" ) && argv[2])
@@ -1013,25 +1032,40 @@
             argv += 2;
             continue;
         }
-        DEBUG_Printf(DBG_CHN_MESG, "Usage: winedbg [--debugmsg dbgoptions] [--auto] cmdline\n" );
-        return 1;
+        return DEBUG_Usage();
     }
 
-    DEBUG_InitConsole();
+    if (local_mode == none_mode) local_mode = winedbg_mode;
 
-    DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting... ");
+    /* try the from <myself> pid */
+    if (DEBUG_CurrPid == 0 && argc == 2) 
+    {
+        char*   ptr;
+
+        DEBUG_CurrPid = strtol(argv[1], &ptr, 10);
+        if (DEBUG_CurrPid == 0 || ptr == NULL || 
+            !DEBUG_Attach(DEBUG_CurrPid, local_mode != gdb_mode))
+            DEBUG_CurrPid = 0;
+    }
 
-    if (argc == 3) {
+    /* try the from <myself> pid evt (Win32 JIT debugger) */
+    if (DEBUG_CurrPid == 0 && argc == 3) 
+    {
 	HANDLE	hEvent;
 	DWORD	pid;
+        char*   ptr;
 
-	if ((pid = atoi(argv[1])) != 0 && (hEvent = (HANDLE)atoi(argv[2])) != 0) {
-	    if (!DEBUG_Attach(pid, TRUE)) {
+	if ((pid = strtol(argv[1], &ptr, 10)) != 0 && ptr != NULL && 
+            (hEvent = (HANDLE)strtol(argv[2], &ptr, 10)) != 0 && ptr != NULL)
+        {
+	    if (!DEBUG_Attach(pid, TRUE))
+            {
 		/* don't care about result */
 		SetEvent(hEvent);
 		goto leave;
 	    }
-	    if (!SetEvent(hEvent)) {
+	    if (!SetEvent(hEvent))
+            {
 		DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent);
 		goto leave;
 	    }
@@ -1040,14 +1074,16 @@
 	}
     }
 
-    if (DEBUG_CurrPid == 0 && argc > 1) {
+    if (DEBUG_CurrPid == 0 && argc > 1) 
+    {
 	int	i, len;
 	LPSTR	cmdLine;
 
 	if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
 	cmdLine[0] = '\0';
 
-	for (i = 1; i < argc; i++) {
+	for (i = 1; i < argc; i++) 
+        {
 	    len += strlen(argv[i]) + 1;
 	    if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
 	    strcat(cmdLine, argv[i]);
@@ -1055,25 +1091,27 @@
 	    cmdLine[len - 1] = '\0';
 	}
 
-	if (!DEBUG_Start(cmdLine)) {
+	if (!DEBUG_Start(cmdLine)) 
+        {
 	    DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
 	    goto leave;
 	}
 	DBG_free(DEBUG_LastCmdLine);
 	DEBUG_LastCmdLine = cmdLine;
     }
+    /* don't save local vars in gdb mode */
+    if (local_mode == gdb_mode && DEBUG_CurrPid) 
+        return DEBUG_GdbRemote(gdb_flags);
 
-    if (automatic_mode)
-    {
-        retv = DEBUG_AutoMode();
-        /* don't save modified variables in auto mode */
-    }
-    else
-    {
-        retv = DEBUG_MainLoop();
-        /* saves modified variables */
-        DEBUG_IntVarsRW(FALSE);
-    }
+    /* Initialize the type handling stuff. */
+    DEBUG_InitTypes();
+    DEBUG_InitCVDataTypes();
+
+    DEBUG_InitConsole();
+
+    retv = DEBUG_MainLoop();
+    /* don't save modified variables in auto mode */
+    if (local_mode != automatic_mode) DEBUG_IntVarsRW(FALSE);
 
  leave:
     return retv;


More information about the wine-patches mailing list