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).
diff --git a/debugger/Makefile.in b/debugger/Makefile.in
index d3ee22a..a5524d7 100644
--- a/debugger/Makefile.in
+++ b/debugger/Makefile.in
@@ -20,7 +20,8 @@
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
diff --git a/debugger/break.c b/debugger/break.c
index 68150d1..db80414 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
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_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 @@
}
breakpoints[num].enabled = FALSE;
- breakpoints[num].in_use = FALSE;
+ breakpoints[num].refcount = 0;
breakpoints[num].skipcount = 0;
}
@@ -304,12 +278,12 @@
*/
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 @@
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 @@
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 @@
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 @@
*/
DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
if( list.sourcefile != NULL )
- {
+ {
DEBUG_List(&list, NULL, 0);
- }
+ }
return FALSE;
}
@@ -460,8 +389,7 @@
* 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 @@
#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 @@
int delta;
int status;
enum exec_mode ret_mode;
- BYTE *instr;
+ DWORD instr;
+ unsigned char ch;
DEBUG_GetCurrentAddress( &addr );
@@ -548,7 +487,7 @@
{
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 @@
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 @@
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 @@
* 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 @@
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 @@
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;
diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c
index 42cf385..e6783a9 100644
--- a/debugger/db_disasm.c
+++ b/debugger/db_disasm.c
@@ -892,27 +892,29 @@
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 @@
/* 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 @@
* 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 );
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 663a4e3..30e26ec 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -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 @@
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 @@
| 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 @@
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 @@
| 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 @@
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 @@
*
* 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 );
- ret_ok = DEBUG_ValidateRegisters();
- if (ret_ok) ret_ok = DBG_CHECK_READ_PTR( &addr, 1 );
+ 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;
+
} 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;
diff --git a/debugger/debug.l b/debugger/debug.l
index 045ec39..de15577 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -119,7 +119,6 @@
<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; }
diff --git a/debugger/debugger.h b/debugger/debugger.h
new file mode 100644
index 0000000..d51ddc3
--- /dev/null
+++ b/debugger/debugger.h
@@ -0,0 +1,395 @@
+/*
+ * Debugger definitions
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#ifndef __WINE_DEBUGGER_H
+#define __WINE_DEBUGGER_H
+
+#include <sys/types.h> /* u_long ... */
+#include "windef.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
+#define SYM_WIN32 0x2
+#define SYM_WINE 0x4
+#define SYM_INVALID 0x8
+#define SYM_TRAMPOLINE 0x10
+#define SYM_STEP_THROUGH 0x20
+
+enum debug_type {DT_BASIC, DT_CONST, DT_POINTER, DT_ARRAY, DT_STRUCT, DT_ENUM, DT_TYPEDEF, DT_FUNC, DT_BITFIELD};
+
+
+/*
+ * Return values for DEBUG_CheckLinenoStatus. Used to determine
+ * what to do when the 'step' command is given.
+ */
+#define FUNC_HAS_NO_LINES (0)
+#define NOT_ON_LINENUMBER (1)
+#define AT_LINENUMBER (2)
+#define FUNC_IS_TRAMPOLINE (3)
+
+/*
+ * For constants generated by the parser, we use this datatype
+ */
+extern struct datatype * DEBUG_TypeInt;
+extern struct datatype * DEBUG_TypeIntConst;
+extern struct datatype * DEBUG_TypeUSInt;
+extern struct datatype * DEBUG_TypeString;
+
+typedef struct
+{
+ struct datatype * type;
+ DWORD seg; /* 0xffffffff means current default segment (cs or ds) */
+ DWORD off;
+} DBG_ADDR;
+
+struct list_id
+{
+ char * sourcefile;
+ int line;
+};
+
+struct wine_lines {
+ unsigned long line_number;
+ DBG_ADDR pc_offset;
+};
+
+struct symbol_info
+{
+ struct name_hash * sym;
+ struct list_id list;
+};
+
+typedef struct wine_lines WineLineNo;
+
+/*
+ * This structure holds information about stack variables, function
+ * parameters, and register variables, which are all local to this
+ * function.
+ */
+struct wine_locals {
+ unsigned int regno:8; /* For register symbols */
+ signed int offset:24; /* offset from esp/ebp to symbol */
+ unsigned int pc_start; /* For RBRAC/LBRAC */
+ unsigned int pc_end; /* For RBRAC/LBRAC */
+ char * name; /* Name of symbol */
+ struct datatype * type; /* Datatype of symbol */
+};
+
+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__
+#ifdef REG_SP /* Some Sun includes define this */
+#undef REG_SP
+#endif
+
+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
+};
+#endif
+
+#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 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 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);
+
+ /* debugger/db_disasm.c */
+extern void DEBUG_Disasm( DBG_ADDR *addr, int display );
+
+ /* debugger/expr.c */
+extern void DEBUG_FreeExprMem(void);
+struct expr * DEBUG_RegisterExpr(enum debug_regs);
+struct expr * DEBUG_SymbolExpr(const char * name);
+struct expr * DEBUG_ConstExpr(int val);
+struct expr * DEBUG_StringExpr(const char * str);
+struct expr * DEBUG_SegAddr(struct expr *, struct expr *);
+struct expr * DEBUG_USConstExpr(unsigned int val);
+struct expr * DEBUG_BinopExpr(int oper, struct expr *, struct expr *);
+struct expr * DEBUG_UnopExpr(int oper, struct expr *);
+struct expr * DEBUG_StructPExpr(struct expr *, const char * element);
+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(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);
+extern int DEBUG_DisplayExpr(struct expr * exp);
+
+ /* more debugger/break.c */
+extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
+
+ /* debugger/display.c */
+extern int DEBUG_DoDisplay(void);
+extern int DEBUG_AddDisplay(struct expr * exp, int count, char format);
+extern int DEBUG_DoDisplay(void);
+extern int DEBUG_DelDisplay(int displaynum);
+extern int DEBUG_InfoDisplay(void);
+
+ /* debugger/hash.c */
+extern struct name_hash * DEBUG_AddSymbol( const char *name,
+ const DBG_ADDR *addr,
+ const char * sourcefile,
+ int flags);
+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 );
+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,
+ unsigned int ebp,
+ struct list_id * source);
+extern void DEBUG_ReadSymbolTable( const char * filename );
+extern int DEBUG_LoadEntryPoints( const char * prefix );
+extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num,
+ unsigned long offset );
+extern struct wine_locals *
+ DEBUG_AddLocal( struct name_hash * func, int regno,
+ int offset,
+ int pc_start,
+ int pc_end,
+ char * name);
+extern int DEBUG_CheckLinenoStatus(const DBG_ADDR *addr);
+extern void DEBUG_GetFuncInfo(struct list_id * ret, const char * file,
+ const char * func);
+extern int DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len);
+extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len);
+extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr);
+extern int DEBUG_cmp_sym(const void * p1, const void * p2);
+extern BOOL DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno,
+ DBG_ADDR *addr, int bp_flag );
+
+extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym,
+ struct datatype * type);
+BOOL DEBUG_Normalize(struct name_hash * nh );
+
+ /* debugger/info.c */
+extern void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format );
+extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr,
+ int addrlen, int flag );
+extern void DEBUG_Help(void);
+extern void DEBUG_HelpInfo(void);
+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 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 );
+extern int DEBUG_GetRegister( enum debug_regs reg );
+extern void DEBUG_InfoRegisters(void);
+extern BOOL DEBUG_ValidateRegisters(void);
+extern int DEBUG_PrintRegister(enum debug_regs reg);
+
+ /* debugger/stack.c */
+extern void DEBUG_InfoStack(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,
+ unsigned int * eip,
+ unsigned int * ebp);
+
+ /* debugger/stabs.c */
+extern int DEBUG_ReadExecutableDbgInfo(void);
+extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff, int stablen, unsigned int strtaboff, int strtablen);
+
+ /* debugger/msc.c */
+extern int DEBUG_RegisterDebugInfo( HMODULE, const char *);
+extern int DEBUG_ProcessDeferredDebug(void);
+extern int DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, const char * name);
+extern void DEBUG_InfoShare(void);
+extern void DEBUG_InitCVDataTypes(void);
+
+ /* debugger/types.c */
+extern int DEBUG_nchar;
+extern void DEBUG_InitTypes(void);
+extern struct datatype * DEBUG_NewDataType(enum debug_type xtype,
+ const char * typename);
+extern unsigned int
+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);
+extern int DEBUG_SetStructSize(struct datatype * dt, int size);
+extern int DEBUG_SetPointerType(struct datatype * dt, struct datatype * dt2);
+extern int DEBUG_SetArrayParams(struct datatype * dt, int min, int max,
+ struct datatype * dt2);
+extern void DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level );
+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(const DBG_ADDR * addr, DBG_ADDR * result, int index);
+extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
+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);
+extern enum debug_type DEBUG_GetType(struct datatype * dt);
+extern struct datatype * DEBUG_TypeCast(enum debug_type, const char *);
+extern int DEBUG_PrintTypeCast(struct datatype *);
+
+ /* debugger/source.c */
+extern void DEBUG_ShowDir(void);
+extern void DEBUG_AddPath(const char * path);
+extern void DEBUG_List(struct list_id * line1, struct list_id * line2,
+ int delta);
+extern void DEBUG_NukePath(void);
+extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset );
+
+ /* debugger/external.c */
+extern void DEBUG_ExternalDebugger(void);
+
+ /* debugger/dbg.y */
+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 */
+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,
+ malloc() arena (and other heaps) can be totally wasted and it'll still
+ work, etc... if someone could make optimized routines so it wouldn't
+ take so long to load, it could be made default) */
+#include "heap.h"
+#define DBG_alloc(x) HEAP_xalloc(dbg_heap,0,x)
+#define DBG_realloc(x,y) HEAP_xrealloc(dbg_heap,0,x,y)
+#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 */
diff --git a/debugger/display.c b/debugger/display.c
index df9f9fc..431a289 100644
--- a/debugger/display.c
+++ b/debugger/display.c
@@ -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>
diff --git a/debugger/expr.c b/debugger/expr.c
index fbee595..b4e4345 100644
--- a/debugger/expr.c
+++ b/debugger/expr.c
@@ -299,7 +299,6 @@
DBG_ADDR exp1;
DBG_ADDR exp2;
unsigned int cexp[5];
- int (*fptr)();
int scale1;
int scale2;
int scale3;
@@ -332,12 +331,20 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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]);
diff --git a/debugger/hash.c b/debugger/hash.c
index 8d79102..35aaf6b 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -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 @@
* 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 @@
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 @@
char * lineinfo, *sourcefile;
int i;
char linebuff[16];
+ unsigned val;
if( rtn != NULL )
{
@@ -637,9 +637,9 @@
{
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 @@
/* 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 @@
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 @@
}
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
diff --git a/debugger/info.c b/debugger/info.c
index ec1f098..2a6e00b 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -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 @@
}
default_format = NULL;
- value = DEBUG_GetExprValue((DBG_ADDR *) addr, &default_format);
+ value = DEBUG_GetExprValue(addr, &default_format);
switch(format)
{
@@ -188,3 +192,264 @@
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");
+}
diff --git a/debugger/memory.c b/debugger/memory.c
index 63d1d52..07759ee 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -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 @@
*/
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 @@
*/
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_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 @@
* 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 @@
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);
}
}
diff --git a/debugger/registers.c b/debugger/registers.c
index 65f953a..9f6610f 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -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 @@
#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 @@
#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 @@
#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 @@
BOOL DEBUG_ValidateRegisters(void)
{
#ifdef __i386__
- WORD cs, ds;
+ if (DEBUG_context.EFlags & V86_FLAG) return TRUE;
- if (ISV86(&DEBUG_context)) 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 @@
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;
diff --git a/debugger/source.c b/debugger/source.c
index 6ce1aee..0b7e7c6 100644
--- a/debugger/source.c
+++ b/debugger/source.c
@@ -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 @@
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 @@
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 @@
}
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);
diff --git a/debugger/stabs.c b/debugger/stabs.c
index e0376d8..7407847 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -134,8 +134,6 @@
*dest++ = '\0';
}
-extern void DEBUG_PrintAType(struct datatype*, int);
-
typedef struct {
char* name;
unsigned long value;
diff --git a/debugger/stack.c b/debugger/stack.c
index 4965e1b..62f9b43 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -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 @@
DWORD ip;
WORD cs;
} FRAME32;
-
+#endif
/***********************************************************************
@@ -57,18 +57,20 @@
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 @@
{
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 @@
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 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
}
diff --git a/debugger/types.c b/debugger/types.c
index 1719586..c827866 100644
--- a/debugger/types.c
+++ b/debugger/types.c
@@ -345,7 +345,7 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
}
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;
diff --git a/debugger/winedbg.c b/debugger/winedbg.c
new file mode 100644
index 0000000..c5fe7d4
--- /dev/null
+++ b/debugger/winedbg.c
@@ -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);
+}
+