Commit 21b366e6 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Added the detach command to the debugger.

parent fbccb38e
...@@ -47,7 +47,7 @@ int yyerror(char *); ...@@ -47,7 +47,7 @@ int yyerror(char *);
%token <string> tPATH %token <string> tPATH
%token <string> tIDENTIFIER tSTRING tDEBUGSTR tINTVAR %token <string> tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
%token <integer> tNUM tFORMAT %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 tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED
%token tSTRUCT tUNION tENUM %token tSTRUCT tUNION tENUM
...@@ -89,31 +89,31 @@ line: command ...@@ -89,31 +89,31 @@ line: command
| error tEOL { yyerrok; } | error tEOL { yyerrok; }
command: command:
tQUIT tEOL { return FALSE; } tQUIT tEOL { return EXIT_QUIT; }
| tHELP tEOL { DEBUG_Help(); } | tHELP tEOL { DEBUG_Help(); }
| tHELP tINFO tEOL { DEBUG_HelpInfo(); } | tHELP tINFO tEOL { DEBUG_HelpInfo(); }
| tCONT tEOL { DEBUG_CurrThread->dbg_exec_count = 1; | 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; | 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; | 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; | 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; | 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; | 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; | 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; | 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; | 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; | 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; | 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); } | tABORT tEOL { kill(getpid(), SIGABRT); }
| tMODE tNUM tEOL { mode_command($2); } | tMODE tNUM tEOL { mode_command($2); }
| tMODE tVM86 tEOL { DEBUG_CurrThread->dbg_mode = MODE_VM86; } | tMODE tVM86 tEOL { DEBUG_CurrThread->dbg_mode = MODE_VM86; }
...@@ -128,7 +128,7 @@ command: ...@@ -128,7 +128,7 @@ command:
| tDOWN tNUM tEOL { DEBUG_SetFrame( curr_frame - $2 ); } | tDOWN tNUM tEOL { DEBUG_SetFrame( curr_frame - $2 ); }
| tFRAME tNUM tEOL { DEBUG_SetFrame( $2 ); } | tFRAME tNUM tEOL { DEBUG_SetFrame( $2 ); }
| tFINISH tEOL { DEBUG_CurrThread->dbg_exec_count = 0; | 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(); } | tSHOW tDIR tEOL { DEBUG_ShowDir(); }
| tDIR pathname tEOL { DEBUG_AddPath( $2 ); } | tDIR pathname tEOL { DEBUG_AddPath( $2 ); }
| tDIR tEOL { DEBUG_NukePath(); } | tDIR tEOL { DEBUG_NukePath(); }
...@@ -143,7 +143,8 @@ command: ...@@ -143,7 +143,8 @@ command:
| tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); } | tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); }
| tSYMBOLFILE pathname tEOL { DEBUG_ReadSymbolTable($2); } | tSYMBOLFILE pathname tEOL { DEBUG_ReadSymbolTable($2); }
| tWHATIS expr_addr tEOL { DEBUG_PrintType(&$2); DEBUG_FreeExprMem(); } | 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 | list_command
| disassemble_command | disassemble_command
| set_command | set_command
...@@ -391,10 +392,10 @@ static WINE_EXCEPTION_FILTER(wine_dbg_cmd) ...@@ -391,10 +392,10 @@ static WINE_EXCEPTION_FILTER(wine_dbg_cmd)
* *
* Debugger editline parser * Debugger editline parser
*/ */
BOOL DEBUG_Parser(void) enum exit_mode DEBUG_Parser(void)
{ {
BOOL ret_ok; BOOL ret_ok;
BOOL ret = TRUE; enum exit_mode ret = EXIT_CONT;
#ifdef YYDEBUG #ifdef YYDEBUG
yydebug = 0; yydebug = 0;
#endif #endif
......
...@@ -117,6 +117,7 @@ STRING \"[^\n"]+\" ...@@ -117,6 +117,7 @@ STRING \"[^\n"]+\"
<INITIAL>watch|watc|wat { BEGIN(NOCMD); return tWATCH; } <INITIAL>watch|watc|wat { BEGIN(NOCMD); return tWATCH; }
<INITIAL>whatis|whati|what { BEGIN(NOCMD); return tWHATIS; } <INITIAL>whatis|whati|what { BEGIN(NOCMD); return tWHATIS; }
<INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;} <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; } <NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; }
<INFO_CMD>share|shar|sha { return tSHARE; } <INFO_CMD>share|shar|sha { return tSHARE; }
<INFO_CMD>locals|local|loca|loc { return tLOCAL; } <INFO_CMD>locals|local|loca|loc { return tLOCAL; }
......
...@@ -157,6 +157,10 @@ enum dbg_mode ...@@ -157,6 +157,10 @@ enum dbg_mode
}; };
enum exit_mode
{
EXIT_CONT, EXIT_QUIT, EXIT_DETACH
};
/* Wine extension; Windows doesn't have a name for this code. This is an /* Wine extension; Windows doesn't have a name for this code. This is an
undocumented exception understood by MS VC debugger, allowing the program undocumented exception understood by MS VC debugger, allowing the program
...@@ -287,7 +291,7 @@ extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp); ...@@ -287,7 +291,7 @@ extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
extern void DEBUG_Disasm( DBG_ADDR *addr, int display ); extern void DEBUG_Disasm( DBG_ADDR *addr, int display );
/* debugger/dbg.y */ /* debugger/dbg.y */
extern BOOL DEBUG_Parser(void); extern enum exit_mode DEBUG_Parser(void);
extern void DEBUG_Exit( DWORD ); extern void DEBUG_Exit( DWORD );
/* debugger/debug.l */ /* debugger/debug.l */
...@@ -502,6 +506,7 @@ extern int DEBUG_Printf(int chn, const char* format, ...); ...@@ -502,6 +506,7 @@ extern int DEBUG_Printf(int chn, const char* format, ...);
#endif #endif
extern DBG_INTVAR* DEBUG_GetIntVar(const char*); extern DBG_INTVAR* DEBUG_GetIntVar(const char*);
extern BOOL DEBUG_Attach(DWORD pid, BOOL cofe); extern BOOL DEBUG_Attach(DWORD pid, BOOL cofe);
extern BOOL DEBUG_Detach(void);
extern void DEBUG_Run(const char* args); extern void DEBUG_Run(const char* args);
extern DBG_PROCESS* DEBUG_GetProcess(DWORD pid); extern DBG_PROCESS* DEBUG_GetProcess(DWORD pid);
extern DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid); extern DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid);
......
...@@ -285,6 +285,23 @@ BOOL DEBUG_Attach(DWORD pid, BOOL cofe) ...@@ -285,6 +285,23 @@ BOOL DEBUG_Attach(DWORD pid, BOOL cofe)
return TRUE; 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) static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
{ {
DBG_ADDR addr; DBG_ADDR addr;
...@@ -387,10 +404,10 @@ static DWORD DEBUG_ExceptionEpilog(void) ...@@ -387,10 +404,10 @@ static DWORD DEBUG_ExceptionEpilog(void)
return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE; 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 is_debug = FALSE;
BOOL ret = TRUE; enum exit_mode ret = EXIT_CONT;
THREADNAME_INFO *pThreadName; THREADNAME_INFO *pThreadName;
DBG_THREAD *pThread; DBG_THREAD *pThread;
...@@ -415,14 +432,14 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL ...@@ -415,14 +432,14 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
DEBUG_Printf (DBG_CHN_MESG, DEBUG_Printf (DBG_CHN_MESG,
"Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n", "Thread ID=0x%lx renamed using MS VC6 extension (name==\"%s\")\n",
pThread->tid, pThread->name); pThread->tid, pThread->name);
return TRUE; return EXIT_CONT;
} }
if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance)) if (first_chance && !is_debug && !force && !DBG_IVAR(BreakOnFirstChance))
{ {
/* pass exception to program except for debug exceptions */ /* pass exception to program except for debug exceptions */
*cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED; *cont = is_debug ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED;
return TRUE; return EXIT_CONT;
} }
if (!is_debug) if (!is_debug)
...@@ -480,7 +497,7 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL ...@@ -480,7 +497,7 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
if (!DBG_IVAR(BreakOnCritSectTimeOut)) if (!DBG_IVAR(BreakOnCritSectTimeOut))
{ {
DEBUG_Printf(DBG_CHN_MESG, "\n"); DEBUG_Printf(DBG_CHN_MESG, "\n");
return TRUE; return EXIT_CONT;
} }
break; break;
case EXCEPTION_WINE_STUB: case EXCEPTION_WINE_STUB:
...@@ -523,12 +540,12 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL ...@@ -523,12 +540,12 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
if (automatic_mode) if (automatic_mode)
{ {
DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode); DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode);
return FALSE; /* terminate execution */ return EXIT_QUIT; /* terminate execution */
} }
if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) { if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) {
DEBUG_interactiveP = TRUE; DEBUG_interactiveP = TRUE;
while ((ret = DEBUG_Parser())) { while ((ret = DEBUG_Parser()) == EXIT_CONT) {
if (DEBUG_ValidateRegisters()) { if (DEBUG_ValidateRegisters()) {
if (DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance) if (DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance)
break; break;
...@@ -556,13 +573,13 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL ...@@ -556,13 +573,13 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont) static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
{ {
char buffer[256]; char buffer[256];
BOOL ret; enum exit_mode ret;
DEBUG_CurrPid = de->dwProcessId; DEBUG_CurrPid = de->dwProcessId;
DEBUG_CurrTid = de->dwThreadId; DEBUG_CurrTid = de->dwThreadId;
__TRY { __TRY {
ret = TRUE; ret = EXIT_CONT;
*cont = 0L; *cont = 0L;
if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
...@@ -799,7 +816,7 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont) ...@@ -799,7 +816,7 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
} __EXCEPT(wine_dbg) { } __EXCEPT(wine_dbg) {
*cont = 0; *cont = 0;
ret = TRUE; ret = EXIT_CONT;
} }
__ENDTRY; __ENDTRY;
return ret; return ret;
...@@ -809,20 +826,29 @@ static DWORD DEBUG_MainLoop(void) ...@@ -809,20 +826,29 @@ static DWORD DEBUG_MainLoop(void)
{ {
DEBUG_EVENT de; DEBUG_EVENT de;
DWORD cont; DWORD cont;
BOOL ret; enum exit_mode ret = EXIT_CONT;
DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid); 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 */ /* wait until we get at least one loaded process */
while (!DEBUG_ProcessList && (ret = DEBUG_Parser())); while (!DEBUG_ProcessList && (ret = DEBUG_Parser()) == EXIT_CONT);
if (!ret) break; 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); ret = DEBUG_HandleDebugEvent(&de, &cont);
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, 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); DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
...@@ -833,11 +859,11 @@ static DWORD DEBUG_AutoMode(void) ...@@ -833,11 +859,11 @@ static DWORD DEBUG_AutoMode(void)
{ {
DEBUG_EVENT de; DEBUG_EVENT de;
DWORD cont; DWORD cont;
BOOL ret = TRUE; enum exit_mode ret = EXIT_CONT;
DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid); 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); ret = DEBUG_HandleDebugEvent(&de, &cont);
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont); ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
...@@ -903,6 +929,7 @@ static void DEBUG_InitConsole(void) ...@@ -903,6 +929,7 @@ static void DEBUG_InitConsole(void)
FreeConsole(); FreeConsole();
AllocConsole(); AllocConsole();
} }
/* this would be nicer for output */ /* this would be nicer for output */
c.X = 132; c.X = 132;
c.Y = 500; c.Y = 500;
......
...@@ -1010,7 +1010,8 @@ wine -debug myprog.exe ...@@ -1010,7 +1010,8 @@ wine -debug myprog.exe
<note> <note>
<title>Note 2</title> <title>Note 2</title>
<para> <para>
<command>wineinstall</command> sets up this correctly. <command>wineinstall</command> (available in Wine source)
sets up this correctly.
However, due to some limitation of the registry installed, However, due to some limitation of the registry installed,
if a previous Wine installation exists, it's safer to if a previous Wine installation exists, it's safer to
remove the whole remove the whole
...@@ -1281,6 +1282,8 @@ quit exits the debugger ...@@ -1281,6 +1282,8 @@ quit exits the debugger
attach N attach to a W-process (N is its ID). IDs can be attach N attach to a W-process (N is its ID). IDs can be
obtained using the walk process command obtained using the walk process command
detach detach from a W-process. WineDbg will exit (this may
be changed later on)
</screen> </screen>
<screen> <screen>
help prints some help on the commands help prints some help on the commands
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment