Added the detach command to the debugger.

oldstable
Eric Pouech 2002-02-27 01:29:18 +00:00 committed by Alexandre Julliard
parent fbccb38e18
commit 21b366e6e2
5 changed files with 75 additions and 38 deletions

View File

@ -47,7 +47,7 @@ int yyerror(char *);
%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
@ -89,31 +89,31 @@ line: command
| 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; }
@ -128,7 +128,7 @@ command:
| 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(); }
@ -143,7 +143,8 @@ command:
| 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
@ -391,10 +392,10 @@ static WINE_EXCEPTION_FILTER(wine_dbg_cmd)
*
* 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

View File

@ -117,6 +117,7 @@ STRING \"[^\n"]+\"
<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; }

View File

@ -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
undocumented exception understood by MS VC debugger, allowing the program
@ -287,7 +291,7 @@ extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
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 @@ 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 DBG_PROCESS* DEBUG_GetProcess(DWORD pid);
extern DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid);

View File

@ -285,6 +285,23 @@ BOOL DEBUG_Attach(DWORD pid, BOOL cofe)
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;
@ -387,10 +404,10 @@ static DWORD DEBUG_ExceptionEpilog(void)
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;
@ -415,14 +432,14 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
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)
@ -480,7 +497,7 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
if (!DBG_IVAR(BreakOnCritSectTimeOut))
{
DEBUG_Printf(DBG_CHN_MESG, "\n");
return TRUE;
return EXIT_CONT;
}
break;
case EXCEPTION_WINE_STUB:
@ -523,12 +540,12 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
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;
@ -556,13 +573,13 @@ static BOOL DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
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)
@ -799,7 +816,7 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
} __EXCEPT(wine_dbg) {
*cont = 0;
ret = TRUE;
ret = EXIT_CONT;
}
__ENDTRY;
return ret;
@ -809,20 +826,29 @@ static DWORD DEBUG_MainLoop(void)
{
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);
@ -833,11 +859,11 @@ static DWORD DEBUG_AutoMode(void)
{
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);
@ -903,6 +929,7 @@ static void DEBUG_InitConsole(void)
FreeConsole();
AllocConsole();
}
/* this would be nicer for output */
c.X = 132;
c.Y = 500;

View File

@ -1010,7 +1010,8 @@ wine -debug myprog.exe
<note>
<title>Note 2</title>
<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,
if a previous Wine installation exists, it's safer to
remove the whole
@ -1281,6 +1282,8 @@ quit exits the debugger
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