Added ability to defer breakpoint setting for breakpoint defined by an
absolute address.
diff --git a/debugger/break.c b/debugger/break.c
index ff59b68..df40eae 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -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( value.type != NULL && value.type == DEBUG_GetBasicType(DT_BASIC_CONST_INT) )
+ 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;
+}
+
+/***********************************************************************
+ * 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;
+ DBG_VALUE value;
+ int i;
- if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE)) {
- DEBUG_AddBreakpoint(&value, NULL);
- return;
- }
+ if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE))
+ {
+ DEBUG_AddBreakpoint(&value, NULL, TRUE);
+ return;
+ }
- 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);
+ 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].name = strcpy(DBG_alloc(strlen(name) + 1), name);
- DEBUG_CurrProcess->delayed_bp[DEBUG_CurrProcess->num_delayed_bp - 1].lineno = lineno;
+ 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;
+ DBG_VALUE value;
- DEBUG_GetCurrentAddress(&value.addr);
+ DEBUG_GetCurrentAddress(&value.addr);
- if (lineno != -1) {
- struct name_hash* nh;
+ 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);
- }
+ 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 );
+ 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;
+ DBG_VALUE value;
+ int i;
+ 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++;
- }
- }
+ 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));
+ }
}
/***********************************************************************
diff --git a/debugger/dbg.y b/debugger/dbg.y
index a49349b..0f0785a 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -164,7 +164,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 +212,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); }
diff --git a/debugger/debugger.h b/debugger/debugger.h
index 439c3f1..b3371bc 100644
--- a/debugger/debugger.h
+++ b/debugger/debugger.h
@@ -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.
*/
@@ -288,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 );
diff --git a/debugger/intvar.h b/debugger/intvar.h
index c63534f..d11d1c1 100644
--- a/debugger/intvar.h
+++ b/debugger/intvar.h
@@ -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)
diff --git a/debugger/stabs.c b/debugger/stabs.c
index ec45057..8d1e1c9 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -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);
}
diff --git a/debugger/winedbg.c b/debugger/winedbg.c
index cac80a8..b61737a 100644
--- a/debugger/winedbg.c
+++ b/debugger/winedbg.c
@@ -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 {