since we can now detach the debugger, the detach command has been added to the wine debugger however, because of some debugger internals (like symbols are globally handled and are not freed on process deletion), the detach command will also exit the debugger (but the debuggee will keep on running) I might fix it in a while A+
Name: wdbg_detach ChangeLog: added the detach command to the debugger GenDate: 2002/02/23 21:35:12 UTC ModifiedFiles: debugger/dbg.y debugger/debug.l debugger/debugger.h debugger/winedbg.c documentation/debugger.sgml AddedFiles: =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/debugger/dbg.y,v retrieving revision 1.48 diff -u -u -r1.48 dbg.y --- debugger/dbg.y 4 Feb 2002 18:40:40 -0000 1.48 +++ debugger/dbg.y 6 Feb 2002 19:15:13 -0000 @@ -46,7 +46,7 @@ %token <string> tPATH %token <string> tIDENTIFIER tSTRING tDEBUGSTR tINTVAR %token <integer> tNUM tFORMAT -%token tSYMBOLFILE tRUN tATTACH tNOPROCESS +%token tSYMBOLFILE tRUN tATTACH tDETACH tNOPROCESS %token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED %token tSTRUCT tUNION tENUM @@ -88,31 +88,31 @@ | error tEOL { yyerrok; } command: - tQUIT tEOL { return FALSE; } + tQUIT tEOL { return EXIT_QUIT; } | tHELP tEOL { DEBUG_Help(); } | tHELP tINFO tEOL { DEBUG_HelpInfo(); } | tCONT tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return EXIT_CONT; } | tPASS tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return EXIT_CONT; } | tCONT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; - DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return EXIT_CONT; } | tSTEP tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return EXIT_CONT; } | tNEXT tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return EXIT_CONT; } | tSTEP tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return EXIT_CONT; } | tNEXT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return EXIT_CONT; } | tSTEPI tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return EXIT_CONT; } | tNEXTI tEOL { DEBUG_CurrThread->dbg_exec_count = 1; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return EXIT_CONT; } | tSTEPI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return EXIT_CONT; } | tNEXTI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; - DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return EXIT_CONT; } | tABORT tEOL { kill(getpid(), SIGABRT); } | tMODE tNUM tEOL { mode_command($2); } | tMODE tVM86 tEOL { DEBUG_CurrThread->dbg_mode = MODE_VM86; } @@ -127,7 +127,7 @@ | tDOWN tNUM tEOL { DEBUG_SetFrame( curr_frame - $2 ); } | tFRAME tNUM tEOL { DEBUG_SetFrame( $2 ); } | tFINISH tEOL { DEBUG_CurrThread->dbg_exec_count = 0; - DEBUG_CurrThread->dbg_exec_mode = EXEC_FINISH; return TRUE; } + DEBUG_CurrThread->dbg_exec_mode = EXEC_FINISH; return EXIT_CONT; } | tSHOW tDIR tEOL { DEBUG_ShowDir(); } | tDIR pathname tEOL { DEBUG_AddPath( $2 ); } | tDIR tEOL { DEBUG_NukePath(); } @@ -142,7 +142,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 TRUE; } + | tATTACH tNUM tEOL { if (DEBUG_Attach($2, FALSE)) return EXIT_CONT; } + | tDETACH tEOL { return EXIT_DETACH; } | list_command | disassemble_command | set_command @@ -390,10 +391,10 @@ * * Debugger editline parser */ -BOOL DEBUG_Parser(void) +enum exit_mode DEBUG_Parser(void) { - BOOL ret_ok; - BOOL ret = TRUE; + BOOL ret_ok; + enum exit_mode ret = EXIT_CONT; #ifdef YYDEBUG yydebug = 0; #endif Index: debugger/debug.l =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/debugger/debug.l,v retrieving revision 1.23 diff -u -u -r1.23 debug.l --- debugger/debug.l 4 Feb 2002 18:40:40 -0000 1.23 +++ debugger/debug.l 6 Feb 2002 19:04:31 -0000 @@ -117,6 +117,7 @@ <INITIAL>watch|watc|wat { BEGIN(NOCMD); return tWATCH; } <INITIAL>whatis|whati|what { BEGIN(NOCMD); return tWHATIS; } <INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;} +<INITIAL>detach|detac|deta|det { BEGIN(NOCMD); return tDETACH; } <NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; } <INFO_CMD>share|shar|sha { return tSHARE; } <INFO_CMD>locals|local|loca|loc { return tLOCAL; } Index: debugger/debugger.h =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/debugger/debugger.h,v retrieving revision 1.28 diff -u -u -r1.28 debugger.h --- debugger/debugger.h 4 Feb 2002 18:40:40 -0000 1.28 +++ debugger/debugger.h 6 Feb 2002 19:04:31 -0000 @@ -157,6 +157,10 @@ }; +enum exit_mode +{ + EXIT_CONT, EXIT_QUIT, EXIT_DETACH +}; /* Wine extension; Windows doesn't have a name for this code. This is an undocumented exception understood by MS VC debugger, allowing the program @@ -287,7 +291,7 @@ extern void DEBUG_Disasm( DBG_ADDR *addr, int display ); /* debugger/dbg.y */ -extern BOOL DEBUG_Parser(void); +extern enum exit_mode DEBUG_Parser(void); extern void DEBUG_Exit( DWORD ); /* debugger/debug.l */ @@ -502,6 +506,7 @@ #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 DBG_PROCESS* DEBUG_GetProcess(DWORD pid); extern DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid); Index: debugger/winedbg.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/debugger/winedbg.c,v retrieving revision 1.46 diff -u -u -r1.46 winedbg.c --- debugger/winedbg.c 29 Jan 2002 03:12:20 -0000 1.46 +++ debugger/winedbg.c 20 Feb 2002 21:33:01 -0000 @@ -284,6 +284,23 @@ return TRUE; } +BOOL DEBUG_Detach(void) +{ + /* remove all set breakpoints in debuggee code */ + DEBUG_SetBreakpoints(FALSE); + /* needed for single stepping (ugly). + * should this be handled inside the server ??? */ +#ifdef __i386__ + DEBUG_context.EFlags &= ~STEP_FLAG; +#endif + SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context); + DebugActiveProcessStop(DEBUG_CurrProcess->pid); + DEBUG_DelProcess(DEBUG_CurrProcess); + DEBUG_CurrProcess = NULL; + /* FIXME: should zero out the symbol table too */ + return TRUE; +} + static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code) { DBG_ADDR addr; @@ -386,10 +403,10 @@ return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE; } -static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force, LPDWORD cont) +static enum exit_mode DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force, LPDWORD cont) { BOOL is_debug = FALSE; - BOOL ret = TRUE; + enum exit_mode ret = EXIT_CONT; THREADNAME_INFO *pThreadName; DBG_THREAD *pThread; @@ -414,14 +431,14 @@ DEBUG_Printf (DBG_CHN_MESG, "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n", pThread->tid, pThread->name); - return TRUE; + return EXIT_CONT; } if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance)) { /* pass exception to program except for debug exceptions */ *cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED; - return TRUE; + return EXIT_CONT; } if (!is_debug) @@ -479,7 +496,7 @@ if (!DBG_IVAR(BreakOnCritSectTimeOut)) { DEBUG_Printf(DBG_CHN_MESG, "\n"); - return TRUE; + return EXIT_CONT; } break; case EXCEPTION_WINE_STUB: @@ -522,12 +539,12 @@ if (automatic_mode) { DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode); - return FALSE; /* terminate execution */ + return EXIT_QUIT; /* terminate execution */ } if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) { DEBUG_interactiveP = TRUE; - while ((ret = DEBUG_Parser())) { + while ((ret = DEBUG_Parser()) == EXIT_CONT) { if (DEBUG_ValidateRegisters()) { if (DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance) break; @@ -555,13 +572,13 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont) { char buffer[256]; - BOOL ret; + enum exit_mode ret; DEBUG_CurrPid = de->dwProcessId; DEBUG_CurrTid = de->dwThreadId; __TRY { - ret = TRUE; + ret = EXIT_CONT; *cont = 0L; if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) @@ -798,7 +815,7 @@ } __EXCEPT(wine_dbg) { *cont = 0; - ret = TRUE; + ret = EXIT_CONT; } __ENDTRY; return ret; @@ -808,20 +825,29 @@ { DEBUG_EVENT de; DWORD cont; - BOOL ret; + enum exit_mode ret = EXIT_CONT; DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid); - for (ret = TRUE; ret; ) { + while (ret == EXIT_CONT) + { /* wait until we get at least one loaded process */ - while (!DEBUG_ProcessList && (ret = DEBUG_Parser())); - if (!ret) break; + while (!DEBUG_ProcessList && (ret = DEBUG_Parser()) == EXIT_CONT); + if (ret != EXIT_CONT) break; - while (ret && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) { + while (ret == EXIT_CONT && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) { ret = DEBUG_HandleDebugEvent(&de, &cont); ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont); } - }; + if (ret == EXIT_DETACH && DEBUG_Detach()) + { + /* ret = EXIT_CONT; */ + /* FIXME: as we don't have a simple way to zero out the process symbol table + * we simply quit the debugger on detach... + */ + ret = EXIT_QUIT; + } + } DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid); @@ -832,11 +858,11 @@ { DEBUG_EVENT de; DWORD cont; - BOOL ret = TRUE; + enum exit_mode ret = EXIT_CONT; DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid); - while (ret && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) + while (ret == EXIT_CONT && DEBUG_ProcessList && WaitForDebugEvent(&de, INFINITE)) { ret = DEBUG_HandleDebugEvent(&de, &cont); ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont); @@ -902,6 +928,7 @@ FreeConsole(); AllocConsole(); } + /* this would be nicer for output */ c.X = 132; c.Y = 500; Index: documentation/debugger.sgml =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/documentation/debugger.sgml,v retrieving revision 1.9 diff -u -u -r1.9 debugger.sgml --- documentation/debugger.sgml 12 Jan 2002 21:15:36 -0000 1.9 +++ documentation/debugger.sgml 20 Feb 2002 21:38:15 -0000 @@ -1281,6 +1281,8 @@ attach N attach to a W-process (N is its ID). IDs can be obtained using the walk process command +detach detach from a W-process. WineDbg will exit (this may + be changed later on) </screen> <screen> help prints some help on the commands