1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-08 20:06:18 +00:00

No longer directly accessing debuggee memory.

Execution context (mode, steps...) are now linked to a thread.
Removed some X11 crst hacks.
Rewrote info/walk commands.
Removed direct debugger invocation code (and moved the rest to the new
winedbg.c file).
This commit is contained in:
Eric Pouech 2000-03-08 16:44:54 +00:00 committed by Alexandre Julliard
parent 00641d5b1c
commit 527eea99f8
19 changed files with 1785 additions and 1302 deletions

View File

@ -20,7 +20,8 @@ C_SRCS = \
source.c \
stabs.c \
stack.c \
types.c
types.c \
winedbg.c
EXTRA_SRCS = dbg.y debug.l
EXTRA_OBJS = y.tab.o lex.yy.o

View File

@ -7,83 +7,43 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "wine/winbase16.h"
#include "module.h"
#include "neexe.h"
#include "process.h"
#include "task.h"
#include "miscemu.h"
#include "toolhelp.h"
#include "debugger.h"
#include "dosexe.h"
#define INT3 0xcc /* int 3 opcode */
#define MAX_BREAKPOINTS 100
typedef struct
{
DBG_ADDR addr;
BYTE addrlen;
BYTE opcode;
BOOL16 enabled;
WORD skipcount;
BOOL16 in_use;
struct expr * condition;
} BREAKPOINT;
static BREAKPOINT breakpoints[MAX_BREAKPOINTS];
static int next_bp = 1; /* breakpoint 0 is reserved for step-over */
/***********************************************************************
* DEBUG_ChangeOpcode
*
* Change the opcode at segment:addr.
*/
static void DEBUG_SetOpcode( const DBG_ADDR *addr, BYTE op )
{
BYTE *ptr = DBG_ADDR_TO_LIN(addr);
/* There are a couple of problems with this. On Linux prior to
1.1.62, this call fails (ENOACCESS) due to a bug in fs/exec.c.
This code is currently not tested at all on BSD.
How do I get the old protection in order to restore it later on?
*/
if (mprotect((caddr_t)((int)ptr & (~4095)), 4096,
PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
{
perror( "Can't set break point" );
return;
}
*ptr = op;
/* mprotect((caddr_t)(addr->off & ~4095), 4096,
PROT_READ | PROT_EXEC ); */
}
/***********************************************************************
* DEBUG_IsStepOverInstr
*
* Determine if the instruction at CS:EIP is an instruction that
* we need to step over (like a call or a repetitive string move).
*/
static BOOL DEBUG_IsStepOverInstr()
static BOOL DEBUG_IsStepOverInstr(void)
{
#ifdef __i386__
BYTE *instr = (BYTE *)CTX_SEG_OFF_TO_LIN( &DEBUG_context,
CS_reg(&DEBUG_context),
EIP_reg(&DEBUG_context) );
BYTE* instr;
BYTE ch;
DBG_ADDR addr;
addr.seg = DEBUG_context.SegCs;
addr.off = DEBUG_context.Eip;
/* FIXME: old code was using V86BASE(DEBUG_context)
* instead of passing thru DOSMEM_MemoryBase
*/
instr = (BYTE*)DEBUG_ToLinear(&addr);
for (;;)
{
switch(*instr)
if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
return FALSE;
switch (ch)
{
/* Skip all prefixes */
@ -109,8 +69,9 @@ static BOOL DEBUG_IsStepOverInstr()
return TRUE;
case 0xff: /* call <regmodrm> */
return (((instr[1] & 0x38) == 0x10) ||
((instr[1] & 0x38) == 0x18));
if (!DEBUG_READ_MEM(instr + 1, &ch, sizeof(ch)))
return FALSE;
return (((ch & 0x38) == 0x10) || ((ch & 0x38) == 0x18));
/* Handle string instructions */
@ -149,21 +110,21 @@ static BOOL DEBUG_IsStepOverInstr()
BOOL DEBUG_IsFctReturn(void)
{
#ifdef __i386__
BYTE *instr = (BYTE *)CTX_SEG_OFF_TO_LIN( &DEBUG_context,
CS_reg(&DEBUG_context),
EIP_reg(&DEBUG_context) );
BYTE* instr;
BYTE ch;
DBG_ADDR addr;
for (;;)
{
switch(*instr)
{
case 0xc2:
case 0xc3:
return TRUE;
default:
return FALSE;
}
}
addr.seg = DEBUG_context.SegCs;
addr.off = DEBUG_context.Eip;
/* FIXME: old code was using V86BASE(DEBUG_context)
* instead of passing thru DOSMEM_MemoryBase
*/
instr = (BYTE*)DEBUG_ToLinear(&addr);
if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch)))
return FALSE;
return (ch == 0xc2) || (ch == 0xc3);
#else
return FALSE;
#endif
@ -177,21 +138,20 @@ BOOL DEBUG_IsFctReturn(void)
*/
void DEBUG_SetBreakpoints( BOOL set )
{
int i;
int i;
char ch;
for (i = 0; i < MAX_BREAKPOINTS; i++)
{
if (breakpoints[i].in_use && breakpoints[i].enabled)
if (breakpoints[i].refcount && breakpoints[i].enabled)
{
/* Note: we check for read here, because if reading is allowed */
/* writing permission will be forced in DEBUG_SetOpcode. */
if (DEBUG_IsBadReadPtr( &breakpoints[i].addr, 1 ))
ch = set ? INT3 : breakpoints[i].opcode;
if (!DEBUG_WRITE_MEM( (void*)DEBUG_ToLinear(&breakpoints[i].addr), &ch, sizeof(ch) ))
{
fprintf( stderr, "Invalid address for breakpoint %d, disabling it\n", i );
breakpoints[i].enabled = FALSE;
}
else DEBUG_SetOpcode( &breakpoints[i].addr,
set ? INT3 : breakpoints[i].opcode );
}
}
}
@ -209,7 +169,7 @@ int DEBUG_FindBreakpoint( const DBG_ADDR *addr )
for (i = 0; i < MAX_BREAKPOINTS; i++)
{
if (breakpoints[i].in_use && breakpoints[i].enabled &&
if (breakpoints[i].refcount && breakpoints[i].enabled &&
breakpoints[i].addr.seg == addr->seg &&
breakpoints[i].addr.off == addr->off) return i;
}
@ -227,9 +187,9 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address )
DBG_ADDR addr = *address;
int num;
unsigned int seg2;
BYTE *p;
BYTE ch;
DBG_FIX_ADDR_SEG( &addr, CS_reg(&DEBUG_context) );
DEBUG_FixAddress( &addr, DEBUG_context.SegCs );
if( addr.type != NULL && addr.type == DEBUG_TypeIntConst )
{
@ -243,27 +203,38 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address )
addr.off = DEBUG_GetExprValue(&addr, NULL);
addr.seg = seg2;
}
if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
if ((num = DEBUG_FindBreakpoint(&addr)) >= 1)
{
breakpoints[num].refcount++;
return;
}
if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, sizeof(ch)))
return;
if (next_bp < MAX_BREAKPOINTS)
num = next_bp++;
else /* try to find an empty slot */
{
for (num = 1; num < MAX_BREAKPOINTS; num++)
if (!breakpoints[num].in_use) break;
if (!breakpoints[num].refcount) break;
if (num >= MAX_BREAKPOINTS)
{
fprintf( stderr, "Too many breakpoints. Please delete some.\n" );
return;
}
}
p = DBG_ADDR_TO_LIN( &addr );
breakpoints[num].addr = addr;
breakpoints[num].addrlen = !addr.seg ? 32 :
(GET_SEL_FLAGS(addr.seg) & LDT_FLAGS_32BIT) ? 32 : 16;
breakpoints[num].opcode = *p;
breakpoints[num].addrlen = 32;
#ifdef __i386__
if (addr.seg)
breakpoints[num].addrlen = DEBUG_GetSelectorType( addr.seg );
if (breakpoints[num].addrlen == 0) fprintf(stderr, "in bad shape\n");
#endif
breakpoints[num].opcode = ch;
breakpoints[num].enabled = TRUE;
breakpoints[num].in_use = TRUE;
breakpoints[num].refcount = 1;
breakpoints[num].skipcount = 0;
fprintf( stderr, "Breakpoint %d at ", num );
DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].addrlen,
@ -279,12 +250,15 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address )
*/
void DEBUG_DelBreakpoint( int num )
{
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
{
fprintf( stderr, "Invalid breakpoint number %d\n", num );
return;
}
if (--breakpoints[num].refcount > 0)
return;
if( breakpoints[num].condition != NULL )
{
DEBUG_FreeExpr(breakpoints[num].condition);
@ -292,7 +266,7 @@ void DEBUG_DelBreakpoint( int num )
}
breakpoints[num].enabled = FALSE;
breakpoints[num].in_use = FALSE;
breakpoints[num].refcount = 0;
breakpoints[num].skipcount = 0;
}
@ -304,12 +278,12 @@ void DEBUG_DelBreakpoint( int num )
*/
void DEBUG_EnableBreakpoint( int num, BOOL enable )
{
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
{
fprintf( stderr, "Invalid breakpoint number %d\n", num );
return;
}
breakpoints[num].enabled = enable;
breakpoints[num].enabled = (enable) ? TRUE : FALSE;
breakpoints[num].skipcount = 0;
}
@ -326,67 +300,21 @@ void DEBUG_InfoBreakpoints(void)
fprintf( stderr, "Breakpoints:\n" );
for (i = 1; i < next_bp; i++)
{
if (breakpoints[i].in_use)
if (breakpoints[i].refcount)
{
fprintf( stderr, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n');
DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen,
TRUE);
fprintf( stderr, "\n" );
DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen, TRUE);
fprintf( stderr, " (%u)\n", breakpoints[i].refcount );
if( breakpoints[i].condition != NULL )
{
fprintf(stderr, "\t\tstop when ");
{
fprintf(stderr, "\t\tstop when ");
DEBUG_DisplayExpr(breakpoints[i].condition);
fprintf(stderr, "\n");
}
}
}
}
}
/***********************************************************************
* DEBUG_AddTaskEntryBreakpoint
*
* Add a breakpoint at the entry point of the given task
*/
void DEBUG_AddTaskEntryBreakpoint( HTASK16 hTask )
{
TDB *pTask = (TDB *)GlobalLock16( hTask );
NE_MODULE *pModule;
DBG_ADDR addr = { NULL, 0, 0 };
if ( pTask )
{
if (!(pModule = NE_GetPtr( pTask->hModule ))) return;
if (pModule->flags & NE_FFLAGS_LIBMODULE) return; /* Library */
if (pModule->lpDosTask) { /* DOS module */
addr.seg = pModule->lpDosTask->init_cs | ((DWORD)pModule->self << 16);
addr.off = pModule->lpDosTask->init_ip;
fprintf( stderr, "DOS task '%s': ", NE_MODULE_NAME( pModule ) );
DEBUG_AddBreakpoint( &addr );
} else
if (!(pModule->flags & NE_FFLAGS_WIN32)) /* NE module */
{
addr.seg =
GlobalHandleToSel16(NE_SEG_TABLE(pModule)[pModule->cs-1].hSeg);
addr.off = pModule->ip;
fprintf( stderr, "Win16 task '%s': ", NE_MODULE_NAME( pModule ) );
DEBUG_AddBreakpoint( &addr );
}
else /* PE module */
{
addr.seg = 0;
addr.off = (DWORD)RVA_PTR( pModule->module32,
OptionalHeader.AddressOfEntryPoint);
fprintf( stderr, "Win32 task '%s': ", NE_MODULE_NAME( pModule ) );
DEBUG_AddBreakpoint( &addr );
}
}
DEBUG_SetBreakpoints( TRUE ); /* Setup breakpoints */
}
/***********************************************************************
* DEBUG_ShouldContinue
*
@ -401,21 +329,22 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
struct list_id list;
#ifdef __i386__
/* If not single-stepping, back up over the int3 instruction */
if (!(EFL_reg(&DEBUG_context) & STEP_FLAG)) EIP_reg(&DEBUG_context)--;
/* If not single-stepping, back up over the int3 instruction */
if (!(DEBUG_context.EFlags & STEP_FLAG))
DEBUG_context.Eip--;
#endif
DEBUG_GetCurrentAddress( &addr );
bpnum = DEBUG_FindBreakpoint( &addr );
breakpoints[0].enabled = 0; /* disable the step-over breakpoint */
breakpoints[0].enabled = FALSE; /* disable the step-over breakpoint */
if ((bpnum != 0) && (bpnum != -1))
{
if( breakpoints[bpnum].condition != NULL )
{
{
cond_addr = DEBUG_EvalExpr(breakpoints[bpnum].condition);
if( cond_addr.type == NULL )
{
{
/*
* Something wrong - unable to evaluate this expression.
*/
@ -423,21 +352,21 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
DEBUG_DisplayExpr(breakpoints[bpnum].condition);
fprintf(stderr, "\nTurning off condition\n");
DEBUG_AddBPCondition(bpnum, NULL);
}
}
else if( ! DEBUG_GetExprValue( &cond_addr, NULL) )
{
{
return TRUE;
}
}
}
}
if( breakpoints[bpnum].skipcount > 0 )
{
{
breakpoints[bpnum].skipcount--;
if( breakpoints[bpnum].skipcount > 0 )
{
{
return TRUE;
}
}
}
}
fprintf( stderr, "Stopped on breakpoint %d at ", bpnum );
DEBUG_PrintAddress( &breakpoints[bpnum].addr,
breakpoints[bpnum].addrlen, TRUE );
@ -449,9 +378,9 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
*/
DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
if( list.sourcefile != NULL )
{
{
DEBUG_List(&list, NULL, 0);
}
}
return FALSE;
}
@ -460,8 +389,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
* get the current function, and figure out if we are exactly
* on a line number or not.
*/
if( mode == EXEC_STEP_OVER
|| mode == EXEC_STEP_INSTR )
if( mode == EXEC_STEP_OVER || mode == EXEC_STEP_INSTR )
{
if( DEBUG_CheckLinenoStatus(&addr) == AT_LINENUMBER )
{
@ -499,14 +427,24 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count )
#ifdef __i386__
/* If there's no breakpoint and we are not single-stepping, then we */
/* must have encountered an int3 in the Windows program; let's skip it. */
if ((bpnum == -1) && !(EFL_reg(&DEBUG_context) & STEP_FLAG))
EIP_reg(&DEBUG_context)++;
if ((bpnum == -1) && !(DEBUG_context.EFlags & STEP_FLAG))
DEBUG_context.Eip++;
#endif
/* no breakpoint, continue if in continuous mode */
/* no breakpoint, continue if in continuous mode */
return (mode == EXEC_CONT || mode == EXEC_PASS || mode == EXEC_FINISH);
}
/***********************************************************************
* DEBUG_RestartExecution
*
* Remove all breakpoints before entering the debug loop
*/
void DEBUG_SuspendExecution( void )
{
DEBUG_SetBreakpoints( FALSE );
breakpoints[0] = DEBUG_CurrThread->stepOverBP;
}
/***********************************************************************
* DEBUG_RestartExecution
@ -522,7 +460,8 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
int delta;
int status;
enum exec_mode ret_mode;
BYTE *instr;
DWORD instr;
unsigned char ch;
DEBUG_GetCurrentAddress( &addr );
@ -548,7 +487,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
{
if( mode == EXEC_CONT && count > 1 )
{
fprintf(stderr,"Not stopped at any breakpoint; argument ignored.\n");
fprintf(stderr, "Not stopped at any breakpoint; argument ignored.\n");
}
}
@ -557,16 +496,17 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
mode = ret_mode = EXEC_STEPI_INSTR;
}
instr = DBG_ADDR_TO_LIN( &addr );
instr = DEBUG_ToLinear( &addr );
DEBUG_READ_MEM((void*)instr, &ch, sizeof(ch));
/*
* See if the function we are stepping into has debug info
* and line numbers. If not, then we step over it instead.
* FIXME - we need to check for things like thunks or trampolines,
* as the actual function may in fact have debug info.
*/
if( *instr == 0xe8 )
if( ch == 0xe8 )
{
delta = *(unsigned int*) (instr + 1);
DEBUG_READ_MEM((void*)(instr + 1), &delta, sizeof(delta));
addr2 = addr;
DEBUG_Disasm(&addr2, FALSE);
addr2.off += delta;
@ -612,7 +552,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
case EXEC_CONT: /* Continuous execution */
case EXEC_PASS: /* Continue, passing exception */
#ifdef __i386__
EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
DEBUG_context.EFlags &= ~STEP_FLAG;
#endif
DEBUG_SetBreakpoints( TRUE );
break;
@ -625,14 +565,16 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
* address just after the call.
*/
#ifdef __i386__
addr.off = *((unsigned int *) ESP_reg(&DEBUG_context) + 2);
EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
DEBUG_READ_MEM((void*)(DEBUG_context.Esp +
2 * sizeof(unsigned int)),
&addr.off, sizeof(addr.off));
DEBUG_context.EFlags &= ~STEP_FLAG;
#endif
breakpoints[0].addr = addr;
breakpoints[0].enabled = TRUE;
breakpoints[0].in_use = TRUE;
breakpoints[0].refcount = 1;
breakpoints[0].skipcount = 0;
breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char));
DEBUG_SetBreakpoints( TRUE );
break;
@ -642,14 +584,14 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
if (DEBUG_IsStepOverInstr())
{
#ifdef __i386__
EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
DEBUG_context.EFlags &= ~STEP_FLAG;
#endif
DEBUG_Disasm(&addr, FALSE);
breakpoints[0].addr = addr;
breakpoints[0].enabled = TRUE;
breakpoints[0].in_use = TRUE;
breakpoints[0].refcount = 1;
breakpoints[0].skipcount = 0;
breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char));
DEBUG_SetBreakpoints( TRUE );
break;
}
@ -658,17 +600,18 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
case EXEC_STEP_INSTR: /* Single-stepping an instruction */
case EXEC_STEPI_INSTR: /* Single-stepping an instruction */
#ifdef __i386__
EFL_reg(&DEBUG_context) |= STEP_FLAG;
DEBUG_context.EFlags |= STEP_FLAG;
#endif
break;
}
DEBUG_CurrThread->stepOverBP = breakpoints[0];
return ret_mode;
}
int
DEBUG_AddBPCondition(int num, struct expr * exp)
{
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount)
{
fprintf( stderr, "Invalid breakpoint number %d\n", num );
return FALSE;

View File

@ -892,27 +892,29 @@ static const int db_lengths[] = {
static unsigned int db_get_task_value( const DBG_ADDR *addr,
int size, int is_signed )
{
unsigned int result;
unsigned char *p = DBG_ADDR_TO_LIN( addr );
unsigned int result = 0;
char buffer[4];
switch(size)
{
case 4:
if (is_signed) result = (unsigned int) *(int *)p;
else result = *(unsigned int *)p;
break;
case 2:
if (is_signed) result = (unsigned int) *(short int *)p;
else result = *(unsigned short int *)p;
break;
case 1:
if (is_signed) result = (unsigned int) *(char *)p;
else result = *(unsigned char *)p;
break;
default:
if (size != 1 && size != 2 && size != 4) {
fprintf(stderr, "Illegal size specified\n");
result = 0;
break;
} else {
DEBUG_READ_MEM((void*)DEBUG_ToLinear( addr ), buffer, size);
switch(size)
{
case 4:
if (is_signed) result = (unsigned int) *(int *)buffer;
else result = *(unsigned int *)buffer;
break;
case 2:
if (is_signed) result = (unsigned int) *(short int *)buffer;
else result = *(unsigned short int *)buffer;
break;
case 1:
if (is_signed) result = (unsigned int) *(char *)buffer;
else result = *(unsigned char *)buffer;
break;
}
}
return result;
}
@ -1041,18 +1043,16 @@ void db_print_address(char *seg, int size, struct i_addr *addrp, int byref)
/* try to get destination of indirect call
does not work for segmented adresses */
if (!seg && byref) {
DBG_ADDR dbg_addr = {NULL, 0, 0};
void* a1;
void* a2;
dbg_addr.off = addrp->disp;
fprintf(stderr,"0x%x -> ", addrp->disp);
if (DEBUG_IsBadReadPtr( &dbg_addr, sizeof(LPDWORD))) {
fprintf(stderr, "(invalid source)");
} else {
dbg_addr.off = *(LPDWORD)(addrp->disp);
if (DEBUG_IsBadReadPtr( &dbg_addr, sizeof(DWORD)))
fprintf(stderr, "(invalid destination)");
else
db_task_printsym(dbg_addr.off, 0);
if (!DEBUG_READ_MEM((void*)addrp->disp, &a1, sizeof(a1))) {
fprintf(stderr, "(invalid source)");
} else if (!DEBUG_READ_MEM(a1, &a2, sizeof(a2))) {
fprintf(stderr, "(invalid destination)");
} else {
db_task_printsym((unsigned long)a1, 0);
}
}
else
@ -1172,7 +1172,11 @@ void DEBUG_Disasm( DBG_ADDR *addr, int display )
* Set this so we get can supress the printout if we need to.
*/
db_display = display;
db_disasm_16 = IS_SELECTOR_V86(addr->seg) || !IS_SELECTOR_32BIT(addr->seg);
switch (DEBUG_GetSelectorType(addr->seg)) {
case 16: db_disasm_16 = 1; break;
case 32: db_disasm_16 = 0; break;
default: fprintf(stderr, "Bad selector %ld\n", addr->seg); return;
}
get_value_inc( inst, addr, 1, FALSE );

View File

@ -12,51 +12,21 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include "winbase.h"
#include "module.h"
#include "task.h"
#include "options.h"
#include "queue.h"
#include "wine/winbase16.h"
#include "winnt.h"
#include "x11drv.h"
#include "win.h"
#include "debugger.h"
#include "neexe.h"
#include "process.h"
#include "server.h"
#include "main.h"
#include "expr.h"
#include "user.h"
#include "wine/exception.h"
extern FILE * yyin;
unsigned int dbg_mode = 0;
HANDLE dbg_heap = 0;
int curr_frame = 0;
static enum exec_mode dbg_exec_mode = EXEC_CONT;
static int dbg_exec_count = 0;
void issue_prompt(void);
void mode_command(int);
void flush_symbols(void);
int yylex(void);
int yyerror(char *);
#ifdef DBG_need_heap
#define malloc(x) DBG_alloc(x)
#define realloc(x,y) DBG_realloc(x,y)
#define free(x) DBG_free(x)
#endif
extern void VIRTUAL_Dump(void); /* memory/virtual.c */
%}
%union
@ -126,41 +96,41 @@ command:
tQUIT tEOL { DEBUG_Exit(0); }
| tHELP tEOL { DEBUG_Help(); }
| tHELP tINFO tEOL { DEBUG_HelpInfo(); }
| tCONT tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_CONT; return 0; }
| tPASS tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_PASS; return 0; }
| tCONT tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_CONT; return 0; }
| tSTEP tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
| tNEXT tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_STEP_OVER; return 0; }
| tSTEP tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
| tNEXT tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_STEP_OVER; return 0; }
| tSTEPI tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
| tNEXTI tEOL { dbg_exec_count = 1;
dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
| tSTEPI tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
| tNEXTI tNUM tEOL { dbg_exec_count = $2;
dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
| tCONT tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; }
| tPASS tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return 0; }
| tCONT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; }
| tSTEP tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
| tNEXT tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
| tSTEP tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
| tNEXT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
| tSTEPI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
| tNEXTI tEOL { DEBUG_CurrThread->dbg_exec_count = 1;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
| tSTEPI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
| tNEXTI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2;
DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
| tABORT tEOL { kill(getpid(), SIGABRT); }
| tMODE tNUM tEOL { mode_command($2); }
| tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); }
| tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); }
| tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); }
| tBACKTRACE tEOL { DEBUG_BackTrace(); }
| tBACKTRACE tEOL { DEBUG_BackTrace(TRUE); }
| tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); }
| tUP tNUM tEOL { DEBUG_SetFrame( curr_frame + $2 ); }
| tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); }
| tDOWN tNUM tEOL { DEBUG_SetFrame( curr_frame - $2 ); }
| tFRAME tNUM tEOL { DEBUG_SetFrame( $2 ); }
| tFINISH tEOL { dbg_exec_count = 0;
dbg_exec_mode = EXEC_FINISH; return 0; }
| tFINISH tEOL { DEBUG_CurrThread->dbg_exec_count = 0;
DEBUG_CurrThread->dbg_exec_mode = EXEC_FINISH; return 0; }
| tSHOW tDIR tEOL { DEBUG_ShowDir(); }
| tDIR pathname tEOL { DEBUG_AddPath( $2 ); }
| tDIR tEOL { DEBUG_NukePath(); }
@ -173,7 +143,6 @@ command:
| tUNDISPLAY tEOL { DEBUG_DelDisplay( -1 ); }
| tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); }
| tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); }
| tDEBUGMSG tDEBUGSTR tEOL { MAIN_ParseDebugOptions($2); }
| tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); }
| list_command
| disassemble_command
@ -274,32 +243,30 @@ break_command:
info_command:
tINFO tBREAK tEOL { DEBUG_InfoBreakpoints(); }
| tINFO tCLASS expr_value tEOL { CLASS_DumpClass( (struct tagCLASS *)$3 );
DEBUG_FreeExprMem(); }
| tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); }
| tINFO tSHARE tEOL { DEBUG_InfoShare(); }
| tINFO tMODULE expr_value tEOL { NE_DumpModule( $3 );
| tINFO tMODULE expr_value tEOL { DEBUG_DumpModule( $3 );
DEBUG_FreeExprMem(); }
| tINFO tQUEUE expr_value tEOL { QUEUE_DumpQueue( $3 );
| tINFO tQUEUE expr_value tEOL { DEBUG_DumpQueue( $3 );
DEBUG_FreeExprMem(); }
| tINFO tREGS tEOL { DEBUG_InfoRegisters(); }
| tINFO tSEGMENTS expr_value tEOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 );
DEBUG_FreeExprMem(); }
| tINFO tSEGMENTS tEOL { LDT_Print( 0, -1 ); }
| tINFO tSEGMENTS expr_value tEOL { DEBUG_InfoSegments( $3, 1 ); DEBUG_FreeExprMem(); }
| tINFO tSEGMENTS tEOL { DEBUG_InfoSegments( 0, -1 ); }
| tINFO tSTACK tEOL { DEBUG_InfoStack(); }
| tINFO tMAPS tEOL { VIRTUAL_Dump(); }
| tINFO tWND expr_value tEOL { WIN_DumpWindow( $3 );
| tINFO tMAPS tEOL { DEBUG_InfoVirtual(); }
| tINFO tWND expr_value tEOL { DEBUG_InfoWindow( (HWND)$3 );
DEBUG_FreeExprMem(); }
| tINFO tLOCAL tEOL { DEBUG_InfoLocals(); }
| tINFO tDISPLAY tEOL { DEBUG_InfoDisplay(); }
walk_command:
tWALK tCLASS tEOL { CLASS_WalkClasses(); }
| tWALK tMODULE tEOL { NE_WalkModules(); }
| tWALK tQUEUE tEOL { QUEUE_WalkQueues(); }
| tWALK tWND tEOL { WIN_WalkWindows( 0, 0 ); }
| tWALK tWND tNUM tEOL { WIN_WalkWindows( $3, 0 ); }
| tWALK tPROCESS tEOL { PROCESS_WalkProcess(); }
| tWALK tMODREF expr_value tEOL { MODULE_WalkModref( $3 ); }
tWALK tCLASS tEOL { DEBUG_WalkClasses(); }
| tWALK tMODULE tEOL { DEBUG_WalkModules(); }
| tWALK tQUEUE tEOL { DEBUG_WalkQueues(); }
| tWALK tWND tEOL { DEBUG_WalkWindows( 0, 0 ); }
| tWALK tWND tNUM tEOL { DEBUG_WalkWindows( $3, 0 ); }
| tWALK tPROCESS tEOL { DEBUG_WalkProcess(); }
| tWALK tMODREF expr_value tEOL { DEBUG_WalkModref( $3 ); }
type_cast:
@ -326,11 +293,13 @@ type_expr:
| tENUM tIDENTIFIER { $$ = DEBUG_TypeCast(DT_ENUM, $2); }
expr_addr:
expr { $$ = DEBUG_EvalExpr($1); }
expr { $$ = DEBUG_EvalExpr($1); }
expr_value:
expr { DBG_ADDR addr = DEBUG_EvalExpr($1);
$$ = addr.off ? *(unsigned int *) addr.off : 0; }
expr { DBG_ADDR addr = DEBUG_EvalExpr($1);
/* expr_value is typed as an integer */
if (!addr.off || !DEBUG_READ_MEM((void*)addr.off, &$$, sizeof($$)))
$$ = 0; }
/*
* The expr rule builds an expression tree. When we are done, we call
* EvalExpr to evaluate the value of the expression. The advantage of
@ -410,50 +379,27 @@ issue_prompt(){
void mode_command(int newmode)
{
if ((newmode == 16) || (newmode == 32)) dbg_mode = newmode;
if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode;
else fprintf(stderr,"Invalid mode (use 16 or 32)\n");
}
/***********************************************************************
* DEBUG_Freeze
*/
static void DEBUG_Freeze( BOOL freeze )
static WINE_EXCEPTION_FILTER(no_symbol)
{
static BOOL frozen = FALSE;
if ( freeze && !frozen )
{
if ( X11DRV_CritSection.LockSemaphore )
{
/* Don't freeze thread currently holding the X crst! */
EnterCriticalSection( &X11DRV_CritSection );
CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL );
LeaveCriticalSection( &X11DRV_CritSection );
}
else
CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL );
frozen = TRUE;
}
if ( !freeze && frozen )
{
CLIENT_DebuggerRequest( DEBUGGER_UNFREEZE_ALL );
frozen = FALSE;
}
if (GetExceptionCode() == DEBUG_STATUS_NO_SYMBOL)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
/***********************************************************************
* DEBUG_Exit
*
* Kill current process.
*
*/
void DEBUG_Exit( DWORD exit_code )
{
DEBUG_Freeze( FALSE );
TASK_KillTask( 0 ); /* FIXME: should not be necessary */
TerminateProcess( GetCurrentProcess(), exit_code );
TASK_KillTask( 0 ); /* FIXME: should not be necessary */
TerminateProcess( DEBUG_CurrProcess->handle, exit_code );
}
/***********************************************************************
@ -461,261 +407,131 @@ void DEBUG_Exit( DWORD exit_code )
*
* Debugger main loop.
*/
static void DEBUG_Main( BOOL is_debug )
BOOL DEBUG_Main( BOOL is_debug, BOOL force )
{
static int loaded_symbols = 0;
static BOOL in_debugger = FALSE;
char SymbolTableFile[256];
int newmode;
BOOL ret_ok;
char ch;
#ifdef YYDEBUG
yydebug = 0;
#endif
if (in_debugger)
{
fprintf( stderr, " inside debugger, trying to invoke external debugger.\n" );
DEBUG_ExternalDebugger();
DEBUG_Exit(1);
}
in_debugger = TRUE;
yyin = stdin;
DEBUG_SetBreakpoints( FALSE );
DEBUG_SuspendExecution();
if (!is_debug)
{
#ifdef __i386__
if (IS_SELECTOR_SYSTEM(CS_reg(&DEBUG_context)))
fprintf( stderr, " in 32-bit code (0x%08lx).\n", EIP_reg(&DEBUG_context));
if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs))
fprintf( stderr, " in 32-bit code (0x%08lx).\n", DEBUG_context.Eip );
else
fprintf( stderr, " in 16-bit code (%04x:%04lx).\n",
(WORD)CS_reg(&DEBUG_context), EIP_reg(&DEBUG_context) );
(WORD)DEBUG_context.SegCs, DEBUG_context.Eip );
#else
fprintf( stderr, " (%p).\n", GET_IP(&DEBUG_context) );
fprintf( stderr, " (%p).\n", GET_IP(DEBUG_CurrThread->context) );
#endif
}
if (!loaded_symbols)
{
loaded_symbols++;
if (DEBUG_LoadEntryPoints("Loading new modules symbols:\n"))
DEBUG_ProcessDeferredDebug();
DEBUG_Freeze( TRUE );
#ifdef DBG_need_heap
/*
* Initialize the debugger heap.
*/
dbg_heap = HeapCreate(HEAP_NO_SERIALIZE, 0x1000, 0x8000000); /* 128MB */
#endif
/*
* Initialize the type handling stuff.
*/
DEBUG_InitTypes();
DEBUG_InitCVDataTypes();
/*
* In some cases we can read the stabs information directly
* from the executable. If this is the case, we don't need
* to bother with trying to read a symbol file, as the stabs
* also have line number and local variable information.
* As long as gcc is used for the compiler, stabs will
* be the default. On SVr4, DWARF could be used, but we
* don't grok that yet, and in this case we fall back to using
* the wine.sym file.
*/
if( DEBUG_ReadExecutableDbgInfo() == FALSE )
{
char *symfilename = "wine.sym";
struct stat statbuf;
if (-1 == stat(symfilename, &statbuf) )
symfilename = LIBDIR "wine.sym";
PROFILE_GetWineIniString( "wine", "SymbolTableFile", symfilename,
SymbolTableFile, sizeof(SymbolTableFile));
DEBUG_ReadSymbolTable( SymbolTableFile );
}
DEBUG_LoadEntryPoints(NULL);
DEBUG_ProcessDeferredDebug();
}
else
{
if (DEBUG_LoadEntryPoints("Loading new modules symbols:\n"))
DEBUG_ProcessDeferredDebug();
}
#if 0
fprintf(stderr, "Entering debugger PC=%x, mode=%d, count=%d\n",
EIP_reg(&DEBUG_context),
dbg_exec_mode, dbg_exec_count);
sleep(1);
#endif
if (!is_debug || !DEBUG_ShouldContinue( dbg_exec_mode, &dbg_exec_count ))
if (force || !(is_debug && DEBUG_ShouldContinue( DEBUG_CurrThread->dbg_exec_mode, &DEBUG_CurrThread->dbg_exec_count )))
{
DBG_ADDR addr;
DEBUG_GetCurrentAddress( &addr );
DEBUG_Freeze( TRUE );
/* Put the display in a correct state */
if (USER_Driver) USER_Driver->pBeginDebugging();
/* EPP if (USER_Driver) USER_Driver->pBeginDebugging(); */
#ifdef __i386__
newmode = ISV86(&DEBUG_context) ? 16 : IS_SELECTOR_32BIT(addr.seg) ? 32 : 16;
switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
case 16: case 32: break;
default: fprintf(stderr, "Bad CS (%ld)\n", addr.seg); newmode = 32;
}
#else
newmode = 32;
#endif
if (newmode != dbg_mode)
fprintf(stderr,"In %d bit mode.\n", dbg_mode = newmode);
if (newmode != DEBUG_CurrThread->dbg_mode)
fprintf(stderr,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode);
DEBUG_DoDisplay();
if (!is_debug) /* This is a real crash, dump some info */
{
DEBUG_InfoRegisters();
DEBUG_InfoStack();
#ifdef __i386__
if (dbg_mode == 16)
{
LDT_Print( SELECTOR_TO_ENTRY(DS_reg(&DEBUG_context)), 1 );
if (ES_reg(&DEBUG_context) != DS_reg(&DEBUG_context))
LDT_Print( SELECTOR_TO_ENTRY(ES_reg(&DEBUG_context)), 1 );
}
LDT_Print( SELECTOR_TO_ENTRY(FS_reg(&DEBUG_context)), 1 );
#endif
DEBUG_BackTrace();
}
else
if (is_debug || force)
{
/*
* Do a quiet backtrace so that we have an idea of what the situation
* is WRT the source files.
*/
DEBUG_SilentBackTrace();
DEBUG_BackTrace(FALSE);
}
else
{
/* This is a real crash, dump some info */
DEBUG_InfoRegisters();
DEBUG_InfoStack();
#ifdef __i386__
if (DEBUG_CurrThread->dbg_mode == 16)
{
DEBUG_InfoSegments( DEBUG_context.SegDs >> 3, 1 );
if (DEBUG_context.SegEs != DEBUG_context.SegDs)
DEBUG_InfoSegments( DEBUG_context.SegEs >> 3, 1 );
}
DEBUG_InfoSegments( DEBUG_context.SegFs >> 3, 1 );
#endif
DEBUG_BackTrace(TRUE);
}
if (!is_debug ||
(dbg_exec_mode == EXEC_STEPI_OVER) ||
(dbg_exec_mode == EXEC_STEPI_INSTR))
(DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
(DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR))
{
/* Show where we crashed */
curr_frame = 0;
DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
fprintf(stderr,": ");
if (DBG_CHECK_READ_PTR( &addr, 1 ))
{
DEBUG_Disasm( &addr, TRUE );
fprintf(stderr,"\n");
}
DEBUG_Disasm( &addr, TRUE );
fprintf( stderr, "\n" );
}
ret_ok = 0;
do
{
issue_prompt();
yyparse();
flush_symbols();
__TRY
{
issue_prompt();
yyparse();
flush_symbols();
DEBUG_GetCurrentAddress( &addr );
if ((ret_ok = DEBUG_ValidateRegisters()))
ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 );
}
__EXCEPT(no_symbol)
{
fprintf(stderr, "Undefined symbol\n");
ret_ok = 0;
}
__ENDTRY;
DEBUG_GetCurrentAddress( &addr );
ret_ok = DEBUG_ValidateRegisters();
if (ret_ok) ret_ok = DBG_CHECK_READ_PTR( &addr, 1 );
} while (!ret_ok);
}
dbg_exec_mode = DEBUG_RestartExecution( dbg_exec_mode, dbg_exec_count );
DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution( DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count );
/*
* This will have gotten absorbed into the breakpoint info
* if it was used. Otherwise it would have been ignored.
* In any case, we don't mess with it any more.
*/
if ((dbg_exec_mode == EXEC_CONT) || (dbg_exec_mode == EXEC_PASS))
{
dbg_exec_count = 0;
if ((DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT) || (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS))
DEBUG_CurrThread->dbg_exec_count = 0;
DEBUG_Freeze( FALSE );
}
in_debugger = FALSE;
if (USER_Driver) USER_Driver->pEndDebugging();
/* EPP if (USER_Driver) USER_Driver->pEndDebugging(); */
return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE;
}
DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance )
{
BOOL is_debug = FALSE;
if (first_chance && !Options.debug) return 0; /* pass to app first */
switch(rec->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
is_debug = TRUE;
break;
case CONTROL_C_EXIT:
if (!Options.debug) DEBUG_Exit(0);
break;
}
if (!is_debug)
{
/* print some infos */
fprintf( stderr, "%s: ",
first_chance ? "First chance exception" : "Unhandled exception" );
switch(rec->ExceptionCode)
{
case EXCEPTION_INT_DIVIDE_BY_ZERO:
fprintf( stderr, "divide by zero" );
break;
case EXCEPTION_INT_OVERFLOW:
fprintf( stderr, "overflow" );
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
fprintf( stderr, "array bounds " );
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
fprintf( stderr, "illegal instruction" );
break;
case EXCEPTION_STACK_OVERFLOW:
fprintf( stderr, "stack overflow" );
break;
case EXCEPTION_PRIV_INSTRUCTION:
fprintf( stderr, "priviledged instruction" );
break;
case EXCEPTION_ACCESS_VIOLATION:
if (rec->NumberParameters == 2)
fprintf( stderr, "page fault on %s access to 0x%08lx",
rec->ExceptionInformation[0] ? "write" : "read",
rec->ExceptionInformation[1] );
else
fprintf( stderr, "page fault" );
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
fprintf( stderr, "Alignment" );
break;
case CONTROL_C_EXIT:
fprintf( stderr, "^C" );
break;
case EXCEPTION_CRITICAL_SECTION_WAIT:
fprintf( stderr, "critical section %08lx wait failed", rec->ExceptionInformation[0] );
break;
default:
fprintf( stderr, "%08lx", rec->ExceptionCode );
break;
}
}
DEBUG_context = *context;
DEBUG_Main( is_debug );
*context = DEBUG_context;
return (dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE;
}
int yyerror(char * s)
int yyerror(char* s)
{
fprintf(stderr,"%s\n", s);
return 0;

View File

@ -119,7 +119,6 @@ $gs { yylval.reg = REG_GS; return tREG; }
<INITIAL>frame|fram|fra|fr { BEGIN(NOCMD); return tFRAME; }
<INITIAL>list|lis|li|l { BEGIN(PATH_EXPECTED); return tLIST; }
<INITIAL>enable|enabl|enab|ena { BEGIN(NOCMD); return tENABLE;}
<INITIAL>debugmsg|debugms|debugm|debug|debu|deb { BEGIN(DEBUGSTR); return tDEBUGMSG;}
<INITIAL>disable|disabl|disab|disa|dis { BEGIN(NOCMD); return tDISABLE; }
<INITIAL>disassemble|disassembl|disassemb|disassem|disasse|disass|disas { BEGIN(NOCMD); return tDISASSEMBLE; }
<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; }

View File

@ -9,9 +9,12 @@
#include <sys/types.h> /* u_long ... */
#include "windef.h"
#include "miscemu.h"
#include "winbase.h"
#ifdef __i386__
#define STEP_FLAG 0x100 /* single step flag */
#define V86_FLAG 0x00020000
#endif
#define SYM_FUNC 0x0
#define SYM_DATA 0x1
@ -83,43 +86,73 @@ struct wine_locals {
typedef struct wine_locals WineLocals;
enum exec_mode
{
EXEC_CONT, /* Continuous execution */
EXEC_PASS, /* Continue, passing exception to app */
EXEC_STEP_OVER, /* Stepping over a call to next source line */
EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */
EXEC_STEPI_OVER, /* Stepping over a call */
EXEC_STEPI_INSTR, /* Single-stepping an instruction */
EXEC_FINISH, /* Step until we exit current frame */
EXEC_STEP_OVER_TRAMPOLINE /* Step over trampoline. Requires that
* we dig the real return value off the stack
* and set breakpoint there - not at the
* instr just after the call.
*/
};
typedef struct
{
DBG_ADDR addr;
BYTE addrlen;
BYTE opcode;
WORD skipcount;
WORD enabled : 1,
refcount;
struct expr * condition;
} BREAKPOINT;
typedef struct tagWINE_DBG_THREAD {
struct tagWINE_DBG_PROCESS* process;
HANDLE handle;
DWORD tid;
LPVOID start;
LPVOID teb;
int wait_for_first_exception;
int dbg_mode;
enum exec_mode dbg_exec_mode;
int dbg_exec_count;
BREAKPOINT stepOverBP;
struct tagWINE_DBG_THREAD* next;
struct tagWINE_DBG_THREAD* prev;
} WINE_DBG_THREAD;
typedef struct tagWINE_DBG_PROCESS {
HANDLE handle;
DWORD pid;
WINE_DBG_THREAD* threads;
struct tagWINE_DBG_PROCESS* next;
struct tagWINE_DBG_PROCESS* prev;
} WINE_DBG_PROCESS;
extern WINE_DBG_PROCESS* DEBUG_CurrProcess;
extern WINE_DBG_THREAD* DEBUG_CurrThread;
extern CONTEXT DEBUG_context;
#define DEBUG_READ_MEM(addr, buf, len) \
(ReadProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL))
#define DEBUG_WRITE_MEM(addr, buf, len) \
(WriteProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL))
#define DEBUG_READ_MEM_VERBOSE(addr, buf, len) \
(DEBUG_READ_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
#define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \
(DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0))
#ifdef __i386__
#define DBG_V86_MODULE(seg) ((seg)>>16)
#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg)
#define DBG_FIX_ADDR_SEG(addr,default) { \
if ((addr)->seg == 0xffffffff) (addr)->seg = (default); \
if (!IS_SELECTOR_V86((addr)->seg)) \
if (IS_SELECTOR_SYSTEM((addr)->seg)) (addr)->seg = 0; }
#define DBG_ADDR_TO_LIN(addr) \
(IS_SELECTOR_V86((addr)->seg) \
? (char*)(DOSMEM_MemoryBase(DBG_V86_MODULE((addr)->seg)) + \
((((addr)->seg)&0xFFFF)<<4)+(addr)->off) : \
(IS_SELECTOR_SYSTEM((addr)->seg) ? (char *)(addr)->off \
: (char *)PTR_SEG_OFF_TO_LIN((addr)->seg,(addr)->off)))
#else /* __i386__ */
#define DBG_FIX_ADDR_SEG(addr,default)
#define DBG_ADDR_TO_LIN(addr) ((char *)(addr)->off)
#endif /* __386__ */
#define DBG_CHECK_READ_PTR(addr,len) \
(!DEBUG_IsBadReadPtr((addr),(len)) || \
(fprintf(stderr,"*** Invalid address "), \
DEBUG_PrintAddress((addr),dbg_mode, FALSE), \
fprintf(stderr,"\n"),0))
#define DBG_CHECK_WRITE_PTR(addr,len) \
(!DEBUG_IsBadWritePtr((addr),(len)) || \
(fprintf(stderr,"*** Invalid address "), \
DEBUG_PrintAddress(addr,dbg_mode, FALSE), \
fprintf(stderr,"\n"),0))
#ifdef REG_SP /* Some Sun includes define this */
#undef REG_SP
#endif
@ -128,42 +161,24 @@ enum debug_regs
{
REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_ESI,
REG_EDI, REG_EBP, REG_EFL, REG_EIP, REG_ESP,
REG_AX, REG_BX, REG_CX, REG_DX, REG_SI,
REG_DI, REG_BP, REG_FL, REG_IP, REG_SP,
REG_CS, REG_DS, REG_ES, REG_SS, REG_FS, REG_GS
REG_AX, REG_BX, REG_CX, REG_DX, REG_SI,
REG_DI, REG_BP, REG_FL, REG_IP, REG_SP,
REG_CS, REG_DS, REG_ES, REG_SS, REG_FS, REG_GS
};
#endif
enum exec_mode
{
EXEC_CONT, /* Continuous execution */
EXEC_PASS, /* Continue, passing exception to app */
EXEC_STEP_OVER, /* Stepping over a call to next source line */
EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */
EXEC_STEPI_OVER, /* Stepping over a call */
EXEC_STEPI_INSTR, /* Single-stepping an instruction */
EXEC_FINISH, /* Step until we exit current frame */
EXEC_STEP_OVER_TRAMPOLINE /* Step over trampoline. Requires that
* we dig the real return value off the stack
* and set breakpoint there - not at the
* instr just after the call.
*/
};
extern CONTEXT DEBUG_context; /* debugger/registers.c */
extern unsigned int dbg_mode;
extern HANDLE dbg_heap;
#define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
/* debugger/break.c */
extern void DEBUG_SetBreakpoints( BOOL set );
extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr );
extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr );
extern void DEBUG_AddBreakpoint( const DBG_ADDR *addr );
extern void DEBUG_DelBreakpoint( int num );
extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
extern void DEBUG_InfoBreakpoints(void);
extern void DEBUG_AddTaskEntryBreakpoint( HTASK16 hTask );
extern BOOL DEBUG_HandleTrap(void);
extern BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count );
extern void DEBUG_SuspendExecution( void );
extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
extern BOOL DEBUG_IsFctReturn(void);
@ -185,8 +200,8 @@ struct expr * DEBUG_StructExpr(struct expr *, const char * element);
struct expr * DEBUG_ArrayExpr(struct expr *, struct expr * index);
struct expr * DEBUG_CallExpr(const char *, int nargs, ...);
struct expr * DEBUG_TypeCastExpr(struct datatype *, struct expr *);
extern int DEBUG_ExprValue(DBG_ADDR *, unsigned int *);
DBG_ADDR DEBUG_EvalExpr(struct expr *);
extern int DEBUG_ExprValue(const DBG_ADDR *, unsigned int *);
extern DBG_ADDR DEBUG_EvalExpr(struct expr *);
extern int DEBUG_DelDisplay(int displaynum);
extern struct expr * DEBUG_CloneExpr(struct expr * exp);
extern int DEBUG_FreeExpr(struct expr * exp);
@ -211,7 +226,7 @@ extern struct name_hash * DEBUG_AddInvSymbol( const char *name,
const DBG_ADDR *addr,
const char * sourcefile);
extern BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
DBG_ADDR *addr, int );
DBG_ADDR *addr, int );
extern BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr );
extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
struct name_hash ** rtn,
@ -251,13 +266,32 @@ extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr,
int addrlen,
unsigned int ebp,
int flag );
extern void DEBUG_InfoClass(const char* clsName);
extern void DEBUG_WalkClasses(void);
extern void DEBUG_WalkModref(DWORD p);
extern void DEBUG_DumpModule(DWORD mod);
extern void DEBUG_WalkModules(void);
extern void DEBUG_WalkProcess(void);
extern void DEBUG_DumpQueue(DWORD q);
extern void DEBUG_WalkQueues(void);
extern void DEBUG_InfoSegments(DWORD s, int v);
extern void DEBUG_InfoVirtual(void);
extern void DEBUG_InfoWindow(HWND hWnd);
extern void DEBUG_WalkWindows(HWND hWnd, int indent);
/* debugger/memory.c */
extern BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size );
extern BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size );
extern int DEBUG_ReadMemory( const DBG_ADDR *address );
extern void DEBUG_WriteMemory( const DBG_ADDR *address, int value );
extern void DEBUG_ExamineMemory( const DBG_ADDR *addr, int count, char format);
extern void DEBUG_InvalLinAddr( void* addr );
#ifdef __i386__
extern void DEBUG_GetCurrentAddress( DBG_ADDR * );
extern DWORD DEBUG_ToLinear( const DBG_ADDR *address );
extern void DEBUG_FixAddress( DBG_ADDR *address, DWORD def );
extern BOOL DEBUG_FixSegment( DBG_ADDR* addr );
extern int DEBUG_GetSelectorType( WORD sel );
extern int DEBUG_IsSelectorSystem( WORD sel );
#endif
/* debugger/registers.c */
extern void DEBUG_SetRegister( enum debug_regs reg, int val );
@ -268,8 +302,7 @@ extern int DEBUG_PrintRegister(enum debug_regs reg);
/* debugger/stack.c */
extern void DEBUG_InfoStack(void);
extern void DEBUG_BackTrace(void);
extern void DEBUG_SilentBackTrace(void);
extern void DEBUG_BackTrace(BOOL noisy);
extern int DEBUG_InfoLocals(void);
extern int DEBUG_SetFrame(int newframe);
extern int DEBUG_GetCurrentFrame(struct name_hash ** name,
@ -293,7 +326,7 @@ extern void DEBUG_InitTypes(void);
extern struct datatype * DEBUG_NewDataType(enum debug_type xtype,
const char * typename);
extern unsigned int
DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype);
DEBUG_TypeDerefPointer(const DBG_ADDR * addr, struct datatype ** newtype);
extern int DEBUG_AddStructElement(struct datatype * dt,
char * name, struct datatype * type,
int offset, int size);
@ -306,9 +339,9 @@ extern unsigned int DEBUG_FindStructElement(DBG_ADDR * addr,
const char * ele_name, int * tmpbuf);
extern struct datatype * DEBUG_GetPointerType(struct datatype * dt);
extern int DEBUG_GetObjectSize(struct datatype * dt);
extern unsigned int DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index);
extern unsigned int DEBUG_ArrayIndex(const DBG_ADDR * addr, DBG_ADDR * result, int index);
extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
extern long long int DEBUG_GetExprValue(DBG_ADDR * addr, char ** format);
extern long long int DEBUG_GetExprValue(const DBG_ADDR * addr, char ** format);
extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset,
int nbits, struct datatype * dt2);
extern int DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2);
@ -322,24 +355,26 @@ 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_GetCurrentAddress( DBG_ADDR * );
extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset );
/* debugger/external.c */
extern void DEBUG_ExternalDebugger(void);
/* debugger/dbg.y */
extern DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
extern void DEBUG_Exit( DWORD exit_code );
extern BOOL DEBUG_Main( BOOL is_debug, BOOL force );
/* Choose your allocator! */
#if 1
/* this one is libc's fast one */
#include "xmalloc.h"
#define DBG_alloc(x) xmalloc(x)
#define DBG_realloc(x,y) xrealloc(x,y)
#define DBG_free(x) free(x)
#define DBG_strdup(x) xstrdup(x)
extern void* DEBUG_XMalloc(size_t size);
extern void* DEBUG_XReAlloc(void *ptr, size_t size);
extern char* DEBUG_XStrDup(const char *str);
#define DBG_alloc(x) DEBUG_XMalloc(x)
#define DBG_realloc(x,y) DEBUG_XReAlloc(x,y)
#define DBG_free(x) free(x)
#define DBG_strdup(x) DEBUG_XStrDup(x)
#else
/* this one is slow (takes 5 minutes to load the debugger on my machine),
but is pretty crash-proof (can step through malloc() without problems,
@ -352,6 +387,9 @@ extern void DEBUG_Exit( DWORD exit_code );
#define DBG_free(x) HeapFree(dbg_heap,0,x)
#define DBG_strdup(x) HEAP_strdupA(dbg_heap,0,x)
#define DBG_need_heap
extern HANDLE dbg_heap;
#endif
#define DEBUG_STATUS_NO_SYMBOL 0x80003000
#endif /* __WINE_DEBUGGER_H */

