mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 08:49:15 +00:00
Added ability to defer breakpoint setting for breakpoint defined by an
absolute address.
This commit is contained in:
parent
6f129541d1
commit
72a7369ebc
6 changed files with 136 additions and 76 deletions
181
debugger/break.c
181
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));
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue