diff --git a/debugger/break.c b/debugger/break.c index ff59b68a5bd..df40eaefa09 100644 --- a/debugger/break.c +++ b/debugger/break.c @@ -274,7 +274,7 @@ static int DEBUG_FindBreakpoint( const DBG_ADDR *addr, int type ) * * 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 @@ static BOOL DEBUG_GetWatchedValue( int num, LPDWORD val ) * * 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 @@ void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) ) 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_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) ) */ 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_AddBreakpointFromId(const char *name, int lineno) */ 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_AddBreakpointFromLineno(int lineno) */ 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 a49349b5c51..0f0785a9154 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -164,7 +164,7 @@ command: ; 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 @@ print_command: ; 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 439c3f159e9..b3371bc493e 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -209,8 +209,14 @@ typedef struct tagDBG_THREAD { } 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 @@ typedef struct tagDBG_PROCESS { 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 @@ 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 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 c63534f3984..d11d1c10fda 100644 --- a/debugger/intvar.h +++ b/debugger/intvar.h @@ -25,6 +25,7 @@ INTERNAL_VAR(BreakOnCritSectTimeOut, FALSE, NULL, DT_BASIC_CONST 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 ec450576e3c..8d1e1c94efb 100644 --- a/debugger/stabs.c +++ b/debugger/stabs.c @@ -1453,7 +1453,7 @@ enum DbgInfoLoad DEBUG_ReadExecutableDbgInfo(const char* exe_name) 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 cac80a8d9bc..b61737a643e 100644 --- a/debugger/winedbg.c +++ b/debugger/winedbg.c @@ -196,9 +196,10 @@ void DEBUG_DelProcess(DBG_PROCESS* p) 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 @@ static void DEBUG_InitCurrThread(void) 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 {