Objet : winedbg improvement - display I've just hacked winedbg 'display' handling. It now allows for temporary disabling of displays and restricting them to one function. Look for yourselves, comments welcome. :)
since I'm away from home on a poor remote connection, I couldn't spend much time on this
from a first look, enable/disable facility is fine
but, here are, at least, two remarks : - first, I don't think we should have two ways of expressing the same thing (like disable display 1 and display disable 1). IMO, we should stick the former form (as we currently do) (I agree that current undisplay 1 and delete display 1 are may be a bit overkill too) - secondly, and most important, I don't like storing the frame context in the display information. I don't see how you're going to ensure that we got a correct context for evaluating an expression. Keeping the local frame name isn't even sufficient when calling the same function recursively. What I'm afraid of here is the user's perception of this specific context for evaluation. I know gdb has some of those tricks (i.e. that no one, except the one who wrote the code, is going to understand what context is going to be used for evaluating the expression). I really wonder what gdb does here.
A+
Thanks for answering,
On Wed, Apr 16, 2003 at 09:18:04PM +0200, Pouech Eric DMI AEI CAEN wrote:
but, here are, at least, two remarks :
- first, I don't think we should have two ways of expressing the same thing (like disable display 1 and display disable 1). IMO, we should stick the former form (as we currently do) (I agree that current undisplay 1 and delete display 1 are may be a bit overkill too)
I've changed display commands as you suggested. I've also made 'break' parts after 'enable', 'disable' and 'delete' optional as it is in gdb.
- secondly, and most important, I don't like storing the frame context in the display information. I don't see how you're going to ensure that we got a correct context for evaluating an expression. Keeping the local frame name isn't even sufficient when calling the same function recursively. What I'm afraid of here is the user's perception of this specific context for evaluation. I know gdb has some of those tricks (i.e. that no one, except the one who wrote the code, is going to understand what context is going to be used for evaluating the expression). I really wonder what gdb does here.
Well, to be clear, my intent was to allow displays to be bound to one function: when you step out of it, or step into another function, the 'local' displays disappear, and when you happen to get back to the function again - you have them intact. I think it works somewhat like that in DDD for displaying local variables. In recursive calls you will see expressions evaluated in currently selected stack frame ('up'/'down' should set apropriate context for display/print/list/disassemble. Though I haven't looked into it, yet.).
I s/frame/function/'d the display structure to be less confusing.
Second version appended.
-- Michal Miroslaw
Index: programs/winedbg/Makefile.in =================================================================== RCS file: /home/wine/wine/programs/winedbg/Makefile.in,v retrieving revision 1.2 diff -u -r1.2 Makefile.in --- programs/winedbg/Makefile.in 15 Dec 2002 01:19:53 -0000 1.2 +++ programs/winedbg/Makefile.in 16 Apr 2003 21:46:27 -0000 @@ -31,6 +31,8 @@
@MAKE_PROG_RULES@
+DEFS += -DYYERROR_VERBOSE + y.tab.c y.tab.h: dbg.y $(YACC) -d -t $(SRCDIR)/dbg.y
Index: programs/winedbg/dbg.y =================================================================== RCS file: /home/wine/wine/programs/winedbg/dbg.y,v retrieving revision 1.9 diff -u -r1.9 dbg.y --- programs/winedbg/dbg.y 1 Apr 2003 00:12:50 -0000 1.9 +++ programs/winedbg/dbg.y 16 Apr 2003 21:46:28 -0000 @@ -52,8 +52,6 @@
%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN %token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT tVM86 -%token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tSYMBOL tREGS tWND tLOCAL tEXCEPTION -%token tPROCESS tTHREAD tEOL tEOF %token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tSYMBOL tREGS tWND tQUEUE tLOCAL tEXCEPTION %token tPROCESS tTHREAD tMODREF tEOL tEOF %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE @@ -124,9 +122,6 @@ | tABORT tEOL { abort(); } | tMODE tNUM tEOL { mode_command($2); } | tMODE tVM86 tEOL { DEBUG_CurrThread->dbg_mode = MODE_VM86; } - | 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(DEBUG_CurrTid, TRUE); } | tBACKTRACE tNUM tEOL { DEBUG_BackTrace($2, TRUE); } | tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); } @@ -137,13 +132,6 @@ | 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); } | tSOURCE pathname tEOL { DEBUG_Parser($2); } @@ -157,7 +145,8 @@ | set_command | x_command | print_command - | break_command + | break_commands + | display_commands | watch_command | info_command | walk_command @@ -165,6 +154,20 @@ | noprocess_state ;
+display_commands: + | tDISPLAY tEOL { DEBUG_InfoDisplay(); } + | tDISPLAY expr tEOL { DEBUG_AddDisplay($2, 1, 0, FALSE); } + | tDISPLAY tFORMAT expr tEOL{ DEBUG_AddDisplay($3, $2 >> 8, $2 & 0xff, FALSE); } + | tLOCAL tDISPLAY expr tEOL { DEBUG_AddDisplay($3, 1, 0, TRUE); } + | tLOCAL tDISPLAY tFORMAT expr tEOL { DEBUG_AddDisplay($4, $3 >> 8, $3 & 0xff, TRUE); } + | tENABLE tDISPLAY tNUM tEOL{ DEBUG_EnableDisplay( $3, TRUE ); } + | tDISABLE tDISPLAY tNUM tEOL { DEBUG_EnableDisplay( $3, FALSE ); } + | tDELETE tDISPLAY tNUM tEOL{ DEBUG_DelDisplay( $3 ); } + | tDELETE tDISPLAY tEOL { DEBUG_DelDisplay( -1 ); } + | tUNDISPLAY tNUM tEOL { DEBUG_DelDisplay( $2 ); } + | tUNDISPLAY tEOL { DEBUG_DelDisplay( -1 ); } + ; + set_command: tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory(&$2, $4); } | tSET '+' tIDENTIFIER tEOL { DEBUG_DbgChannel(TRUE, NULL, $3); } @@ -210,12 +213,18 @@ | tPRINT tFORMAT expr_addr tEOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff, 0 ); } ;
-break_command: +break_commands: tBREAK '*' expr_addr tEOL{ DEBUG_AddBreakpointFromValue( &$3 ); } | tBREAK identifier tEOL { DEBUG_AddBreakpointFromId($2, -1); } | tBREAK identifier ':' tNUM tEOL { DEBUG_AddBreakpointFromId($2, $4); } | tBREAK tNUM tEOL { DEBUG_AddBreakpointFromLineno($2); } | tBREAK tEOL { DEBUG_AddBreakpointFromLineno(-1); } + | tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); } + | tENABLE tBREAK tNUM tEOL { DEBUG_EnableBreakpoint( $3, TRUE ); } + | tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); } + | tDISABLE tBREAK tNUM tEOL { DEBUG_EnableBreakpoint( $3, FALSE ); } + | tDELETE tNUM tEOL { DEBUG_DelBreakpoint( $2 ); } + | tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); } ;
watch_command: Index: programs/winedbg/debug.l =================================================================== RCS file: /home/wine/wine/programs/winedbg/debug.l,v retrieving revision 1.3 diff -u -r1.3 debug.l --- programs/winedbg/debug.l 30 Jan 2003 00:24:18 -0000 1.3 +++ programs/winedbg/debug.l 16 Apr 2003 21:46:28 -0000 @@ -54,7 +54,8 @@ %s PATH_EXPECTED %s INFO_CMD %s HELP_CMD -%s DEL_CMD +%s BD_CMD +%s LOCAL_CMD %s WALK_CMD %s SHOW_CMD %s MODE_CMD @@ -102,12 +103,14 @@ <INITIAL>down|dow|do { BEGIN(NOCMD); return tDOWN; } <INITIAL>frame|fram|fra|fr { BEGIN(NOCMD); return tFRAME; } <INITIAL>list|lis|li|l { BEGIN(PATH_EXPECTED); return tLIST; } -<INITIAL>enable|enabl|enab|ena { BEGIN(NOCMD); return tENABLE;} -<INITIAL>disable|disabl|disab|disa|dis { BEGIN(NOCMD); return tDISABLE; } +<INITIAL>enable|enabl|enab|ena { BEGIN(BD_CMD); return tENABLE;} +<INITIAL>disable|disabl|disab|disa|dis { BEGIN(BD_CMD); return tDISABLE; } <INITIAL>disassemble|disassembl|disassemb|disassem|disasse|disass|disas { BEGIN(NOCMD); return tDISASSEMBLE; } -<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; } +<INITIAL>locally|local { BEGIN(LOCAL_CMD); return tLOCAL; } +<INITIAL,LOCAL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; } +<INFO_CMD,BD_CMD>display|displa|displ|disp|dis|di|d { BEGIN(NOCMD); 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>delete|delet|dele|del { BEGIN(BD_CMD); return tDELETE; } <INITIAL,NOPROCESS>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; } <INITIAL>set|se { BEGIN(NOCMD); return tSET; } <INITIAL,NOPROCESS>walk|w { BEGIN(WALK_CMD); return tWALK; } @@ -134,7 +137,7 @@ <INITIAL,NOPROCESS>source|sourc|sour|src { BEGIN(PATH_EXPECTED); return tSOURCE; } <INITIAL>symbolfile|symbols|symbol|sf { BEGIN(PATH_EXPECTED); return tSYMBOLFILE; }
-<INITIAL,INFO_CMD,DEL_CMD>break|brea|bre|br|b { BEGIN(NOCMD); return tBREAK; } +<INITIAL,INFO_CMD,BD_CMD>break|brea|bre|br|b { BEGIN(NOCMD); return tBREAK; } <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;} Index: programs/winedbg/debugger.h =================================================================== RCS file: /home/wine/wine/programs/winedbg/debugger.h,v retrieving revision 1.9 diff -u -r1.9 debugger.h --- programs/winedbg/debugger.h 1 Apr 2003 00:02:36 -0000 1.9 +++ programs/winedbg/debugger.h 16 Apr 2003 21:46:29 -0000 @@ -327,10 +327,11 @@ extern int DEBUG_ReadLine(const char* pfx, char* buffer, int size);
/* debugger/display.c */ -extern int DEBUG_DoDisplay(void); -extern int DEBUG_AddDisplay(struct expr * exp, int count, char format); -extern int DEBUG_DelDisplay(int displaynum); -extern int DEBUG_InfoDisplay(void); +int DEBUG_DoDisplay(void); +int DEBUG_AddDisplay(struct expr * exp, int count, char format, int local_frame); +int DEBUG_DelDisplay(int displaynum); +int DEBUG_InfoDisplay(void); +int DEBUG_EnableDisplay(int displaynum, int enable);
/* debugger/expr.c */ extern void DEBUG_FreeExprMem(void); @@ -386,6 +387,7 @@ struct datatype * type); extern BOOL DEBUG_Normalize(struct name_hash * nh ); void DEBUG_InfoSymbols(const char* str); +const char *DEBUG_GetSymbolName(const struct name_hash *);
/* debugger/info.c */ extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format ); Index: programs/winedbg/display.c =================================================================== RCS file: /home/wine/wine/programs/winedbg/display.c,v retrieving revision 1.1 diff -u -r1.1 display.c --- programs/winedbg/display.c 13 Sep 2002 17:54:28 -0000 1.1 +++ programs/winedbg/display.c 16 Apr 2003 21:46:29 -0000 @@ -2,6 +2,7 @@ * File display.c - display handling for Wine internal debugger. * * Copyright (C) 1997, Eric Youngdale. + * Improved a bit by Michał Mirosław. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,130 +28,172 @@
#include <stdarg.h>
-#define MAX_DISPLAY 25 +#define DISPTAB_DELTA 8 /* needs to be power of 2, search for MARK to see why :) */
-struct display -{ - struct expr * exp; - int count; - char format; +struct display { + struct expr *exp; + int count; + char format; + char enabled; + struct name_hash *function_name; };
-static struct display displaypoints[MAX_DISPLAY]; +static struct display *displaypoints = NULL; +static unsigned int maxdisplays = 0, ndisplays = 0;
-int -DEBUG_AddDisplay(struct expr * exp, int count, char format) +static struct name_hash *DEBUG_GetCurrentFrameFunctionName(void) { - int i; + struct name_hash *name; + unsigned int eip, ebp;
- /* - * First find a slot where we can store this display. - */ - for(i=0; i < MAX_DISPLAY; i++ ) - { - if( displaypoints[i].exp == NULL ) - { - displaypoints[i].exp = DEBUG_CloneExpr(exp); - displaypoints[i].count = count; - displaypoints[i].format = format; - break; - } - } - - return TRUE; -} - -int -DEBUG_InfoDisplay(void) -{ - int i; - - /* - * First find a slot where we can store this display. - */ - for(i=0; i < MAX_DISPLAY; i++ ) - { - if( displaypoints[i].exp != NULL ) - { - DEBUG_Printf(DBG_CHN_MESG, "%d : ", i+1); - DEBUG_DisplayExpr(displaypoints[i].exp); - DEBUG_Printf(DBG_CHN_MESG, "\n"); - } - } - - return TRUE; -} - -int -DEBUG_DoDisplay(void) -{ - DBG_VALUE value; - int i; - - /* - * First find a slot where we can store this display. - */ - for(i=0; i < MAX_DISPLAY; i++ ) - { - if( displaypoints[i].exp != NULL ) - { - value = DEBUG_EvalExpr(displaypoints[i].exp); - if( value.type == NULL ) - { - DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression "); - DEBUG_DisplayExpr(displaypoints[i].exp); - DEBUG_Printf(DBG_CHN_MESG, "\nDisabling...\n"); - DEBUG_DelDisplay(i); - } - else - { - DEBUG_Printf(DBG_CHN_MESG, "%d : ", i + 1); - DEBUG_DisplayExpr(displaypoints[i].exp); - DEBUG_Printf(DBG_CHN_MESG, " = "); - if( displaypoints[i].format == 'i' ) - { - DEBUG_ExamineMemory( &value, - displaypoints[i].count, - displaypoints[i].format); - } - else - { - DEBUG_Print( &value, - displaypoints[i].count, - displaypoints[i].format, 0); + if (DEBUG_GetCurrentFrame(&name, &eip, &ebp)) + return name; + return NULL; +} + +int DEBUG_AddDisplay(struct expr *exp, int count, char format, int in_frame) +{ + int i; + + for (i = 0; i < ndisplays; i++) + if (displaypoints[i].exp == NULL) + break; + + if (i == maxdisplays) /* no space left - expand */ + displaypoints = DBG_realloc(displaypoints, + (maxdisplays += DISPTAB_DELTA) * sizeof(*displaypoints)); + + if (i == ndisplays) + ++ndisplays; + + displaypoints[i].exp = DEBUG_CloneExpr(exp); + displaypoints[i].count = count; + displaypoints[i].format = format; + displaypoints[i].enabled = TRUE; + displaypoints[i].function_name = + (in_frame ? DEBUG_GetCurrentFrameFunctionName() : NULL); + + return TRUE; +} + +int DEBUG_InfoDisplay(void) +{ + int i; + + for (i = 0; i < ndisplays; i++) { + if (displaypoints[i].exp == NULL) + continue; + + if (displaypoints[i].function_name) + DEBUG_Printf(DBG_CHN_MESG, "%d in %s%s : ", i + 1, + DEBUG_GetSymbolName(displaypoints[i].function_name), + (displaypoints[i].enabled ? + (displaypoints[i].function_name != DEBUG_GetCurrentFrameFunctionName() ? + " (out of scope)" : "") + : " (disabled)") + ); + else + DEBUG_Printf(DBG_CHN_MESG, "%d%s : ", i + 1, + (displaypoints[i].enabled ? "" : " (disabled)")); + DEBUG_DisplayExpr(displaypoints[i].exp); + DEBUG_Printf(DBG_CHN_MESG, "\n"); + } + + return TRUE; +} + +void DEBUG_PrintOneDisplay(int i) +{ + DBG_VALUE value; + + if (displaypoints[i].enabled) { + value = DEBUG_EvalExpr(displaypoints[i].exp); + if (value.type == NULL) { + DEBUG_Printf(DBG_CHN_MESG, "Unable to evaluate expression "); + DEBUG_DisplayExpr(displaypoints[i].exp); + DEBUG_Printf(DBG_CHN_MESG, "\nDisabling display %d ...\n", i + 1); + displaypoints[i].enabled = FALSE; + return; } - } } - }
- return TRUE; + DEBUG_Printf(DBG_CHN_MESG, "%d : ", i + 1); + DEBUG_DisplayExpr(displaypoints[i].exp); + DEBUG_Printf(DBG_CHN_MESG, " = "); + if (!displaypoints[i].enabled) + DEBUG_Printf(DBG_CHN_MESG, "(disabled)\n"); + else + if (displaypoints[i].format == 'i') + DEBUG_ExamineMemory(&value, displaypoints[i].count, displaypoints[i].format); + else + DEBUG_Print(&value, displaypoints[i].count, displaypoints[i].format, 0); }
-int -DEBUG_DelDisplay(int displaynum) -{ - int i; - - if( displaynum >= MAX_DISPLAY || displaynum == 0 || displaynum < -1 ) - { - DEBUG_Printf(DBG_CHN_MESG, "Invalid display number\n"); - return TRUE; - } - if( displaynum == -1 ) - { - for(i=0; i < MAX_DISPLAY; i++ ) - { - if( displaypoints[i].exp != NULL ) - { - DEBUG_FreeExpr(displaypoints[i].exp); - displaypoints[i].exp = NULL; - } - } - } - else if( displaypoints[displaynum - 1].exp != NULL ) - { - DEBUG_FreeExpr(displaypoints[displaynum - 1].exp); - displaypoints[displaynum - 1].exp = NULL; - } - return TRUE; +int DEBUG_DoDisplay(void) +{ + int i; + struct name_hash *cur_function_name = DEBUG_GetCurrentFrameFunctionName(); + + for (i = 0; i < ndisplays; i++) { + if (displaypoints[i].exp == NULL || !displaypoints[i].enabled) + continue; + if (displaypoints[i].function_name + && displaypoints[i].function_name != cur_function_name) + continue; + DEBUG_PrintOneDisplay(i); + } + + return TRUE; +} + +int DEBUG_DelDisplay(int displaynum) +{ + int i; + + if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 + || displaypoints[displaynum - 1].exp == NULL) { + DEBUG_Printf(DBG_CHN_MESG, "Invalid display number\n"); + return TRUE; + } + + if (displaynum == -1) { + for (i = 0; i < ndisplays; i++) { + if (displaypoints[i].exp != NULL) { + DEBUG_FreeExpr(displaypoints[i].exp); + displaypoints[i].exp = NULL; + } + } + displaypoints = DBG_realloc(displaypoints, + (maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints)); + ndisplays = 0; + } else if (displaypoints[--displaynum].exp != NULL) { + DEBUG_FreeExpr(displaypoints[displaynum].exp); + displaypoints[displaynum].exp = NULL; + while (displaynum == ndisplays - 1 + && displaypoints[displaynum].exp == NULL) + --ndisplays, --displaynum; + if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA) { + maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1); /* MARK */ + displaypoints = DBG_realloc(displaypoints, + maxdisplays * sizeof(*displaypoints)); + } + } + return TRUE; } + +int DEBUG_EnableDisplay(int displaynum, int enable) +{ + --displaynum; + if (displaynum >= ndisplays || displaynum < 0 || displaypoints[displaynum].exp == NULL) { + DEBUG_Printf(DBG_CHN_MESG, "Invalid display number\n"); + return TRUE; + } + + displaypoints[displaynum].enabled = enable; + if (!displaypoints[displaynum].function_name + || displaypoints[displaynum].function_name == DEBUG_GetCurrentFrameFunctionName()) + DEBUG_PrintOneDisplay(displaynum); + + return TRUE; +} + Index: programs/winedbg/hash.c =================================================================== RCS file: /home/wine/wine/programs/winedbg/hash.c,v retrieving revision 1.7 diff -u -r1.7 hash.c --- programs/winedbg/hash.c 19 Feb 2003 03:41:48 -0000 1.7 +++ programs/winedbg/hash.c 16 Apr 2003 21:46:29 -0000 @@ -1314,6 +1314,11 @@ return TRUE; }
+const char *DEBUG_GetSymbolName(const struct name_hash * sym) +{ + return sym->name; +} + #ifdef HAVE_REGEX_H
static int cmp_sym_by_name(const void * p1, const void * p2) Index: programs/winedbg/info.c =================================================================== RCS file: /home/wine/wine/programs/winedbg/info.c,v retrieving revision 1.5 diff -u -r1.5 info.c --- programs/winedbg/info.c 14 Feb 2003 19:22:48 -0000 1.5 +++ programs/winedbg/info.c 16 Apr 2003 21:46:30 -0000 @@ -214,15 +214,16 @@ " stepi [N] nexti [N]", " x <addr> print <expr>", " display <expr> undisplay <disnum>", -" delete display <disnum> pass", +" local display <expr> delete display <disnum>", +" enable display <disnum> disable display <disnum>", " bt frame <n>", " up down", " list <lines> disassemble [<addr>][,<addr>]", " show dir dir <path>", " set <reg> = <expr> set *<addr> = <expr>", -" mode [16,32,vm86] walk [wnd,class,module,maps,", -" whatis process,thread,exception]", -" info (see 'help info' for options)", +" mode [16,32,vm86] pass", +" whatis walk [wnd,class,module,maps,", +" info (see 'help info' for options) process,thread,exception]",
"The 'x' command accepts repeat counts and formats (including 'i') in the", "same way that gdb does.\n", @@ -230,8 +231,8 @@ " The following are examples of legal expressions:", " $eax $eax+0x3 0x1000 ($eip + 256) *$eax *($esp + 3)", " Also, a nm format symbol table can be read from a file using the", -" symbolfile command. Symbols can also be defined individually with", -" the define command.", +" symbolfile command.", /* Symbols can also be defined individually with", +" the define command.", */ "", NULL };