View File

@ -11,9 +11,6 @@
#include <limits.h>
#include <sys/types.h>
#include "neexe.h"
#include "module.h"
#include "selectors.h"
#include "debugger.h"
#include <stdarg.h>

View File

@ -299,7 +299,6 @@ DEBUG_EvalExpr(struct expr * exp)
DBG_ADDR exp1;
DBG_ADDR exp2;
unsigned int cexp[5];
int (*fptr)();
int scale1;
int scale2;
int scale3;
@ -332,12 +331,20 @@ DEBUG_EvalExpr(struct expr * exp)
rtn.seg = 0;
break;
case EXPR_TYPE_SYMBOL:
if( !DEBUG_GetSymbolValue(exp->un.symbol.name, -1, &rtn, FALSE ) )
{
rtn.type = NULL;
rtn.off = 0;
rtn.seg = 0;
};
if( !DEBUG_GetSymbolValue(exp->un.symbol.name, -1, &rtn, FALSE) )
{
#if 1
RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL);
#else
static char ret[128];
/* FIXME: this is an ugly hack... but at least we know
* the symbol is not defined
*/
sprintf(ret, "\"Symbol %s is not defined.\"", exp->un.symbol.name);
rtn = DEBUG_EvalExpr(DEBUG_StringExpr(ret));
#endif
}
break;
case EXPR_TYPE_PSTRUCT:
exp1 = DEBUG_EvalExpr(exp->un.structure.exp1);
@ -388,6 +395,13 @@ DEBUG_EvalExpr(struct expr * exp)
break;
}
#if 0
/* FIXME: NEWDBG NIY */
/* Anyway, I wonder how this could work depending on the calling order of
* the function (cdecl vs pascal for example)
*/
int (*fptr)();
fptr = (int (*)()) rtn.off;
switch(exp->un.call.nargs)
{
@ -410,8 +424,16 @@ DEBUG_EvalExpr(struct expr * exp)
exp->un.call.result = (*fptr)(cexp[0], cexp[1], cexp[2], cexp[3], cexp[4]);
break;
}
#else
fprintf(stderr, "Function call no longer implemented\n");
/* would need to set up a call to this function, and then restore the current
* context afterwards...
*/
exp->un.call.result = 0;
#endif
rtn.type = DEBUG_TypeInt;
rtn.off = (unsigned int) &exp->un.call.result;
break;
case EXPR_TYPE_REGISTER:
rtn.type = DEBUG_TypeIntConst;
@ -419,11 +441,11 @@ DEBUG_EvalExpr(struct expr * exp)
rtn.off = (unsigned int) &exp->un.rgister.result;
#ifdef __i386__
if( exp->un.rgister.reg == REG_EIP )
rtn.seg = CS_reg(&DEBUG_context);
rtn.seg = DEBUG_context.SegCs;
else
rtn.seg = DS_reg(&DEBUG_context);
rtn.seg = DEBUG_context.SegDs;
#endif
DBG_FIX_ADDR_SEG( &rtn, 0 );
DEBUG_FixAddress( &rtn, 0 );
break;
case EXPR_TYPE_BINOP:
exp1 = DEBUG_EvalExpr(exp->un.binop.exp1);
@ -497,11 +519,7 @@ DEBUG_EvalExpr(struct expr * exp)
rtn.seg = VAL(exp1);
exp->un.binop.result = VAL(exp2);
#ifdef __i386__
if (ISV86(&DEBUG_context)) {
TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() );
rtn.seg |= (DWORD)(pTask?(pTask->hModule):0)<<16;
GlobalUnlock16( GetCurrentTask() );
}
DEBUG_FixSegment(&rtn);
#endif
break;
case EXP_OP_LOR:
@ -623,12 +641,12 @@ DEBUG_EvalExpr(struct expr * exp)
exp->un.unop.result = ~VAL(exp1);
break;
case EXP_OP_DEREF:
rtn.seg = 0;
rtn.seg = 0;
rtn.off = (unsigned int) DEBUG_TypeDerefPointer(&exp1, &rtn.type);
break;
case EXP_OP_FORCE_DEREF:
rtn.seg = exp1.seg;
rtn.off = *(unsigned int *) exp1.off;
rtn.off = DEBUG_READ_MEM((void*)exp1.off, &rtn.off, sizeof(rtn.off));
break;
case EXP_OP_ADDR:
rtn.seg = 0;
@ -686,10 +704,6 @@ DEBUG_DisplayExpr(struct expr * exp)
fprintf(stderr, ".%s", exp->un.structure.element_name);
break;
case EXPR_TYPE_CALL:
/*
* First, evaluate all of the arguments. If any of them are not
* evaluable, then bail.
*/
fprintf(stderr, "%s(",exp->un.call.funcname);
for(i=0; i < exp->un.call.nargs; i++)
{
@ -841,10 +855,6 @@ DEBUG_CloneExpr(struct expr * exp)
rtn->un.structure.element_name = DBG_strdup(exp->un.structure.element_name);
break;
case EXPR_TYPE_CALL:
/*
* First, evaluate all of the arguments. If any of them are not
* evaluable, then bail.
*/
for(i=0; i < exp->un.call.nargs; i++)
{
rtn->un.call.arg[i] = DEBUG_CloneExpr(exp->un.call.arg[i]);
@ -898,10 +908,6 @@ DEBUG_FreeExpr(struct expr * exp)
DBG_free((char *) exp->un.structure.element_name);
break;
case EXPR_TYPE_CALL:
/*
* First, evaluate all of the arguments. If any of them are not
* evaluable, then bail.
*/
for(i=0; i < exp->un.call.nargs; i++)
{
DEBUG_FreeExpr(exp->un.call.arg[i]);

View File

@ -14,7 +14,6 @@
#include "neexe.h"
#include "module.h"
#include "process.h"
#include "selectors.h"
#include "debugger.h"
#include "toolhelp.h"
@ -335,7 +334,7 @@ BOOL DEBUG_Normalize(struct name_hash * nh )
* Get the address of a named symbol.
*/
BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
DBG_ADDR *addr, int bp_flag )
DBG_ADDR *addr, int bp_flag )
{
char buffer[256];
struct name_hash *nh;
@ -450,7 +449,7 @@ BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
if (!nh) return FALSE;
nh->addr = *addr;
nh->flags &= SYM_INVALID;
DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(&DEBUG_context) );
DEBUG_FixAddress( &nh->addr, DEBUG_context.SegDs );
return TRUE;
}
@ -477,6 +476,7 @@ const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
char * lineinfo, *sourcefile;
int i;
char linebuff[16];
unsigned val;
if( rtn != NULL )
{
@ -637,9 +637,9 @@ const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
{
strcat(arglist, ", ");
}
DEBUG_READ_MEM_VERBOSE(ptr, &val, sizeof(val));
sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name, val);
sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name,
*ptr);
strcat(arglist, argtmp);
}
if( arglist[0] == '(' )
@ -1367,13 +1367,26 @@ BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
/* FIXME: what if regno == 0 ($eax) */
if( curr_func->local_vars[i].regno != 0 )
{
#if 0
/* FIXME: NEWDBG NIY */
/* this is a hack: addr points to the current processor context
* (as defined while entering the debugger), and uses a pointer
* to main memory (thus sharing the process address space *AND*
* the debugger address space, which is not good with address
* space separation in place)
*/
/*
* Register variable. Point to DEBUG_context field.
*/
addr->seg = 0;
addr->off = ((DWORD)&DEBUG_context) + reg_ofs[curr_func->local_vars[i].regno];
addr->off = ((DWORD)DEBUG_context) + reg_ofs[curr_func->local_vars[i].regno];
addr->type = curr_func->local_vars[i].type;
#else
fprintf(stderr, "No longer supported: value of register variable\n");
addr->seg = 0;
addr->off = 0;
addr->type = NULL;
#endif
return TRUE;
}
@ -1395,7 +1408,7 @@ DEBUG_InfoLocals()
unsigned int eip;
int i;
unsigned int * ptr;
int rtn = FALSE;
unsigned int val;
if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
{
@ -1433,16 +1446,14 @@ DEBUG_InfoLocals()
}
else
{
ptr = (unsigned int *) (ebp + curr_func->local_vars[i].offset);
DEBUG_READ_MEM_VERBOSE((void*)(ebp + curr_func->local_vars[i].offset),
&val, sizeof(val));
fprintf(stderr, "%s:%s == 0x%8.8x\n",
curr_func->name, curr_func->local_vars[i].name,
*ptr);
curr_func->name, curr_func->local_vars[i].name, val);
}
}
rtn = TRUE;
return (rtn);
return TRUE;
}
int

