fixed a number of long standing bugs:
- segmented expressions didn't display correctly - using dynamic size array for nested types parsing - correct display of source code after a crash factorized some code
This commit is contained in:
parent
78547774cc
commit
71189b5224
|
@ -326,27 +326,9 @@ void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) )
|
|||
{
|
||||
DBG_VALUE value = *_value;
|
||||
int num;
|
||||
unsigned int seg2;
|
||||
BYTE ch;
|
||||
|
||||
assert(_value->cookie == DV_TARGET || _value->cookie == DV_HOST);
|
||||
|
||||
#ifdef __i386__
|
||||
DEBUG_FixAddress( &value.addr, DEBUG_context.SegCs );
|
||||
#endif
|
||||
|
||||
if( value.type != NULL && value.type == DEBUG_TypeIntConst )
|
||||
{
|
||||
/*
|
||||
* We know that we have the actual offset stored somewhere
|
||||
* else in 32-bit space. Grab it, and we
|
||||
* should be all set.
|
||||
*/
|
||||
seg2 = value.addr.seg;
|
||||
value.addr.seg = 0;
|
||||
value.addr.off = DEBUG_GetExprValue(&value, NULL);
|
||||
value.addr.seg = seg2;
|
||||
}
|
||||
if( !DEBUG_GrabAddress(&value, TRUE) ) return;
|
||||
|
||||
if ((num = DEBUG_FindBreakpoint(&value.addr, DBG_BREAK)) >= 1)
|
||||
{
|
||||
|
@ -558,7 +540,7 @@ static int DEBUG_FindTriggeredWatchpoint(LPDWORD oldval)
|
|||
int i;
|
||||
|
||||
/* Method 1 => get triggered watchpoint from context (doesn't work on Linux
|
||||
* 2.2.x)
|
||||
* 2.2.x). This should be fixed in >= 2.2.16
|
||||
*/
|
||||
for (i = 0; i < next_bp; i++)
|
||||
{
|
||||
|
@ -746,7 +728,7 @@ BOOL DEBUG_ShouldContinue( DWORD code, enum exec_mode mode, int * count )
|
|||
if (!DEBUG_ShallBreak(wpnum)) return TRUE;
|
||||
|
||||
#ifdef __i386__
|
||||
addrlen = !addr.seg? 32 : DEBUG_GetSelectorType( addr.seg );
|
||||
if (addr.seg) addrlen = DEBUG_GetSelectorType( addr.seg );
|
||||
#endif
|
||||
DEBUG_Printf(DBG_CHN_MESG, "Stopped on watchpoint %d at ", wpnum);
|
||||
syminfo = DEBUG_PrintAddress( &addr, addrlen, TRUE );
|
||||
|
|
|
@ -53,14 +53,17 @@ typedef struct
|
|||
DWORD off;
|
||||
} DBG_ADDR;
|
||||
|
||||
#define DV_TARGET 0xF00D
|
||||
#define DV_HOST 0x50DA
|
||||
#define DV_INVALID 0x0000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct datatype* type;
|
||||
int cookie; /* DV_??? */
|
||||
/* DV_TARGET references an address in debugger's address space, whereas DV_HOST
|
||||
* references the debuggee address space
|
||||
*/
|
||||
# define DV_TARGET 0xF00D
|
||||
# define DV_HOST 0x50DA
|
||||
# define DV_INVALID 0x0000
|
||||
|
||||
DBG_ADDR addr;
|
||||
} DBG_VALUE;
|
||||
|
||||
|
@ -353,6 +356,7 @@ extern void DEBUG_InvalAddr( const DBG_ADDR* addr );
|
|||
extern void DEBUG_InvalLinAddr( void* addr );
|
||||
extern DWORD DEBUG_ToLinear( const DBG_ADDR *address );
|
||||
extern void DEBUG_GetCurrentAddress( DBG_ADDR * );
|
||||
extern BOOL DEBUG_GrabAddress( DBG_VALUE* value, BOOL fromCode );
|
||||
#ifdef __i386__
|
||||
extern void DEBUG_FixAddress( DBG_ADDR *address, DWORD def );
|
||||
extern BOOL DEBUG_FixSegment( DBG_ADDR* addr );
|
||||
|
@ -381,6 +385,15 @@ extern void DEBUG_InitCVDataTypes(void);
|
|||
extern void DEBUG_InfoRegisters(void);
|
||||
extern BOOL DEBUG_ValidateRegisters(void);
|
||||
|
||||
/* debugger/source.c */
|
||||
extern void DEBUG_ShowDir(void);
|
||||
extern void DEBUG_AddPath(const char * path);
|
||||
extern void DEBUG_List(struct list_id * line1, struct list_id * line2,
|
||||
int delta);
|
||||
extern void DEBUG_NukePath(void);
|
||||
extern void DEBUG_Disassemble(const DBG_VALUE *, const DBG_VALUE*, int offset);
|
||||
extern BOOL DEBUG_DisassembleInstruction(DBG_ADDR *addr);
|
||||
|
||||
/* debugger/stack.c */
|
||||
extern void DEBUG_InfoStack(void);
|
||||
extern void DEBUG_BackTrace(BOOL noisy);
|
||||
|
@ -425,14 +438,6 @@ extern struct datatype * DEBUG_TypeCast(enum debug_type, const char *);
|
|||
extern int DEBUG_PrintTypeCast(const struct datatype *);
|
||||
extern int DEBUG_PrintType( const DBG_VALUE* addr );
|
||||
|
||||
/* debugger/source.c */
|
||||
extern void DEBUG_ShowDir(void);
|
||||
extern void DEBUG_AddPath(const char * path);
|
||||
extern void DEBUG_List(struct list_id * line1, struct list_id * line2,
|
||||
int delta);
|
||||
extern void DEBUG_NukePath(void);
|
||||
extern void DEBUG_Disassemble( const DBG_VALUE *, const DBG_VALUE*, int offset );
|
||||
|
||||
/* debugger/winedbg.c */
|
||||
#define DBG_CHN_MESG 1
|
||||
#define DBG_CHN_ERR 2
|
||||
|
|
|
@ -510,8 +510,9 @@ DBG_VALUE DEBUG_EvalExpr(struct expr * exp)
|
|||
break;
|
||||
case EXP_OP_SEG:
|
||||
rtn.cookie = DV_TARGET;
|
||||
rtn.type = NULL;
|
||||
rtn.addr.seg = VAL(exp1);
|
||||
exp->un.binop.result = VAL(exp2);
|
||||
rtn.addr.off = VAL(exp2);
|
||||
#ifdef __i386__
|
||||
DEBUG_FixSegment(&rtn.addr);
|
||||
#endif
|
||||
|
|
|
@ -206,6 +206,50 @@ void DEBUG_WriteMemory( const DBG_VALUE* val, int value )
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DEBUG_GrabAddress
|
||||
*
|
||||
* Get the address from a value
|
||||
*/
|
||||
BOOL DEBUG_GrabAddress( DBG_VALUE* value, BOOL fromCode )
|
||||
{
|
||||
assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
|
||||
|
||||
#ifdef __i386__
|
||||
DEBUG_FixAddress( &value->addr,
|
||||
(fromCode) ? DEBUG_context.SegCs : DEBUG_context.SegDs);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dereference pointer to get actual memory address we need to be
|
||||
* reading. We will use the same segment as what we have already,
|
||||
* and hope that this is a sensible thing to do.
|
||||
*/
|
||||
if (value->type != NULL) {
|
||||
if (value->type == DEBUG_TypeIntConst) {
|
||||
/*
|
||||
* We know that we have the actual offset stored somewhere
|
||||
* else in 32-bit space. Grab it, and we
|
||||
* should be all set.
|
||||
*/
|
||||
unsigned int seg2 = value->addr.seg;
|
||||
value->addr.seg = 0;
|
||||
value->addr.off = DEBUG_GetExprValue(value, NULL);
|
||||
value->addr.seg = seg2;
|
||||
} else {
|
||||
struct datatype * testtype;
|
||||
|
||||
if (DEBUG_TypeDerefPointer(value, &testtype) == 0)
|
||||
return FALSE;
|
||||
if (testtype != NULL || value->type == DEBUG_TypeIntConst)
|
||||
value->addr.off = DEBUG_GetExprValue(value, NULL);
|
||||
}
|
||||
} else if (!value->addr.seg && !value->addr.off) {
|
||||
DEBUG_Printf(DBG_CHN_MESG,"Invalid expression\n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DEBUG_ExamineMemory
|
||||
|
@ -217,51 +261,8 @@ void DEBUG_ExamineMemory( const DBG_VALUE *_value, int count, char format )
|
|||
DBG_VALUE value = *_value;
|
||||
int i;
|
||||
unsigned char * pnt;
|
||||
struct datatype * testtype;
|
||||
|
||||
assert(_value->cookie == DV_TARGET || _value->cookie == DV_HOST);
|
||||
|
||||
#ifdef __i386__
|
||||
DEBUG_FixAddress( &value.addr,
|
||||
(format == 'i') ?
|
||||
DEBUG_context.SegCs :
|
||||
DEBUG_context.SegDs );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dereference pointer to get actual memory address we need to be
|
||||
* reading. We will use the same segment as what we have already,
|
||||
* and hope that this is a sensible thing to do.
|
||||
*/
|
||||
if( value.type != NULL )
|
||||
{
|
||||
if( value.type == DEBUG_TypeIntConst )
|
||||
{
|
||||
/*
|
||||
* We know that we have the actual offset stored somewhere
|
||||
* else in 32-bit space. Grab it, and we
|
||||
* should be all set.
|
||||
*/
|
||||
unsigned int seg2 = value.addr.seg;
|
||||
value.addr.seg = 0;
|
||||
value.addr.off = DEBUG_GetExprValue(&value, NULL);
|
||||
value.addr.seg = seg2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DEBUG_TypeDerefPointer(&value, &testtype) == 0)
|
||||
return;
|
||||
if( testtype != NULL || value.type == DEBUG_TypeIntConst )
|
||||
{
|
||||
value.addr.off = DEBUG_GetExprValue(&value, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!value.addr.seg && !value.addr.off)
|
||||
{
|
||||
DEBUG_Printf(DBG_CHN_MESG,"Invalid expression\n");
|
||||
return;
|
||||
}
|
||||
if (!DEBUG_GrabAddress(&value, (format == 'i'))) return;
|
||||
|
||||
if (format != 'i' && count > 1)
|
||||
{
|
||||
|
@ -301,13 +302,7 @@ void DEBUG_ExamineMemory( const DBG_VALUE *_value, int count, char format )
|
|||
return;
|
||||
}
|
||||
case 'i':
|
||||
while (count--)
|
||||
{
|
||||
DEBUG_PrintAddress( &value.addr, DEBUG_CurrThread->dbg_mode, TRUE );
|
||||
DEBUG_Printf(DBG_CHN_MESG,": ");
|
||||
DEBUG_Disasm( &value.addr, TRUE );
|
||||
DEBUG_Printf(DBG_CHN_MESG,"\n");
|
||||
}
|
||||
while (count-- && DEBUG_DisassembleInstruction( &value.addr ));
|
||||
return;
|
||||
#define DO_DUMP2(_t,_l,_f,_vv) { \
|
||||
_t _v; \
|
||||
|
|
|
@ -187,7 +187,7 @@ DEBUG_DisplaySource(char * sourcefile, int start, int end)
|
|||
/*
|
||||
* Still couldn't find it. Ask user for path to add.
|
||||
*/
|
||||
sprintf(zbuf, "Enter path to file %s: ", sourcefile);
|
||||
sprintf(zbuf, "Enter path to file '%s': ", sourcefile);
|
||||
lstrcpynA(tmppath, readline(zbuf), sizeof(tmppath));
|
||||
|
||||
if( tmppath[strlen(tmppath)-1] == '\n' )
|
||||
|
@ -425,56 +425,21 @@ DEBUG_List(struct list_id * source1, struct list_id * source2,
|
|||
|
||||
DBG_ADDR DEBUG_LastDisassemble={0,0};
|
||||
|
||||
static int
|
||||
_disassemble(DBG_ADDR *addr)
|
||||
BOOL DEBUG_DisassembleInstruction(DBG_ADDR *addr)
|
||||
{
|
||||
char ch;
|
||||
char ch;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
DEBUG_PrintAddress( addr, DEBUG_CurrThread->dbg_mode, TRUE );
|
||||
DEBUG_Printf(DBG_CHN_MESG,": ");
|
||||
if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr), &ch, sizeof(ch))) return 0;
|
||||
DEBUG_Disasm( addr, TRUE );
|
||||
DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, TRUE);
|
||||
DEBUG_Printf(DBG_CHN_MESG, ": ");
|
||||
if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr), &ch, sizeof(ch))) {
|
||||
DEBUG_Printf(DBG_CHN_MESG, "-- no code --");
|
||||
ret = FALSE;
|
||||
} else {
|
||||
DEBUG_Disasm(addr, TRUE);
|
||||
}
|
||||
DEBUG_Printf(DBG_CHN_MESG,"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
_disassemble_fixaddr(DBG_VALUE *value) {
|
||||
DWORD seg2;
|
||||
struct datatype *testtype;
|
||||
|
||||
assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
|
||||
|
||||
#ifdef __i386__
|
||||
DEBUG_FixAddress(&value->addr, DEBUG_context.SegCs);
|
||||
#endif
|
||||
|
||||
if( value->type != NULL )
|
||||
{
|
||||
if( value->type == DEBUG_TypeIntConst )
|
||||
{
|
||||
/*
|
||||
* We know that we have the actual offset stored somewhere
|
||||
* else in 32-bit space. Grab it, and we
|
||||
* should be all set.
|
||||
*/
|
||||
seg2 = value->addr.seg;
|
||||
value->addr.seg = 0;
|
||||
value->addr.off = DEBUG_GetExprValue(value, NULL);
|
||||
value->addr.seg = seg2;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_TypeDerefPointer(value, &testtype);
|
||||
if( testtype != NULL || value->type == DEBUG_TypeIntConst )
|
||||
value->addr.off = DEBUG_GetExprValue(value, NULL);
|
||||
}
|
||||
}
|
||||
else if (!value->addr.seg && !value->addr.off)
|
||||
{
|
||||
DEBUG_Printf(DBG_CHN_MESG,"Invalid expression\n");
|
||||
return;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -486,11 +451,11 @@ DEBUG_Disassemble(const DBG_VALUE *xstart,const DBG_VALUE *xend,int offset)
|
|||
|
||||
if (xstart) {
|
||||
start = *xstart;
|
||||
_disassemble_fixaddr(&start);
|
||||
DEBUG_GrabAddress(&start, TRUE);
|
||||
}
|
||||
if (xend) {
|
||||
end = *xend;
|
||||
_disassemble_fixaddr(&end);
|
||||
DEBUG_GrabAddress(&end, TRUE);
|
||||
}
|
||||
if (!xstart && !xend) {
|
||||
last = DEBUG_LastDisassemble;
|
||||
|
@ -498,35 +463,20 @@ DEBUG_Disassemble(const DBG_VALUE *xstart,const DBG_VALUE *xend,int offset)
|
|||
DEBUG_GetCurrentAddress( &last );
|
||||
|
||||
for (i=0;i<offset;i++)
|
||||
if (!_disassemble(&last)) break;
|
||||
if (!DEBUG_DisassembleInstruction(&last)) break;
|
||||
DEBUG_LastDisassemble = last;
|
||||
return;
|
||||
}
|
||||
last = start.addr;
|
||||
if (!xend) {
|
||||
for (i=0;i<offset;i++)
|
||||
if (!_disassemble(&last)) break;
|
||||
if (!DEBUG_DisassembleInstruction(&last)) break;
|
||||
DEBUG_LastDisassemble = last;
|
||||
return;
|
||||
}
|
||||
while (last.off <= end.addr.off)
|
||||
if (!_disassemble(&last)) break;
|
||||
if (!DEBUG_DisassembleInstruction(&last)) break;
|
||||
DEBUG_LastDisassemble = last;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
main(void)
|
||||
{
|
||||
int i, j;
|
||||
DEBUG_AddPath("../../de");
|
||||
while(1==1)
|
||||
{
|
||||
fscanf(stdin,"%d %d", &i, &j);
|
||||
DEBUG_DisplaySource("dumpexe.c", i, j);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -100,7 +100,9 @@ struct known_typedef
|
|||
|
||||
#define NR_STAB_HASH 521
|
||||
|
||||
struct known_typedef * ktd_head[NR_STAB_HASH] = {NULL,};
|
||||
static struct known_typedef * ktd_head[NR_STAB_HASH] = {NULL,};
|
||||
static struct datatype ** curr_types = NULL;
|
||||
static int allocated_types = 0;
|
||||
|
||||
static unsigned int stab_hash( const char * name )
|
||||
{
|
||||
|
@ -236,8 +238,6 @@ DEBUG_FreeIncludes(void)
|
|||
cu_nrofentries = 0;
|
||||
}
|
||||
|
||||
#define MAX_TD_NESTING 128
|
||||
|
||||
static
|
||||
struct datatype**
|
||||
DEBUG_FileSubNr2StabEnum(int filenr, int subnr)
|
||||
|
@ -462,7 +462,6 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
char * c;
|
||||
struct datatype * curr_type;
|
||||
struct datatype * datatype;
|
||||
struct datatype * curr_types[MAX_TD_NESTING];
|
||||
char element_name[1024];
|
||||
int ntypes = 0, ntp;
|
||||
int offset;
|
||||
|
@ -476,7 +475,7 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
|
||||
if( DEBUG_HandlePreviousTypedef(typename, ptr) )
|
||||
return TRUE;
|
||||
|
||||
|
||||
/*
|
||||
* Go from back to front. First we go through and figure out what
|
||||
* type numbers we need, and register those types. Then we go in
|
||||
|
@ -490,13 +489,11 @@ DEBUG_ParseTypedefStab(char * ptr, const char * typename)
|
|||
*/
|
||||
struct datatype** dt = DEBUG_ReadTypeEnumBackwards(c-1);
|
||||
|
||||
if( ntypes >= MAX_TD_NESTING )
|
||||
if( ntypes >= allocated_types )
|
||||
{
|
||||
/*
|
||||
* If this ever happens, just bump the counter.
|
||||
*/
|
||||
DEBUG_Printf(DBG_CHN_MESG, "Typedef nesting overflow\n");
|
||||
return FALSE;
|
||||
allocated_types += 64;
|
||||
curr_types = DBG_realloc(curr_types, sizeof(struct datatype*) * allocated_types);
|
||||
if (!curr_types) return FALSE;
|
||||
}
|
||||
|
||||
switch(c[1])
|
||||
|
@ -1087,6 +1084,9 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
|
|||
|
||||
DEBUG_FreeRegisteredTypedefs();
|
||||
DEBUG_FreeIncludes();
|
||||
DBG_free(curr_types);
|
||||
curr_types = NULL;
|
||||
allocated_types = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -338,12 +338,16 @@ static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
|
|||
if (!is_debug ||
|
||||
(DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
|
||||
(DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR)) {
|
||||
|
||||
struct list_id list;
|
||||
|
||||
/* Show where we crashed */
|
||||
curr_frame = 0;
|
||||
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
|
||||
DEBUG_Printf(DBG_CHN_MESG,": ");
|
||||
DEBUG_Disasm( &addr, TRUE );
|
||||
DEBUG_Printf( DBG_CHN_MESG, "\n" );
|
||||
DEBUG_DisassembleInstruction(&addr);
|
||||
|
||||
/* resets list internal arguments so we can look at source code when needed */
|
||||
DEBUG_FindNearestSymbol(&addr, TRUE, NULL, 0, &list);
|
||||
if (list.sourcefile) DEBUG_List(&list, NULL, 0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue