Inverted inner loops (Win32 debug event handling / WineDbg command

line parser).
This commit is contained in:
Eric Pouech 2002-07-20 20:18:17 +00:00 committed by Alexandre Julliard
parent 57807fa11f
commit 40912b9033
6 changed files with 427 additions and 391 deletions

View File

@ -836,8 +836,8 @@ BOOL DEBUG_ShouldContinue( DBG_ADDR *addr, DWORD code, int * count )
*/ */
if (mode != EXEC_CONT && mode != EXEC_FINISH) if (mode != EXEC_CONT && mode != EXEC_FINISH)
{ {
DEBUG_FindNearestSymbol( addr, TRUE, NULL, 0, &syminfo.list); DEBUG_FindNearestSymbol(addr, TRUE, NULL, 0, &syminfo.list);
if( syminfo.list.sourcefile != NULL ) if (syminfo.list.sourcefile != NULL)
{ {
DEBUG_List(&syminfo.list, NULL, 0); DEBUG_List(&syminfo.list, NULL, 0);
} }
@ -847,8 +847,8 @@ BOOL DEBUG_ShouldContinue( DBG_ADDR *addr, DWORD code, int * count )
/* If there's no breakpoint and we are not single-stepping, then /* If there's no breakpoint and we are not single-stepping, then
* either we must have encountered an int3 in the Windows program * either we must have encountered an int3 in the Windows program
* or someone is trying to stop us * or someone is trying to stop us
* If the later, (no int3 opcode at current address) then stop, * If the later, (no int3 opcode at current address) then stop,
* otherwise, let's skip it. * otherwise, let's skip it.
*/ */
if ((bpnum == -1) && code == EXCEPTION_BREAKPOINT) if ((bpnum == -1) && code == EXCEPTION_BREAKPOINT)
{ {

View File

@ -105,30 +105,21 @@ line: command
; ;
command: command:
tQUIT tEOL { DEBUG_ExitMode = EXIT_QUIT; return 1; } tQUIT tEOL { /*DEBUG_Quit();*/ return 1; }
| tHELP tEOL { DEBUG_Help(); } | tHELP tEOL { DEBUG_Help(); }
| tHELP tINFO tEOL { DEBUG_HelpInfo(); } | tHELP tINFO tEOL { DEBUG_HelpInfo(); }
| tCONT tEOL { DEBUG_CurrThread->exec_count = 1; | tPASS tEOL { DEBUG_WaitNextException(DBG_EXCEPTION_NOT_HANDLED, 0, 0); }
DEBUG_CurrThread->exec_mode = EXEC_CONT; return 1; } | tCONT tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 1, EXEC_CONT); }
| tPASS tEOL { DEBUG_ExitMode = EXIT_PASS; return 1; } | tCONT tNUM tEOL { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_CONT); }
| tCONT tNUM tEOL { DEBUG_CurrThread->exec_count = $2; | tSTEP tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 1, EXEC_STEP_INSTR); }
DEBUG_CurrThread->exec_mode = EXEC_CONT; return 1; } | tSTEP tNUM tEOL { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEP_INSTR); }
| tSTEP tEOL { DEBUG_CurrThread->exec_count = 1; | tNEXT tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 1, EXEC_STEP_OVER); }
DEBUG_CurrThread->exec_mode = EXEC_STEP_INSTR; return 1; } | tNEXT tNUM tEOL { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEP_OVER); }
| tNEXT tEOL { DEBUG_CurrThread->exec_count = 1; | tSTEPI tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 1, EXEC_STEPI_INSTR); }
DEBUG_CurrThread->exec_mode = EXEC_STEP_OVER; return 1; } | tSTEPI tNUM tEOL { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEPI_INSTR); }
| tSTEP tNUM tEOL { DEBUG_CurrThread->exec_count = $2; | tNEXTI tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 1, EXEC_STEPI_OVER); }
DEBUG_CurrThread->exec_mode = EXEC_STEP_INSTR; return 1; } | tNEXTI tNUM tEOL { DEBUG_WaitNextException(DBG_CONTINUE, $2, EXEC_STEPI_OVER); }
| tNEXT tNUM tEOL { DEBUG_CurrThread->exec_count = $2; | tFINISH tEOL { DEBUG_WaitNextException(DBG_CONTINUE, 0, EXEC_FINISH); }
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; }
| 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; }
@ -142,8 +133,6 @@ command:
| tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); } | tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); }
| 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->exec_count = 0;
DEBUG_CurrThread->exec_mode = EXEC_FINISH; return 1; }
| 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(); }
@ -158,8 +147,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 1; } | tATTACH tNUM tEOL { DEBUG_Attach($2, FALSE); }
| tDETACH tEOL { DEBUG_ExitMode = EXIT_DETACH; return 1; } | 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 | list_command
| disassemble_command | disassemble_command
| set_command | set_command
@ -173,7 +162,7 @@ command:
| noprocess_state | noprocess_state
; ;
set_command: set_command:
tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory(&$2,$4); DEBUG_FreeExprMem(); } tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory(&$2,$4); DEBUG_FreeExprMem(); }
| tSET '+' tIDENTIFIER tEOL {DEBUG_DbgChannel(TRUE, NULL, $3);} | tSET '+' tIDENTIFIER tEOL {DEBUG_DbgChannel(TRUE, NULL, $3);}
| tSET '-' tIDENTIFIER tEOL {DEBUG_DbgChannel(FALSE, NULL, $3);} | tSET '-' tIDENTIFIER tEOL {DEBUG_DbgChannel(FALSE, NULL, $3);}
@ -415,6 +404,7 @@ static WINE_EXCEPTION_FILTER(wine_dbg_cmd)
break; break;
default: default:
DEBUG_Printf(DBG_CHN_MESG, "Exception %lx\n", GetExceptionCode()); DEBUG_Printf(DBG_CHN_MESG, "Exception %lx\n", GetExceptionCode());
DEBUG_ExternalDebugger();
break; break;
} }
@ -434,8 +424,6 @@ void DEBUG_Parser(void)
#endif #endif
yyin = stdin; yyin = stdin;
DEBUG_ExitMode = EXIT_CONTINUE;
ret_ok = FALSE; ret_ok = FALSE;
do { do {
__TRY { __TRY {

View File

@ -241,7 +241,7 @@ extern DBG_THREAD* DEBUG_CurrThread;
extern DWORD DEBUG_CurrTid; extern DWORD DEBUG_CurrTid;
extern DWORD DEBUG_CurrPid; extern DWORD DEBUG_CurrPid;
extern CONTEXT DEBUG_context; extern CONTEXT DEBUG_context;
extern BOOL DEBUG_interactiveP; extern BOOL DEBUG_InteractiveP;
extern enum exit_mode DEBUG_ExitMode; extern enum exit_mode DEBUG_ExitMode;
#define DEBUG_READ_MEM(addr, buf, len) \ #define DEBUG_READ_MEM(addr, buf, len) \
@ -516,21 +516,30 @@ extern struct datatype * DEBUG_GetBasicType(enum debug_type_basic);
#define DBG_CHN_WARN 4 #define DBG_CHN_WARN 4
#define DBG_CHN_FIXME 8 #define DBG_CHN_FIXME 8
#define DBG_CHN_TRACE 16 #define DBG_CHN_TRACE 16
extern void DEBUG_OutputA(int chn, const char* 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); extern void DEBUG_OutputW(int chn, const WCHAR* buffer, int len);
#ifdef __GNUC__ #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 #else
extern int DEBUG_Printf(int chn, const char* format, ...); 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 BOOL DEBUG_Detach(void);
extern void DEBUG_Run(const char* args); 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 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 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 curr_frame;
extern int automatic_mode;
/* gdbproxy.c */
extern BOOL DEBUG_GdbRemote(unsigned int);
/* Choose your allocator! */ /* Choose your allocator! */
#if 1 #if 1

View File

@ -399,7 +399,7 @@ BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
if (num == 0) { if (num == 0) {
return FALSE; return FALSE;
} else if (!DEBUG_interactiveP || num == 1) { } else if (!DEBUG_InteractiveP || num == 1) {
i = 0; i = 0;
} else { } else {
char buffer[256]; char buffer[256];

View File

@ -196,7 +196,7 @@ DEBUG_DisplaySource(char * sourcefile, int start, int end)
if( sl == NULL ) if( sl == NULL )
{ {
if (!automatic_mode) if (DEBUG_InteractiveP)
{ {
char zbuf[256]; char zbuf[256];
/* /*
@ -495,4 +495,3 @@ DEBUG_Disassemble(const DBG_VALUE *xstart,const DBG_VALUE *xend,int offset)
DEBUG_LastDisassemble = last; DEBUG_LastDisassemble = last;
return; return;
} }

View File

@ -39,13 +39,13 @@ DBG_THREAD* DEBUG_CurrThread = NULL;
DWORD DEBUG_CurrTid; DWORD DEBUG_CurrTid;
DWORD DEBUG_CurrPid; DWORD DEBUG_CurrPid;
CONTEXT DEBUG_context; CONTEXT DEBUG_context;
BOOL DEBUG_interactiveP = FALSE; BOOL DEBUG_InteractiveP = FALSE;
enum exit_mode DEBUG_ExitMode = EXIT_CONTINUE;
int curr_frame = 0; int curr_frame = 0;
int automatic_mode = 0;
static char* DEBUG_LastCmdLine = NULL; static char* DEBUG_LastCmdLine = NULL;
static DBG_PROCESS* DEBUG_ProcessList = 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]; DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
void DEBUG_OutputA(int chn, const char* buffer, int len) void DEBUG_OutputA(int chn, const char* buffer, int len)
@ -142,13 +142,6 @@ DBG_INTVAR* DEBUG_GetIntVar(const char* name)
return NULL; 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* DEBUG_GetProcess(DWORD pid)
{ {
DBG_PROCESS* p; DBG_PROCESS* p;
@ -158,11 +151,25 @@ DBG_PROCESS* DEBUG_GetProcess(DWORD pid)
return p; 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)); DBG_PROCESS* p;
if (!p)
return NULL; 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->handle = h;
p->pid = pid; p->pid = pid;
p->imageName = imageName ? DBG_strdup(imageName) : NULL; p->imageName = imageName ? DBG_strdup(imageName) : NULL;
@ -183,16 +190,12 @@ static DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h, const char* imageName)
return p; return p;
} }
static void DEBUG_DelThread(DBG_THREAD* p); void DEBUG_DelProcess(DBG_PROCESS* p)
static void DEBUG_DelProcess(DBG_PROCESS* p)
{ {
int i; int i;
if (p->threads != NULL) { while (p->threads) DEBUG_DelThread(p->threads);
DEBUG_Printf(DBG_CHN_ERR, "Shouldn't happen\n");
while (p->threads) DEBUG_DelThread(p->threads);
}
for (i = 0; i < p->num_delayed_bp; i++) { for (i = 0; i < p->num_delayed_bp; i++) {
DBG_free(p->delayed_bp[i].name); DBG_free(p->delayed_bp[i].name);
} }
@ -209,14 +212,14 @@ static void DEBUG_InitCurrProcess(void)
{ {
} }
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; DWORD sz;
*(WCHAR*)buffer = 0; *(WCHAR*)buffer = 0;
return (addr && ReadProcessMemory(hp, addr, buffer, size, &sz)); 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; LPVOID ad;
DWORD sz; DWORD sz;
@ -235,13 +238,14 @@ DBG_THREAD* DEBUG_GetThread(DBG_PROCESS* p, DWORD tid)
{ {
DBG_THREAD* t; DBG_THREAD* t;
if (!p) return NULL;
for (t = p->threads; t; t = t->next) for (t = p->threads; t; t = t->next)
if (t->tid == tid) break; if (t->tid == tid) break;
return t; return t;
} }
static DBG_THREAD* DEBUG_AddThread(DBG_PROCESS* p, DWORD tid, DBG_THREAD* DEBUG_AddThread(DBG_PROCESS* p, DWORD tid,
HANDLE h, LPVOID start, LPVOID teb) HANDLE h, LPVOID start, LPVOID teb)
{ {
DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD)); DBG_THREAD* t = DBG_alloc(sizeof(DBG_THREAD));
if (!t) if (!t)
@ -287,7 +291,7 @@ static void DEBUG_InitCurrThread(void)
} }
} }
static void DEBUG_DelThread(DBG_THREAD* t) void DEBUG_DelThread(DBG_THREAD* t)
{ {
if (t->prev) t->prev->next = t->next; if (t->prev) t->prev->next = t->next;
if (t->next) t->next->prev = t->prev; if (t->next) t->next->prev = t->prev;
@ -336,7 +340,8 @@ static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
DEBUG_GetCurrentAddress(&addr); DEBUG_GetCurrentAddress(&addr);
DEBUG_SuspendExecution(); DEBUG_SuspendExecution();
if (!is_debug) { if (!is_debug)
{
if (!addr.seg) if (!addr.seg)
DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off); DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx)", addr.off);
else else
@ -425,7 +430,7 @@ static void DEBUG_ExceptionEpilog(void)
DEBUG_CurrThread->exec_count = 0; 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; BOOL is_debug = FALSE;
THREADNAME_INFO *pThreadName; THREADNAME_INFO *pThreadName;
@ -433,8 +438,6 @@ static void DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
assert(DEBUG_CurrThread); assert(DEBUG_CurrThread);
DEBUG_ExitMode = EXIT_CONTINUE;
switch (rec->ExceptionCode) switch (rec->ExceptionCode)
{ {
case EXCEPTION_BREAKPOINT: case EXCEPTION_BREAKPOINT:
@ -453,14 +456,13 @@ static void 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; return FALSE;
} }
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 */
if (!is_debug) DEBUG_ExitMode = EXIT_PASS; return FALSE;
return;
} }
if (!is_debug) if (!is_debug)
@ -518,7 +520,7 @@ static void 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; return FALSE;
} }
break; break;
case EXCEPTION_WINE_STUB: case EXCEPTION_WINE_STUB:
@ -547,354 +549,344 @@ static void DEBUG_HandleException(EXCEPTION_RECORD *rec, BOOL first_chance, BOOL
} }
} }
#if 0 if (local_mode == automatic_mode)
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)
{ {
DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode); DEBUG_ExceptionProlog(is_debug, FALSE, rec->ExceptionCode);
DEBUG_ExitMode = EXIT_QUIT; DEBUG_ExceptionEpilog();
return; /* terminate execution */ return TRUE; /* terminate execution */
} }
if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) { if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode))
DEBUG_interactiveP = TRUE; {
for (;;) DEBUG_InteractiveP = TRUE;
{ return TRUE;
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;
} }
DEBUG_ExceptionEpilog(); DEBUG_ExceptionEpilog();
#if 0 return FALSE;
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
} }
static void DEBUG_HandleDebugEvent(DEBUG_EVENT* de) static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de)
{ {
char buffer[256]; char buffer[256];
BOOL ret = FALSE;
DEBUG_CurrPid = de->dwProcessId; DEBUG_CurrPid = de->dwProcessId;
DEBUG_CurrTid = de->dwThreadId; DEBUG_CurrTid = de->dwThreadId;
DEBUG_ExitMode = EXIT_CONTINUE; if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL)
__TRY { DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId);
if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) else
DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId); DEBUG_CurrThread = NULL;
else
DEBUG_CurrThread = NULL;
switch (de->dwDebugEventCode) { switch (de->dwDebugEventCode)
case EXCEPTION_DEBUG_EVENT: {
if (!DEBUG_CurrThread) { case EXCEPTION_DEBUG_EVENT:
DEBUG_Printf(DBG_CHN_ERR, "%08lx:%08lx: not a registered process or thread (perhaps a 16 bit one ?)\n", if (!DEBUG_CurrThread)
de->dwProcessId, de->dwThreadId); {
break; 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", DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exception code=%08lx\n",
de->dwProcessId, de->dwThreadId, de->dwProcessId, de->dwThreadId,
de->u.Exception.ExceptionRecord.ExceptionCode); de->u.Exception.ExceptionRecord.ExceptionCode);
if (DEBUG_CurrProcess->continue_on_first_exception) { if (DEBUG_CurrProcess->continue_on_first_exception)
DEBUG_CurrProcess->continue_on_first_exception = FALSE; {
if (!DBG_IVAR(BreakOnAttach)) { DEBUG_CurrProcess->continue_on_first_exception = FALSE;
break; if (!DBG_IVAR(BreakOnAttach)) break;
} }
}
DEBUG_context.ContextFlags = CONTEXT_CONTROL DEBUG_context.ContextFlags = CONTEXT_CONTROL
| CONTEXT_INTEGER | CONTEXT_INTEGER
#ifdef CONTEXT_SEGMENTS #ifdef CONTEXT_SEGMENTS
| CONTEXT_SEGMENTS | CONTEXT_SEGMENTS
#endif #endif
#ifdef CONTEXT_DEBUG_REGISTERS #ifdef CONTEXT_DEBUG_REGISTERS
| CONTEXT_DEBUG_REGISTERS | CONTEXT_DEBUG_REGISTERS
#endif #endif
; ;
if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) { if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context))
DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n"); {
break; DEBUG_Printf(DBG_CHN_WARN, "Can't get thread's context\n");
} break;
}
DEBUG_HandleException(&de->u.Exception.ExceptionRecord, ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
de->u.Exception.dwFirstChance, de->u.Exception.dwFirstChance,
DEBUG_CurrThread->wait_for_first_exception); DEBUG_CurrThread->wait_for_first_exception);
if (DEBUG_CurrThread) { if (DEBUG_CurrThread)
DEBUG_CurrThread->wait_for_first_exception = 0; {
SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context); DEBUG_CurrThread->wait_for_first_exception = 0;
} SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
break; }
break;
case CREATE_THREAD_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId, DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread D @%08lx\n", de->dwProcessId, de->dwThreadId,
(unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress); (unsigned long)(LPVOID)de->u.CreateThread.lpStartAddress);
if (DEBUG_CurrProcess == NULL) { if (DEBUG_CurrProcess == NULL)
DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n"); {
break; 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"); if (DEBUG_GetThread(DEBUG_CurrProcess, de->dwThreadId) != NULL)
break; {
} DEBUG_Printf(DBG_CHN_TRACE, "Thread already listed, skipping\n");
break;
}
DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess, DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
de->dwThreadId, de->dwThreadId,
de->u.CreateThread.hThread, de->u.CreateThread.hThread,
de->u.CreateThread.lpStartAddress, de->u.CreateThread.lpStartAddress,
de->u.CreateThread.lpThreadLocalBase); de->u.CreateThread.lpThreadLocalBase);
if (!DEBUG_CurrThread) { if (!DEBUG_CurrThread)
DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n"); {
break; DEBUG_Printf(DBG_CHN_ERR, "Couldn't create thread\n");
} break;
DEBUG_InitCurrThread(); }
break; DEBUG_InitCurrThread();
break;
case CREATE_PROCESS_DEBUG_EVENT: case CREATE_PROCESS_DEBUG_EVENT:
DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer),
de->u.CreateProcessInfo.hProcess, de->u.CreateProcessInfo.hProcess,
de->u.CreateProcessInfo.lpImageName); de->u.CreateProcessInfo.lpImageName);
/* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */ /* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n", DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create process '%s'/%p @%08lx (%ld<%ld>)\n",
de->dwProcessId, de->dwThreadId, de->dwProcessId, de->dwThreadId,
buffer, de->u.CreateProcessInfo.lpImageName, buffer, de->u.CreateProcessInfo.lpImageName,
(unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress, (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress,
de->u.CreateProcessInfo.dwDebugInfoFileOffset, de->u.CreateProcessInfo.dwDebugInfoFileOffset,
de->u.CreateProcessInfo.nDebugInfoSize); de->u.CreateProcessInfo.nDebugInfoSize);
if ((DEBUG_CurrProcess = DEBUG_GetProcess(de->dwProcessId)) != NULL) { DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId,
if (DEBUG_CurrProcess->handle) { de->u.CreateProcessInfo.hProcess,
DEBUG_Printf(DBG_CHN_ERR, "Skipping already defined process\n"); buffer[0] ? buffer : "<Debugged Process>");
break; if (DEBUG_CurrProcess == NULL)
} {
DEBUG_CurrProcess->handle = de->u.CreateProcessInfo.hProcess; DEBUG_Printf(DBG_CHN_ERR, "Couldn't create process\n");
if (DEBUG_CurrProcess->imageName == NULL) break;
DEBUG_CurrProcess->imageName = DBG_strdup(buffer[0] ? buffer : "<Debugged Process>"); }
} else { DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n",
DEBUG_CurrProcess = DEBUG_AddProcess(de->dwProcessId, de->dwProcessId, de->dwThreadId,
de->u.CreateProcessInfo.hProcess, (unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress);
buffer[0] ? buffer : "<Debugged Process>");
if (DEBUG_CurrProcess == NULL) {
DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n");
break;
}
}
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: create thread I @%08lx\n", DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
de->dwProcessId, de->dwThreadId, de->dwThreadId,
(unsigned long)(LPVOID)de->u.CreateProcessInfo.lpStartAddress); 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, DEBUG_InitCurrProcess();
de->dwThreadId, DEBUG_InitCurrThread();
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_InitCurrProcess(); /* module is either PE, NE or ELF module (for WineLib), but all
DEBUG_InitCurrThread(); * are loaded with wine, so load its symbols, then the main module
*/
do
{
char* ptr = getenv("WINELOADER");
/* module is either PE, NE or ELF module (for WineLib), but all if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR)
* are loaded with wine, so load its symbols, then the main module DEBUG_ReadExecutableDbgInfo( "wine" );
*/ } while (0);
do
{
char* ptr = getenv("WINELOADER");
if (!ptr || DEBUG_ReadExecutableDbgInfo( ptr ) == DIL_ERROR) DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile,
DEBUG_ReadExecutableDbgInfo( "wine" ); (DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
} while (0);
DEBUG_LoadModule32(DEBUG_CurrProcess->imageName, de->u.CreateProcessInfo.hFile, break;
(DWORD)de->u.CreateProcessInfo.lpBaseOfImage);
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);
case EXIT_THREAD_DEBUG_EVENT: if (DEBUG_CurrThread == NULL)
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit thread (%ld)\n", {
de->dwProcessId, de->dwThreadId, de->u.ExitThread.dwExitCode); DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
break;
}
/* FIXME: remove break point set on thread startup */
DEBUG_DelThread(DEBUG_CurrThread);
break;
if (DEBUG_CurrThread == NULL) { case EXIT_PROCESS_DEBUG_EVENT:
DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n"); DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n",
break; de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode);
}
/* FIXME: remove break point set on thread startup */
DEBUG_DelThread(DEBUG_CurrThread);
break;
case EXIT_PROCESS_DEBUG_EVENT: if (DEBUG_CurrProcess == NULL)
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: exit process (%ld)\n", {
de->dwProcessId, de->dwThreadId, de->u.ExitProcess.dwExitCode); 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);
if (DEBUG_CurrProcess == NULL) { DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
DEBUG_Printf(DBG_CHN_ERR, "Unknown process\n"); break;
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); case LOAD_DLL_DEBUG_EVENT:
break; 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);
case LOAD_DLL_DEBUG_EVENT: /* FIXME unicode: de->u.LoadDll.fUnicode */
if (DEBUG_CurrThread == NULL) { DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n",
DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n"); de->dwProcessId, de->dwThreadId,
break; buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll,
} de->u.LoadDll.dwDebugInfoFileOffset,
DEBUG_ProcessGetStringIndirect(buffer, sizeof(buffer), de->u.LoadDll.nDebugInfoSize);
DEBUG_CurrThread->process->handle, _strupr(buffer);
de->u.LoadDll.lpImageName); 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);
ret = TRUE;
}
break;
/* FIXME unicode: de->u.LoadDll.fUnicode */ case UNLOAD_DLL_DEBUG_EVENT:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: loads DLL %s @%08lx (%ld<%ld>)\n", DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId,
de->dwProcessId, de->dwThreadId, (unsigned long)de->u.UnloadDll.lpBaseOfDll);
buffer, (unsigned long)de->u.LoadDll.lpBaseOfDll, break;
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;
case UNLOAD_DLL_DEBUG_EVENT: case OUTPUT_DEBUG_STRING_EVENT:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unload DLL @%08lx\n", de->dwProcessId, de->dwThreadId, if (DEBUG_CurrThread == NULL)
(unsigned long)de->u.UnloadDll.lpBaseOfDll); {
break; DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n");
break;
}
case OUTPUT_DEBUG_STRING_EVENT: DEBUG_ProcessGetString(buffer, sizeof(buffer),
if (DEBUG_CurrThread == NULL) { DEBUG_CurrThread->process->handle,
DEBUG_Printf(DBG_CHN_ERR, "Unknown thread\n"); de->u.DebugString.lpDebugStringData);
break;
}
DEBUG_ProcessGetString(buffer, sizeof(buffer), /* FIXME unicode de->u.DebugString.fUnicode ? */
DEBUG_CurrThread->process->handle, DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n",
de->u.DebugString.lpDebugStringData); de->dwProcessId, de->dwThreadId, buffer);
break;
/* FIXME unicode de->u.DebugString.fUnicode ? */ case RIP_EVENT:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: output debug string (%s)\n", DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n",
de->dwProcessId, de->dwThreadId, buffer); de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError,
break; de->u.RipInfo.dwType);
break;
case RIP_EVENT: default:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: rip error=%ld type=%ld\n", DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n",
de->dwProcessId, de->dwThreadId, de->u.RipInfo.dwError, de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
de->u.RipInfo.dwType);
break;
default:
DEBUG_Printf(DBG_CHN_TRACE, "%08lx:%08lx: unknown event (%ld)\n",
de->dwProcessId, de->dwThreadId, de->dwDebugEventCode);
}
} __EXCEPT(wine_dbg) {
DEBUG_ExitMode = EXIT_CONTINUE;
} }
__ENDTRY;
return ret;
}
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);
}
void DEBUG_WaitNextException(DWORD cont, int count, int mode)
{
DEBUG_EVENT de;
if (cont == DBG_CONTINUE)
{
DEBUG_CurrThread->exec_count = count;
DEBUG_CurrThread->exec_mode = mode;
}
DEBUG_ResumeDebuggee(cont);
while (DEBUG_CurrProcess && WaitForDebugEvent(&de, INFINITE))
{
if (DEBUG_HandleDebugEvent(&de)) break;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
}
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) static DWORD DEBUG_MainLoop(void)
{ {
DEBUG_EVENT de; DEBUG_EVENT de;
DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid); DEBUG_Printf(DBG_CHN_MESG, "WineDbg starting on pid %lx\n", DEBUG_CurrPid);
while (DEBUG_ExitMode == EXIT_CONTINUE) /* wait for first exception */
while (WaitForDebugEvent(&de, INFINITE))
{ {
/* wait until we get at least one loaded process */ if (DEBUG_HandleDebugEvent(&de)) break;
while (!DEBUG_ProcessList) ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
{ }
DEBUG_Parser(); if (local_mode == automatic_mode)
if (DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_QUIT) break; {
} /* print some extra information */
if (DEBUG_ExitMode != EXIT_CONTINUE) break; DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
DEBUG_WalkModules();
while ((DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_PASS) && DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
DEBUG_ProcessList && DEBUG_WalkThreads();
WaitForDebugEvent(&de, INFINITE)) }
{ else
DEBUG_HandleDebugEvent(&de); {
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DEBUG_InteractiveP = TRUE;
(DEBUG_ExitMode == EXIT_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE); DEBUG_Parser();
}
if (DEBUG_ExitMode == EXIT_DETACH && DEBUG_Detach())
{
/* 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_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid); DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
return 0; return 0;
} }
static DWORD DEBUG_AutoMode(void)
{
DEBUG_EVENT de;
DEBUG_Printf(DBG_CHN_MESG, " on pid %lx\n", DEBUG_CurrPid);
while ((DEBUG_ExitMode == EXIT_CONTINUE || DEBUG_ExitMode == EXIT_PASS) &&
DEBUG_ProcessList &&
WaitForDebugEvent(&de, INFINITE))
{
DEBUG_HandleDebugEvent(&de);
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
(DEBUG_ExitMode == EXIT_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE);
}
/* print some extra information */
DEBUG_Printf(DBG_CHN_MESG, "Modules:\n");
DEBUG_WalkModules();
DEBUG_Printf(DBG_CHN_MESG, "Threads:\n");
DEBUG_WalkThreads();
DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %lx\n", DEBUG_CurrPid);
return 0;
}
static BOOL DEBUG_Start(LPSTR cmdLine) static BOOL DEBUG_Start(LPSTR cmdLine)
{ {
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
@ -905,8 +897,13 @@ static BOOL DEBUG_Start(LPSTR cmdLine)
startup.dwFlags = STARTF_USESHOWWINDOW; startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = SW_SHOWNORMAL; 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, 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); DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
return FALSE; return FALSE;
} }
@ -980,13 +977,16 @@ static void DEBUG_InitConsole(void)
SetConsoleCtrlHandler(DEBUG_CtrlCHandler, TRUE); 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) int main(int argc, char** argv)
{ {
DWORD retv = 0; DWORD retv = 0;
unsigned gdb_flags = 0;
/* Initialize the type handling stuff. */
DEBUG_InitTypes();
DEBUG_InitCVDataTypes();
/* Initialize internal vars (types must have been initialized before) */ /* Initialize internal vars (types must have been initialized before) */
if (!DEBUG_IntVarsRW(TRUE)) return -1; if (!DEBUG_IntVarsRW(TRUE)) return -1;
@ -996,14 +996,33 @@ int main(int argc, char** argv)
{ {
if (!strcmp( argv[1], "--auto" )) if (!strcmp( argv[1], "--auto" ))
{ {
automatic_mode = 1; if (local_mode != none_mode) return DEBUG_Usage();
local_mode = automatic_mode;
/* force some internal variables */ /* force some internal variables */
DBG_IVAR(UseXTerm) = 0; DBG_IVAR(UseXTerm) = 0;
DBG_IVAR(BreakOnDllLoad) = 0; DBG_IVAR(BreakOnDllLoad) = 0;
DBG_IVAR(ConChannelMask) = 0; DBG_IVAR(ConChannelMask) = 0;
DBG_IVAR(StdChannelMask) = DBG_CHN_MESG; DBG_IVAR(StdChannelMask) = DBG_CHN_MESG;
argc--; argc--; argv++;
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; continue;
} }
if (!strcmp( argv[1], "--debugmsg" ) && argv[2]) if (!strcmp( argv[1], "--debugmsg" ) && argv[2])
@ -1013,25 +1032,40 @@ int main(int argc, char** argv)
argv += 2; argv += 2;
continue; continue;
} }
DEBUG_Printf(DBG_CHN_MESG, "Usage: winedbg [--debugmsg dbgoptions] [--auto] cmdline\n" ); return DEBUG_Usage();
return 1;
} }
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;
if (argc == 3) { DEBUG_CurrPid = strtol(argv[1], &ptr, 10);
if (DEBUG_CurrPid == 0 || ptr == NULL ||
!DEBUG_Attach(DEBUG_CurrPid, local_mode != gdb_mode))
DEBUG_CurrPid = 0;
}
/* try the from <myself> pid evt (Win32 JIT debugger) */
if (DEBUG_CurrPid == 0 && argc == 3)
{
HANDLE hEvent; HANDLE hEvent;
DWORD pid; DWORD pid;
char* ptr;
if ((pid = atoi(argv[1])) != 0 && (hEvent = (HANDLE)atoi(argv[2])) != 0) { if ((pid = strtol(argv[1], &ptr, 10)) != 0 && ptr != NULL &&
if (!DEBUG_Attach(pid, TRUE)) { (hEvent = (HANDLE)strtol(argv[2], &ptr, 10)) != 0 && ptr != NULL)
{
if (!DEBUG_Attach(pid, TRUE))
{
/* don't care about result */ /* don't care about result */
SetEvent(hEvent); SetEvent(hEvent);
goto leave; goto leave;
} }
if (!SetEvent(hEvent)) { if (!SetEvent(hEvent))
{
DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent); DEBUG_Printf(DBG_CHN_ERR, "Invalid event handle: %p\n", hEvent);
goto leave; goto leave;
} }
@ -1040,14 +1074,16 @@ int main(int argc, char** argv)
} }
} }
if (DEBUG_CurrPid == 0 && argc > 1) { if (DEBUG_CurrPid == 0 && argc > 1)
{
int i, len; int i, len;
LPSTR cmdLine; LPSTR cmdLine;
if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave; if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
cmdLine[0] = '\0'; cmdLine[0] = '\0';
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++)
{
len += strlen(argv[i]) + 1; len += strlen(argv[i]) + 1;
if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave; if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
strcat(cmdLine, argv[i]); strcat(cmdLine, argv[i]);
@ -1055,25 +1091,29 @@ int main(int argc, char** argv)
cmdLine[len - 1] = '\0'; cmdLine[len - 1] = '\0';
} }
if (!DEBUG_Start(cmdLine)) { if (!DEBUG_Start(cmdLine))
{
DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine); DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
goto leave; goto leave;
} }
DBG_free(DEBUG_LastCmdLine); DBG_free(DEBUG_LastCmdLine);
DEBUG_LastCmdLine = cmdLine; DEBUG_LastCmdLine = cmdLine;
} }
/* don't save local vars in gdb mode */
#if 0
if (local_mode == gdb_mode && DEBUG_CurrPid)
return DEBUG_GdbRemote(gdb_flags);
#endif
if (automatic_mode) /* Initialize the type handling stuff. */
{ DEBUG_InitTypes();
retv = DEBUG_AutoMode(); DEBUG_InitCVDataTypes();
/* don't save modified variables in auto mode */
} DEBUG_InitConsole();
else
{ retv = DEBUG_MainLoop();
retv = DEBUG_MainLoop(); /* don't save modified variables in auto mode */
/* saves modified variables */ if (local_mode != automatic_mode) DEBUG_IntVarsRW(FALSE);
DEBUG_IntVarsRW(FALSE);
}
leave: leave:
return retv; return retv;