View File

@ -8,6 +8,10 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "toolhelp.h"
#include "debugger.h"
#include "expr.h"
@ -28,7 +32,7 @@ void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format )
}
default_format = NULL;
value = DEBUG_GetExprValue((DBG_ADDR *) addr, &default_format);
value = DEBUG_GetExprValue(addr, &default_format);
switch(format)
{
@ -188,3 +192,264 @@ NULL
while(infotext[i]) fprintf(stderr,"%s\n", infotext[i++]);
}
/* FIXME: merge InfoClass and InfoClass2 */
void DEBUG_InfoClass(const char* name)
{
WNDCLASSEXA wca;
if (!GetClassInfoExA(0, name, &wca)) {
fprintf(stderr, "Cannot find class '%s'\n", name);
return;
}
fprintf(stderr, "Class '%s':\n", name);
fprintf(stderr,
"style=%08x wndProc=%08lx\n"
"inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
"clsExtra=%d winExtra=%d\n",
wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
wca.hIcon, wca.hCursor, wca.hbrBackground,
wca.cbClsExtra, wca.cbWndExtra);
/* FIXME:
* + print #windows (or even list of windows...)
* + print extra bytes => this requires a window handle on this very class...
*/
}
static void DEBUG_InfoClass2(HWND hWnd, const char* name)
{
WNDCLASSEXA wca;
if (!GetClassInfoExA(GetWindowLongA(hWnd, GWL_HINSTANCE), name, &wca)) {
fprintf(stderr, "Cannot find class '%s'\n", name);
return;
}
fprintf(stderr, "Class '%s':\n", name);
fprintf(stderr,
"style=%08x wndProc=%08lx\n"
"inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n"
"clsExtra=%d winExtra=%d\n",
wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance,
wca.hIcon, wca.hCursor, wca.hbrBackground,
wca.cbClsExtra, wca.cbWndExtra);
if (wca.cbClsExtra) {
int i;
WORD w;
fprintf(stderr, "Extra bytes:" );
for (i = 0; i < wca.cbClsExtra / 2; i++) {
w = GetClassWord(hWnd, i * 2);
/* FIXME: depends on i386 endian-ity */
fprintf(stderr, " %02x", HIBYTE(w));
fprintf(stderr, " %02x", LOBYTE(w));
}
fprintf(stderr, "\n" );
}
fprintf(stderr, "\n" );
}
struct class_walker {
ATOM* table;
int used;
int alloc;
};
static void DEBUG_WalkClassesHelper(HWND hWnd, struct class_walker* cw)
{
char clsName[128];
int i;
ATOM atom;
HWND child;
if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
return;
if ((atom = FindAtomA(clsName)) == 0)
return;
for (i = 0; i < cw->used; i++) {
if (cw->table[i] == atom)
break;
}
if (i == cw->used) {
if (cw->used >= cw->alloc) {
cw->alloc += 16;
cw->table = DBG_realloc(cw->table, cw->alloc * sizeof(ATOM));
}
cw->table[cw->used++] = atom;
DEBUG_InfoClass2(hWnd, clsName);
}
do {
if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
DEBUG_WalkClassesHelper(child, cw);
} while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
}
void DEBUG_WalkClasses(void)
{
struct class_walker cw;
cw.table = NULL;
cw.used = cw.alloc = 0;
DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw);
DBG_free(cw.table);
}
void DEBUG_DumpModule(DWORD mod)
{
fprintf(stderr, "No longer doing info module '0x%08lx'\n", mod);
}
void DEBUG_WalkModules(void)
{
fprintf(stderr, "No longer walking modules list\n");
}
void DEBUG_DumpQueue(DWORD q)
{
fprintf(stderr, "No longer doing info queue '0x%08lx'\n", q);
}
void DEBUG_WalkQueues(void)
{
fprintf(stderr, "No longer walking queues list\n");
}
void DEBUG_InfoWindow(HWND hWnd)
{
char clsName[128];
char wndName[128];
RECT clientRect;
RECT windowRect;
int i;
WORD w;
if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
strcpy(clsName, "-- Unknown --");
if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
strcpy(wndName, "-- Empty --");
if (!GetClientRect(hWnd, &clientRect))
SetRectEmpty(&clientRect);
if (!GetWindowRect(hWnd, &windowRect))
SetRectEmpty(&windowRect);
/* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */
fprintf(stderr,
"next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n"
"inst=%08lx active=%04x idmenu=%08lx\n"
"style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n"
"client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n",
GetWindow(hWnd, GW_HWNDNEXT),
GetWindow(hWnd, GW_CHILD),
GetParent(hWnd),
GetWindow(hWnd, GW_OWNER),
clsName,
GetWindowLongA(hWnd, GWL_HINSTANCE),
GetLastActivePopup(hWnd),
GetWindowLongA(hWnd, GWL_ID),
GetWindowLongA(hWnd, GWL_STYLE),
GetWindowLongA(hWnd, GWL_EXSTYLE),
GetWindowLongA(hWnd, GWL_WNDPROC),
wndName,
clientRect.left, clientRect.top, clientRect.right, clientRect.bottom,
windowRect.left, windowRect.top, windowRect.right, windowRect.bottom,
GetSystemMenu(hWnd, FALSE));
if (GetClassLongA(hWnd, GCL_CBWNDEXTRA)) {
fprintf(stderr, "Extra bytes:" );
for (i = 0; i < GetClassLongA(hWnd, GCL_CBWNDEXTRA) / 2; i++) {
w = GetWindowWord(hWnd, i * 2);
/* FIXME: depends on i386 endian-ity */
fprintf(stderr, " %02x", HIBYTE(w));
fprintf(stderr, " %02x", LOBYTE(w));
}
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
}
void DEBUG_WalkWindows(HWND hWnd, int indent)
{
char clsName[128];
char wndName[128];
HWND child;
if (!IsWindow(hWnd))
hWnd = GetDesktopWindow();
if (!indent) /* first time around */
fprintf(stderr,
"%-16.16s %-17.17s %-8.8s %s\n",
"hwnd", "Class Name", " Style", " WndProc Text");
do {
if (!GetClassNameA(hWnd, clsName, sizeof(clsName)))
strcpy(clsName, "-- Unknown --");
if (!GetWindowTextA(hWnd, wndName, sizeof(wndName)))
strcpy(wndName, "-- Empty --");
/* FIXME: missing hmemTaskQ */
fprintf(stderr, "%*s%04x%*s", indent, "", hWnd, 13-indent,"");
fprintf(stderr, "%-17.17s %08lx %08lx %.14s\n",
clsName, GetWindowLongA(hWnd, GWL_STYLE),
GetWindowLongA(hWnd, GWL_WNDPROC), wndName);
if ((child = GetWindow(hWnd, GW_CHILD)) != 0)
DEBUG_WalkWindows(child, indent + 1 );
} while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0);
}
void DEBUG_WalkProcess(void)
{
fprintf(stderr, "No longer walking processes list\n");
}
void DEBUG_WalkModref(DWORD p)
{
fprintf(stderr, "No longer walking module references list\n");
}
void DEBUG_InfoSegments(DWORD start, int length)
{
char flags[3];
DWORD i;
LDT_ENTRY le;
if (length == -1) length = (8192 - start);
for (i = start; i < start + length; i++)
{
if (!GetThreadSelectorEntry(DEBUG_CurrThread->handle, (i << 3)|7, &le))
continue;
if (le.HighWord.Bits.Type & 0x08)
{
flags[0] = (le.HighWord.Bits.Type & 0x2) ? 'r' : '-';
flags[1] = '-';
flags[2] = 'x';
}
else
{
flags[0] = 'r';
flags[1] = (le.HighWord.Bits.Type & 0x2) ? 'w' : '-';
flags[2] = '-';
}
fprintf(stderr,
"%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n",
i, (i<<3)|7,
(le.HighWord.Bits.BaseHi << 24) +
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow,
((le.HighWord.Bits.LimitHi << 8) + le.LimitLow) <<
(le.HighWord.Bits.Granularity ? 12 : 0),
le.HighWord.Bits.Default_Big ? 32 : 16,
flags[0], flags[1], flags[2] );
}
}
void DEBUG_InfoVirtual(void)
{
fprintf(stderr, "No longer providing virtual mapping information\n");
}

