Added the detach command to the debugger.
This commit is contained in:
parent
fbccb38e18
commit
21b366e6e2
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue