- cleaned-up break handling
- better integration of debugger inner loops (parser & events)
- added attach command
- improved parser so that it can be entered without any process loaded
- added BreakOnFirstChance internal variable
- disabled NE module symbol module (which is broken with ASS)
- misc portability cleanups
diff --git a/debugger/break.c b/debugger/break.c
index 7c00b59..2a1e4e9 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -369,6 +369,47 @@
DEBUG_Printf( DBG_CHN_MESG, "\n" );
}
+/***********************************************************************
+ * DEBUG_AddBreakpointFromId
+ *
+ * Add a breakpoint from a function name (and eventually a line #)
+ */
+void DEBUG_AddBreakpointFromId(const char *name, int lineno)
+{
+ DBG_VALUE value;
+
+ if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE))
+ DEBUG_AddBreakpoint(&value, NULL);
+ else
+ DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint\n");
+}
+
+/***********************************************************************
+ * DEBUG_AddBreakpointFromLineno
+ *
+ * Add a breakpoint from a line number in current file
+ */
+void DEBUG_AddBreakpointFromLineno(int lineno)
+{
+ DBG_VALUE value;
+
+ DEBUG_GetCurrentAddress(&value.addr);
+
+ if (lineno != -1) {
+ struct name_hash* nh;
+
+ DEBUG_FindNearestSymbol(&value.addr, TRUE, &nh, 0, NULL);
+ if (nh == NULL) {
+ DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
+ return;
+ }
+ DEBUG_GetLineNumberAddr(nh, lineno, &value.addr, TRUE);
+ }
+
+ value.type = NULL;
+ value.cookie = DV_TARGET;
+ DEBUG_AddBreakpoint( &value, NULL );
+}
/***********************************************************************
* DEBUG_AddWatchpoint
@@ -439,6 +480,21 @@
}
/***********************************************************************
+ * DEBUG_AddWathpointFromId
+ *
+ * Add a watchpoint from a symbol name (and eventually a line #)
+ */
+void DEBUG_AddWatchpointFromId(const char *name, int lineno)
+{
+ DBG_VALUE value;
+
+ if( DEBUG_GetSymbolValue(name, lineno, &value, TRUE) )
+ DEBUG_AddWatchpoint( &value, 1 );
+ else
+ DEBUG_Printf(DBG_CHN_MESG, "Unable to add watchpoint\n");
+}
+
+/***********************************************************************
* DEBUG_DelBreakpoint
*
* Delete a breakpoint.
@@ -921,8 +977,6 @@
DEBUG_context.EFlags |= STEP_FLAG;
#endif
break;
- case EXEC_KILL:
- break;
default:
RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
}
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 7d1fdde..4d93dda 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -21,7 +21,6 @@
#include "task.h"
extern FILE * yyin;
-int curr_frame = 0;
static void issue_prompt(void);
static void mode_command(int);
@@ -37,20 +36,19 @@
int integer;
struct list_id listing;
struct expr * expression;
- struct datatype * type;
+ struct datatype* type;
}
%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
%token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT
%token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
-%token tPROCESS tTHREAD tMODREF
-%token tEOL tSTRING tDEBUGSTR
+%token tPROCESS tTHREAD tMODREF tEOL
%token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS
%token <string> tPATH
%token <string> tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
%token <integer> tNUM tFORMAT
-%token tSYMBOLFILE
+%token tSYMBOLFILE tRUN tATTACH tNOPROCESS
%token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED
%token tSTRUCT tUNION tENUM
@@ -84,67 +82,67 @@
%%
-input: line { issue_prompt(); }
- | input line { issue_prompt(); }
+input: line { issue_prompt(); }
+ | input line { issue_prompt(); }
line: command
| tEOL
- | error tEOL { yyerrok; }
+ | error tEOL { yyerrok; }
command:
- tQUIT tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_KILL; return 1; }
- | 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 0; }
- | tPASS tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return 0; }
- | tCONT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; }
- | tSTEP tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
- | tNEXT tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
- | tSTEP tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
- | tNEXT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
- | tSTEPI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
- | tNEXTI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
- | tSTEPI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
- | tNEXTI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
- DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
- | tABORT tEOL { kill(getpid(), SIGABRT); }
- | tMODE tNUM tEOL { mode_command($2); }
- | tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); }
- | tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); }
- | tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); }
- | tBACKTRACE tEOL { DEBUG_BackTrace(TRUE); }
- | tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); }
- | tUP tNUM tEOL { DEBUG_SetFrame( curr_frame + $2 ); }
- | tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); }
- | 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 0; }
- | tSHOW tDIR tEOL { DEBUG_ShowDir(); }
- | tDIR pathname tEOL { DEBUG_AddPath( $2 ); }
- | tDIR tEOL { DEBUG_NukePath(); }
- | tDISPLAY tEOL { DEBUG_InfoDisplay(); }
- | tDISPLAY expr tEOL { DEBUG_AddDisplay($2, 1, 0); }
- | tDISPLAY tFORMAT expr tEOL { DEBUG_AddDisplay($3, $2 >> 8, $2 & 0xff); }
- | tDELETE tDISPLAY tNUM tEOL { DEBUG_DelDisplay( $3 ); }
- | tDELETE tDISPLAY tEOL { DEBUG_DelDisplay( -1 ); }
- | tUNDISPLAY tNUM tEOL { DEBUG_DelDisplay( $2 ); }
- | tUNDISPLAY tEOL { DEBUG_DelDisplay( -1 ); }
- | tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); }
- | tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); }
- | tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); }
- | tWHATIS expr_addr tEOL { DEBUG_PrintType(&$2); DEBUG_FreeExprMem(); }
+ tQUIT tEOL { return FALSE; }
+ | 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; }
+ | tPASS tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return TRUE; }
+ | tCONT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return TRUE; }
+ | tSTEP tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return TRUE; }
+ | tNEXT tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return TRUE; }
+ | tSTEP tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return TRUE; }
+ | tNEXT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return TRUE; }
+ | tSTEPI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return TRUE; }
+ | tNEXTI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return TRUE; }
+ | tSTEPI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return TRUE; }
+ | tNEXTI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
+ DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return TRUE; }
+ | tABORT tEOL { kill(getpid(), SIGABRT); }
+ | tMODE tNUM tEOL { mode_command($2); }
+ | tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); }
+ | tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); }
+ | tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); }
+ | tBACKTRACE tEOL { DEBUG_BackTrace(TRUE); }
+ | tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); }
+ | tUP tNUM tEOL { DEBUG_SetFrame( curr_frame + $2 ); }
+ | tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); }
+ | 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; }
+ | tSHOW tDIR tEOL { DEBUG_ShowDir(); }
+ | tDIR pathname tEOL { DEBUG_AddPath( $2 ); }
+ | tDIR tEOL { DEBUG_NukePath(); }
+ | tDISPLAY tEOL { DEBUG_InfoDisplay(); }
+ | tDISPLAY expr tEOL { DEBUG_AddDisplay($2, 1, 0); }
+ | tDISPLAY tFORMAT expr tEOL{ DEBUG_AddDisplay($3, $2 >> 8, $2 & 0xff); }
+ | tDELETE tDISPLAY tNUM tEOL{ DEBUG_DelDisplay( $3 ); }
+ | tDELETE tDISPLAY tEOL { DEBUG_DelDisplay( -1 ); }
+ | tUNDISPLAY tNUM tEOL { DEBUG_DelDisplay( $2 ); }
+ | tUNDISPLAY tEOL { DEBUG_DelDisplay( -1 ); }
+ | tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); }
+ | 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 { DEBUG_Attach($2, FALSE); return TRUE; }
| list_command
| disassemble_command
| set_command
@@ -154,6 +152,8 @@
| watch_command
| info_command
| walk_command
+ | run_command
+ | noprocess_state
set_command:
tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory( &$2, $4 );
@@ -180,83 +180,33 @@
| pathname ':' tNUM { $$.sourcefile = $1; $$.line = $3; }
| tIDENTIFIER { DEBUG_GetFuncInfo( & $$, NULL, $1); }
| pathname ':' tIDENTIFIER { DEBUG_GetFuncInfo( & $$, $1, $3); }
- | '*' expr_addr { DEBUG_FindNearestSymbol( & $2.addr, FALSE, NULL,
- 0, & $$ );
- DEBUG_FreeExprMem(); }
+ | '*' expr_addr { DEBUG_FindNearestSymbol( & $2.addr, FALSE, NULL, 0, & $$ );
+ DEBUG_FreeExprMem(); }
x_command:
- tEXAM expr_addr tEOL { DEBUG_ExamineMemory( &$2, 1, 'x');
- DEBUG_FreeExprMem(); }
+ tEXAM expr_addr tEOL { DEBUG_ExamineMemory( &$2, 1, 'x'); DEBUG_FreeExprMem(); }
| tEXAM tFORMAT expr_addr tEOL { DEBUG_ExamineMemory( &$3, $2>>8, $2&0xff );
- DEBUG_FreeExprMem(); }
+ DEBUG_FreeExprMem(); }
print_command:
- tPRINT expr_addr tEOL { DEBUG_Print( &$2, 1, 0, 0 );
- DEBUG_FreeExprMem(); }
+ tPRINT expr_addr tEOL { DEBUG_Print( &$2, 1, 0, 0 ); DEBUG_FreeExprMem(); }
| tPRINT tFORMAT expr_addr tEOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff, 0 );
- DEBUG_FreeExprMem(); }
+ DEBUG_FreeExprMem(); }
break_command:
- tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3, NULL );
- DEBUG_FreeExprMem(); }
- | tBREAK tIDENTIFIER tEOL { DBG_VALUE value;
- if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
- {
- DEBUG_AddBreakpoint( &value, NULL );
- }
- else
- {
- DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
- }
- }
- | tBREAK tIDENTIFIER ':' tNUM tEOL { DBG_VALUE value;
- if( DEBUG_GetSymbolValue($2, $4, &value, TRUE) )
- {
- DEBUG_AddBreakpoint( &value, NULL );
- }
- else
- {
- DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
- }
- }
- | tBREAK tNUM tEOL { struct name_hash *nh;
- DBG_VALUE value;
- DEBUG_GetCurrentAddress( &value.addr );
- DEBUG_FindNearestSymbol(&value.addr, TRUE,
- &nh, 0, NULL);
- if( nh != NULL )
- {
- DEBUG_GetLineNumberAddr(nh, $2, &value.addr, TRUE);
- value.type = NULL;
- value.cookie = DV_TARGET;
- DEBUG_AddBreakpoint( &value, NULL );
- }
- else
- {
- DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
- }
- }
-
- | tBREAK tEOL { DBG_VALUE value;
- DEBUG_GetCurrentAddress( &value.addr );
- value.type = NULL;
- value.cookie = DV_TARGET;
- DEBUG_AddBreakpoint( &value, NULL );
- }
+ tBREAK '*' expr_addr tEOL{ DEBUG_AddBreakpoint( &$3, NULL ); DEBUG_FreeExprMem(); }
+ | tBREAK tIDENTIFIER tEOL { DEBUG_AddBreakpointFromId($2, -1); }
+ | tBREAK tIDENTIFIER ':' tNUM tEOL { DEBUG_AddBreakpointFromId($2, $4); }
+ | tBREAK tNUM tEOL { DEBUG_AddBreakpointFromLineno($2); }
+ | tBREAK tEOL { DEBUG_AddBreakpointFromLineno(-1); }
watch_command:
- tWATCH '*' expr_addr tEOL { DEBUG_AddWatchpoint( &$3, 1 );
- DEBUG_FreeExprMem(); }
- | tWATCH tIDENTIFIER tEOL { DBG_VALUE value;
- if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
- DEBUG_AddWatchpoint( &value, 1 );
- else
- DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
- }
+ tWATCH '*' expr_addr tEOL { DEBUG_AddWatchpoint( &$3, 1 ); DEBUG_FreeExprMem(); }
+ | tWATCH tIDENTIFIER tEOL { DEBUG_AddWatchpointFromId($2, -1); }
info_command:
tINFO tBREAK tEOL { DEBUG_InfoBreakpoints(); }
- | tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); }
+ | tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); }
| tINFO tSHARE tEOL { DEBUG_InfoShare(); }
| tINFO tMODULE expr_value tEOL { DEBUG_DumpModule( $3 ); DEBUG_FreeExprMem(); }
| tINFO tQUEUE expr_value tEOL { DEBUG_DumpQueue( $3 ); DEBUG_FreeExprMem(); }
@@ -265,8 +215,7 @@
| tINFO tSEGMENTS tEOL { DEBUG_InfoSegments( 0, -1 ); }
| tINFO tSTACK tEOL { DEBUG_InfoStack(); }
| tINFO tMAPS tEOL { DEBUG_InfoVirtual(); }
- | tINFO tWND expr_value tEOL { DEBUG_InfoWindow( (HWND)$3 );
- DEBUG_FreeExprMem(); }
+ | tINFO tWND expr_value tEOL{ DEBUG_InfoWindow( (HWND)$3 ); DEBUG_FreeExprMem(); }
| tINFO tLOCAL tEOL { DEBUG_InfoLocals(); }
| tINFO tDISPLAY tEOL { DEBUG_InfoDisplay(); }
@@ -278,8 +227,15 @@
| tWALK tWND tNUM tEOL { DEBUG_WalkWindows( $3, 0 ); }
| tWALK tPROCESS tEOL { DEBUG_WalkProcess(); }
| tWALK tTHREAD tEOL { DEBUG_WalkThreads(); }
- | tWALK tMODREF expr_value tEOL { DEBUG_WalkModref( $3 ); }
+ | tWALK tMODREF expr_value tEOL { DEBUG_WalkModref( $3 ); DEBUG_FreeExprMem(); }
+run_command:
+ tRUN tEOL { DEBUG_Run(NULL); }
+ | tRUN tSTRING tEOL { DEBUG_Run($2); }
+
+noprocess_state:
+ tNOPROCESS tEOL {} /* <CR> shall not barf anything */
+ | tNOPROCESS tSTRING tEOL { DEBUG_Printf(DBG_CHN_MESG, "No process loaded, cannot execute '%s'\n", $2); }
type_cast:
'(' type_expr ')' { $$ = $2; }
@@ -292,7 +248,7 @@
| tUNSIGNED tINT { $$ = DEBUG_TypeCast(DT_BASIC, "unsigned int"); }
| tLONG tUNSIGNED tINT { $$ = DEBUG_TypeCast(DT_BASIC, "long unsigned int"); }
| tLONG tLONG tINT { $$ = DEBUG_TypeCast(DT_BASIC, "long long int"); }
- | tLONG tLONG tUNSIGNED tINT { $$ = DEBUG_TypeCast(DT_BASIC, "long long unsigned int"); }
+ | tLONG tLONG tUNSIGNED tINT{ $$ = DEBUG_TypeCast(DT_BASIC, "long long unsigned int"); }
| tSHORT tINT { $$ = DEBUG_TypeCast(DT_BASIC, "short int"); }
| tSHORT tUNSIGNED tINT { $$ = DEBUG_TypeCast(DT_BASIC, "short unsigned int"); }
| tSIGNED tCHAR { $$ = DEBUG_TypeCast(DT_BASIC, "signed char"); }
@@ -424,136 +380,41 @@
}
/***********************************************************************
- * DEBUG_Main
+ * DEBUG_Parser
*
- * Debugger main loop.
+ * Debugger editline parser
*/
-BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code )
+BOOL DEBUG_Parser(void)
{
- int newmode;
- BOOL ret_ok;
- char ch;
-
+ BOOL ret_ok;
+ BOOL ret = TRUE;
#ifdef YYDEBUG
yydebug = 0;
#endif
-
yyin = stdin;
- DEBUG_SuspendExecution();
-
- if (!is_debug)
- {
-#ifdef __i386__
- if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs))
- DEBUG_Printf( DBG_CHN_MESG, " in 32-bit code (0x%08lx).\n", DEBUG_context.Eip );
- else
- DEBUG_Printf( DBG_CHN_MESG, " in 16-bit code (%04x:%04lx).\n",
- (WORD)DEBUG_context.SegCs, DEBUG_context.Eip );
-#else
- DEBUG_Printf( DBG_CHN_MESG, " (0x%08lx).\n", GET_IP(&DEBUG_context) );
-#endif
- }
-
- DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
-
- if (force || !(is_debug && DEBUG_ShouldContinue( code,
- DEBUG_CurrThread->dbg_exec_mode,
- &DEBUG_CurrThread->dbg_exec_count )))
- {
- DBG_ADDR addr;
- DEBUG_GetCurrentAddress( &addr );
-
-#ifdef __i386__
- switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
- case 16: case 32: break;
- default: DEBUG_Printf(DBG_CHN_MESG, "Bad CS (%ld)\n", addr.seg); newmode = 32;
- }
-#else
- newmode = 32;
-#endif
- if (newmode != DEBUG_CurrThread->dbg_mode)
- DEBUG_Printf(DBG_CHN_MESG,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode);
-
- DEBUG_DoDisplay();
-
- if (is_debug || force)
- {
- /*
- * Do a quiet backtrace so that we have an idea of what the situation
- * is WRT the source files.
- */
- DEBUG_BackTrace(FALSE);
- }
- else
- {
- /* This is a real crash, dump some info */
- DEBUG_InfoRegisters();
- DEBUG_InfoStack();
-#ifdef __i386__
- if (DEBUG_CurrThread->dbg_mode == 16)
- {
- DEBUG_InfoSegments( DEBUG_context.SegDs >> 3, 1 );
- if (DEBUG_context.SegEs != DEBUG_context.SegDs)
- DEBUG_InfoSegments( DEBUG_context.SegEs >> 3, 1 );
- }
- DEBUG_InfoSegments( DEBUG_context.SegFs >> 3, 1 );
-#endif
- DEBUG_BackTrace(TRUE);
- }
-
- if (!is_debug ||
- (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
- (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR))
- {
- /* Show where we crashed */
- curr_frame = 0;
- DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
- DEBUG_Printf(DBG_CHN_MESG,": ");
- DEBUG_Disasm( &addr, TRUE );
- DEBUG_Printf( DBG_CHN_MESG, "\n" );
- }
-
- ret_ok = 0;
- do
- {
- __TRY
- {
- issue_prompt();
- if (yyparse()) {
- DEBUG_CurrThread->dbg_exec_mode = EXEC_KILL;
- ret_ok = TRUE;
- } else {
- flush_symbols();
-
- DEBUG_GetCurrentAddress( &addr );
- ret_ok = DEBUG_ValidateRegisters() &&
- DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(&addr), &ch, 1);
- }
- }
- __EXCEPT(wine_dbg_cmd)
- {
- ret_ok = FALSE;
- }
- __ENDTRY;
-
- } while (!ret_ok);
- }
-
- DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution( DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count );
- /*
- * This will have gotten absorbed into the breakpoint info
- * if it was used. Otherwise it would have been ignored.
- * In any case, we don't mess with it any more.
- */
- if (DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT || DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)
- DEBUG_CurrThread->dbg_exec_count = 0;
-
- return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+ ret_ok = FALSE;
+ do {
+ __TRY {
+ issue_prompt();
+ if ((ret = yyparse())) {
+ DEBUG_FlushSymbols();
+
+ ret_ok = (DEBUG_CurrThread) ? DEBUG_ValidateRegisters() : TRUE;
+ } else {
+ ret_ok = TRUE;
+ }
+ } __EXCEPT(wine_dbg_cmd) {
+ ret_ok = FALSE;
+ }
+ __ENDTRY;
+
+ } while (!ret_ok);
+ return ret;
}
int yyerror(char* s)
{
- DEBUG_Printf(DBG_CHN_MESG,"%s\n", s);
+ DEBUG_Printf(DBG_CHN_MESG, "%s\n", s);
return 0;
}
diff --git a/debugger/debug.l b/debugger/debug.l
index 0adf93c..cb8dc64 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -2,6 +2,7 @@
* Lexical scanner for command line parsing
*
* Copyright 1993 Eric Youngdale
+ * 2000 Eric Pouech
*/
%{
@@ -10,12 +11,6 @@
#include "debugger.h"
#include "y.tab.h"
-#ifdef DBG_need_heap
-#define malloc(x) DBG_alloc(x)
-#define realloc(x,y) DBG_realloc(x,y)
-#define free(x) DBG_free(x)
-#endif
-
#ifndef DONT_USE_READLINE
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
@@ -23,7 +18,7 @@
YY_FATAL_ERROR( "read() in flex scanner failed" );
static int dbg_read(char * buf, int size);
-static char * make_symbol(char *);
+static char * DEBUG_MakeSymbol(char *);
#endif /* DONT_USE_READLINE */
@@ -47,40 +42,42 @@
%s WALK_CMD
%s SHOW_CMD
%s NOCMD
-%s DEBUGSTR
+%x ASTRING_EXPECTED
+%x NOPROCESS
%%
+ /* set to special state when no process is loaded. */
+ if (!DEBUG_CurrProcess && YYSTATE == INITIAL) {BEGIN(NOPROCESS);}
-\n { BEGIN(0); syntax_error = 0;
- return tEOL; } /*Indicates end of command. Reset state. */
+<*>\n { BEGIN(INITIAL); syntax_error = 0; return tEOL; }
+ /* Indicates end of command. Reset state. */
-"||" { return OP_LOR; }
-"&&" { return OP_LAND; }
-"==" { return OP_EQ; }
-"!=" { return OP_NE; }
-"<=" { return OP_LE; }
-">=" { return OP_GE; }
-"<<" { return OP_SHL; }
-">>" { return OP_SHR; }
-"->" { return OP_DRF; }
-[-+<=>|&^()*/%:!~,\.] { return *yytext; }
-"[" { return *yytext; }
-"]" { return *yytext; }
+"||" { return OP_LOR; }
+"&&" { return OP_LAND; }
+"==" { return OP_EQ; }
+"!=" { return OP_NE; }
+"<=" { return OP_LE; }
+">=" { return OP_GE; }
+"<<" { return OP_SHL; }
+">>" { return OP_SHR; }
+"->" { return OP_DRF; }
+[-+<=>|&^()*/%:!~,\.] { return *yytext; }
+"[" { return *yytext; }
+"]" { return *yytext; }
-"0x"{HEXDIGIT}+ { sscanf(yytext, "%x", &yylval.integer); return tNUM; }
-{DIGIT}+ { sscanf(yytext, "%d", &yylval.integer); return tNUM; }
+"0x"{HEXDIGIT}+ { sscanf(yytext, "%x", &yylval.integer); return tNUM; }
+{DIGIT}+ { sscanf(yytext, "%d", &yylval.integer); return tNUM; }
+<FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT} { char* last;
+ yylval.integer = strtol( yytext+1, &last, NULL ) << 8;
+ yylval.integer |= *last;
+ return tFORMAT; }
-<FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT} { char * last;
- yylval.integer = strtol( yytext+1, &last, NULL );
- yylval.integer = (yylval.integer << 8) | *last;
- return tFORMAT; }
+<FORMAT_EXPECTED>"/"{FORMAT} { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
-
-<FORMAT_EXPECTED>"/"{FORMAT} { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
-
-{STRING} { yylval.string = make_symbol(yytext); return tSTRING; }
-<DEBUGSTR>[a-z+\-,]* { yylval.string = yytext; return tDEBUGSTR; }
+{STRING} { yylval.string = DEBUG_MakeSymbol(yytext); return tSTRING; }
+<ASTRING_EXPECTED>[^\n]+ { char* p = yytext; while (*p == ' ' || *p == '\t') p++;
+ yylval.string = DEBUG_MakeSymbol(p); return tSTRING; }
<INITIAL>info|inf|in { BEGIN(INFO_CMD); return tINFO; }
<INITIAL>up { BEGIN(NOCMD); return tUP; }
@@ -93,9 +90,9 @@
<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; }
<INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und { BEGIN(NOCMD); return tUNDISPLAY; }
<INITIAL>delete|delet|dele|del { BEGIN(DEL_CMD); return tDELETE; }
-<INITIAL>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; }
+<INITIAL,NOPROCESS>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; }
<INITIAL>set|se { BEGIN(NOCMD); return tSET; }
-<INITIAL>walk|w { BEGIN(WALK_CMD); return tWALK; }
+<INITIAL,NOPROCESS>walk|w { BEGIN(WALK_CMD); return tWALK; }
<INITIAL>x { BEGIN(FORMAT_EXPECTED); return tEXAM; }
<INITIAL>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; }
@@ -121,11 +118,12 @@
<INITIAL,INFO_CMD,DEL_CMD>break|brea|bre|br|b { BEGIN(PATH_EXPECTED); return tBREAK; }
<INITIAL>watch|watc|wat { BEGIN(PATH_EXPECTED); return tWATCH; }
<INITIAL>whatis|whati|what { BEGIN(PATH_EXPECTED); return tWHATIS; }
-
+<INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;}
+<NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; }
<INFO_CMD>share|shar|sha { return tSHARE; }
<INFO_CMD>locals|local|loca|loc { return tLOCAL; }
<INFO_CMD,WALK_CMD>class|clas|cla { return tCLASS; }
-<INFO_CMD,WALK_CMD>module|modul|modu|mod { return tMODULE; }
+<INFO_CMD,WALK_CMD>module|modul|modu|mod { return tMODULE; }
<INFO_CMD,WALK_CMD>queue|queu|que { return tQUEUE; }
<INFO_CMD,WALK_CMD>process|proces|proce|proc { return tPROCESS; }
<INFO_CMD,WALK_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
@@ -138,7 +136,7 @@
<HELP_CMD>info|inf|in { return tINFO; }
<INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir {
- BEGIN(PATH_EXPECTED); return tDIR; }
+ BEGIN(PATH_EXPECTED); return tDIR; }
char { return tCHAR; }
short { return tSHORT; }
@@ -152,20 +150,18 @@
union { return tUNION; }
enum { return tENUM; }
-{IDENTIFIER} { yylval.string = make_symbol(yytext); return tIDENTIFIER; }
-"$"{IDENTIFIER} { yylval.string = make_symbol(yytext+1); return tINTVAR; }
+{IDENTIFIER} { yylval.string = DEBUG_MakeSymbol(yytext); return tIDENTIFIER; }
+"$"{IDENTIFIER} { yylval.string = DEBUG_MakeSymbol(yytext+1); return tINTVAR; }
-<PATH_EXPECTED>{PATHNAME} { yylval.string = make_symbol(yytext); return tPATH; }
+<PATH_EXPECTED>{PATHNAME} { yylval.string = DEBUG_MakeSymbol(yytext); return tPATH; }
-[ \t]+ /* Eat up whitespace */
+<*>[ \t]+ /* Eat up whitespace */
-. { if (syntax_error == 0)
- {
- syntax_error ++; DEBUG_Printf(DBG_CHN_MESG, "Syntax Error\n");
- }
- }
-
-
+<NOPROCESS>. { BEGIN(ASTRING_EXPECTED); yyless(0); return tNOPROCESS;}
+<*>. { if (syntax_error == 0) {
+ syntax_error++;
+ DEBUG_Printf(DBG_CHN_MESG, "Syntax Error (%s)\n", yytext); }
+ }
%%
#ifndef yywrap
@@ -206,7 +202,7 @@
for (;;)
{
- flush_symbols();
+ DEBUG_FlushSymbols();
line = readline ("Wine-dbg>");
if (!line)
{
@@ -226,7 +222,7 @@
add_history( line );
strncpy( last_line, line, 255 );
last_line[255] = '\0';
- }
+ }
free( line );
line = last_line;
@@ -249,14 +245,15 @@
static char *local_symbols[30];
static int next_symbol;
-static char * make_symbol(char * symbol)
+static char * DEBUG_MakeSymbol(char * symbol)
{
- return local_symbols[next_symbol++] = DBG_strdup(symbol);
+ assert(0 <= next_symbol && next_symbol < (sizeof(local_symbols) / sizeof(local_symbols[0])));
+ return local_symbols[next_symbol++] = DBG_strdup(symbol);
}
-void flush_symbols(void)
+void DEBUG_FlushSymbols(void)
{
- while(--next_symbol>= 0) DBG_free(local_symbols[next_symbol]);
+ while(--next_symbol >= 0) DBG_free(local_symbols[next_symbol]);
next_symbol = 0;
}
diff --git a/debugger/debugger.h b/debugger/debugger.h
index 3514380..4ee5935 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -112,7 +112,6 @@
* and set breakpoint there - not at the
* instr just after the call.
*/
- EXEC_KILL /* terminate debugging session */
};
#define DBG_BREAK 0
@@ -224,24 +223,16 @@
#define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
-
-
-#ifdef __i386__
-# define GET_IP(context) ((DWORD)(context)->Eip)
-#endif
-#ifdef __sparc__
-# define GET_IP(context) ((DWORD)(context)->pc)
-#endif
-
-#if !defined(GET_IP)
-# error You must define GET_IP for this CPU
-#endif
-
+ /* from winelib.so */
+extern void DEBUG_ExternalDebugger(void);
/* debugger/break.c */
extern void DEBUG_SetBreakpoints( BOOL set );
extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void) );
+extern void DEBUG_AddBreakpointFromId( const char *name, int lineno );
+extern void DEBUG_AddBreakpointFromLineno( int lineno );
extern void DEBUG_AddWatchpoint( const DBG_VALUE *addr, int is_write );
+extern void DEBUG_AddWatchpointFromId( const char *name, int lineno );
extern void DEBUG_DelBreakpoint( int num );
extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
extern void DEBUG_InfoBreakpoints(void);
@@ -250,17 +241,17 @@
extern void DEBUG_SuspendExecution( void );
extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
extern BOOL DEBUG_IsFctReturn(void);
-extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
+extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
/* debugger/db_disasm.c */
extern void DEBUG_Disasm( DBG_ADDR *addr, int display );
/* debugger/dbg.y */
-extern BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code );
+extern BOOL DEBUG_Parser(void);
extern void DEBUG_Exit( DWORD );
/* debugger/debug.l */
-extern void flush_symbols(void);
+extern void DEBUG_FlushSymbols(void);
/* debugger/display.c */
extern int DEBUG_DoDisplay(void);
@@ -294,9 +285,6 @@
extern int DEBUG_FreeExpr(struct expr * exp);
extern int DEBUG_DisplayExpr(const struct expr * exp);
- /* debugger/external.c */
-extern void DEBUG_ExternalDebugger(void);
-
/* debugger/hash.c */
extern struct name_hash * DEBUG_AddSymbol( const char *name,
const DBG_VALUE *addr,
@@ -378,6 +366,7 @@
void* mod_addr, HMODULE hmod);
extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type);
extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type);
+extern DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process);
extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name);
extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name);
extern void DEBUG_InfoShare(void);
@@ -456,8 +445,11 @@
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 void DEBUG_Run(const char* args);
+extern int curr_frame;
- /* Choose your allocator! */
+/* Choose your allocator! */
#if 1
/* this one is libc's fast one */
extern void* DEBUG_XMalloc(size_t size);
diff --git a/debugger/intvar.h b/debugger/intvar.h
index 27675b0..ac30a56 100644
--- a/debugger/intvar.h
+++ b/debugger/intvar.h
@@ -9,6 +9,7 @@
INTERNAL_VAR(BreakAllThreadsStartup, FALSE, NULL, DEBUG_TypeIntConst)
INTERNAL_VAR(BreakOnCritSectTimeOut, FALSE, NULL, DEBUG_TypeIntConst)
INTERNAL_VAR(BreakOnAttach, FALSE, NULL, DEBUG_TypeIntConst)
+INTERNAL_VAR(BreakOnFirstChance, TRUE, NULL, DEBUG_TypeIntConst)
/* output handling */
INTERNAL_VAR(ConChannelMask, DBG_CHN_MESG, NULL, DEBUG_TypeIntConst)
diff --git a/debugger/memory.c b/debugger/memory.c
index d1feb93..455e94e 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -117,9 +117,11 @@
if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg))
addr->seg = 0;
addr->off = DEBUG_context.Eip;
+#elif defined(__sparc__)
+ addr->seg = 0;
+ addr->off = DEBUG_context.pc;
#else
- addr->seg = 0;
- addr->off = GET_IP( &DEBUG_context );
+# error You must define GET_IP for this CPU
#endif
}
diff --git a/debugger/module.c b/debugger/module.c
index 5ab651a..011cc75 100644
--- a/debugger/module.c
+++ b/debugger/module.c
@@ -92,6 +92,21 @@
}
/***********************************************************************
+ * DEBUG_GetProcessMainModule
+ */
+DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
+{
+ DBG_MODULE* wmod;
+
+ if (!process) return NULL;
+
+ /* main module is the first to be loaded on a given process, so it's the last on
+ * the list */
+ for (wmod = process->modules; wmod && wmod->next; wmod = wmod->next);
+ return wmod;
+}
+
+/***********************************************************************
* DEBUG_RegisterELFModule
*
* ELF modules are also entered into the list - this is so that we
@@ -139,6 +154,7 @@
return wmod;
}
+#if 0
/***********************************************************************
* DEBUG_GetEP16
*
@@ -230,6 +246,7 @@
}
GlobalUnlock16(module->nrname_handle);
}
+#endif
/***********************************************************************
* DEBUG_LoadModule32
@@ -355,10 +372,14 @@
*/
int DEBUG_LoadEntryPoints(const char* pfx)
{
+ int first = 0;
+ /* FIXME: with address space separation in space, this is plain wrong
+ * it requires the 16 bit WOW debugging interface...
+ */
+#if 0
MODULEENTRY entry;
NE_MODULE module;
void* moduleAddr;
- int first = 0;
int rowcount = 0;
int len;
@@ -390,6 +411,7 @@
DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
} while (ModuleNext16(&entry));
+#endif
if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
return first;
diff --git a/debugger/registers.c b/debugger/registers.c
index 4dde821..4ff5952 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -121,6 +121,9 @@
*/
BOOL DEBUG_ValidateRegisters(void)
{
+ DBG_ADDR addr;
+ char ch;
+
#ifdef __i386__
if (DEBUG_context.EFlags & V86_FLAG) return TRUE;
@@ -157,9 +160,13 @@
(WORD)DEBUG_context.SegSs );
return FALSE;
}
- return TRUE;
+
#undef CHECK_SEG
#else
- return TRUE;
+ /* to be written */
#endif
+
+ /* check if PC is correct */
+ DEBUG_GetCurrentAddress(&addr);
+ return DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(&addr), &ch, 1);
}
diff --git a/debugger/stack.c b/debugger/stack.c
index 36ed896..8e4c99f 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -30,7 +30,6 @@
static int nframe;
static struct bt_info * frames = NULL;
-int curr_frame;
typedef struct
{
diff --git a/debugger/types.c b/debugger/types.c
index cab945b..65cee4a 100644
--- a/debugger/types.c
+++ b/debugger/types.c
@@ -897,7 +897,11 @@
}
}
break;
+ case DT_FUNC:
+ DEBUG_Printf(DBG_CHN_MESG, "Function at ???\n");
+ break;
default:
+ DEBUG_Printf(DBG_CHN_MESG, "Unknown type (%d)\n", value->type->type);
assert(FALSE);
break;
}
diff --git a/debugger/winedbg.c b/debugger/winedbg.c
index e459456..bf4d344 100644
--- a/debugger/winedbg.c
+++ b/debugger/winedbg.c
@@ -28,6 +28,8 @@
DWORD DEBUG_CurrTid;
DWORD DEBUG_CurrPid;
CONTEXT DEBUG_context;
+int curr_frame = 0;
+static char* DEBUG_LastCmdLine = NULL;
static DBG_PROCESS* proc = NULL;
DBG_INTVAR DEBUG_IntVars[DBG_IV_LAST];
@@ -164,6 +166,7 @@
if (p->prev) p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
if (p == proc) proc = p->next;
+ if (p == DEBUG_CurrProcess) DEBUG_CurrProcess = NULL;
DBG_free(p);
}
@@ -253,17 +256,120 @@
if (t->next) t->next->prev = t->prev;
if (t == t->process->threads) t->process->threads = t->next;
t->process->num_threads--;
+ if (t == DEBUG_CurrThread) DEBUG_CurrThread = NULL;
DBG_free(t);
}
-static BOOL DEBUG_HandleException( EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force )
+BOOL DEBUG_Attach(DWORD pid, BOOL cofe)
+{
+ if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0))) return FALSE;
+
+ if (!DebugActiveProcess(pid)) {
+ DEBUG_Printf(DBG_CHN_ERR, "Can't attach process %ld: %ld\n",
+ pid, GetLastError());
+ return FALSE;
+ }
+ DEBUG_CurrProcess->continue_on_first_exception = cofe;
+ return TRUE;
+}
+
+static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
+{
+ DBG_ADDR addr;
+ int newmode;
+
+ DEBUG_GetCurrentAddress(&addr);
+ DEBUG_SuspendExecution();
+
+ if (!is_debug) {
+#ifdef __i386__
+ if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs))
+ DEBUG_Printf(DBG_CHN_MESG, " in 32-bit code (0x%08lx).\n", addr.off);
+ else
+ DEBUG_Printf(DBG_CHN_MESG, " in 16-bit code (%04x:%04lx).\n",
+ LOWORD(addr.seg), addr.off);
+#else
+ DEBUG_Printf(DBG_CHN_MESG, " (0x%08lx).\n", addr.off);
+#endif
+ }
+
+ DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
+
+ if (!force && is_debug &&
+ DEBUG_ShouldContinue(code,
+ DEBUG_CurrThread->dbg_exec_mode,
+ &DEBUG_CurrThread->dbg_exec_count))
+ return FALSE;
+
+#ifdef __i386__
+ switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
+ case 16: case 32: break;
+ default: DEBUG_Printf(DBG_CHN_MESG, "Bad CS (%ld)\n", addr.seg); newmode = 32;
+ }
+#else
+ newmode = 32;
+#endif
+ if (newmode != DEBUG_CurrThread->dbg_mode)
+ DEBUG_Printf(DBG_CHN_MESG,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode);
+
+ DEBUG_DoDisplay();
+
+ if (is_debug || force) {
+ /*
+ * Do a quiet backtrace so that we have an idea of what the situation
+ * is WRT the source files.
+ */
+ DEBUG_BackTrace(FALSE);
+ } else {
+ /* This is a real crash, dump some info */
+ DEBUG_InfoRegisters();
+ DEBUG_InfoStack();
+#ifdef __i386__
+ if (DEBUG_CurrThread->dbg_mode == 16) {
+ DEBUG_InfoSegments(DEBUG_context.SegDs >> 3, 1);
+ if (DEBUG_context.SegEs != DEBUG_context.SegDs)
+ DEBUG_InfoSegments(DEBUG_context.SegEs >> 3, 1);
+ }
+ DEBUG_InfoSegments(DEBUG_context.SegFs >> 3, 1);
+#endif
+ DEBUG_BackTrace(TRUE);
+ }
+
+ if (!is_debug ||
+ (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
+ (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR)) {
+ /* Show where we crashed */
+ curr_frame = 0;
+ DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
+ DEBUG_Printf(DBG_CHN_MESG,": ");
+ DEBUG_Disasm( &addr, TRUE );
+ DEBUG_Printf( DBG_CHN_MESG, "\n" );
+ }
+ return TRUE;
+}
+
+static DWORD DEBUG_ExceptionEpilog(void)
+{
+ DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution(DEBUG_CurrThread->dbg_exec_mode,
+ DEBUG_CurrThread->dbg_exec_count);
+ /*
+ * This will have gotten absorbed into the breakpoint info
+ * if it was used. Otherwise it would have been ignored.
+ * In any case, we don't mess with it any more.
+ */
+ if (DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT || DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)
+ DEBUG_CurrThread->dbg_exec_count = 0;
+
+ 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)
{
BOOL is_debug = FALSE;
- BOOL ret;
+ BOOL ret = TRUE;
- /* FIXME: need for a configuration var ? */
- /* pass to app first ??? */
- /* if (first_chance && !force) return 0; */
+ *cont = DBG_CONTINUE;
+ if (first_chance && !force && !DBG_IVAR(BreakOnFirstChance)) return TRUE;
switch (rec->ExceptionCode)
{
@@ -276,50 +382,50 @@
if (!is_debug)
{
/* print some infos */
- DEBUG_Printf( DBG_CHN_MESG, "%s: ",
- first_chance ? "First chance exception" : "Unhandled exception" );
+ DEBUG_Printf(DBG_CHN_MESG, "%s: ",
+ first_chance ? "First chance exception" : "Unhandled exception");
switch (rec->ExceptionCode)
{
case EXCEPTION_INT_DIVIDE_BY_ZERO:
- DEBUG_Printf( DBG_CHN_MESG, "divide by zero" );
+ DEBUG_Printf(DBG_CHN_MESG, "divide by zero");
break;
case EXCEPTION_INT_OVERFLOW:
- DEBUG_Printf( DBG_CHN_MESG, "overflow" );
+ DEBUG_Printf(DBG_CHN_MESG, "overflow");
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- DEBUG_Printf( DBG_CHN_MESG, "array bounds " );
+ DEBUG_Printf(DBG_CHN_MESG, "array bounds ");
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
- DEBUG_Printf( DBG_CHN_MESG, "illegal instruction" );
+ DEBUG_Printf(DBG_CHN_MESG, "illegal instruction");
break;
case EXCEPTION_STACK_OVERFLOW:
- DEBUG_Printf( DBG_CHN_MESG, "stack overflow" );
+ DEBUG_Printf(DBG_CHN_MESG, "stack overflow");
break;
case EXCEPTION_PRIV_INSTRUCTION:
- DEBUG_Printf( DBG_CHN_MESG, "priviledged instruction" );
+ DEBUG_Printf(DBG_CHN_MESG, "priviledged instruction");
break;
case EXCEPTION_ACCESS_VIOLATION:
if (rec->NumberParameters == 2)
- DEBUG_Printf( DBG_CHN_MESG, "page fault on %s access to 0x%08lx",
+ DEBUG_Printf(DBG_CHN_MESG, "page fault on %s access to 0x%08lx",
rec->ExceptionInformation[0] ? "write" : "read",
- rec->ExceptionInformation[1] );
+ rec->ExceptionInformation[1]);
else
- DEBUG_Printf( DBG_CHN_MESG, "page fault" );
+ DEBUG_Printf(DBG_CHN_MESG, "page fault");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
- DEBUG_Printf( DBG_CHN_MESG, "Alignment" );
+ DEBUG_Printf(DBG_CHN_MESG, "Alignment");
break;
case CONTROL_C_EXIT:
- DEBUG_Printf( DBG_CHN_MESG, "^C" );
+ DEBUG_Printf(DBG_CHN_MESG, "^C");
break;
case EXCEPTION_CRITICAL_SECTION_WAIT:
- DEBUG_Printf( DBG_CHN_MESG, "critical section %08lx wait failed",
- rec->ExceptionInformation[0] );
+ DEBUG_Printf(DBG_CHN_MESG, "critical section %08lx wait failed",
+ rec->ExceptionInformation[0]);
if (!DBG_IVAR(BreakOnCritSectTimeOut))
- return DBG_CONTINUE;
+ return TRUE;
break;
default:
- DEBUG_Printf( DBG_CHN_MESG, "%08lx", rec->ExceptionCode );
+ DEBUG_Printf(DBG_CHN_MESG, "%08lx", rec->ExceptionCode);
break;
}
DEBUG_Printf(DBG_CHN_MESG, "\n");
@@ -334,7 +440,15 @@
#endif
DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
- ret = DEBUG_Main( is_debug, force, rec->ExceptionCode );
+ if (DEBUG_ExceptionProlog(is_debug, force, rec->ExceptionCode)) {
+ for (;;) {
+ ret = DEBUG_Parser();
+ if (!ret || DEBUG_CurrThread->dbg_exec_mode != EXEC_PASS || first_chance)
+ break;
+ DEBUG_Printf(DBG_CHN_MESG, "Cannot pass on last chance exception. You must use cont\n");
+ }
+ }
+ *cont = DEBUG_ExceptionEpilog();
DEBUG_Printf(DBG_CHN_TRACE,
"Exiting debugger PC=%lx EFL=%08lx mode=%d count=%d\n",
@@ -352,7 +466,7 @@
{
char buffer[256];
BOOL ret;
-
+
DEBUG_CurrPid = de->dwProcessId;
DEBUG_CurrTid = de->dwThreadId;
@@ -400,12 +514,11 @@
break;
}
- *cont = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
- de->u.Exception.dwFirstChance,
- DEBUG_CurrThread->wait_for_first_exception);
- if (DEBUG_CurrThread->dbg_exec_mode == EXEC_KILL) {
- ret = FALSE;
- } else {
+ ret = DEBUG_HandleException(&de->u.Exception.ExceptionRecord,
+ de->u.Exception.dwFirstChance,
+ DEBUG_CurrThread->wait_for_first_exception,
+ cont);
+ if (DEBUG_CurrThread) {
DEBUG_CurrThread->wait_for_first_exception = 0;
SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
}
@@ -533,7 +646,8 @@
/* kill last thread */
DEBUG_DelThread(DEBUG_CurrProcess->threads);
DEBUG_DelProcess(DEBUG_CurrProcess);
- ret = FALSE;
+
+ DEBUG_Printf(DBG_CHN_MESG, "Process of pid=%08lx has terminated\n", DEBUG_CurrPid);
break;
case LOAD_DLL_DEBUG_EVENT:
@@ -591,31 +705,73 @@
ret = TRUE;
}
__ENDTRY;
-
return ret;
}
-static DWORD DEBUG_MainLoop(DWORD pid)
+static DWORD DEBUG_MainLoop(void)
{
DEBUG_EVENT de;
DWORD cont;
- BOOL ret = TRUE;
+ BOOL ret;
- DEBUG_Printf(DBG_CHN_MESG, " on pid %ld\n", pid);
+ DEBUG_Printf(DBG_CHN_MESG, " on pid %ld\n", DEBUG_CurrPid);
- while (ret && WaitForDebugEvent(&de, INFINITE)) {
- ret = DEBUG_HandleDebugEvent(&de, &cont);
- ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
- }
+ for (ret = TRUE; ret; ) {
+ /* wait until we get at least one loaded process */
+ while (!proc && (ret = DEBUG_Parser()));
+ if (!ret) break;
+
+ while (ret && WaitForDebugEvent(&de, INFINITE)) {
+ ret = DEBUG_HandleDebugEvent(&de, &cont);
+ ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
+ }
+ };
- DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %ld\n", pid);
+ DEBUG_Printf(DBG_CHN_MESG, "WineDbg terminated on pid %ld\n", DEBUG_CurrPid);
return 0;
}
+static BOOL DEBUG_Start(LPSTR cmdLine)
+{
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+
+ if (!CreateProcess(NULL, cmdLine, NULL, NULL,
+ FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info)) {
+ DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
+ return FALSE;
+ }
+ DEBUG_CurrPid = info.dwProcessId;
+ if (!(DEBUG_CurrProcess = DEBUG_AddProcess(DEBUG_CurrPid, 0))) return FALSE;
+
+ return TRUE;
+}
+
+void DEBUG_Run(const char* args)
+{
+ DBG_MODULE* wmod = DEBUG_GetProcessMainModule(DEBUG_CurrProcess);
+ const char* pgm = (wmod) ? wmod->module_name : "none";
+
+ if (args) {
+ DEBUG_Printf(DBG_CHN_MESG, "Run (%s) with '%s'\n", pgm, args);
+ } else {
+ if (!DEBUG_LastCmdLine) {
+ DEBUG_Printf(DBG_CHN_MESG, "Cannot find previously used command line.\n");
+ return;
+ }
+ DEBUG_Start(DEBUG_LastCmdLine);
+ }
+}
+
int DEBUG_main(int argc, char** argv)
{
- DWORD pid = 0, retv = 0;
+ DWORD retv = 0;
#ifdef DBG_need_heap
/* Initialize the debugger heap. */
@@ -641,66 +797,55 @@
}
DEBUG_Printf(DBG_CHN_MESG, "Starting WineDbg... ");
+
if (argc == 3) {
HANDLE hEvent;
+ DWORD pid;
if ((pid = atoi(argv[1])) != 0 && (hEvent = atoi(argv[2])) != 0) {
- if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0))) goto leave;
- DEBUG_CurrProcess->continue_on_first_exception = TRUE;
+ BOOL ret = DEBUG_Attach(pid, TRUE);
- if (!DebugActiveProcess(pid)) {
- DEBUG_Printf(DBG_CHN_ERR, "Can't attach process %ld: %ld\n",
- pid, GetLastError());
- SetEvent(hEvent);
- goto leave;
- }
SetEvent(hEvent);
- } else {
- pid = 0;
- }
- }
- if (argc == 1) {
- LPSTR org, ptr;
-
- DEBUG_Printf(DBG_CHN_MESG, "\n");
- DEBUG_WalkProcess();
- pid = strtol(org = readline("Enter pid to debug: "), &ptr, 0);
- if (pid && ptr && ptr != org && *ptr == '\0') {
- if (!(DEBUG_CurrProcess = DEBUG_AddProcess(pid, 0))) goto leave;
-
- if (!DebugActiveProcess(pid)) {
+ if (!ret) {
DEBUG_Printf(DBG_CHN_ERR, "Can't attach process %ld: %ld\n",
- pid, GetLastError());
+ DEBUG_CurrPid, GetLastError());
goto leave;
}
- } else {
- pid = 0;
+ DEBUG_CurrPid = pid;
}
}
- if (pid == 0) {
- PROCESS_INFORMATION info;
- STARTUPINFOA startup;
+ if (DEBUG_CurrPid == 0 && argc > 1) {
+ int i, len;
+ LPSTR cmdLine;
+
+ if (!(cmdLine = DBG_alloc(len = 1))) goto oom_leave;
+ cmdLine[0] = '\0';
- memset(&startup, 0, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_SHOWNORMAL;
+ for (i = 1; i < argc; i++) {
+ len += strlen(argv[i]) + 1;
+ if (!(cmdLine = DBG_realloc(cmdLine, len))) goto oom_leave;
+ strcat(cmdLine, argv[i]);
+ cmdLine[len - 2] = ' ';
+ cmdLine[len - 1] = '\0';
+ }
- if (!CreateProcess(NULL, argv[1], NULL, NULL,
- FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info)) {
- DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", argv[1]);
+ if (!DEBUG_Start(cmdLine)) {
+ DEBUG_Printf(DBG_CHN_MESG, "Couldn't start process '%s'\n", cmdLine);
goto leave;
}
- pid = info.dwProcessId;
+ DBG_free(DEBUG_LastCmdLine);
+ DEBUG_LastCmdLine = cmdLine;
}
- if (pid) retv = DEBUG_MainLoop(pid);
+ retv = DEBUG_MainLoop();
leave:
/* saves modified variables */
DEBUG_IntVarsRW(FALSE);
return retv;
+
+ oom_leave:
+ DEBUG_Printf(DBG_CHN_MESG, "Out of memory\n");
+ goto leave;
}
-
-