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