View File

@ -8,147 +8,126 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "wine/winbase16.h"
#include <string.h>
#include "debugger.h"
#include "miscemu.h"
#include "winbase.h"
/************************************************************
*
* Check if linear pointer in [addr, addr+size[
* read (rwflag == 1)
* or
* write (rwflag == 0)
************************************************************/
BOOL DEBUG_checkmap_bad( const char *addr, size_t size, int rwflag)
{
FILE *fp;
char buf[200]; /* temporary line buffer */
char prot[5]; /* protection string */
char *start, *end;
int ret = TRUE;
#ifdef linux
/*
The entries in /proc/self/maps are of the form:
08000000-08002000 r-xp 00000000 03:41 2361
08002000-08003000 rw-p 00001000 03:41 2361
08003000-08005000 rwxp 00000000 00:00 0
40000000-40005000 r-xp 00000000 03:41 67219
40005000-40006000 rw-p 00004000 03:41 67219
40006000-40007000 rw-p 00000000 00:00 0
...
start end perm ??? major:minor inode
Only permissions start and end are used here
*/
#else
/*
% cat /proc/curproc/map
start end resident private perm type
0x1000 0xe000 12 0 r-x COW vnode
0xe000 0x10000 2 2 rwx COW vnode
0x10000 0x27000 4 4 rwx default
0x800e000 0x800f000 1 1 rw- default
0xefbde000 0xefbfe000 1 1 rwx default
COW = "copy on write"
% cat /proc/curproc/map on FreeBSD 3.0
start end ? ? ? prot ? ? ? ? ? ?
0x8048000 0x8054000 12 14 114770 r-x 2 1 0x0 COW NC vnode
0x8054000 0x8055000 1 0 166664 rwx 1 0 0x2180 COW NNC vnode
0x8055000 0x806a000 5 0 166662 rwx 1 0 0x2180 NCOW NNC default
0x28054000 0x28055000 1 0 166666 rwx 1 0 0x2180 NCOW NNC default
0xefbde000 0xefbfe000 1 0 166663 rwx 1 0 0x2180 NCOW NNC default
*/
#endif
if (!(fp = fopen("/proc/self/maps","r")) &&
!(fp = fopen("/proc/curproc/map","r"))
)
return FALSE;
#ifdef __FreeBSD__
/*
* *FOO* read(2) less than length of /proc/.../map fails with EFBIG
*
* $ dd bs=256 </proc/curproc/map
* dd: stdin: File too large
* 0+0 records in
* 0+0 records out
* 0 bytes transferred in 0.001595 secs (0 bytes/sec)
*/
setvbuf(fp, (char *)NULL, _IOFBF, 0x4000);
#endif
while (fgets( buf, sizeof(buf)-1, fp)) {
#ifdef linux
sscanf(buf, "%x-%x %3s", (int *) &start, (int *) &end, prot);
#else
sscanf(buf, "%x %x %*d %*d %3s", (int *) &start, (int *) &end, prot);
if (prot[0]!='r' && prot[0]!='-') /* FreeBSD 3.0 format */
sscanf(buf, "%x %x %*d %*d %*d %3s", (int *) &start, (int *) &end, prot);
#endif
if ( end <= addr)
continue;
if (start <= addr && addr+size <= end) {
if (rwflag)
ret = (prot[0] != 'r'); /* test for reading */
else
ret = (prot[1] != 'w'); /* test for writing */
}
break;
}
fclose( fp);
return ret;
}
/***********************************************************************
* DEBUG_IsBadReadPtr
*
* Check if we are allowed to read memory at 'address'.
*/
BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size )
{
#ifdef __i386__
if (!IS_SELECTOR_V86(address->seg))
if (address->seg) /* segmented addr */
{
if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
(WORD)address->seg ), size ))
return TRUE;
}
#endif
return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1);
}
#include "wine/winbase16.h"
#define DBG_V86_MODULE(seg) ((seg)>>16)
#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg)
/***********************************************************************
* DEBUG_IsBadWritePtr
*
* Check if we are allowed to write memory at 'address'.
*/
BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
static void DEBUG_Die(const char* msg)
{
#ifdef __i386__
if (!IS_SELECTOR_V86(address->seg))
if (address->seg) /* segmented addr */
{
/* Note: we use IsBadReadPtr here because we are */
/* always allowed to write to read-only segments */
if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off,
(WORD)address->seg ), size ))
return TRUE;
}
#endif
return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0);
fprintf(stderr, msg);
exit(1);
}
void* DEBUG_XMalloc(size_t size)
{
void *res = malloc(size ? size : 1);
if (res == NULL)
DEBUG_Die("Memory exhausted.\n");
memset(res, 0, size);
return res;
}
void* DEBUG_XReAlloc(void *ptr, size_t size)
{
void* res = realloc(ptr, size);
if ((res == NULL) && size)
DEBUG_Die("Memory exhausted.\n");
return res;
}
char* DEBUG_XStrDup(const char *str)
{
char *res = strdup(str);
if (!res)
DEBUG_Die("Memory exhausted.\n");
return res;
}
void DEBUG_FixAddress( DBG_ADDR *addr, DWORD def)
{
if (addr->seg == 0xffffffff) addr->seg = def;
if (!IS_SELECTOR_V86(addr->seg) && DEBUG_IsSelectorSystem(addr->seg)) addr->seg = 0;
}
BOOL DEBUG_FixSegment( DBG_ADDR* addr )
{
/* V86 mode ? */
if (DEBUG_context.EFlags & V86_FLAG) {
addr->seg |= (DWORD)(GetExePtr(GetCurrentTask())) << 16;
return TRUE;
}
return FALSE;
}
DWORD DEBUG_ToLinear( const DBG_ADDR *addr )
{
LDT_ENTRY le;
if (IS_SELECTOR_V86(addr->seg))
return DOSMEM_MemoryBase(DBG_V86_MODULE(addr->seg)) + (((addr->seg)&0xFFFF)<<4) + addr->off;
if (DEBUG_IsSelectorSystem(addr->seg))
return addr->off;
if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, addr->seg, &le)) {
return (le.HighWord.Bits.BaseHi << 24) + (le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->off;
}
return 0;
}
int DEBUG_GetSelectorType( WORD sel )
{
LDT_ENTRY le;
if (sel == 0)
return 32;
if (IS_SELECTOR_V86(sel))
return 16;
if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, sel, &le))
return le.HighWord.Bits.Default_Big ? 32 : 16;
/* selector doesn't exist */
return 0;
}
/* Determine if sel is a system selector (i.e. not managed by Wine) */
BOOL DEBUG_IsSelectorSystem(WORD sel)
{
return !(sel & 4) || (((sel & 0xFFFF) >> 3) < 17);
}
#endif /* __i386__ */
void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
{
addr->type = NULL;
#ifdef __i386__
addr->seg = DEBUG_context.SegCs;
if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg))
addr->seg = 0;
addr->off = DEBUG_context.Eip;
#else
addr->seg = 0;
addr->off = 0;
#endif
}
void DEBUG_InvalLinAddr( void* addr )
{
DBG_ADDR address;
address.type = NULL;
address.seg = 0;
address.off = (unsigned long)addr;
fprintf(stderr,"*** Invalid address ");
DEBUG_PrintAddress(&address, DEBUG_CurrThread->dbg_mode, FALSE);
fprintf(stderr,"\n");
}
/***********************************************************************
* DEBUG_ReadMemory
@ -157,11 +136,15 @@ BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size )
*/
int DEBUG_ReadMemory( const DBG_ADDR *address )
{
DBG_ADDR addr = *address;
DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0;
return *(int *)DBG_ADDR_TO_LIN( &addr );
DBG_ADDR addr = *address;
void* lin;
int value;
DEBUG_FixAddress( &addr, DEBUG_context.SegDs );
lin = (void*)DEBUG_ToLinear( &addr );
if (!DEBUG_READ_MEM_VERBOSE(lin, &value, sizeof(value)))
value = 0;
return value;
}
@ -172,11 +155,12 @@ int DEBUG_ReadMemory( const DBG_ADDR *address )
*/
void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
{
DBG_ADDR addr = *address;
DBG_ADDR addr = *address;
void* lin;
DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) );
if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return;
*(int *)DBG_ADDR_TO_LIN( &addr ) = value;
DEBUG_FixAddress( &addr, DEBUG_context.SegDs );
lin = (void*)DEBUG_ToLinear( &addr );
DEBUG_WRITE_MEM_VERBOSE(lin, &value, sizeof(value));
}
@ -188,15 +172,14 @@ void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
{
DBG_ADDR addr = * address;
unsigned int * dump;
int i;
unsigned char * pnt;
unsigned int seg2;
struct datatype * testtype;
unsigned short int * wdump;
DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
DEBUG_FixAddress( &addr,
(format == 'i') ?
DEBUG_context.SegCs :
DEBUG_context.SegDs );
/*
* Dereference pointer to get actual memory address we need to be
@ -212,15 +195,15 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
* else in 32-bit space. Grab it, and we
* should be all set.
*/
seg2 = addr.seg;
unsigned int seg2 = addr.seg;
addr.seg = 0;
addr.off = DEBUG_GetExprValue(&addr, NULL);
addr.seg = seg2;
}
else
{
if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
DEBUG_TypeDerefPointer(&addr, &testtype);
if (DEBUG_TypeDerefPointer(&addr, &testtype) == 0)
return;
if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
{
addr.off = DEBUG_GetExprValue(&addr, NULL);
@ -235,135 +218,71 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
if (format != 'i' && count > 1)
{
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE );
fprintf(stderr,": ");
}
pnt = DBG_ADDR_TO_LIN( &addr );
pnt = (void*)DEBUG_ToLinear( &addr );
switch(format)
{
case 'u': {
WCHAR *ptr = (WCHAR*)pnt;
WCHAR wch;
if (count == 1) count = 256;
while (count--)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return;
if (!*ptr) break;
addr.off++;
fputc( (char)*ptr++, stderr );
if (!DEBUG_READ_MEM_VERBOSE(pnt, &wch, sizeof(wch)))
break;
pnt += sizeof(wch);
fputc( (char)wch, stderr );
}
fprintf(stderr,"\n");
return;
}
case 's':
case 's': {
char ch;
if (count == 1) count = 256;
while (count--)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
if (!*pnt) break;
addr.off++;
fputc( *pnt++, stderr );
if (!DEBUG_READ_MEM_VERBOSE(pnt, &ch, sizeof(ch)))
break;
pnt++;
fputc( ch, stderr );
}
fprintf(stderr,"\n");
return;
}
case 'i':
while (count--)
{
DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
fprintf(stderr,": ");
if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
DEBUG_Disasm( &addr, TRUE );
fprintf(stderr,"\n");
}
return;
case 'x':
dump = (unsigned int *)pnt;
for(i=0; i<count; i++)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
fprintf(stderr," %8.8x", *dump++);
addr.off += sizeof(int);
if ((i % 4) == 3)
{
fprintf(stderr,"\n");
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
fprintf(stderr,": ");
}
}
fprintf(stderr,"\n");
return;
case 'd':
dump = (unsigned int *)pnt;
for(i=0; i<count; i++)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
fprintf(stderr," %10d", *dump++);
addr.off += sizeof(int);
if ((i % 4) == 3)
{
fprintf(stderr,"\n");
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
fprintf(stderr,": ");
}
}
fprintf(stderr,"\n");
return;
case 'w':
wdump = (unsigned short *)pnt;
for(i=0; i<count; i++)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
fprintf(stderr," %04x", *wdump++);
addr.off += sizeof(short);
if ((i % 8) == 7)
{
fprintf(stderr,"\n");
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
fprintf(stderr,": ");
}
}
fprintf(stderr,"\n");
return;
case 'c':
for(i=0; i<count; i++)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
if(*pnt < 0x20)
{
fprintf(stderr," ");
pnt++;
}
else fprintf(stderr," %c", *pnt++);
addr.off++;
if ((i % 32) == 31)
{
fprintf(stderr,"\n");
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
fprintf(stderr,": ");
}
}
fprintf(stderr,"\n");
return;
case 'b':
for(i=0; i<count; i++)
{
if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
fprintf(stderr," %02x", (*pnt++) & 0xff);
addr.off++;
if ((i % 16) == 15)
{
fprintf(stderr,"\n");
DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
fprintf(stderr,": ");
}
}
fprintf(stderr,"\n");
return;
#define DO_DUMP2(_t,_l,_f,_vv) { \
_t _v; \
for(i=0; i<count; i++) { \
if (!DEBUG_READ_MEM_VERBOSE(pnt, &_v, sizeof(_t))) break; \
fprintf(stderr,_f,(_vv)); \
pnt += sizeof(_t); addr.off += sizeof(_t); \
if ((i % (_l)) == (_l)-1) { \
fprintf(stderr,"\n"); \
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE );\
fprintf(stderr,": ");\
} \
} \
fprintf(stderr,"\n"); \
} \
return
#define DO_DUMP(_t,_l,_f) DO_DUMP2(_t,_l,_f,_v)
case 'x': DO_DUMP(int, 4, " %8.8x");
case 'd': DO_DUMP(unsigned int, 4, " %10d");
case 'w': DO_DUMP(unsigned short, 8, " %04x");
case 'c': DO_DUMP2(char, 32, " %c", (_v < 0x20) ? ' ' : _v);
case 'b': DO_DUMP2(char, 16, " %02x", (_v) & 0xff);
}
}

