winedbg: deferring breakpoint
Eric Pouech
eric.pouech at wanadoo.fr
Mon Jul 29 15:29:00 CDT 2002
upon Massimo request, here's a patch that allows setting breakpoint by
address even if the memory where the bp is to be set is not valid yet
the debugger will try, each time a new DLL is loaded, to set the
breakpoint by its address
however, since this is a very dangerous feature (you don't know where
you're going to set the bp), I decided to disable the feature by default
it must be turned on by setting the $CanDeferOnBPByAddr internal
variable to 1
A+
-------------- next part --------------
Name: wdbg_bp
ChangeLog: added ability to defer breakpoint setting for breakpoint defined by an absolute address
License: X11
GenDate: 2002/07/29 20:15:37 UTC
ModifiedFiles: debugger/break.c debugger/dbg.y debugger/debugger.h debugger/intvar.h debugger/stabs.c debugger/winedbg.c
AddedFiles:
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/break.c,v
retrieving revision 1.34
diff -u -u -r1.34 break.c
--- debugger/break.c 20 Jul 2002 20:18:17 -0000 1.34
+++ debugger/break.c 29 Jul 2002 19:34:47 -0000
@@ -274,7 +274,7 @@
*
* Find an empty slot in BP table to add a new break/watch point
*/
-static int DEBUG_InitXPoint(int type, DBG_ADDR* addr)
+static int DEBUG_InitXPoint(int type, const DBG_ADDR* addr)
{
int num;
@@ -336,13 +336,48 @@
*
* Add a breakpoint.
*/
-void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) )
+BOOL DEBUG_AddBreakpoint( const DBG_VALUE *value, BOOL (*func)(void), BOOL verbose )
{
- DBG_VALUE value = *_value;
int num;
BYTE ch;
+
+ if ((num = DEBUG_FindBreakpoint(&value->addr, DBG_BREAK)) >= 1)
+ {
+ breakpoints[num].refcount++;
+ return TRUE;
+ }
+
+ if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear( &value->addr ), &ch, sizeof(ch)))
+ {
+ if (verbose)
+ DEBUG_Printf( DBG_CHN_MESG, "Invalid address, can't set breakpoint\n");
+ return FALSE;
+ }
+
+ if ((num = DEBUG_InitXPoint(DBG_BREAK, &value->addr)) == -1)
+ return FALSE;
+
+ breakpoints[num].u.b.opcode = ch;
+ breakpoints[num].u.b.func = func;
+
+ DEBUG_Printf( DBG_CHN_MESG, "Breakpoint %d at ", num );
+ DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16,
+ TRUE );
+ DEBUG_Printf( DBG_CHN_MESG, "\n" );
+
+ return FALSE;
+}
- if( value.type != NULL && value.type == DEBUG_GetBasicType(DT_BASIC_CONST_INT) )
+/***********************************************************************
+ * DEBUG_AddBreakpointFromValue
+ *
+ * Add a breakpoint.
+ */
+BOOL DEBUG_AddBreakpointFromValue( const DBG_VALUE *_value )
+{
+ DBG_VALUE value = *_value;
+
+ if (value.type != NULL && value.type == DEBUG_GetBasicType(DT_BASIC_CONST_INT) && value.cookie == DV_HOST)
{
/*
* We know that we have the actual offset stored somewhere
@@ -353,30 +388,27 @@
value.addr.seg = 0;
value.addr.off = DEBUG_GetExprValue(&value, NULL);
value.addr.seg = seg2;
+ value.cookie = DV_TARGET;
}
- if ((num = DEBUG_FindBreakpoint(&value.addr, DBG_BREAK)) >= 1)
+ if (!DEBUG_AddBreakpoint( &value, NULL, TRUE ))
{
- breakpoints[num].refcount++;
- return;
+ if (!DBG_IVAR(CanDeferOnBPByAddr))
+ {
+ DEBUG_Printf( DBG_CHN_MESG, "Invalid address, can't set breakpoint\n"
+ "You can turn on deferring breakpoints by address by setting $CanDeferOnBPByAddr to 1\n");
+ return FALSE;
+ }
+ DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint, will check again any time a new DLL is loaded\n");
+ DEBUG_CurrProcess->delayed_bp = DBG_realloc(DEBUG_CurrProcess->delayed_bp,
+ sizeof(DBG_DELAYED_BP) * ++DEBUG_CurrProcess->num_delayed_bp);
+
+ DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].is_symbol = FALSE;
+ DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].u.value = value;
+ return TRUE;
}
- if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &value.addr ), &ch, sizeof(ch)))
- {
- DEBUG_Printf( DBG_CHN_MESG, "Invalid address, can't set breakpoint\n");
- return;
- }
-
- if ((num = DEBUG_InitXPoint(DBG_BREAK, &value.addr)) == -1)
- return;
-
- breakpoints[num].u.b.opcode = ch;
- breakpoints[num].u.b.func = func;
-
- DEBUG_Printf( DBG_CHN_MESG, "Breakpoint %d at ", num );
- DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].is32 ? MODE_32 : MODE_16,
- TRUE );
- DEBUG_Printf( DBG_CHN_MESG, "\n" );
+ return TRUE;
}
/***********************************************************************
@@ -386,26 +418,29 @@
*/
void DEBUG_AddBreakpointFromId(const char *name, int lineno)
{
- DBG_VALUE value;
- int i;
-
- if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE)) {
- DEBUG_AddBreakpoint(&value, NULL);
- return;
- }
+ DBG_VALUE value;
+ int i;
- DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint, will check again when a new DLL is loaded\n");
- for (i = 0; i < DEBUG_CurrProcess->num_delayed_bp; i++) {
- if (!strcmp(name, DEBUG_CurrProcess->delayed_bp[i].name) &&
- lineno == DEBUG_CurrProcess->delayed_bp[i].lineno) {
- return;
- }
- }
- DEBUG_CurrProcess->delayed_bp = DBG_realloc(DEBUG_CurrProcess->delayed_bp,
- sizeof(DBG_DELAYED_BP) * ++DEBUG_CurrProcess->num_delayed_bp);
+ if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE))
+ {
+ DEBUG_AddBreakpoint(&value, NULL, TRUE);
+ return;
+ }
- DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].name = strcpy(DBG_alloc(strlen(name) + 1), name);
- DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].lineno = lineno;
+ DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint, will check again when a new DLL is loaded\n");
+ for (i = 0; i < DEBUG_CurrProcess->num_delayed_bp; i++)
+ {
+ if (DEBUG_CurrProcess->delayed_bp[i].is_symbol &&
+ !strcmp(name, DEBUG_CurrProcess->delayed_bp[i].u.symbol.name) &&
+ lineno == DEBUG_CurrProcess->delayed_bp[i].u.symbol.lineno)
+ return;
+ }
+ DEBUG_CurrProcess->delayed_bp = DBG_realloc(DEBUG_CurrProcess->delayed_bp,
+ sizeof(DBG_DELAYED_BP) * ++DEBUG_CurrProcess->num_delayed_bp);
+
+ DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].is_symbol = TRUE;
+ DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].u.symbol.name = strcpy(DBG_alloc(strlen(name) + 1), name);
+ DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].u.symbol.lineno = lineno;
}
/***********************************************************************
@@ -415,24 +450,26 @@
*/
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 );
+ 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, TRUE );
}
/***********************************************************************
@@ -442,18 +479,32 @@
*/
void DEBUG_CheckDelayedBP(void)
{
- DBG_VALUE value;
- int i = 0;
- DBG_DELAYED_BP* dbp = DEBUG_CurrProcess->delayed_bp;
-
- while (i < DEBUG_CurrProcess->num_delayed_bp) {
- if (DEBUG_GetSymbolValue(dbp[i].name, dbp[i].lineno, &value, TRUE)) {
- DEBUG_AddBreakpoint(&value, NULL);
- memmove(&dbp[i], &dbp[i+1], (--DEBUG_CurrProcess->num_delayed_bp - i) * sizeof(*dbp));
- } else {
- i++;
- }
- }
+ DBG_VALUE value;
+ int i;
+ DBG_DELAYED_BP* dbp = DEBUG_CurrProcess->delayed_bp;
+
+ for (i = 0; i < DEBUG_CurrProcess->num_delayed_bp; i++)
+ {
+ if (dbp[i].is_symbol)
+ {
+ if (!DEBUG_GetSymbolValue(dbp[i].u.symbol.name, dbp[i].u.symbol.lineno, &value, TRUE))
+ continue;
+ }
+ else
+ value = dbp[i].u.value;
+ DEBUG_Printf(DBG_CHN_MESG, "trying to add delayed %s-bp\n", dbp[i].is_symbol ? "S" : "A");
+ if (!dbp[i].is_symbol)
+ DEBUG_Printf(DBG_CHN_MESG, "\t%04x %04lx:%08lx\n",
+ dbp[i].u.value.cookie,
+ dbp[i].u.value.addr.seg,
+ dbp[i].u.value.addr.off);
+ else
+ DEBUG_Printf(DBG_CHN_MESG, "\t'%s' @ %d\n",
+ dbp[i].u.symbol.name, dbp[i].u.symbol.lineno);
+
+ if (DEBUG_AddBreakpoint(&value, NULL, FALSE))
+ memmove(&dbp[i], &dbp[i+1], (--DEBUG_CurrProcess->num_delayed_bp - i) * sizeof(*dbp));
+ }
}
/***********************************************************************
Index: debugger/dbg.y
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/dbg.y,v
retrieving revision 1.59
diff -u -u -r1.59 dbg.y
--- debugger/dbg.y 23 Jul 2002 20:53:41 -0000 1.59
+++ debugger/dbg.y 29 Jul 2002 20:07:21 -0000
@@ -164,7 +166,7 @@
;
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(FALSE, NULL, $3);}
| tSET tIDENTIFIER '+' tIDENTIFIER tEOL {DEBUG_DbgChannel(TRUE, $2, $4);}
@@ -212,7 +214,7 @@
;
break_command:
- tBREAK '*' expr_addr tEOL{ DEBUG_AddBreakpoint( &$3, NULL ); DEBUG_FreeExprMem(); }
+ tBREAK '*' expr_addr tEOL{ DEBUG_AddBreakpointFromValue( &$3 ); DEBUG_FreeExprMem(); }
| tBREAK identifier tEOL { DEBUG_AddBreakpointFromId($2, -1); }
| tBREAK identifier ':' tNUM tEOL { DEBUG_AddBreakpointFromId($2, $4); }
| tBREAK tNUM tEOL { DEBUG_AddBreakpointFromLineno($2); }
Index: debugger/debugger.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/debugger.h,v
retrieving revision 1.38
diff -u -u -r1.38 debugger.h
--- debugger/debugger.h 23 Jul 2002 20:53:41 -0000 1.38
+++ debugger/debugger.h 29 Jul 2002 19:35:31 -0000
@@ -209,8 +209,14 @@
} DBG_THREAD;
typedef struct tagDBG_DELAYED_BP {
- int lineno;
- char* name;
+ BOOL is_symbol;
+ union {
+ struct {
+ int lineno;
+ char* name;
+ } symbol;
+ DBG_VALUE value;
+ } u;
} DBG_DELAYED_BP;
typedef struct tagDBG_PROCESS {
@@ -227,7 +233,7 @@
int num_delayed_bp;
/*
* This is an index we use to keep track of the debug information
- * when we have multiple sources. We use the same database to also
+ * when we have multiple sources. We use the same database to also
* allow us to do an 'info shared' type of deal, and we use the index
* to eliminate duplicates.
*/
@@ -286,7 +294,8 @@
/* debugger/break.c */
extern void DEBUG_SetBreakpoints( BOOL set );
-extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void) );
+extern BOOL DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void), BOOL verbose );
+extern BOOL DEBUG_AddBreakpointFromValue( const DBG_VALUE *addr );
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 );
Index: debugger/intvar.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/intvar.h,v
retrieving revision 1.8
diff -u -u -r1.8 intvar.h
--- debugger/intvar.h 9 Mar 2002 23:50:37 -0000 1.8
+++ debugger/intvar.h 29 Jul 2002 14:21:22 -0000
@@ -25,6 +25,7 @@
INTERNAL_VAR(BreakOnAttach, FALSE, NULL, DT_BASIC_CONST_INT)
INTERNAL_VAR(BreakOnFirstChance, TRUE, NULL, DT_BASIC_CONST_INT)
INTERNAL_VAR(BreakOnDllLoad, FALSE, NULL, DT_BASIC_CONST_INT)
+INTERNAL_VAR(CanDeferOnBPByAddr, FALSE, NULL, DT_BASIC_CONST_INT)
/* output handling */
INTERNAL_VAR(ConChannelMask, DBG_CHN_MESG, NULL, DT_BASIC_CONST_INT)
Index: debugger/stabs.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/stabs.c,v
retrieving revision 1.50
diff -u -u -r1.50 stabs.c
--- debugger/stabs.c 22 Jul 2002 20:38:10 -0000 1.50
+++ debugger/stabs.c 29 Jul 2002 19:33:14 -0000
@@ -1453,7 +1453,7 @@
value.cookie = DV_TARGET;
value.addr.seg = 0;
value.addr.off = (DWORD)dbg_hdr.r_brk;
- DEBUG_AddBreakpoint(&value, DEBUG_RescanElf);
+ DEBUG_AddBreakpoint(&value, DEBUG_RescanElf, TRUE);
DEBUG_SetBreakpoints(TRUE);
}
Index: debugger/winedbg.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/debugger/winedbg.c,v
retrieving revision 1.60
diff -u -u -r1.60 winedbg.c
--- debugger/winedbg.c 20 Jul 2002 20:29:09 -0000 1.60
+++ debugger/winedbg.c 29 Jul 2002 20:01:45 -0000
@@ -196,9 +196,10 @@
while (p->threads) DEBUG_DelThread(p->threads);
- for (i = 0; i < p->num_delayed_bp; i++) {
- DBG_free(p->delayed_bp[i].name);
- }
+ for (i = 0; i < p->num_delayed_bp; i++)
+ if (p->delayed_bp[i].is_symbol)
+ DBG_free(p->delayed_bp[i].u.symbol.name);
+
DBG_free(p->delayed_bp);
if (p->prev) p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
@@ -283,7 +284,7 @@
value.cookie = DV_TARGET;
value.addr.seg = 0;
value.addr.off = (DWORD)DEBUG_CurrThread->start;
- DEBUG_AddBreakpoint(&value, NULL);
+ DEBUG_AddBreakpointFromValue(&value);
DEBUG_SetBreakpoints(TRUE);
}
} else {
More information about the wine-patches
mailing list