View File

@ -7,11 +7,8 @@
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "selectors.h"
#include "debugger.h"
CONTEXT DEBUG_context;
/***********************************************************************
* DEBUG_SetRegister
*
@ -22,70 +19,73 @@ void DEBUG_SetRegister( enum debug_regs reg, int val )
#ifdef __i386__
switch(reg)
{
case REG_EAX: EAX_reg(&DEBUG_context) = val; break;
case REG_EBX: EBX_reg(&DEBUG_context) = val; break;
case REG_ECX: ECX_reg(&DEBUG_context) = val; break;
case REG_EDX: EDX_reg(&DEBUG_context) = val; break;
case REG_ESI: ESI_reg(&DEBUG_context) = val; break;
case REG_EDI: EDI_reg(&DEBUG_context) = val; break;
case REG_EBP: EBP_reg(&DEBUG_context) = val; break;
case REG_EFL: EFL_reg(&DEBUG_context) = val; break;
case REG_EIP: EIP_reg(&DEBUG_context) = val; break;
case REG_ESP: ESP_reg(&DEBUG_context) = val; break;
case REG_CS: CS_reg(&DEBUG_context) = val; break;
case REG_DS: DS_reg(&DEBUG_context) = val; break;
case REG_ES: ES_reg(&DEBUG_context) = val; break;
case REG_SS: SS_reg(&DEBUG_context) = val; break;
case REG_FS: FS_reg(&DEBUG_context) = val; break;
case REG_GS: GS_reg(&DEBUG_context) = val; break;
case REG_AX: SET_LOWORD(EAX_reg(&DEBUG_context),val); break;
case REG_BX: SET_LOWORD(EBX_reg(&DEBUG_context),val); break;
case REG_CX: SET_LOWORD(ECX_reg(&DEBUG_context),val); break;
case REG_DX: SET_LOWORD(EDX_reg(&DEBUG_context),val); break;
case REG_SI: SET_LOWORD(ESI_reg(&DEBUG_context),val); break;
case REG_DI: SET_LOWORD(EDI_reg(&DEBUG_context),val); break;
case REG_BP: SET_LOWORD(EBP_reg(&DEBUG_context),val); break;
case REG_FL: SET_LOWORD(EFL_reg(&DEBUG_context),val); break;
case REG_IP: SET_LOWORD(EIP_reg(&DEBUG_context),val); break;
case REG_SP: SET_LOWORD(ESP_reg(&DEBUG_context),val); break;
case REG_EAX: DEBUG_context.Eax = val; break;
case REG_EBX: DEBUG_context.Ebx = val; break;
case REG_ECX: DEBUG_context.Ecx = val; break;
case REG_EDX: DEBUG_context.Edx = val; break;
case REG_ESI: DEBUG_context.Esi = val; break;
case REG_EDI: DEBUG_context.Edi = val; break;
case REG_EBP: DEBUG_context.Ebp = val; break;
case REG_EFL: DEBUG_context.EFlags = val; break;
case REG_EIP: DEBUG_context.Eip = val; break;
case REG_ESP: DEBUG_context.Esp = val; break;
case REG_CS: DEBUG_context.SegCs = val; break;
case REG_DS: DEBUG_context.SegDs = val; break;
case REG_ES: DEBUG_context.SegEs = val; break;
case REG_SS: DEBUG_context.SegSs = val; break;
case REG_FS: DEBUG_context.SegFs = val; break;
case REG_GS: DEBUG_context.SegGs = val; break;
#define SET_LOW_WORD(dw,lw) ((dw) = ((dw) & 0xFFFF0000) | LOWORD(lw))
case REG_AX: SET_LOW_WORD(DEBUG_context.Eax,val); break;
case REG_BX: SET_LOW_WORD(DEBUG_context.Ebx,val); break;
case REG_CX: SET_LOW_WORD(DEBUG_context.Ecx,val); break;
case REG_DX: SET_LOW_WORD(DEBUG_context.Edx,val); break;
case REG_SI: SET_LOW_WORD(DEBUG_context.Esi,val); break;
case REG_DI: SET_LOW_WORD(DEBUG_context.Edi,val); break;
case REG_BP: SET_LOW_WORD(DEBUG_context.Ebp,val); break;
case REG_FL: SET_LOW_WORD(DEBUG_context.EFlags,val); break;
case REG_IP: SET_LOW_WORD(DEBUG_context.Eip,val); break;
case REG_SP: SET_LOW_WORD(DEBUG_context.Esp,val); break;
#undef SET_LOWORD
}
#endif
}
int
DEBUG_PrintRegister(enum debug_regs reg)
int DEBUG_PrintRegister(enum debug_regs reg)
{
#ifdef __i386__
char* val = NULL;
switch(reg)
{
case REG_EAX: fprintf(stderr, "%%eax"); break;
case REG_EBX: fprintf(stderr, "%%ebx"); break;
case REG_ECX: fprintf(stderr, "%%ecx"); break;
case REG_EDX: fprintf(stderr, "%%edx"); break;
case REG_ESI: fprintf(stderr, "%%esi"); break;
case REG_EDI: fprintf(stderr, "%%edi"); break;
case REG_EBP: fprintf(stderr, "%%ebp"); break;
case REG_EFL: fprintf(stderr, "%%efl"); break;
case REG_EIP: fprintf(stderr, "%%eip"); break;
case REG_ESP: fprintf(stderr, "%%esp"); break;
case REG_AX: fprintf(stderr, "%%ax"); break;
case REG_BX: fprintf(stderr, "%%bx"); break;
case REG_CX: fprintf(stderr, "%%cx"); break;
case REG_DX: fprintf(stderr, "%%dx"); break;
case REG_SI: fprintf(stderr, "%%si"); break;
case REG_DI: fprintf(stderr, "%%di"); break;
case REG_BP: fprintf(stderr, "%%bp"); break;
case REG_FL: fprintf(stderr, "%%fl"); break;
case REG_IP: fprintf(stderr, "%%ip"); break;
case REG_SP: fprintf(stderr, "%%sp"); break;
case REG_CS: fprintf(stderr, "%%cs"); break;
case REG_DS: fprintf(stderr, "%%ds"); break;
case REG_ES: fprintf(stderr, "%%es"); break;
case REG_SS: fprintf(stderr, "%%ss"); break;
case REG_FS: fprintf(stderr, "%%fs"); break;
case REG_GS: fprintf(stderr, "%%gs"); break;
case REG_EAX: val = "%%eax"; break;
case REG_EBX: val = "%%ebx"; break;
case REG_ECX: val = "%%ecx"; break;
case REG_EDX: val = "%%edx"; break;
case REG_ESI: val = "%%esi"; break;
case REG_EDI: val = "%%edi"; break;
case REG_EBP: val = "%%ebp"; break;
case REG_EFL: val = "%%efl"; break;
case REG_EIP: val = "%%eip"; break;
case REG_ESP: val = "%%esp"; break;
case REG_AX: val = "%%ax"; break;
case REG_BX: val = "%%bx"; break;
case REG_CX: val = "%%cx"; break;
case REG_DX: val = "%%dx"; break;
case REG_SI: val = "%%si"; break;
case REG_DI: val = "%%di"; break;
case REG_BP: val = "%%bp"; break;
case REG_FL: val = "%%fl"; break;
case REG_IP: val = "%%ip"; break;
case REG_SP: val = "%%sp"; break;
case REG_CS: val = "%%cs"; break;
case REG_DS: val = "%%ds"; break;
case REG_ES: val = "%%es"; break;
case REG_SS: val = "%%ss"; break;
case REG_FS: val = "%%fs"; break;
case REG_GS: val = "%%gs"; break;
}
if (val) fprintf(stderr, val);
return TRUE;
#else
return FALSE;
@ -102,32 +102,32 @@ int DEBUG_GetRegister( enum debug_regs reg )
#ifdef __i386__
switch(reg)
{
case REG_EAX: return EAX_reg(&DEBUG_context);
case REG_EBX: return EBX_reg(&DEBUG_context);
case REG_ECX: return ECX_reg(&DEBUG_context);
case REG_EDX: return EDX_reg(&DEBUG_context);
case REG_ESI: return ESI_reg(&DEBUG_context);
case REG_EDI: return EDI_reg(&DEBUG_context);
case REG_EBP: return EBP_reg(&DEBUG_context);
case REG_EFL: return EFL_reg(&DEBUG_context);
case REG_EIP: return EIP_reg(&DEBUG_context);
case REG_ESP: return ESP_reg(&DEBUG_context);
case REG_CS: return CS_reg(&DEBUG_context);
case REG_DS: return DS_reg(&DEBUG_context);
case REG_ES: return ES_reg(&DEBUG_context);
case REG_SS: return SS_reg(&DEBUG_context);
case REG_FS: return FS_reg(&DEBUG_context);
case REG_GS: return GS_reg(&DEBUG_context);
case REG_AX: return LOWORD(EAX_reg(&DEBUG_context));
case REG_BX: return LOWORD(EBX_reg(&DEBUG_context));
case REG_CX: return LOWORD(ECX_reg(&DEBUG_context));
case REG_DX: return LOWORD(EDX_reg(&DEBUG_context));
case REG_SI: return LOWORD(ESI_reg(&DEBUG_context));
case REG_DI: return LOWORD(EDI_reg(&DEBUG_context));
case REG_BP: return LOWORD(EBP_reg(&DEBUG_context));
case REG_FL: return LOWORD(EFL_reg(&DEBUG_context));
case REG_IP: return LOWORD(EIP_reg(&DEBUG_context));
case REG_SP: return LOWORD(ESP_reg(&DEBUG_context));
case REG_EAX: return DEBUG_context.Eax;
case REG_EBX: return DEBUG_context.Ebx;
case REG_ECX: return DEBUG_context.Ecx;
case REG_EDX: return DEBUG_context.Edx;
case REG_ESI: return DEBUG_context.Esi;
case REG_EDI: return DEBUG_context.Edi;
case REG_EBP: return DEBUG_context.Ebp;
case REG_EFL: return DEBUG_context.EFlags;
case REG_EIP: return DEBUG_context.Eip;
case REG_ESP: return DEBUG_context.Esp;
case REG_CS: return DEBUG_context.SegCs;
case REG_DS: return DEBUG_context.SegDs;
case REG_ES: return DEBUG_context.SegEs;
case REG_SS: return DEBUG_context.SegSs;
case REG_FS: return DEBUG_context.SegFs;
case REG_GS: return DEBUG_context.SegGs;
case REG_AX: return LOWORD(DEBUG_context.Eax);
case REG_BX: return LOWORD(DEBUG_context.Ebx);
case REG_CX: return LOWORD(DEBUG_context.Ecx);
case REG_DX: return LOWORD(DEBUG_context.Edx);
case REG_SI: return LOWORD(DEBUG_context.Esi);
case REG_DI: return LOWORD(DEBUG_context.Edi);
case REG_BP: return LOWORD(DEBUG_context.Ebp);
case REG_FL: return LOWORD(DEBUG_context.EFlags);
case REG_IP: return LOWORD(DEBUG_context.Eip);
case REG_SP: return LOWORD(DEBUG_context.Esp);
}
#endif
return 0; /* should not happen */
@ -200,35 +200,35 @@ void DEBUG_InfoRegisters(void)
#ifdef __i386__
/* First get the segment registers out of the way */
fprintf( stderr," CS:%04x SS:%04x DS:%04x ES:%04x FS:%04x GS:%04x",
(WORD)CS_reg(&DEBUG_context), (WORD)SS_reg(&DEBUG_context),
(WORD)DS_reg(&DEBUG_context), (WORD)ES_reg(&DEBUG_context),
(WORD)FS_reg(&DEBUG_context), (WORD)GS_reg(&DEBUG_context) );
if (dbg_mode == 16)
(WORD)DEBUG_context.SegCs, (WORD)DEBUG_context.SegSs,
(WORD)DEBUG_context.SegDs, (WORD)DEBUG_context.SegEs,
(WORD)DEBUG_context.SegFs, (WORD)DEBUG_context.SegGs );
if (DEBUG_CurrThread->dbg_mode == 16)
{
char flag[33];
fprintf( stderr,"\n IP:%04x SP:%04x BP:%04x FLAGS:%04x(%s)\n",
LOWORD(EIP_reg(&DEBUG_context)), LOWORD(ESP_reg(&DEBUG_context)),
LOWORD(EBP_reg(&DEBUG_context)), LOWORD(EFL_reg(&DEBUG_context)),
DEBUG_Flags(LOWORD(EFL_reg(&DEBUG_context)), flag));
LOWORD(DEBUG_context.Eip), LOWORD(DEBUG_context.Esp),
LOWORD(DEBUG_context.Ebp), LOWORD(DEBUG_context.EFlags),
DEBUG_Flags(LOWORD(DEBUG_context.EFlags), flag));
fprintf( stderr," AX:%04x BX:%04x CX:%04x DX:%04x SI:%04x DI:%04x\n",
AX_reg(&DEBUG_context), BX_reg(&DEBUG_context),
CX_reg(&DEBUG_context), DX_reg(&DEBUG_context),
SI_reg(&DEBUG_context), DI_reg(&DEBUG_context) );
LOWORD(DEBUG_context.Eax), LOWORD(DEBUG_context.Ebx),
LOWORD(DEBUG_context.Ecx), LOWORD(DEBUG_context.Edx),
LOWORD(DEBUG_context.Esi), LOWORD(DEBUG_context.Edi) );
}
else /* 32-bit mode */
{
char flag[33];
fprintf( stderr, "\n EIP:%08lx ESP:%08lx EBP:%08lx EFLAGS:%08lx(%s)\n",
EIP_reg(&DEBUG_context), ESP_reg(&DEBUG_context),
EBP_reg(&DEBUG_context), EFL_reg(&DEBUG_context),
DEBUG_Flags(EFL_reg(&DEBUG_context), flag));
DEBUG_context.Eip, DEBUG_context.Esp,
DEBUG_context.Ebp, DEBUG_context.EFlags,
DEBUG_Flags(DEBUG_context.EFlags, flag));
fprintf( stderr, " EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\n",
EAX_reg(&DEBUG_context), EBX_reg(&DEBUG_context),
ECX_reg(&DEBUG_context), EDX_reg(&DEBUG_context) );
DEBUG_context.Eax, DEBUG_context.Ebx,
DEBUG_context.Ecx, DEBUG_context.Edx );
fprintf( stderr, " ESI:%08lx EDI:%08lx\n",
ESI_reg(&DEBUG_context), EDI_reg(&DEBUG_context) );
DEBUG_context.Esi, DEBUG_context.Edi );
}
#endif
}
@ -243,15 +243,12 @@ void DEBUG_InfoRegisters(void)
BOOL DEBUG_ValidateRegisters(void)
{
#ifdef __i386__
WORD cs, ds;
if (ISV86(&DEBUG_context)) return TRUE;
if (DEBUG_context.EFlags & V86_FLAG) return TRUE;
#if 0
/* Check that a selector is a valid ring-3 LDT selector, or a NULL selector */
#define CHECK_SEG(seg,name) \
if (((seg) & ~3) && \
((((seg) & 7) != 7) || IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(seg)))) \
{ \
if (((seg) & ~3) && ((((seg) & 7) != 7) || !DEBUG_IsSelector(seg))) { \
fprintf( stderr, "*** Invalid value for %s register: %04x\n", \
(name), (WORD)(seg) ); \
return FALSE; \
@ -259,26 +256,26 @@ BOOL DEBUG_ValidateRegisters(void)
cs = __get_cs();
ds = __get_ds();
if (CS_reg(&DEBUG_context) != cs) CHECK_SEG(CS_reg(&DEBUG_context), "CS");
if (SS_reg(&DEBUG_context) != ds) CHECK_SEG(SS_reg(&DEBUG_context), "SS");
if (DS_reg(&DEBUG_context) != ds) CHECK_SEG(DS_reg(&DEBUG_context), "DS");
if (ES_reg(&DEBUG_context) != ds) CHECK_SEG(ES_reg(&DEBUG_context), "ES");
if (FS_reg(&DEBUG_context) != ds) CHECK_SEG(FS_reg(&DEBUG_context), "FS");
if (GS_reg(&DEBUG_context) != ds) CHECK_SEG(GS_reg(&DEBUG_context), "GS");
if (CS_reg(DEBUG_context) != cs) CHECK_SEG(CS_reg(DEBUG_context), "CS");
if (SS_reg(DEBUG_context) != ds) CHECK_SEG(SS_reg(DEBUG_context), "SS");
if (DS_reg(DEBUG_context) != ds) CHECK_SEG(DS_reg(DEBUG_context), "DS");
if (ES_reg(DEBUG_context) != ds) CHECK_SEG(ES_reg(DEBUG_context), "ES");
if (FS_reg(DEBUG_context) != ds) CHECK_SEG(FS_reg(DEBUG_context), "FS");
if (GS_reg(DEBUG_context) != ds) CHECK_SEG(GS_reg(DEBUG_context), "GS");
#endif
/* Check that CS and SS are not NULL */
if (!ISV86(&DEBUG_context))
if (!(CS_reg(&DEBUG_context) & ~3))
if (!(DEBUG_context.SegCs & ~3))
{
fprintf( stderr, "*** Invalid value for CS register: %04x\n",
(WORD)CS_reg(&DEBUG_context) );
(WORD)DEBUG_context.SegCs );
return FALSE;
}
if (!(SS_reg(&DEBUG_context) & ~3))
if (!(DEBUG_context.SegSs & ~3))
{
fprintf( stderr, "*** Invalid value for SS register: %04x\n",
(WORD)SS_reg(&DEBUG_context) );
(WORD)DEBUG_context.SegSs );
return FALSE;
}
return TRUE;

View File

@ -22,11 +22,7 @@
#define PATH_MAX _MAX_PATH
#endif
#include "wine/winbase16.h"
#include "pe_image.h"
#include "peexe.h"
#include "debugger.h"
#include "task.h"
struct searchlist
{
@ -428,36 +424,17 @@ DEBUG_List(struct list_id * source1, struct list_id * source2,
DBG_ADDR DEBUG_LastDisassemble={NULL,0,0};
void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
{
#ifdef __i386__
TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() );
addr->type = NULL;
addr->seg = CS_reg(&DEBUG_context);
addr->off = EIP_reg(&DEBUG_context);
if (ISV86(&DEBUG_context)) addr->seg |= (DWORD)(pTask? pTask->hModule : 0) << 16;
else if (IS_SELECTOR_SYSTEM(addr->seg)) addr->seg = 0;
GlobalUnlock16( GetCurrentTask() );
#else
addr->type = NULL;
addr->seg = 0;
addr->off = (DWORD)GET_IP(&DEBUG_context);
#endif
}
static int
_disassemble(DBG_ADDR *addr)
{
DEBUG_PrintAddress( addr, dbg_mode, TRUE );
fprintf(stderr,": ");
if (!DBG_CHECK_READ_PTR( addr, 1 )) return 0;
DEBUG_Disasm( addr, TRUE );
fprintf(stderr,"\n");
return 1;
char ch;
DEBUG_PrintAddress( addr, DEBUG_CurrThread->dbg_mode, TRUE );
fprintf(stderr,": ");
if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr), &ch, sizeof(ch))) return 0;
DEBUG_Disasm( addr, TRUE );
fprintf(stderr,"\n");
return 1;
}
void
@ -465,7 +442,7 @@ _disassemble_fixaddr(DBG_ADDR *addr) {
DWORD seg2;
struct datatype *testtype;
DBG_FIX_ADDR_SEG(addr,CS_reg(&DEBUG_context));
DEBUG_FixAddress(addr, DEBUG_context.SegCs);
if( addr->type != NULL )
{
if( addr->type == DEBUG_TypeIntConst )
@ -482,7 +459,6 @@ _disassemble_fixaddr(DBG_ADDR *addr) {
}
else
{
if (!DBG_CHECK_READ_PTR( addr, 1 )) return;
DEBUG_TypeDerefPointer(addr, &testtype);
if( testtype != NULL || addr->type == DEBUG_TypeIntConst )
addr->off = DEBUG_GetExprValue(addr, NULL);

View File

@ -134,8 +134,6 @@ static void stab_strcpy(char * dest, const char * source)
*dest++ = '\0';
}
extern void DEBUG_PrintAType(struct datatype*, int);
typedef struct {
char* name;
unsigned long value;

View File

@ -12,7 +12,7 @@
#include "debugger.h"
#include "stackframe.h"
#ifdef __i386__
/*
* We keep this info for each frame, so that we can
* find local variable information correctly.
@ -43,7 +43,7 @@ typedef struct
DWORD ip;
WORD cs;
} FRAME32;
#endif
/***********************************************************************
@ -57,18 +57,20 @@ void DEBUG_InfoStack(void)
DBG_ADDR addr;
addr.type = NULL;
addr.seg = SS_reg(&DEBUG_context);
addr.off = ESP_reg(&DEBUG_context);
addr.seg = DEBUG_context.SegSs;
addr.off = DEBUG_context.Esp;
fprintf(stderr,"Stack dump:\n");
if (IS_SELECTOR_32BIT(addr.seg))
{ /* 32-bit mode */
DEBUG_ExamineMemory( &addr, 24, 'x' );
}
else /* 16-bit mode */
{
switch (DEBUG_GetSelectorType(addr.seg)) {
case 32: /* 32-bit mode */
DEBUG_ExamineMemory( &addr, 24, 'x' );
break;
case 16: /* 16-bit mode */
addr.off &= 0xffff;
DEBUG_ExamineMemory( &addr, 24, 'w' );
break;
default:
fprintf(stderr, "Bad segment (%ld)\n", addr.seg);
}
fprintf(stderr,"\n");
#endif
@ -79,7 +81,7 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b
{
int theframe = nframe++;
frames = (struct bt_info *)DBG_realloc(frames,
nframe*sizeof(struct bt_info));
nframe*sizeof(struct bt_info));
if (noisy)
fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "),
frameno);
@ -87,7 +89,7 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b
frames[theframe].eip = code->off;
if (noisy)
frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, bits,
stack->off, TRUE );
stack->off, TRUE );
else
DEBUG_FindNearestSymbol( code, TRUE,
&frames[theframe].frame.sym, stack->off,
@ -101,265 +103,284 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b
static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
{
unsigned int ss = addr->seg, possible_cs = 0;
FRAME16 *frame = (FRAME16 *)DBG_ADDR_TO_LIN(addr);
int theframe = nframe;
if (DEBUG_IsBadReadPtr( addr, sizeof(FRAME16) )) {
if (noisy) {
fprintf(stderr,"*** Invalid address ");
DEBUG_PrintAddress(addr, dbg_mode, FALSE);
fprintf(stderr,"\n");
}
return FALSE;
unsigned int ss = addr->seg, possible_cs = 0;
FRAME16 frame;
int theframe = nframe;
void* p = (void*)DEBUG_ToLinear(addr);
if (!p) return FALSE;
if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
if (noisy) {
fprintf(stderr,"*** Invalid address ");
DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, FALSE);
fprintf(stderr,"\n");
}
return FALSE;
}
if (!frame->bp) return FALSE;
if (!frame.bp) return FALSE;
nframe++;
frames = (struct bt_info *)DBG_realloc(frames,
nframe*sizeof(struct bt_info));
nframe*sizeof(struct bt_info));
if (noisy)
fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "),
frameno);
if (frame->bp & 1) *cs = frame->cs;
fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "),
frameno);
if (frame.bp & 1) *cs = frame.cs;
else {
/* not explicitly marked as far call,
* but check whether it could be anyway */
if (((frame->cs&7)==7) && (frame->cs != *cs) && !IS_SELECTOR_FREE(frame->cs)) {
ldt_entry tcs;
LDT_GetEntry( SELECTOR_TO_ENTRY(frame->cs), &tcs );
if ( tcs.type == SEGMENT_CODE ) {
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases */
*cs = possible_cs = frame->cs;
}
}
/* not explicitly marked as far call,
* but check whether it could be anyway */
if (((frame.cs&7)==7) && (frame.cs != *cs)) {
LDT_ENTRY le;
if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, frame.cs, &le) &&
(le.HighWord.Bits.Type & 0x08)) { /* code segment */
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases */
*cs = possible_cs = frame.cs;
}
}
}
frames[theframe].cs = addr->seg = *cs;
frames[theframe].eip = addr->off = frame->ip;
frames[theframe].eip = addr->off = frame.ip;
if (noisy)
frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16,
frame->bp, TRUE );
frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16,
frame.bp, TRUE );
else
DEBUG_FindNearestSymbol( addr, TRUE,
&frames[theframe].frame.sym, frame->bp,
&frames[theframe].frame.list);
DEBUG_FindNearestSymbol( addr, TRUE,
&frames[theframe].frame.sym, frame.bp,
&frames[theframe].frame.list);
frames[theframe].ss = addr->seg = ss;
frames[theframe].ebp = addr->off = frame->bp & ~1;
frames[theframe].ebp = addr->off = frame.bp & ~1;
if (noisy) {
fprintf( stderr, " (bp=%04lx", addr->off );
if (possible_cs) {
fprintf( stderr, ", far call assumed" );
}
fprintf( stderr, ")\n" );
fprintf( stderr, " (bp=%04lx", addr->off );
if (possible_cs) {
fprintf( stderr, ", far call assumed" );
}
fprintf( stderr, ")\n" );
}
return TRUE;
}
static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
{
unsigned int ss = addr->seg;
FRAME32 *frame = (FRAME32 *)DBG_ADDR_TO_LIN(addr);
int theframe = nframe;
if (DEBUG_IsBadReadPtr( addr, sizeof(FRAME32) )) {
unsigned int ss = addr->seg;
FRAME32 frame;
int theframe = nframe;
void* p = (void*)DEBUG_ToLinear(addr);
if (!p) return FALSE;
if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
if (noisy) {
fprintf(stderr,"*** Invalid address ");
DEBUG_PrintAddress(addr, dbg_mode, FALSE);
DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, FALSE);
fprintf(stderr,"\n");
}
return FALSE;
}
if (!frame->ip) return FALSE;
if (!frame.ip) return FALSE;
nframe++;
frames = (struct bt_info *)DBG_realloc(frames,
nframe*sizeof(struct bt_info));
nframe*sizeof(struct bt_info));
if (noisy)
fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "),
frameno);
fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "),
frameno);
frames[theframe].cs = addr->seg = *cs;
frames[theframe].eip = addr->off = frame->ip;
frames[theframe].eip = addr->off = frame.ip;
if (noisy)
frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32,
frame->bp, TRUE );
frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32,
frame.bp, TRUE );
else
DEBUG_FindNearestSymbol( addr, TRUE,
&frames[theframe].frame.sym, frame->bp,
&frames[theframe].frame.list);
if (noisy) fprintf( stderr, " (ebp=%08lx)\n", frame->bp );
DEBUG_FindNearestSymbol( addr, TRUE,
&frames[theframe].frame.sym, frame.bp,
&frames[theframe].frame.list);
if (noisy) fprintf( stderr, " (ebp=%08lx)\n", frame.bp );
frames[theframe].ss = addr->seg = ss;
frames[theframe].ebp = frame->bp;
if (addr->off == frame->bp) return FALSE;
addr->off = frame->bp;
frames[theframe].ebp = frame.bp;
if (addr->off == frame.bp) return FALSE;
addr->off = frame.bp;
return TRUE;
}
static void DEBUG_DoBackTrace(int noisy)
{
DBG_ADDR addr, sw_addr;
unsigned int ss = SS_reg(&DEBUG_context), cs = CS_reg(&DEBUG_context);
int frameno = 0, is16, ok;
DWORD next_switch, cur_switch;
if (noisy) fprintf( stderr, "Backtrace:\n" );
nframe = 1;
if (frames) DBG_free( frames );
frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) );
if (noisy)
fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : " "), frameno);
if (IS_SELECTOR_SYSTEM(ss)) ss = 0;
if (IS_SELECTOR_SYSTEM(cs)) cs = 0;
/* first stack frame from registers */
if (IS_SELECTOR_32BIT(ss))
{
frames[0].cs = addr.seg = cs;
frames[0].eip = addr.off = EIP_reg(&DEBUG_context);
if (noisy)
frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
else
DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0,
&frames[0].frame.list);
frames[0].ss = addr.seg = ss;
frames[0].ebp = addr.off = EBP_reg(&DEBUG_context);
if (noisy) fprintf( stderr, " (ebp=%08x)\n", frames[0].ebp );
is16 = FALSE;
} else {
frames[0].cs = addr.seg = cs;
frames[0].eip = addr.off = LOWORD(EIP_reg(&DEBUG_context));
if (noisy)
frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE );
else
DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0,
&frames[0].frame.list);
frames[0].ss = addr.seg = ss;
frames[0].ebp = addr.off = BP_reg(&DEBUG_context);
if (noisy) fprintf( stderr, " (bp=%04x)\n", frames[0].ebp );
is16 = TRUE;
}
next_switch = NtCurrentTeb()->cur_stack;
if (is16) {
if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch );
return;
}
cur_switch = (DWORD)((STACK32FRAME*)next_switch)->frame16;
sw_addr.seg = SELECTOROF(cur_switch);
sw_addr.off = OFFSETOF(cur_switch);
} else {
if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) );
return;
}
cur_switch = (DWORD)((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch))->frame32;
sw_addr.seg = ss;
sw_addr.off = cur_switch;
}
if (DEBUG_IsBadReadPtr(&sw_addr,1)) {
sw_addr.seg = (DWORD)-1;
sw_addr.off = (DWORD)-1;
}
for (ok = TRUE; ok;) {
if ((frames[frameno].ss == sw_addr.seg) &&
(frames[frameno].ebp >= sw_addr.off)) {
/* 16<->32 switch...
* yes, I know this is confusing, it gave me a headache too */
if (is16) {
STACK32FRAME *frame = (STACK32FRAME*)next_switch;
DBG_ADDR code;
if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch );
return;
}
code.type = NULL;
code.seg = 0;
code.off = frame->retaddr;
cs = 0;
addr.seg = 0;
addr.off = frame->ebp;
DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy );
next_switch = cur_switch;
if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) );
return;
}
cur_switch = (DWORD)((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch))->frame32;
sw_addr.seg = 0;
sw_addr.off = cur_switch;
is16 = FALSE;
} else {
STACK16FRAME *frame = (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch);
DBG_ADDR code;
if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) );
return;
}
code.type = NULL;
code.seg = frame->cs;
code.off = frame->ip;
cs = frame->cs;
addr.seg = SELECTOROF(next_switch);
addr.off = frame->bp;
DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy );
next_switch = cur_switch;
if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch );
return;
}
cur_switch = (DWORD)((STACK32FRAME*)next_switch)->frame16;
sw_addr.seg = SELECTOROF(cur_switch);
sw_addr.off = OFFSETOF(cur_switch);
is16 = TRUE;
}
if (DEBUG_IsBadReadPtr(&sw_addr,1)) {
sw_addr.seg = (DWORD)-1;
sw_addr.off = (DWORD)-1;
}
} else {
/* ordinary stack frame */
ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy)
: DEBUG_Frame32( &addr, &cs, ++frameno, noisy);
}
}
if (noisy) fprintf( stderr, "\n" );
}
#endif
/***********************************************************************
* DEBUG_BackTrace
*
* Display a stack back-trace.
*/
void DEBUG_BackTrace(void)
void DEBUG_BackTrace(BOOL noisy)
{
#ifdef __i386__
DEBUG_DoBackTrace( TRUE );
#endif
}
#ifdef __i386
DBG_ADDR addr, sw_addr, code, tmp;
unsigned int ss = DEBUG_context.SegSs;
unsigned int cs = DEBUG_context.SegCs;
int frameno = 0, is16, ok;
DWORD next_switch, cur_switch, p;
STACK16FRAME frame16;
STACK32FRAME frame32;
char ch;
/***********************************************************************
* DEBUG_SilentBackTrace
*
* Display a stack back-trace.
*/
void DEBUG_SilentBackTrace(void)
{
#ifdef __i386__
DEBUG_DoBackTrace( FALSE );
if (noisy) fprintf( stderr, "Backtrace:\n" );
nframe = 1;
if (frames) DBG_free( frames );
frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) );
if (noisy)
fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : " "), frameno);
if (DEBUG_IsSelectorSystem(ss)) ss = 0;
if (DEBUG_IsSelectorSystem(cs)) cs = 0;
/* first stack frame from registers */
switch (DEBUG_GetSelectorType(ss))
{
case 32:
frames[0].cs = addr.seg = cs;
frames[0].eip = addr.off = DEBUG_context.Eip;
if (noisy)
frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
else
DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0,
&frames[0].frame.list);
frames[0].ss = addr.seg = ss;
frames[0].ebp = addr.off = DEBUG_context.Ebp;
if (noisy) fprintf( stderr, " (ebp=%08x)\n", frames[0].ebp );
is16 = FALSE;
break;
case 16:
frames[0].cs = addr.seg = cs;
frames[0].eip = addr.off = LOWORD(DEBUG_context.Eip);
if (noisy)
frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE );
else
DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0,
&frames[0].frame.list);
frames[0].ss = addr.seg = ss;
frames[0].ebp = addr.off = LOWORD(DEBUG_context.Ebp);
if (noisy) fprintf( stderr, " (bp=%04x)\n", frames[0].ebp );
is16 = TRUE;
break;
default:
if (noisy) fprintf( stderr, "Bad segment '%u'\n", ss);
return;
}
/* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space
*/
cur_switch = (DWORD)DEBUG_CurrThread->teb + OFFSET_OF(TEB, cur_stack);
if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) {
if (noisy) fprintf( stderr, "Can't read TEB:cur_stack\n");
return;
}
if (is16) {
if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n",
(STACK32FRAME*)next_switch );
return;
}
cur_switch = (DWORD)frame32.frame16;
sw_addr.seg = SELECTOROF(cur_switch);
sw_addr.off = OFFSETOF(cur_switch);
} else {
tmp.seg = SELECTOROF(next_switch);
tmp.off = OFFSETOF(next_switch);
p = DEBUG_ToLinear(&tmp);
if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)p );
return;
}
cur_switch = (DWORD)frame16.frame32;
sw_addr.seg = ss;
sw_addr.off = cur_switch;
}
if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
sw_addr.seg = (DWORD)-1;
sw_addr.off = (DWORD)-1;
}
for (ok = TRUE; ok;) {
if ((frames[frameno].ss == sw_addr.seg) &&
(frames[frameno].ebp >= sw_addr.off)) {
/* 16<->32 switch...
* yes, I know this is confusing, it gave me a headache too */
if (is16) {
if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch );
return;
}
code.type = NULL;
code.seg = 0;
code.off = frame32.retaddr;
cs = 0;
addr.seg = 0;
addr.off = frame32.ebp;
DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy );
next_switch = cur_switch;
tmp.seg = SELECTOROF(next_switch);
tmp.off = OFFSETOF(next_switch);
p = DEBUG_ToLinear(&tmp);
if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n",
(STACK16FRAME*)p );
return;
}
cur_switch = (DWORD)frame16.frame32;
sw_addr.seg = 0;
sw_addr.off = cur_switch;
is16 = FALSE;
} else {
tmp.seg = SELECTOROF(next_switch);
tmp.off = OFFSETOF(next_switch);
p = DEBUG_ToLinear(&tmp);
if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n",
(STACK16FRAME*)p );
return;
}
code.type = NULL;
code.seg = frame16.cs;
code.off = frame16.ip;
cs = frame16.cs;
addr.seg = SELECTOROF(next_switch);
addr.off = frame16.bp;
DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy );
next_switch = cur_switch;
if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
if (noisy) fprintf( stderr, "Bad stack frame %p\n",
(STACK32FRAME*)next_switch );
return;
}
cur_switch = (DWORD)frame32.frame16;
sw_addr.seg = SELECTOROF(cur_switch);
sw_addr.off = OFFSETOF(cur_switch);
is16 = TRUE;
}
if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
sw_addr.seg = (DWORD)-1;
sw_addr.off = (DWORD)-1;
}
} else {
/* ordinary stack frame */
ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy)
: DEBUG_Frame32( &addr, &cs, ++frameno, noisy);
}
}
if (noisy) fprintf( stderr, "\n" );
#endif
}

View File

@ -345,7 +345,7 @@ DEBUG_InitTypes()
}
long long int
DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
DEBUG_GetExprValue(const DBG_ADDR * addr, char ** format)
{
DBG_ADDR address = *addr;
unsigned int rtn;
@ -360,12 +360,10 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
switch(addr->type->type)
{
case DT_BASIC:
if (!DBG_CHECK_READ_PTR( &address, addr->type->un.basic.basic_size))
{
return 0;
}
if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, addr->type->un.basic.basic_size))
return 0;
memcpy(&rtn, (char *) addr->off, addr->type->un.basic.basic_size);
if( (addr->type->un.basic.b_signed)
&& ((addr->type->un.basic.basic_size & 3) != 0)
&& ((rtn >> (addr->type->un.basic.basic_size * 8 - 1)) != 0) )
@ -388,8 +386,9 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
}
break;
case DT_POINTER:
if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0;
rtn = (unsigned int) *((unsigned char **)addr->off);
if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(void*)))
return 0;
type2 = addr->type->un.pointer.pointsto;
if (!type2)
@ -402,9 +401,8 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
if( type2->type == DT_BASIC && type2->un.basic.basic_size == 1 )
{
def_format = "\"%s\"";
address.off = rtn;
address.seg = 0;
if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0;
if (!DEBUG_READ_MEM_VERBOSE((void*)rtn, &rtn, 1))
return 0;
break;
}
else
@ -414,13 +412,13 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
break;
case DT_ARRAY:
case DT_STRUCT:
if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0;
rtn = (unsigned int) *((unsigned char **)addr->off);
if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(rtn)))
return 0;
def_format = "0x%8.8x";
break;
case DT_ENUM:
if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0;
rtn = (unsigned int) *((unsigned char **)addr->off);
if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(rtn)))
return 0;
for(e = addr->type->un.enumeration.members; e; e = e->next )
{
if( e->value == rtn )
@ -452,22 +450,23 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
}
unsigned int
DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype)
DEBUG_TypeDerefPointer(const DBG_ADDR * addr, struct datatype ** newtype)
{
DBG_ADDR address = *addr;
unsigned int val;
/*
* Make sure that this really makes sense.
*/
if( addr->type->type != DT_POINTER )
if( addr->type->type != DT_POINTER || !DEBUG_READ_MEM((void*)addr->off, &val, sizeof(val)))
{
*newtype = NULL;
return 0;
}
*newtype = addr->type->un.pointer.pointsto;
address.off = *(unsigned int*) (addr->off);
return (unsigned int)DBG_ADDR_TO_LIN(&address); /* FIXME: is this right (or "better") ? */
address.off = val;
return DEBUG_ToLinear(&address); /* FIXME: is this right (or "better") ? */
}
unsigned int
@ -718,7 +717,7 @@ int DEBUG_GetObjectSize(struct datatype * dt)
}
unsigned int
DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index)
DEBUG_ArrayIndex(const DBG_ADDR * addr, DBG_ADDR * result, int index)
{
int size;

479
debugger/winedbg.c Normal file
View File

@ -0,0 +1,479 @@
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/* Wine internal debugger
* Interface to Windows debugger API
* Eric Pouech (c) 2000
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include "debugger.h"
#include "winbase.h"
#include "winreg.h"
#include "debugtools.h"
#include "options.h"
#ifdef DBG_need_heap
HANDLE dbg_heap = 0;
#endif
DEFAULT_DEBUG_CHANNEL(winedbg);
WINE_DBG_PROCESS* DEBUG_CurrProcess = NULL;
WINE_DBG_THREAD* DEBUG_CurrThread = NULL;
CONTEXT DEBUG_context;
static WINE_DBG_PROCESS* proc = NULL;
static WINE_DBG_PROCESS* DEBUG_GetProcess(DWORD pid)
{
WINE_DBG_PROCESS* p;
for (p = proc; p; p = p->next)
if (p->pid == pid) break;
return p;
}
static WINE_DBG_PROCESS* DEBUG_AddProcess(DWORD pid, HANDLE h)
{
WINE_DBG_PROCESS* p = DBG_alloc(sizeof(WINE_DBG_PROCESS));
if (!p)
return NULL;
p->handle = h;
p->pid = pid;
p->threads = NULL;
p->next = proc;
p->prev = NULL;
if (proc) proc->prev = p;
proc = p;
return p;
}
static void DEBUG_DelThread(WINE_DBG_THREAD* p);
static void DEBUG_DelProcess(WINE_DBG_PROCESS* p)
{
if (p->threads != NULL) {
ERR("Shouldn't happen\n");
while (p->threads) DEBUG_DelThread(p->threads);
}
if (p->prev) p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
if (p == proc) proc = p->next;
DBG_free(p);
}
static void DEBUG_InitCurrProcess(void)
{
#ifdef DBG_need_heap
/*
* Initialize the debugger heap.
*/
dbg_heap = HeapCreate(HEAP_NO_SERIALIZE, 0x1000, 0x8000000); /* 128MB */
#endif
/*
* Initialize the type handling stuff.
*/
DEBUG_InitTypes();
DEBUG_InitCVDataTypes();
/*
* In some cases we can read the stabs information directly
* from the executable. If this is the case, we don't need
* to bother with trying to read a symbol file, as the stabs
* also have line number and local variable information.
* As long as gcc is used for the compiler, stabs will
* be the default. On SVr4, DWARF could be used, but we
* don't grok that yet, and in this case we fall back to using
* the wine.sym file.
*/
if( DEBUG_ReadExecutableDbgInfo() == FALSE )
{
char* symfilename = "wine.sym";
struct stat statbuf;
HKEY hWineConf, hkey;
DWORD count;
char symbolTableFile[256];
if (-1 == stat(symfilename, &statbuf) )
symfilename = LIBDIR "wine.sym";
strcpy(symbolTableFile, symfilename);
if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config", &hWineConf)) {
if (!RegOpenKeyA(hWineConf, "wine", &hkey)) {
count = sizeof(symbolTableFile);
RegQueryValueA(hkey, "SymbolTableFile", symbolTableFile, &count);
RegCloseKey(hkey);
}
RegCloseKey(hWineConf);
}
DEBUG_ReadSymbolTable(symbolTableFile);
}
DEBUG_LoadEntryPoints(NULL);
DEBUG_ProcessDeferredDebug();
}
static BOOL DEBUG_ProcessGetString(char* buffer, int size,
HANDLE hp, LPVOID addr)
{
LPVOID ad;
DWORD sz;
if ( addr
&& ReadProcessMemory(hp, addr, &ad, sizeof(ad), &sz)
&& sz == sizeof(ad)
&& ad
&& ReadProcessMemory(hp, ad, buffer, size, &sz))
return TRUE;
*(WCHAR*)buffer = 0;
return FALSE;
}
static WINE_DBG_THREAD* DEBUG_GetThread(WINE_DBG_PROCESS* p, DWORD tid)
{
WINE_DBG_THREAD* t;
for (t = p->threads; t; t = t->next)
if (t->tid == tid) break;
return t;
}
static WINE_DBG_THREAD* DEBUG_AddThread(WINE_DBG_PROCESS* p, DWORD tid,
HANDLE h, LPVOID start, LPVOID teb)
{
WINE_DBG_THREAD* t = DBG_alloc(sizeof(WINE_DBG_THREAD));
if (!t)
return NULL;
t->handle = h;
t->tid = tid;
t->start = start;
t->teb = teb;
t->process = p;
t->wait_for_first_exception = 0;
t->dbg_exec_mode = EXEC_CONT;
t->dbg_exec_count = 0;
t->next = p->threads;
t->prev = NULL;
if (p->threads) p->threads->prev = t;
p->threads = t;
return t;
}
static void DEBUG_InitCurrThread(void)
{
if (!Options.debug) return;
if (DEBUG_CurrThread->start) {
DBG_ADDR addr;
DEBUG_SetBreakpoints(FALSE);
addr.seg = 0;
addr.off = (DWORD)DEBUG_CurrThread->start;
DEBUG_AddBreakpoint(&addr);
DEBUG_SetBreakpoints(TRUE);
} else {
DEBUG_CurrThread->wait_for_first_exception = 1;
}
}
static void DEBUG_DelThread(WINE_DBG_THREAD* t)
{
if (t->prev) t->prev->next = t->next;
if (t->next) t->next->prev = t->prev;
if (t == t->process->threads) t->process->threads = t->next;
DBG_free(t);
}
static BOOL DEBUG_HandleException( EXCEPTION_RECORD *rec, BOOL first_chance, BOOL force )
{
BOOL is_debug = FALSE;
BOOL ret;
if (first_chance && !Options.debug && !force ) return 0; /* pass to app first */
switch (rec->ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
case EXCEPTION_SINGLE_STEP:
is_debug = TRUE;
break;
case CONTROL_C_EXIT:
if (!Options.debug) DEBUG_Exit(0);
break;
}
if (!is_debug)
{
/* print some infos */
fprintf( stderr, "%s: ",
first_chance ? "First chance exception" : "Unhandled exception" );
switch(rec->ExceptionCode)
{
case EXCEPTION_INT_DIVIDE_BY_ZERO:
fprintf( stderr, "divide by zero" );
break;
case EXCEPTION_INT_OVERFLOW:
fprintf( stderr, "overflow" );
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
fprintf( stderr, "array bounds " );
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
fprintf( stderr, "illegal instruction" );
break;
case EXCEPTION_STACK_OVERFLOW:
fprintf( stderr, "stack overflow" );
break;
case EXCEPTION_PRIV_INSTRUCTION:
fprintf( stderr, "priviledged instruction" );
break;
case EXCEPTION_ACCESS_VIOLATION:
if (rec->NumberParameters == 2)
fprintf( stderr, "page fault on %s access to 0x%08lx",
rec->ExceptionInformation[0] ? "write" : "read",
rec->ExceptionInformation[1] );
else
fprintf( stderr, "page fault" );
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
fprintf( stderr, "Alignment" );
break;
case CONTROL_C_EXIT:
fprintf( stderr, "^C" );
break;
case EXCEPTION_CRITICAL_SECTION_WAIT:
fprintf( stderr, "critical section %08lx wait failed",
rec->ExceptionInformation[0] );
break;
default:
fprintf( stderr, "%08lx", rec->ExceptionCode );
break;
}
}
#if 1
fprintf(stderr, "Entering debugger PC=%lx EFL=%08lx mode=%d count=%d\n",
DEBUG_context.Eip, DEBUG_context.EFlags,
DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
#endif
ret = DEBUG_Main( is_debug, force );
#if 1
fprintf(stderr, "Exiting debugger PC=%lx EFL=%08lx mode=%d count=%d\n",
DEBUG_context.Eip, DEBUG_context.EFlags,
DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count);
#endif
return ret;
}
static DWORD CALLBACK DEBUG_MainLoop(LPVOID pid)
{
DEBUG_EVENT de;
char buffer[256];
DWORD cont;
TRACE("WineDbg started on pid %ld\n", (DWORD)pid);
if (!DebugActiveProcess((DWORD)pid))
TRACE("Can't debug process %ld: %ld\n", (DWORD)pid, GetLastError());
while (WaitForDebugEvent(&de, INFINITE)) {
cont = 0L;
if ((DEBUG_CurrProcess = DEBUG_GetProcess(de.dwProcessId)) != NULL)
DEBUG_CurrThread = DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId);
else
DEBUG_CurrThread = NULL;
switch (de.dwDebugEventCode) {
case EXCEPTION_DEBUG_EVENT:
if (!DEBUG_CurrThread) break;
TRACE("%08lx:%08lx: exception code=%08lx %d\n",
de.dwProcessId, de.dwThreadId,
de.u.Exception.ExceptionRecord.ExceptionCode,
DEBUG_CurrThread->wait_for_first_exception);
DEBUG_context.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS|CONTEXT_DEBUG_REGISTERS;
if (!GetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context)) {
WARN("Can't get thread's context\n");
break;
}
TRACE("%p:%p\n", de.u.Exception.ExceptionRecord.ExceptionAddress,
(void*)DEBUG_context.Eip);
cont = DEBUG_HandleException(&de.u.Exception.ExceptionRecord,
de.u.Exception.dwFirstChance,
DEBUG_CurrThread->wait_for_first_exception);
if (DEBUG_CurrThread->wait_for_first_exception) {
DEBUG_CurrThread->wait_for_first_exception = 0;
#ifdef __i386__
DEBUG_context.Eip--;
#endif
}
SetThreadContext(DEBUG_CurrThread->handle, &DEBUG_context);
break;
case CREATE_THREAD_DEBUG_EVENT:
TRACE("%08lx:%08lx: create thread D @%p\n", de.dwProcessId, de.dwThreadId,
de.u.CreateThread.lpStartAddress);
if (DEBUG_CurrProcess == NULL) {
ERR("Unknown process\n");
break;
}
if (DEBUG_GetThread(DEBUG_CurrProcess, de.dwThreadId) != NULL) {
TRACE("Thread already listed, skipping\n");
break;
}
DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
de.dwThreadId,
de.u.CreateThread.hThread,
de.u.CreateThread.lpStartAddress,
de.u.CreateThread.lpThreadLocalBase);
if (!DEBUG_CurrThread) {
ERR("Couldn't create thread\n");
break;
}
DEBUG_InitCurrThread();
break;
case CREATE_PROCESS_DEBUG_EVENT:
DEBUG_ProcessGetString(buffer, sizeof(buffer),
de.u.CreateProcessInfo.hProcess,
de.u.LoadDll.lpImageName);
/* FIXME unicode ? de.u.CreateProcessInfo.fUnicode */
TRACE("%08lx:%08lx: create process %s @%p\n",
de.dwProcessId, de.dwThreadId,
buffer,
de.u.CreateProcessInfo.lpStartAddress);
if (DEBUG_GetProcess(de.dwProcessId) != NULL) {
TRACE("Skipping already defined process\n");
break;
}
DEBUG_CurrProcess = DEBUG_AddProcess(de.dwProcessId,
de.u.CreateProcessInfo.hProcess);
if (DEBUG_CurrProcess == NULL) {
ERR("Unknown process\n");
break;
}
TRACE("%08lx:%08lx: create thread I @%p\n", de.dwProcessId, de.dwThreadId,
de.u.CreateProcessInfo.lpStartAddress);
DEBUG_CurrThread = DEBUG_AddThread(DEBUG_CurrProcess,
de.dwThreadId,
de.u.CreateProcessInfo.hThread,
de.u.CreateProcessInfo.lpStartAddress,
de.u.CreateProcessInfo.lpThreadLocalBase);
if (!DEBUG_CurrThread) {
ERR("Couldn't create thread\n");
break;
}
DEBUG_InitCurrProcess();
DEBUG_InitCurrThread();
break;
case EXIT_THREAD_DEBUG_EVENT:
TRACE("%08lx:%08lx: exit thread (%ld)\n",
de.dwProcessId, de.dwThreadId, de.u.ExitThread.dwExitCode);
if (DEBUG_CurrThread == NULL) {
ERR("Unknown thread\n");
break;
}
/* FIXME: remove break point set on thread startup */
DEBUG_DelThread(DEBUG_CurrThread);
break;
case EXIT_PROCESS_DEBUG_EVENT:
TRACE("%08lx:%08lx: exit process (%ld)\n",
de.dwProcessId, de.dwThreadId, de.u.ExitProcess.dwExitCode);
if (DEBUG_CurrProcess == NULL) {
ERR("Unknown process\n");
break;
}
/* kill last thread */
DEBUG_DelThread(DEBUG_CurrProcess->threads);
/* FIXME: remove break point set on thread startup */
DEBUG_DelProcess(DEBUG_CurrProcess);
break;
case LOAD_DLL_DEBUG_EVENT:
if (DEBUG_CurrThread == NULL) {
ERR("Unknown thread\n");
break;
}
DEBUG_ProcessGetString(buffer, sizeof(buffer),
DEBUG_CurrThread->process->handle,
de.u.LoadDll.lpImageName);
/* FIXME unicode: de.u.LoadDll.fUnicode */
TRACE("%08lx:%08lx: loads DLL %s @%p\n", de.dwProcessId, de.dwThreadId,
buffer, de.u.LoadDll.lpBaseOfDll);
break;
case UNLOAD_DLL_DEBUG_EVENT:
TRACE("%08lx:%08lx: unload DLL @%p\n", de.dwProcessId, de.dwThreadId,
de.u.UnloadDll.lpBaseOfDll);
break;
case OUTPUT_DEBUG_STRING_EVENT:
if (DEBUG_CurrThread == NULL) {
ERR("Unknown thread\n");
break;
}
DEBUG_ProcessGetString(buffer, sizeof(buffer),
DEBUG_CurrThread->process->handle,
de.u.DebugString.lpDebugStringData);
/* fixme unicode de.u.DebugString.fUnicode ? */
TRACE("%08lx:%08lx: output debug string (%s)\n",
de.dwProcessId, de.dwThreadId,
buffer);
break;
case RIP_EVENT:
TRACE("%08lx:%08lx: rip error=%ld type=%ld\n",
de.dwProcessId, de.dwThreadId, de.u.RipInfo.dwError,
de.u.RipInfo.dwType);
break;
default:
TRACE("%08lx:%08lx: unknown event (%ld)\n",
de.dwProcessId, de.dwThreadId, de.dwDebugEventCode);
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, cont);
}
TRACE("WineDbg terminated on pid %ld\n", (DWORD)pid);
return 0L;
}
#include "thread.h"
#include "process.h"
void DEBUG_StartDebugger(DWORD pid)
{
if (Options.debug)
CreateThread(NULL, 0, DEBUG_MainLoop, (LPVOID)pid, 0, NULL);
}

View File

@ -163,6 +163,7 @@ char dbch_wave[] = "\003wave";
char dbch_win[] = "\003win";
char dbch_win16drv[] = "\003win16drv";
char dbch_win32[] = "\003win32";
char dbch_winedbg[] = "\003winedbg";
char dbch_wing[] = "\003wing";
char dbch_winsock[] = "\003winsock";
char dbch_winspool[] = "\003winspool";
@ -170,7 +171,7 @@ char dbch_wnet[] = "\003wnet";
char dbch_x11[] = "\003x11";
char dbch_x11drv[] = "\003x11drv";
#define DEBUG_CHANNEL_COUNT 163
#define DEBUG_CHANNEL_COUNT 164
static char * const debug_channels[DEBUG_CHANNEL_COUNT] = {
dbch_accel,
@ -330,6 +331,7 @@ static char * const debug_channels[DEBUG_CHANNEL_COUNT] = {
dbch_win,
dbch_win16drv,
dbch_win32,
dbch_winedbg,
dbch_wing,
dbch_winsock,
dbch_winspool,

View File

@ -7,7 +7,6 @@
#include <assert.h>
#include "wine/winbase16.h"
#include "callback.h"
#include "debugger.h"
#include "main.h"
#include "miscemu.h"
#include "module.h"
@ -22,6 +21,7 @@
static int MAIN_argc;
static char **MAIN_argv;
extern void DEBUG_StartDebugger(DWORD);
/***********************************************************************
* Main loop of initial task
@ -29,7 +29,6 @@ static char **MAIN_argv;
void MAIN_EmulatorRun( void )
{
char startProg[256], defProg[256];
HINSTANCE handle;
int i, tasks = 0;
MSG msg;
BOOL err_msg = FALSE;
@ -71,18 +70,31 @@ void MAIN_EmulatorRun( void )
/* Load and run executables given on command line */
for (i = 1; i < MAIN_argc; i++)
{
if ((handle = WinExec( MAIN_argv[i], SW_SHOWNORMAL )) < 32)
{
PROCESS_INFORMATION info;
STARTUPINFOA startup;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = SW_SHOWNORMAL;
if (!CreateProcessA(NULL, MAIN_argv[i], NULL, NULL, FALSE, 0,
NULL, NULL, &startup, &info)) {
err_msg = TRUE;
MESSAGE("wine: can't exec '%s': ", MAIN_argv[i]);
switch (handle)
{
case 2: MESSAGE("main executable or required DLL not found\n" ); break;
case 11: MESSAGE("invalid exe file\n" ); break;
default: MESSAGE("error=%d\n", handle ); break;
}
MESSAGE("wine: can't exec '%s': ", MAIN_argv[i]);
switch (GetLastError())
{
case 2: MESSAGE("file not found\n" ); break;
case 11: MESSAGE("invalid exe file\n" ); break;
default: MESSAGE("error=%ld\n", GetLastError() ); break;
}
}
else tasks++;
else
{
tasks++;
/* hack until wine debugger can be moved to a separate process */
DEBUG_StartDebugger(info.dwProcessId);
}
}
if (!tasks)