From 527eea99f8ecce26d438604f1c98abc901b1c0ad Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 8 Mar 2000 16:44:54 +0000 Subject: [PATCH] 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). --- debugger/Makefile.in | 3 +- debugger/break.c | 301 ++++++++----------- debugger/db_disasm.c | 64 +++-- debugger/dbg.y | 418 ++++++++------------------- debugger/debug.l | 1 - {include => debugger}/debugger.h | 194 ++++++++----- debugger/display.c | 3 - debugger/expr.c | 64 +++-- debugger/hash.c | 39 ++- debugger/info.c | 267 ++++++++++++++++- debugger/memory.c | 423 +++++++++++---------------- debugger/registers.c | 229 ++++++++------- debugger/source.c | 42 +-- debugger/stabs.c | 2 - debugger/stack.c | 479 ++++++++++++++++--------------- debugger/types.c | 39 ++- debugger/winedbg.c | 479 +++++++++++++++++++++++++++++++ include/debugdefs.h | 4 +- miscemu/main.c | 36 ++- 19 files changed, 1785 insertions(+), 1302 deletions(-) rename {include => debugger}/debugger.h (71%) create mode 100644 debugger/winedbg.c diff --git a/debugger/Makefile.in b/debugger/Makefile.in index d3ee22a6b49..a5524d7e35a 100644 --- a/debugger/Makefile.in +++ b/debugger/Makefile.in @@ -20,7 +20,8 @@ C_SRCS = \ source.c \ stabs.c \ stack.c \ - types.c + types.c \ + winedbg.c EXTRA_SRCS = dbg.y debug.l EXTRA_OBJS = y.tab.o lex.yy.o diff --git a/debugger/break.c b/debugger/break.c index 68150d15de9..db804142c31 100644 --- a/debugger/break.c +++ b/debugger/break.c @@ -7,83 +7,43 @@ #include "config.h" #include -#include -#include -#ifdef HAVE_SYS_MMAN_H -#include -#endif -#include "wine/winbase16.h" -#include "module.h" -#include "neexe.h" -#include "process.h" -#include "task.h" -#include "miscemu.h" -#include "toolhelp.h" #include "debugger.h" -#include "dosexe.h" #define INT3 0xcc /* int 3 opcode */ #define MAX_BREAKPOINTS 100 -typedef struct -{ - DBG_ADDR addr; - BYTE addrlen; - BYTE opcode; - BOOL16 enabled; - WORD skipcount; - BOOL16 in_use; - struct expr * condition; -} BREAKPOINT; - static BREAKPOINT breakpoints[MAX_BREAKPOINTS]; static int next_bp = 1; /* breakpoint 0 is reserved for step-over */ -/*********************************************************************** - * DEBUG_ChangeOpcode - * - * Change the opcode at segment:addr. - */ -static void DEBUG_SetOpcode( const DBG_ADDR *addr, BYTE op ) -{ - BYTE *ptr = DBG_ADDR_TO_LIN(addr); - - /* There are a couple of problems with this. On Linux prior to - 1.1.62, this call fails (ENOACCESS) due to a bug in fs/exec.c. - This code is currently not tested at all on BSD. - How do I get the old protection in order to restore it later on? - */ - if (mprotect((caddr_t)((int)ptr & (~4095)), 4096, - PROT_READ | PROT_WRITE | PROT_EXEC) == -1) - { - perror( "Can't set break point" ); - return; - } - *ptr = op; - /* mprotect((caddr_t)(addr->off & ~4095), 4096, - PROT_READ | PROT_EXEC ); */ -} - - /*********************************************************************** * DEBUG_IsStepOverInstr * * Determine if the instruction at CS:EIP is an instruction that * we need to step over (like a call or a repetitive string move). */ -static BOOL DEBUG_IsStepOverInstr() +static BOOL DEBUG_IsStepOverInstr(void) { #ifdef __i386__ - BYTE *instr = (BYTE *)CTX_SEG_OFF_TO_LIN( &DEBUG_context, - CS_reg(&DEBUG_context), - EIP_reg(&DEBUG_context) ); + BYTE* instr; + BYTE ch; + DBG_ADDR addr; + + addr.seg = DEBUG_context.SegCs; + addr.off = DEBUG_context.Eip; + /* FIXME: old code was using V86BASE(DEBUG_context) + * instead of passing thru DOSMEM_MemoryBase + */ + instr = (BYTE*)DEBUG_ToLinear(&addr); for (;;) { - switch(*instr) + if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch))) + return FALSE; + + switch (ch) { /* Skip all prefixes */ @@ -109,8 +69,9 @@ static BOOL DEBUG_IsStepOverInstr() return TRUE; case 0xff: /* call */ - return (((instr[1] & 0x38) == 0x10) || - ((instr[1] & 0x38) == 0x18)); + if (!DEBUG_READ_MEM(instr + 1, &ch, sizeof(ch))) + return FALSE; + return (((ch & 0x38) == 0x10) || ((ch & 0x38) == 0x18)); /* Handle string instructions */ @@ -149,21 +110,21 @@ static BOOL DEBUG_IsStepOverInstr() BOOL DEBUG_IsFctReturn(void) { #ifdef __i386__ - BYTE *instr = (BYTE *)CTX_SEG_OFF_TO_LIN( &DEBUG_context, - CS_reg(&DEBUG_context), - EIP_reg(&DEBUG_context) ); + BYTE* instr; + BYTE ch; + DBG_ADDR addr; - for (;;) - { - switch(*instr) - { - case 0xc2: - case 0xc3: - return TRUE; - default: - return FALSE; - } - } + addr.seg = DEBUG_context.SegCs; + addr.off = DEBUG_context.Eip; + /* FIXME: old code was using V86BASE(DEBUG_context) + * instead of passing thru DOSMEM_MemoryBase + */ + instr = (BYTE*)DEBUG_ToLinear(&addr); + + if (!DEBUG_READ_MEM(instr, &ch, sizeof(ch))) + return FALSE; + + return (ch == 0xc2) || (ch == 0xc3); #else return FALSE; #endif @@ -177,21 +138,20 @@ BOOL DEBUG_IsFctReturn(void) */ void DEBUG_SetBreakpoints( BOOL set ) { - int i; + int i; + char ch; for (i = 0; i < MAX_BREAKPOINTS; i++) { - if (breakpoints[i].in_use && breakpoints[i].enabled) + if (breakpoints[i].refcount && breakpoints[i].enabled) { - /* Note: we check for read here, because if reading is allowed */ - /* writing permission will be forced in DEBUG_SetOpcode. */ - if (DEBUG_IsBadReadPtr( &breakpoints[i].addr, 1 )) + ch = set ? INT3 : breakpoints[i].opcode; + + if (!DEBUG_WRITE_MEM( (void*)DEBUG_ToLinear(&breakpoints[i].addr), &ch, sizeof(ch) )) { fprintf( stderr, "Invalid address for breakpoint %d, disabling it\n", i ); breakpoints[i].enabled = FALSE; } - else DEBUG_SetOpcode( &breakpoints[i].addr, - set ? INT3 : breakpoints[i].opcode ); } } } @@ -209,7 +169,7 @@ int DEBUG_FindBreakpoint( const DBG_ADDR *addr ) for (i = 0; i < MAX_BREAKPOINTS; i++) { - if (breakpoints[i].in_use && breakpoints[i].enabled && + if (breakpoints[i].refcount && breakpoints[i].enabled && breakpoints[i].addr.seg == addr->seg && breakpoints[i].addr.off == addr->off) return i; } @@ -227,9 +187,9 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address ) DBG_ADDR addr = *address; int num; unsigned int seg2; - BYTE *p; + BYTE ch; - DBG_FIX_ADDR_SEG( &addr, CS_reg(&DEBUG_context) ); + DEBUG_FixAddress( &addr, DEBUG_context.SegCs ); if( addr.type != NULL && addr.type == DEBUG_TypeIntConst ) { @@ -243,27 +203,38 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address ) addr.off = DEBUG_GetExprValue(&addr, NULL); addr.seg = seg2; } - if (!DBG_CHECK_READ_PTR( &addr, 1 )) return; + + if ((num = DEBUG_FindBreakpoint(&addr)) >= 1) + { + breakpoints[num].refcount++; + return; + } + + if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, sizeof(ch))) + return; if (next_bp < MAX_BREAKPOINTS) num = next_bp++; else /* try to find an empty slot */ { for (num = 1; num < MAX_BREAKPOINTS; num++) - if (!breakpoints[num].in_use) break; + if (!breakpoints[num].refcount) break; if (num >= MAX_BREAKPOINTS) { fprintf( stderr, "Too many breakpoints. Please delete some.\n" ); return; } } - p = DBG_ADDR_TO_LIN( &addr ); breakpoints[num].addr = addr; - breakpoints[num].addrlen = !addr.seg ? 32 : - (GET_SEL_FLAGS(addr.seg) & LDT_FLAGS_32BIT) ? 32 : 16; - breakpoints[num].opcode = *p; + breakpoints[num].addrlen = 32; +#ifdef __i386__ + if (addr.seg) + breakpoints[num].addrlen = DEBUG_GetSelectorType( addr.seg ); + if (breakpoints[num].addrlen == 0) fprintf(stderr, "in bad shape\n"); +#endif + breakpoints[num].opcode = ch; breakpoints[num].enabled = TRUE; - breakpoints[num].in_use = TRUE; + breakpoints[num].refcount = 1; breakpoints[num].skipcount = 0; fprintf( stderr, "Breakpoint %d at ", num ); DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].addrlen, @@ -279,12 +250,15 @@ void DEBUG_AddBreakpoint( const DBG_ADDR *address ) */ void DEBUG_DelBreakpoint( int num ) { - if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use) + if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount) { fprintf( stderr, "Invalid breakpoint number %d\n", num ); return; } + if (--breakpoints[num].refcount > 0) + return; + if( breakpoints[num].condition != NULL ) { DEBUG_FreeExpr(breakpoints[num].condition); @@ -292,7 +266,7 @@ void DEBUG_DelBreakpoint( int num ) } breakpoints[num].enabled = FALSE; - breakpoints[num].in_use = FALSE; + breakpoints[num].refcount = 0; breakpoints[num].skipcount = 0; } @@ -304,12 +278,12 @@ void DEBUG_DelBreakpoint( int num ) */ void DEBUG_EnableBreakpoint( int num, BOOL enable ) { - if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use) + if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount) { fprintf( stderr, "Invalid breakpoint number %d\n", num ); return; } - breakpoints[num].enabled = enable; + breakpoints[num].enabled = (enable) ? TRUE : FALSE; breakpoints[num].skipcount = 0; } @@ -326,67 +300,21 @@ void DEBUG_InfoBreakpoints(void) fprintf( stderr, "Breakpoints:\n" ); for (i = 1; i < next_bp; i++) { - if (breakpoints[i].in_use) + if (breakpoints[i].refcount) { fprintf( stderr, "%d: %c ", i, breakpoints[i].enabled ? 'y' : 'n'); - DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen, - TRUE); - fprintf( stderr, "\n" ); + DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen, TRUE); + fprintf( stderr, " (%u)\n", breakpoints[i].refcount ); if( breakpoints[i].condition != NULL ) - { - fprintf(stderr, "\t\tstop when "); + { + fprintf(stderr, "\t\tstop when "); DEBUG_DisplayExpr(breakpoints[i].condition); fprintf(stderr, "\n"); - } + } } } } - -/*********************************************************************** - * DEBUG_AddTaskEntryBreakpoint - * - * Add a breakpoint at the entry point of the given task - */ -void DEBUG_AddTaskEntryBreakpoint( HTASK16 hTask ) -{ - TDB *pTask = (TDB *)GlobalLock16( hTask ); - NE_MODULE *pModule; - DBG_ADDR addr = { NULL, 0, 0 }; - - if ( pTask ) - { - if (!(pModule = NE_GetPtr( pTask->hModule ))) return; - if (pModule->flags & NE_FFLAGS_LIBMODULE) return; /* Library */ - - if (pModule->lpDosTask) { /* DOS module */ - addr.seg = pModule->lpDosTask->init_cs | ((DWORD)pModule->self << 16); - addr.off = pModule->lpDosTask->init_ip; - fprintf( stderr, "DOS task '%s': ", NE_MODULE_NAME( pModule ) ); - DEBUG_AddBreakpoint( &addr ); - } else - if (!(pModule->flags & NE_FFLAGS_WIN32)) /* NE module */ - { - addr.seg = - GlobalHandleToSel16(NE_SEG_TABLE(pModule)[pModule->cs-1].hSeg); - addr.off = pModule->ip; - fprintf( stderr, "Win16 task '%s': ", NE_MODULE_NAME( pModule ) ); - DEBUG_AddBreakpoint( &addr ); - } - else /* PE module */ - { - addr.seg = 0; - addr.off = (DWORD)RVA_PTR( pModule->module32, - OptionalHeader.AddressOfEntryPoint); - fprintf( stderr, "Win32 task '%s': ", NE_MODULE_NAME( pModule ) ); - DEBUG_AddBreakpoint( &addr ); - } - } - - DEBUG_SetBreakpoints( TRUE ); /* Setup breakpoints */ -} - - /*********************************************************************** * DEBUG_ShouldContinue * @@ -401,21 +329,22 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) struct list_id list; #ifdef __i386__ - /* If not single-stepping, back up over the int3 instruction */ - if (!(EFL_reg(&DEBUG_context) & STEP_FLAG)) EIP_reg(&DEBUG_context)--; + /* If not single-stepping, back up over the int3 instruction */ + if (!(DEBUG_context.EFlags & STEP_FLAG)) + DEBUG_context.Eip--; #endif DEBUG_GetCurrentAddress( &addr ); bpnum = DEBUG_FindBreakpoint( &addr ); - breakpoints[0].enabled = 0; /* disable the step-over breakpoint */ + breakpoints[0].enabled = FALSE; /* disable the step-over breakpoint */ if ((bpnum != 0) && (bpnum != -1)) { if( breakpoints[bpnum].condition != NULL ) - { + { cond_addr = DEBUG_EvalExpr(breakpoints[bpnum].condition); if( cond_addr.type == NULL ) - { + { /* * Something wrong - unable to evaluate this expression. */ @@ -423,21 +352,21 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) DEBUG_DisplayExpr(breakpoints[bpnum].condition); fprintf(stderr, "\nTurning off condition\n"); DEBUG_AddBPCondition(bpnum, NULL); - } + } else if( ! DEBUG_GetExprValue( &cond_addr, NULL) ) - { + { return TRUE; - } - } + } + } if( breakpoints[bpnum].skipcount > 0 ) - { + { breakpoints[bpnum].skipcount--; if( breakpoints[bpnum].skipcount > 0 ) - { + { return TRUE; - } - } + } + } fprintf( stderr, "Stopped on breakpoint %d at ", bpnum ); DEBUG_PrintAddress( &breakpoints[bpnum].addr, breakpoints[bpnum].addrlen, TRUE ); @@ -449,9 +378,9 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) */ DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list); if( list.sourcefile != NULL ) - { + { DEBUG_List(&list, NULL, 0); - } + } return FALSE; } @@ -460,8 +389,7 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) * get the current function, and figure out if we are exactly * on a line number or not. */ - if( mode == EXEC_STEP_OVER - || mode == EXEC_STEP_INSTR ) + if( mode == EXEC_STEP_OVER || mode == EXEC_STEP_INSTR ) { if( DEBUG_CheckLinenoStatus(&addr) == AT_LINENUMBER ) { @@ -499,14 +427,24 @@ BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ) #ifdef __i386__ /* If there's no breakpoint and we are not single-stepping, then we */ /* must have encountered an int3 in the Windows program; let's skip it. */ - if ((bpnum == -1) && !(EFL_reg(&DEBUG_context) & STEP_FLAG)) - EIP_reg(&DEBUG_context)++; + if ((bpnum == -1) && !(DEBUG_context.EFlags & STEP_FLAG)) + DEBUG_context.Eip++; #endif - /* no breakpoint, continue if in continuous mode */ + /* no breakpoint, continue if in continuous mode */ return (mode == EXEC_CONT || mode == EXEC_PASS || mode == EXEC_FINISH); } +/*********************************************************************** + * DEBUG_RestartExecution + * + * Remove all breakpoints before entering the debug loop + */ +void DEBUG_SuspendExecution( void ) +{ + DEBUG_SetBreakpoints( FALSE ); + breakpoints[0] = DEBUG_CurrThread->stepOverBP; +} /*********************************************************************** * DEBUG_RestartExecution @@ -522,7 +460,8 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) int delta; int status; enum exec_mode ret_mode; - BYTE *instr; + DWORD instr; + unsigned char ch; DEBUG_GetCurrentAddress( &addr ); @@ -548,7 +487,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) { if( mode == EXEC_CONT && count > 1 ) { - fprintf(stderr,"Not stopped at any breakpoint; argument ignored.\n"); + fprintf(stderr, "Not stopped at any breakpoint; argument ignored.\n"); } } @@ -557,16 +496,17 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) mode = ret_mode = EXEC_STEPI_INSTR; } - instr = DBG_ADDR_TO_LIN( &addr ); + instr = DEBUG_ToLinear( &addr ); + DEBUG_READ_MEM((void*)instr, &ch, sizeof(ch)); /* * See if the function we are stepping into has debug info * and line numbers. If not, then we step over it instead. * FIXME - we need to check for things like thunks or trampolines, * as the actual function may in fact have debug info. */ - if( *instr == 0xe8 ) + if( ch == 0xe8 ) { - delta = *(unsigned int*) (instr + 1); + DEBUG_READ_MEM((void*)(instr + 1), &delta, sizeof(delta)); addr2 = addr; DEBUG_Disasm(&addr2, FALSE); addr2.off += delta; @@ -612,7 +552,7 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) case EXEC_CONT: /* Continuous execution */ case EXEC_PASS: /* Continue, passing exception */ #ifdef __i386__ - EFL_reg(&DEBUG_context) &= ~STEP_FLAG; + DEBUG_context.EFlags &= ~STEP_FLAG; #endif DEBUG_SetBreakpoints( TRUE ); break; @@ -625,14 +565,16 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) * address just after the call. */ #ifdef __i386__ - addr.off = *((unsigned int *) ESP_reg(&DEBUG_context) + 2); - EFL_reg(&DEBUG_context) &= ~STEP_FLAG; + DEBUG_READ_MEM((void*)(DEBUG_context.Esp + + 2 * sizeof(unsigned int)), + &addr.off, sizeof(addr.off)); + DEBUG_context.EFlags &= ~STEP_FLAG; #endif breakpoints[0].addr = addr; breakpoints[0].enabled = TRUE; - breakpoints[0].in_use = TRUE; + breakpoints[0].refcount = 1; breakpoints[0].skipcount = 0; - breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr ); + DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char)); DEBUG_SetBreakpoints( TRUE ); break; @@ -642,14 +584,14 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) if (DEBUG_IsStepOverInstr()) { #ifdef __i386__ - EFL_reg(&DEBUG_context) &= ~STEP_FLAG; + DEBUG_context.EFlags &= ~STEP_FLAG; #endif DEBUG_Disasm(&addr, FALSE); breakpoints[0].addr = addr; breakpoints[0].enabled = TRUE; - breakpoints[0].in_use = TRUE; + breakpoints[0].refcount = 1; breakpoints[0].skipcount = 0; - breakpoints[0].opcode = *(BYTE *)DBG_ADDR_TO_LIN( &addr ); + DEBUG_READ_MEM((void*)DEBUG_ToLinear( &addr ), &breakpoints[0].opcode, sizeof(char)); DEBUG_SetBreakpoints( TRUE ); break; } @@ -658,17 +600,18 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) case EXEC_STEP_INSTR: /* Single-stepping an instruction */ case EXEC_STEPI_INSTR: /* Single-stepping an instruction */ #ifdef __i386__ - EFL_reg(&DEBUG_context) |= STEP_FLAG; + DEBUG_context.EFlags |= STEP_FLAG; #endif break; } + DEBUG_CurrThread->stepOverBP = breakpoints[0]; return ret_mode; } int DEBUG_AddBPCondition(int num, struct expr * exp) { - if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use) + if ((num <= 0) || (num >= next_bp) || !breakpoints[num].refcount) { fprintf( stderr, "Invalid breakpoint number %d\n", num ); return FALSE; diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c index 42cf385479f..e6783a9e1db 100644 --- a/debugger/db_disasm.c +++ b/debugger/db_disasm.c @@ -892,27 +892,29 @@ static const int db_lengths[] = { static unsigned int db_get_task_value( const DBG_ADDR *addr, int size, int is_signed ) { - unsigned int result; - unsigned char *p = DBG_ADDR_TO_LIN( addr ); + unsigned int result = 0; + char buffer[4]; - switch(size) - { - case 4: - if (is_signed) result = (unsigned int) *(int *)p; - else result = *(unsigned int *)p; - break; - case 2: - if (is_signed) result = (unsigned int) *(short int *)p; - else result = *(unsigned short int *)p; - break; - case 1: - if (is_signed) result = (unsigned int) *(char *)p; - else result = *(unsigned char *)p; - break; - default: + if (size != 1 && size != 2 && size != 4) { fprintf(stderr, "Illegal size specified\n"); - result = 0; - break; + } else { + DEBUG_READ_MEM((void*)DEBUG_ToLinear( addr ), buffer, size); + + switch(size) + { + case 4: + if (is_signed) result = (unsigned int) *(int *)buffer; + else result = *(unsigned int *)buffer; + break; + case 2: + if (is_signed) result = (unsigned int) *(short int *)buffer; + else result = *(unsigned short int *)buffer; + break; + case 1: + if (is_signed) result = (unsigned int) *(char *)buffer; + else result = *(unsigned char *)buffer; + break; + } } return result; } @@ -1041,18 +1043,16 @@ void db_print_address(char *seg, int size, struct i_addr *addrp, int byref) /* try to get destination of indirect call does not work for segmented adresses */ if (!seg && byref) { - DBG_ADDR dbg_addr = {NULL, 0, 0}; + void* a1; + void* a2; - dbg_addr.off = addrp->disp; fprintf(stderr,"0x%x -> ", addrp->disp); - if (DEBUG_IsBadReadPtr( &dbg_addr, sizeof(LPDWORD))) { - fprintf(stderr, "(invalid source)"); - } else { - dbg_addr.off = *(LPDWORD)(addrp->disp); - if (DEBUG_IsBadReadPtr( &dbg_addr, sizeof(DWORD))) - fprintf(stderr, "(invalid destination)"); - else - db_task_printsym(dbg_addr.off, 0); + if (!DEBUG_READ_MEM((void*)addrp->disp, &a1, sizeof(a1))) { + fprintf(stderr, "(invalid source)"); + } else if (!DEBUG_READ_MEM(a1, &a2, sizeof(a2))) { + fprintf(stderr, "(invalid destination)"); + } else { + db_task_printsym((unsigned long)a1, 0); } } else @@ -1172,7 +1172,11 @@ void DEBUG_Disasm( DBG_ADDR *addr, int display ) * Set this so we get can supress the printout if we need to. */ db_display = display; - db_disasm_16 = IS_SELECTOR_V86(addr->seg) || !IS_SELECTOR_32BIT(addr->seg); + switch (DEBUG_GetSelectorType(addr->seg)) { + case 16: db_disasm_16 = 1; break; + case 32: db_disasm_16 = 0; break; + default: fprintf(stderr, "Bad selector %ld\n", addr->seg); return; + } get_value_inc( inst, addr, 1, FALSE ); diff --git a/debugger/dbg.y b/debugger/dbg.y index 663a4e3bb6b..30e26ecfd33 100644 --- a/debugger/dbg.y +++ b/debugger/dbg.y @@ -12,51 +12,21 @@ #include #include #include -#include #include -#ifdef HAVE_ALLOCA_H -#include -#endif -#include "winbase.h" -#include "module.h" -#include "task.h" -#include "options.h" -#include "queue.h" -#include "wine/winbase16.h" -#include "winnt.h" -#include "x11drv.h" -#include "win.h" #include "debugger.h" -#include "neexe.h" -#include "process.h" -#include "server.h" -#include "main.h" #include "expr.h" -#include "user.h" +#include "wine/exception.h" extern FILE * yyin; -unsigned int dbg_mode = 0; -HANDLE dbg_heap = 0; int curr_frame = 0; -static enum exec_mode dbg_exec_mode = EXEC_CONT; -static int dbg_exec_count = 0; - void issue_prompt(void); void mode_command(int); void flush_symbols(void); int yylex(void); int yyerror(char *); -#ifdef DBG_need_heap -#define malloc(x) DBG_alloc(x) -#define realloc(x,y) DBG_realloc(x,y) -#define free(x) DBG_free(x) -#endif - -extern void VIRTUAL_Dump(void); /* memory/virtual.c */ - %} %union @@ -126,41 +96,41 @@ command: tQUIT tEOL { DEBUG_Exit(0); } | tHELP tEOL { DEBUG_Help(); } | tHELP tINFO tEOL { DEBUG_HelpInfo(); } - | tCONT tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_CONT; return 0; } - | tPASS tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_PASS; return 0; } - | tCONT tNUM tEOL { dbg_exec_count = $2; - dbg_exec_mode = EXEC_CONT; return 0; } - | tSTEP tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_STEP_INSTR; return 0; } - | tNEXT tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_STEP_OVER; return 0; } - | tSTEP tNUM tEOL { dbg_exec_count = $2; - dbg_exec_mode = EXEC_STEP_INSTR; return 0; } - | tNEXT tNUM tEOL { dbg_exec_count = $2; - dbg_exec_mode = EXEC_STEP_OVER; return 0; } - | tSTEPI tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_STEPI_INSTR; return 0; } - | tNEXTI tEOL { dbg_exec_count = 1; - dbg_exec_mode = EXEC_STEPI_OVER; return 0; } - | tSTEPI tNUM tEOL { dbg_exec_count = $2; - dbg_exec_mode = EXEC_STEPI_INSTR; return 0; } - | tNEXTI tNUM tEOL { dbg_exec_count = $2; - dbg_exec_mode = EXEC_STEPI_OVER; return 0; } + | tCONT tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; } + | tPASS tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return 0; } + | tCONT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; + DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; } + | tSTEP tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; } + | tNEXT tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; } + | tSTEP tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; } + | tNEXT tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; } + | tSTEPI tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; } + | tNEXTI tEOL { DEBUG_CurrThread->dbg_exec_count = 1; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; } + | tSTEPI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; } + | tNEXTI tNUM tEOL { DEBUG_CurrThread->dbg_exec_count = $2; + DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; } | tABORT tEOL { kill(getpid(), SIGABRT); } | tMODE tNUM tEOL { mode_command($2); } | tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); } | tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); } | tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); } - | tBACKTRACE tEOL { DEBUG_BackTrace(); } + | tBACKTRACE tEOL { DEBUG_BackTrace(TRUE); } | tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); } | tUP tNUM tEOL { DEBUG_SetFrame( curr_frame + $2 ); } | tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); } | tDOWN tNUM tEOL { DEBUG_SetFrame( curr_frame - $2 ); } | tFRAME tNUM tEOL { DEBUG_SetFrame( $2 ); } - | tFINISH tEOL { dbg_exec_count = 0; - dbg_exec_mode = EXEC_FINISH; return 0; } + | tFINISH tEOL { DEBUG_CurrThread->dbg_exec_count = 0; + DEBUG_CurrThread->dbg_exec_mode = EXEC_FINISH; return 0; } | tSHOW tDIR tEOL { DEBUG_ShowDir(); } | tDIR pathname tEOL { DEBUG_AddPath( $2 ); } | tDIR tEOL { DEBUG_NukePath(); } @@ -173,7 +143,6 @@ command: | tUNDISPLAY tEOL { DEBUG_DelDisplay( -1 ); } | tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); } | tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); } - | tDEBUGMSG tDEBUGSTR tEOL { MAIN_ParseDebugOptions($2); } | tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); } | list_command | disassemble_command @@ -274,32 +243,30 @@ break_command: info_command: tINFO tBREAK tEOL { DEBUG_InfoBreakpoints(); } - | tINFO tCLASS expr_value tEOL { CLASS_DumpClass( (struct tagCLASS *)$3 ); - DEBUG_FreeExprMem(); } + | tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); } | tINFO tSHARE tEOL { DEBUG_InfoShare(); } - | tINFO tMODULE expr_value tEOL { NE_DumpModule( $3 ); + | tINFO tMODULE expr_value tEOL { DEBUG_DumpModule( $3 ); DEBUG_FreeExprMem(); } - | tINFO tQUEUE expr_value tEOL { QUEUE_DumpQueue( $3 ); + | tINFO tQUEUE expr_value tEOL { DEBUG_DumpQueue( $3 ); DEBUG_FreeExprMem(); } | tINFO tREGS tEOL { DEBUG_InfoRegisters(); } - | tINFO tSEGMENTS expr_value tEOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 ); - DEBUG_FreeExprMem(); } - | tINFO tSEGMENTS tEOL { LDT_Print( 0, -1 ); } + | tINFO tSEGMENTS expr_value tEOL { DEBUG_InfoSegments( $3, 1 ); DEBUG_FreeExprMem(); } + | tINFO tSEGMENTS tEOL { DEBUG_InfoSegments( 0, -1 ); } | tINFO tSTACK tEOL { DEBUG_InfoStack(); } - | tINFO tMAPS tEOL { VIRTUAL_Dump(); } - | tINFO tWND expr_value tEOL { WIN_DumpWindow( $3 ); + | tINFO tMAPS tEOL { DEBUG_InfoVirtual(); } + | tINFO tWND expr_value tEOL { DEBUG_InfoWindow( (HWND)$3 ); DEBUG_FreeExprMem(); } | tINFO tLOCAL tEOL { DEBUG_InfoLocals(); } | tINFO tDISPLAY tEOL { DEBUG_InfoDisplay(); } walk_command: - tWALK tCLASS tEOL { CLASS_WalkClasses(); } - | tWALK tMODULE tEOL { NE_WalkModules(); } - | tWALK tQUEUE tEOL { QUEUE_WalkQueues(); } - | tWALK tWND tEOL { WIN_WalkWindows( 0, 0 ); } - | tWALK tWND tNUM tEOL { WIN_WalkWindows( $3, 0 ); } - | tWALK tPROCESS tEOL { PROCESS_WalkProcess(); } - | tWALK tMODREF expr_value tEOL { MODULE_WalkModref( $3 ); } + tWALK tCLASS tEOL { DEBUG_WalkClasses(); } + | tWALK tMODULE tEOL { DEBUG_WalkModules(); } + | tWALK tQUEUE tEOL { DEBUG_WalkQueues(); } + | tWALK tWND tEOL { DEBUG_WalkWindows( 0, 0 ); } + | tWALK tWND tNUM tEOL { DEBUG_WalkWindows( $3, 0 ); } + | tWALK tPROCESS tEOL { DEBUG_WalkProcess(); } + | tWALK tMODREF expr_value tEOL { DEBUG_WalkModref( $3 ); } type_cast: @@ -326,11 +293,13 @@ type_expr: | tENUM tIDENTIFIER { $$ = DEBUG_TypeCast(DT_ENUM, $2); } expr_addr: - expr { $$ = DEBUG_EvalExpr($1); } + expr { $$ = DEBUG_EvalExpr($1); } expr_value: - expr { DBG_ADDR addr = DEBUG_EvalExpr($1); - $$ = addr.off ? *(unsigned int *) addr.off : 0; } + expr { DBG_ADDR addr = DEBUG_EvalExpr($1); + /* expr_value is typed as an integer */ + if (!addr.off || !DEBUG_READ_MEM((void*)addr.off, &$$, sizeof($$))) + $$ = 0; } /* * The expr rule builds an expression tree. When we are done, we call * EvalExpr to evaluate the value of the expression. The advantage of @@ -410,50 +379,27 @@ issue_prompt(){ void mode_command(int newmode) { - if ((newmode == 16) || (newmode == 32)) dbg_mode = newmode; + if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode; else fprintf(stderr,"Invalid mode (use 16 or 32)\n"); } -/*********************************************************************** - * DEBUG_Freeze - */ -static void DEBUG_Freeze( BOOL freeze ) +static WINE_EXCEPTION_FILTER(no_symbol) { - static BOOL frozen = FALSE; - - if ( freeze && !frozen ) - { - if ( X11DRV_CritSection.LockSemaphore ) - { - /* Don't freeze thread currently holding the X crst! */ - EnterCriticalSection( &X11DRV_CritSection ); - CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL ); - LeaveCriticalSection( &X11DRV_CritSection ); - } - else - CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL ); - - frozen = TRUE; - } - - if ( !freeze && frozen ) - { - CLIENT_DebuggerRequest( DEBUGGER_UNFREEZE_ALL ); - frozen = FALSE; - } + if (GetExceptionCode() == DEBUG_STATUS_NO_SYMBOL) + return EXCEPTION_EXECUTE_HANDLER; + return EXCEPTION_CONTINUE_SEARCH; } /*********************************************************************** * DEBUG_Exit * * Kill current process. + * */ void DEBUG_Exit( DWORD exit_code ) { - DEBUG_Freeze( FALSE ); - - TASK_KillTask( 0 ); /* FIXME: should not be necessary */ - TerminateProcess( GetCurrentProcess(), exit_code ); + TASK_KillTask( 0 ); /* FIXME: should not be necessary */ + TerminateProcess( DEBUG_CurrProcess->handle, exit_code ); } /*********************************************************************** @@ -461,261 +407,131 @@ void DEBUG_Exit( DWORD exit_code ) * * Debugger main loop. */ -static void DEBUG_Main( BOOL is_debug ) +BOOL DEBUG_Main( BOOL is_debug, BOOL force ) { - static int loaded_symbols = 0; - static BOOL in_debugger = FALSE; - char SymbolTableFile[256]; int newmode; BOOL ret_ok; + char ch; + #ifdef YYDEBUG yydebug = 0; #endif - if (in_debugger) - { - fprintf( stderr, " inside debugger, trying to invoke external debugger.\n" ); - DEBUG_ExternalDebugger(); - DEBUG_Exit(1); - } - in_debugger = TRUE; yyin = stdin; - DEBUG_SetBreakpoints( FALSE ); + DEBUG_SuspendExecution(); if (!is_debug) { #ifdef __i386__ - if (IS_SELECTOR_SYSTEM(CS_reg(&DEBUG_context))) - fprintf( stderr, " in 32-bit code (0x%08lx).\n", EIP_reg(&DEBUG_context)); + if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs)) + fprintf( stderr, " in 32-bit code (0x%08lx).\n", DEBUG_context.Eip ); else fprintf( stderr, " in 16-bit code (%04x:%04lx).\n", - (WORD)CS_reg(&DEBUG_context), EIP_reg(&DEBUG_context) ); + (WORD)DEBUG_context.SegCs, DEBUG_context.Eip ); #else - fprintf( stderr, " (%p).\n", GET_IP(&DEBUG_context) ); + fprintf( stderr, " (%p).\n", GET_IP(DEBUG_CurrThread->context) ); #endif } - if (!loaded_symbols) - { - loaded_symbols++; + if (DEBUG_LoadEntryPoints("Loading new modules symbols:\n")) + DEBUG_ProcessDeferredDebug(); - DEBUG_Freeze( TRUE ); - -#ifdef DBG_need_heap - /* - * Initialize the debugger heap. - */ - dbg_heap = HeapCreate(HEAP_NO_SERIALIZE, 0x1000, 0x8000000); /* 128MB */ -#endif - - /* - * Initialize the type handling stuff. - */ - DEBUG_InitTypes(); - DEBUG_InitCVDataTypes(); - - /* - * In some cases we can read the stabs information directly - * from the executable. If this is the case, we don't need - * to bother with trying to read a symbol file, as the stabs - * also have line number and local variable information. - * As long as gcc is used for the compiler, stabs will - * be the default. On SVr4, DWARF could be used, but we - * don't grok that yet, and in this case we fall back to using - * the wine.sym file. - */ - if( DEBUG_ReadExecutableDbgInfo() == FALSE ) - { - char *symfilename = "wine.sym"; - struct stat statbuf; - if (-1 == stat(symfilename, &statbuf) ) - symfilename = LIBDIR "wine.sym"; - - PROFILE_GetWineIniString( "wine", "SymbolTableFile", symfilename, - SymbolTableFile, sizeof(SymbolTableFile)); - DEBUG_ReadSymbolTable( SymbolTableFile ); - } - DEBUG_LoadEntryPoints(NULL); - DEBUG_ProcessDeferredDebug(); - } - else - { - if (DEBUG_LoadEntryPoints("Loading new modules symbols:\n")) - DEBUG_ProcessDeferredDebug(); - } - -#if 0 - fprintf(stderr, "Entering debugger PC=%x, mode=%d, count=%d\n", - EIP_reg(&DEBUG_context), - dbg_exec_mode, dbg_exec_count); - - sleep(1); -#endif - - if (!is_debug || !DEBUG_ShouldContinue( dbg_exec_mode, &dbg_exec_count )) + if (force || !(is_debug && DEBUG_ShouldContinue( DEBUG_CurrThread->dbg_exec_mode, &DEBUG_CurrThread->dbg_exec_count ))) { DBG_ADDR addr; DEBUG_GetCurrentAddress( &addr ); - DEBUG_Freeze( TRUE ); - - /* Put the display in a correct state */ - if (USER_Driver) USER_Driver->pBeginDebugging(); +/* EPP if (USER_Driver) USER_Driver->pBeginDebugging(); */ #ifdef __i386__ - newmode = ISV86(&DEBUG_context) ? 16 : IS_SELECTOR_32BIT(addr.seg) ? 32 : 16; + switch (newmode = DEBUG_GetSelectorType(addr.seg)) { + case 16: case 32: break; + default: fprintf(stderr, "Bad CS (%ld)\n", addr.seg); newmode = 32; + } #else newmode = 32; #endif - if (newmode != dbg_mode) - fprintf(stderr,"In %d bit mode.\n", dbg_mode = newmode); + if (newmode != DEBUG_CurrThread->dbg_mode) + fprintf(stderr,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode); DEBUG_DoDisplay(); - if (!is_debug) /* This is a real crash, dump some info */ - { - DEBUG_InfoRegisters(); - DEBUG_InfoStack(); -#ifdef __i386__ - if (dbg_mode == 16) - { - LDT_Print( SELECTOR_TO_ENTRY(DS_reg(&DEBUG_context)), 1 ); - if (ES_reg(&DEBUG_context) != DS_reg(&DEBUG_context)) - LDT_Print( SELECTOR_TO_ENTRY(ES_reg(&DEBUG_context)), 1 ); - } - LDT_Print( SELECTOR_TO_ENTRY(FS_reg(&DEBUG_context)), 1 ); -#endif - DEBUG_BackTrace(); - } - else + if (is_debug || force) { /* * Do a quiet backtrace so that we have an idea of what the situation * is WRT the source files. */ - DEBUG_SilentBackTrace(); + DEBUG_BackTrace(FALSE); } + else + { + /* This is a real crash, dump some info */ + DEBUG_InfoRegisters(); + DEBUG_InfoStack(); +#ifdef __i386__ + if (DEBUG_CurrThread->dbg_mode == 16) + { + DEBUG_InfoSegments( DEBUG_context.SegDs >> 3, 1 ); + if (DEBUG_context.SegEs != DEBUG_context.SegDs) + DEBUG_InfoSegments( DEBUG_context.SegEs >> 3, 1 ); + } + DEBUG_InfoSegments( DEBUG_context.SegFs >> 3, 1 ); +#endif + DEBUG_BackTrace(TRUE); + } if (!is_debug || - (dbg_exec_mode == EXEC_STEPI_OVER) || - (dbg_exec_mode == EXEC_STEPI_INSTR)) + (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) || + (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR)) { /* Show where we crashed */ curr_frame = 0; - DEBUG_PrintAddress( &addr, dbg_mode, TRUE ); + DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE ); fprintf(stderr,": "); - if (DBG_CHECK_READ_PTR( &addr, 1 )) - { - DEBUG_Disasm( &addr, TRUE ); - fprintf(stderr,"\n"); - } + DEBUG_Disasm( &addr, TRUE ); + fprintf( stderr, "\n" ); } ret_ok = 0; do { - issue_prompt(); - yyparse(); - flush_symbols(); + __TRY + { + issue_prompt(); + yyparse(); + flush_symbols(); + + DEBUG_GetCurrentAddress( &addr ); + if ((ret_ok = DEBUG_ValidateRegisters())) + ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 ); + } + __EXCEPT(no_symbol) + { + fprintf(stderr, "Undefined symbol\n"); + ret_ok = 0; + } + __ENDTRY; - DEBUG_GetCurrentAddress( &addr ); - ret_ok = DEBUG_ValidateRegisters(); - if (ret_ok) ret_ok = DBG_CHECK_READ_PTR( &addr, 1 ); } while (!ret_ok); } - dbg_exec_mode = DEBUG_RestartExecution( dbg_exec_mode, dbg_exec_count ); + DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution( DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count ); /* * This will have gotten absorbed into the breakpoint info * if it was used. Otherwise it would have been ignored. * In any case, we don't mess with it any more. */ - if ((dbg_exec_mode == EXEC_CONT) || (dbg_exec_mode == EXEC_PASS)) - { - dbg_exec_count = 0; + if ((DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT) || (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)) + DEBUG_CurrThread->dbg_exec_count = 0; - DEBUG_Freeze( FALSE ); - } - - in_debugger = FALSE; - - if (USER_Driver) USER_Driver->pEndDebugging(); +/* EPP if (USER_Driver) USER_Driver->pEndDebugging(); */ + + return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE; } - -DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) -{ - BOOL is_debug = FALSE; - - if (first_chance && !Options.debug) return 0; /* pass to app first */ - - switch(rec->ExceptionCode) - { - case EXCEPTION_BREAKPOINT: - case EXCEPTION_SINGLE_STEP: - is_debug = TRUE; - break; - case CONTROL_C_EXIT: - if (!Options.debug) DEBUG_Exit(0); - break; - } - - if (!is_debug) - { - /* print some infos */ - fprintf( stderr, "%s: ", - first_chance ? "First chance exception" : "Unhandled exception" ); - switch(rec->ExceptionCode) - { - case EXCEPTION_INT_DIVIDE_BY_ZERO: - fprintf( stderr, "divide by zero" ); - break; - case EXCEPTION_INT_OVERFLOW: - fprintf( stderr, "overflow" ); - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - fprintf( stderr, "array bounds " ); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - fprintf( stderr, "illegal instruction" ); - break; - case EXCEPTION_STACK_OVERFLOW: - fprintf( stderr, "stack overflow" ); - break; - case EXCEPTION_PRIV_INSTRUCTION: - fprintf( stderr, "priviledged instruction" ); - break; - case EXCEPTION_ACCESS_VIOLATION: - if (rec->NumberParameters == 2) - fprintf( stderr, "page fault on %s access to 0x%08lx", - rec->ExceptionInformation[0] ? "write" : "read", - rec->ExceptionInformation[1] ); - else - fprintf( stderr, "page fault" ); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - fprintf( stderr, "Alignment" ); - break; - case CONTROL_C_EXIT: - fprintf( stderr, "^C" ); - break; - case EXCEPTION_CRITICAL_SECTION_WAIT: - fprintf( stderr, "critical section %08lx wait failed", rec->ExceptionInformation[0] ); - break; - default: - fprintf( stderr, "%08lx", rec->ExceptionCode ); - break; - } - } - - DEBUG_context = *context; - DEBUG_Main( is_debug ); - *context = DEBUG_context; - return (dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE; -} - -int yyerror(char * s) +int yyerror(char* s) { fprintf(stderr,"%s\n", s); return 0; diff --git a/debugger/debug.l b/debugger/debug.l index 045ec392117..de15577be0c 100644 --- a/debugger/debug.l +++ b/debugger/debug.l @@ -119,7 +119,6 @@ $gs { yylval.reg = REG_GS; return tREG; } frame|fram|fra|fr { BEGIN(NOCMD); return tFRAME; } list|lis|li|l { BEGIN(PATH_EXPECTED); return tLIST; } enable|enabl|enab|ena { BEGIN(NOCMD); return tENABLE;} -debugmsg|debugms|debugm|debug|debu|deb { BEGIN(DEBUGSTR); return tDEBUGMSG;} disable|disabl|disab|disa|dis { BEGIN(NOCMD); return tDISABLE; } disassemble|disassembl|disassemb|disassem|disasse|disass|disas { BEGIN(NOCMD); return tDISASSEMBLE; } display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; } diff --git a/include/debugger.h b/debugger/debugger.h similarity index 71% rename from include/debugger.h rename to debugger/debugger.h index 7428017d23e..d51ddc3e50b 100644 --- a/include/debugger.h +++ b/debugger/debugger.h @@ -9,9 +9,12 @@ #include /* u_long ... */ #include "windef.h" -#include "miscemu.h" +#include "winbase.h" +#ifdef __i386__ #define STEP_FLAG 0x100 /* single step flag */ +#define V86_FLAG 0x00020000 +#endif #define SYM_FUNC 0x0 #define SYM_DATA 0x1 @@ -83,43 +86,73 @@ struct wine_locals { typedef struct wine_locals WineLocals; +enum exec_mode +{ + EXEC_CONT, /* Continuous execution */ + EXEC_PASS, /* Continue, passing exception to app */ + EXEC_STEP_OVER, /* Stepping over a call to next source line */ + EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */ + EXEC_STEPI_OVER, /* Stepping over a call */ + EXEC_STEPI_INSTR, /* Single-stepping an instruction */ + EXEC_FINISH, /* Step until we exit current frame */ + EXEC_STEP_OVER_TRAMPOLINE /* Step over trampoline. Requires that + * we dig the real return value off the stack + * and set breakpoint there - not at the + * instr just after the call. + */ +}; + +typedef struct +{ + DBG_ADDR addr; + BYTE addrlen; + BYTE opcode; + WORD skipcount; + WORD enabled : 1, + refcount; + struct expr * condition; +} BREAKPOINT; + +typedef struct tagWINE_DBG_THREAD { + struct tagWINE_DBG_PROCESS* process; + HANDLE handle; + DWORD tid; + LPVOID start; + LPVOID teb; + int wait_for_first_exception; + int dbg_mode; + enum exec_mode dbg_exec_mode; + int dbg_exec_count; + BREAKPOINT stepOverBP; + struct tagWINE_DBG_THREAD* next; + struct tagWINE_DBG_THREAD* prev; +} WINE_DBG_THREAD; + +typedef struct tagWINE_DBG_PROCESS { + HANDLE handle; + DWORD pid; + WINE_DBG_THREAD* threads; + struct tagWINE_DBG_PROCESS* next; + struct tagWINE_DBG_PROCESS* prev; +} WINE_DBG_PROCESS; + +extern WINE_DBG_PROCESS* DEBUG_CurrProcess; +extern WINE_DBG_THREAD* DEBUG_CurrThread; +extern CONTEXT DEBUG_context; + +#define DEBUG_READ_MEM(addr, buf, len) \ + (ReadProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL)) + +#define DEBUG_WRITE_MEM(addr, buf, len) \ + (WriteProcessMemory(DEBUG_CurrProcess->handle, (addr), (buf), (len), NULL)) + +#define DEBUG_READ_MEM_VERBOSE(addr, buf, len) \ + (DEBUG_READ_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0)) + +#define DEBUG_WRITE_MEM_VERBOSE(addr, buf, len) \ + (DEBUG_WRITE_MEM((addr), (buf), (len)) || (DEBUG_InvalLinAddr( addr ),0)) #ifdef __i386__ - -#define DBG_V86_MODULE(seg) ((seg)>>16) -#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg) - -#define DBG_FIX_ADDR_SEG(addr,default) { \ - if ((addr)->seg == 0xffffffff) (addr)->seg = (default); \ - if (!IS_SELECTOR_V86((addr)->seg)) \ - if (IS_SELECTOR_SYSTEM((addr)->seg)) (addr)->seg = 0; } - -#define DBG_ADDR_TO_LIN(addr) \ - (IS_SELECTOR_V86((addr)->seg) \ - ? (char*)(DOSMEM_MemoryBase(DBG_V86_MODULE((addr)->seg)) + \ - ((((addr)->seg)&0xFFFF)<<4)+(addr)->off) : \ - (IS_SELECTOR_SYSTEM((addr)->seg) ? (char *)(addr)->off \ - : (char *)PTR_SEG_OFF_TO_LIN((addr)->seg,(addr)->off))) - -#else /* __i386__ */ - -#define DBG_FIX_ADDR_SEG(addr,default) -#define DBG_ADDR_TO_LIN(addr) ((char *)(addr)->off) - -#endif /* __386__ */ - -#define DBG_CHECK_READ_PTR(addr,len) \ - (!DEBUG_IsBadReadPtr((addr),(len)) || \ - (fprintf(stderr,"*** Invalid address "), \ - DEBUG_PrintAddress((addr),dbg_mode, FALSE), \ - fprintf(stderr,"\n"),0)) - -#define DBG_CHECK_WRITE_PTR(addr,len) \ - (!DEBUG_IsBadWritePtr((addr),(len)) || \ - (fprintf(stderr,"*** Invalid address "), \ - DEBUG_PrintAddress(addr,dbg_mode, FALSE), \ - fprintf(stderr,"\n"),0)) - #ifdef REG_SP /* Some Sun includes define this */ #undef REG_SP #endif @@ -128,42 +161,24 @@ enum debug_regs { REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_ESI, REG_EDI, REG_EBP, REG_EFL, REG_EIP, REG_ESP, - REG_AX, REG_BX, REG_CX, REG_DX, REG_SI, - REG_DI, REG_BP, REG_FL, REG_IP, REG_SP, - REG_CS, REG_DS, REG_ES, REG_SS, REG_FS, REG_GS + REG_AX, REG_BX, REG_CX, REG_DX, REG_SI, + REG_DI, REG_BP, REG_FL, REG_IP, REG_SP, + REG_CS, REG_DS, REG_ES, REG_SS, REG_FS, REG_GS }; +#endif - -enum exec_mode -{ - EXEC_CONT, /* Continuous execution */ - EXEC_PASS, /* Continue, passing exception to app */ - EXEC_STEP_OVER, /* Stepping over a call to next source line */ - EXEC_STEP_INSTR, /* Step to next source line, stepping in if needed */ - EXEC_STEPI_OVER, /* Stepping over a call */ - EXEC_STEPI_INSTR, /* Single-stepping an instruction */ - EXEC_FINISH, /* Step until we exit current frame */ - EXEC_STEP_OVER_TRAMPOLINE /* Step over trampoline. Requires that - * we dig the real return value off the stack - * and set breakpoint there - not at the - * instr just after the call. - */ -}; - -extern CONTEXT DEBUG_context; /* debugger/registers.c */ -extern unsigned int dbg_mode; -extern HANDLE dbg_heap; +#define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0))) /* debugger/break.c */ extern void DEBUG_SetBreakpoints( BOOL set ); -extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr ); +extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr ); extern void DEBUG_AddBreakpoint( const DBG_ADDR *addr ); extern void DEBUG_DelBreakpoint( int num ); extern void DEBUG_EnableBreakpoint( int num, BOOL enable ); extern void DEBUG_InfoBreakpoints(void); -extern void DEBUG_AddTaskEntryBreakpoint( HTASK16 hTask ); extern BOOL DEBUG_HandleTrap(void); extern BOOL DEBUG_ShouldContinue( enum exec_mode mode, int * count ); +extern void DEBUG_SuspendExecution( void ); extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ); extern BOOL DEBUG_IsFctReturn(void); @@ -185,8 +200,8 @@ struct expr * DEBUG_StructExpr(struct expr *, const char * element); struct expr * DEBUG_ArrayExpr(struct expr *, struct expr * index); struct expr * DEBUG_CallExpr(const char *, int nargs, ...); struct expr * DEBUG_TypeCastExpr(struct datatype *, struct expr *); -extern int DEBUG_ExprValue(DBG_ADDR *, unsigned int *); -DBG_ADDR DEBUG_EvalExpr(struct expr *); +extern int DEBUG_ExprValue(const DBG_ADDR *, unsigned int *); +extern DBG_ADDR DEBUG_EvalExpr(struct expr *); extern int DEBUG_DelDisplay(int displaynum); extern struct expr * DEBUG_CloneExpr(struct expr * exp); extern int DEBUG_FreeExpr(struct expr * exp); @@ -211,7 +226,7 @@ extern struct name_hash * DEBUG_AddInvSymbol( const char *name, const DBG_ADDR *addr, const char * sourcefile); extern BOOL DEBUG_GetSymbolValue( const char * name, const int lineno, - DBG_ADDR *addr, int ); + DBG_ADDR *addr, int ); extern BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr ); extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, struct name_hash ** rtn, @@ -251,13 +266,32 @@ extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen, unsigned int ebp, int flag ); +extern void DEBUG_InfoClass(const char* clsName); +extern void DEBUG_WalkClasses(void); +extern void DEBUG_WalkModref(DWORD p); +extern void DEBUG_DumpModule(DWORD mod); +extern void DEBUG_WalkModules(void); +extern void DEBUG_WalkProcess(void); +extern void DEBUG_DumpQueue(DWORD q); +extern void DEBUG_WalkQueues(void); +extern void DEBUG_InfoSegments(DWORD s, int v); +extern void DEBUG_InfoVirtual(void); +extern void DEBUG_InfoWindow(HWND hWnd); +extern void DEBUG_WalkWindows(HWND hWnd, int indent); /* debugger/memory.c */ -extern BOOL DEBUG_IsBadReadPtr( const DBG_ADDR *address, int size ); -extern BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size ); extern int DEBUG_ReadMemory( const DBG_ADDR *address ); extern void DEBUG_WriteMemory( const DBG_ADDR *address, int value ); extern void DEBUG_ExamineMemory( const DBG_ADDR *addr, int count, char format); +extern void DEBUG_InvalLinAddr( void* addr ); +#ifdef __i386__ +extern void DEBUG_GetCurrentAddress( DBG_ADDR * ); +extern DWORD DEBUG_ToLinear( const DBG_ADDR *address ); +extern void DEBUG_FixAddress( DBG_ADDR *address, DWORD def ); +extern BOOL DEBUG_FixSegment( DBG_ADDR* addr ); +extern int DEBUG_GetSelectorType( WORD sel ); +extern int DEBUG_IsSelectorSystem( WORD sel ); +#endif /* debugger/registers.c */ extern void DEBUG_SetRegister( enum debug_regs reg, int val ); @@ -268,8 +302,7 @@ extern int DEBUG_PrintRegister(enum debug_regs reg); /* debugger/stack.c */ extern void DEBUG_InfoStack(void); -extern void DEBUG_BackTrace(void); -extern void DEBUG_SilentBackTrace(void); +extern void DEBUG_BackTrace(BOOL noisy); extern int DEBUG_InfoLocals(void); extern int DEBUG_SetFrame(int newframe); extern int DEBUG_GetCurrentFrame(struct name_hash ** name, @@ -293,7 +326,7 @@ extern void DEBUG_InitTypes(void); extern struct datatype * DEBUG_NewDataType(enum debug_type xtype, const char * typename); extern unsigned int -DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype); +DEBUG_TypeDerefPointer(const DBG_ADDR * addr, struct datatype ** newtype); extern int DEBUG_AddStructElement(struct datatype * dt, char * name, struct datatype * type, int offset, int size); @@ -306,9 +339,9 @@ extern unsigned int DEBUG_FindStructElement(DBG_ADDR * addr, const char * ele_name, int * tmpbuf); extern struct datatype * DEBUG_GetPointerType(struct datatype * dt); extern int DEBUG_GetObjectSize(struct datatype * dt); -extern unsigned int DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index); +extern unsigned int DEBUG_ArrayIndex(const DBG_ADDR * addr, DBG_ADDR * result, int index); extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype); -extern long long int DEBUG_GetExprValue(DBG_ADDR * addr, char ** format); +extern long long int DEBUG_GetExprValue(const DBG_ADDR * addr, char ** format); extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset, int nbits, struct datatype * dt2); extern int DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2); @@ -322,24 +355,26 @@ extern void DEBUG_AddPath(const char * path); extern void DEBUG_List(struct list_id * line1, struct list_id * line2, int delta); extern void DEBUG_NukePath(void); -extern void DEBUG_GetCurrentAddress( DBG_ADDR * ); extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset ); /* debugger/external.c */ extern void DEBUG_ExternalDebugger(void); /* debugger/dbg.y */ -extern DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ); extern void DEBUG_Exit( DWORD exit_code ); +extern BOOL DEBUG_Main( BOOL is_debug, BOOL force ); /* Choose your allocator! */ #if 1 /* this one is libc's fast one */ -#include "xmalloc.h" -#define DBG_alloc(x) xmalloc(x) -#define DBG_realloc(x,y) xrealloc(x,y) -#define DBG_free(x) free(x) -#define DBG_strdup(x) xstrdup(x) +extern void* DEBUG_XMalloc(size_t size); +extern void* DEBUG_XReAlloc(void *ptr, size_t size); +extern char* DEBUG_XStrDup(const char *str); + +#define DBG_alloc(x) DEBUG_XMalloc(x) +#define DBG_realloc(x,y) DEBUG_XReAlloc(x,y) +#define DBG_free(x) free(x) +#define DBG_strdup(x) DEBUG_XStrDup(x) #else /* this one is slow (takes 5 minutes to load the debugger on my machine), but is pretty crash-proof (can step through malloc() without problems, @@ -352,6 +387,9 @@ extern void DEBUG_Exit( DWORD exit_code ); #define DBG_free(x) HeapFree(dbg_heap,0,x) #define DBG_strdup(x) HEAP_strdupA(dbg_heap,0,x) #define DBG_need_heap +extern HANDLE dbg_heap; #endif +#define DEBUG_STATUS_NO_SYMBOL 0x80003000 + #endif /* __WINE_DEBUGGER_H */ diff --git a/debugger/display.c b/debugger/display.c index df9f9fc5c35..431a289fe33 100644 --- a/debugger/display.c +++ b/debugger/display.c @@ -11,9 +11,6 @@ #include #include -#include "neexe.h" -#include "module.h" -#include "selectors.h" #include "debugger.h" #include diff --git a/debugger/expr.c b/debugger/expr.c index fbee595d173..b4e4345c8cb 100644 --- a/debugger/expr.c +++ b/debugger/expr.c @@ -299,7 +299,6 @@ DEBUG_EvalExpr(struct expr * exp) DBG_ADDR exp1; DBG_ADDR exp2; unsigned int cexp[5]; - int (*fptr)(); int scale1; int scale2; int scale3; @@ -332,12 +331,20 @@ DEBUG_EvalExpr(struct expr * exp) rtn.seg = 0; break; case EXPR_TYPE_SYMBOL: - if( !DEBUG_GetSymbolValue(exp->un.symbol.name, -1, &rtn, FALSE ) ) - { - rtn.type = NULL; - rtn.off = 0; - rtn.seg = 0; - }; + if( !DEBUG_GetSymbolValue(exp->un.symbol.name, -1, &rtn, FALSE) ) + { +#if 1 + RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL); +#else + static char ret[128]; + + /* FIXME: this is an ugly hack... but at least we know + * the symbol is not defined + */ + sprintf(ret, "\"Symbol %s is not defined.\"", exp->un.symbol.name); + rtn = DEBUG_EvalExpr(DEBUG_StringExpr(ret)); +#endif + } break; case EXPR_TYPE_PSTRUCT: exp1 = DEBUG_EvalExpr(exp->un.structure.exp1); @@ -388,6 +395,13 @@ DEBUG_EvalExpr(struct expr * exp) break; } +#if 0 + /* FIXME: NEWDBG NIY */ + /* Anyway, I wonder how this could work depending on the calling order of + * the function (cdecl vs pascal for example) + */ + int (*fptr)(); + fptr = (int (*)()) rtn.off; switch(exp->un.call.nargs) { @@ -410,8 +424,16 @@ DEBUG_EvalExpr(struct expr * exp) exp->un.call.result = (*fptr)(cexp[0], cexp[1], cexp[2], cexp[3], cexp[4]); break; } +#else + fprintf(stderr, "Function call no longer implemented\n"); + /* would need to set up a call to this function, and then restore the current + * context afterwards... + */ + exp->un.call.result = 0; +#endif rtn.type = DEBUG_TypeInt; rtn.off = (unsigned int) &exp->un.call.result; + break; case EXPR_TYPE_REGISTER: rtn.type = DEBUG_TypeIntConst; @@ -419,11 +441,11 @@ DEBUG_EvalExpr(struct expr * exp) rtn.off = (unsigned int) &exp->un.rgister.result; #ifdef __i386__ if( exp->un.rgister.reg == REG_EIP ) - rtn.seg = CS_reg(&DEBUG_context); + rtn.seg = DEBUG_context.SegCs; else - rtn.seg = DS_reg(&DEBUG_context); + rtn.seg = DEBUG_context.SegDs; #endif - DBG_FIX_ADDR_SEG( &rtn, 0 ); + DEBUG_FixAddress( &rtn, 0 ); break; case EXPR_TYPE_BINOP: exp1 = DEBUG_EvalExpr(exp->un.binop.exp1); @@ -497,11 +519,7 @@ DEBUG_EvalExpr(struct expr * exp) rtn.seg = VAL(exp1); exp->un.binop.result = VAL(exp2); #ifdef __i386__ - if (ISV86(&DEBUG_context)) { - TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() ); - rtn.seg |= (DWORD)(pTask?(pTask->hModule):0)<<16; - GlobalUnlock16( GetCurrentTask() ); - } + DEBUG_FixSegment(&rtn); #endif break; case EXP_OP_LOR: @@ -623,12 +641,12 @@ DEBUG_EvalExpr(struct expr * exp) exp->un.unop.result = ~VAL(exp1); break; case EXP_OP_DEREF: - rtn.seg = 0; + rtn.seg = 0; rtn.off = (unsigned int) DEBUG_TypeDerefPointer(&exp1, &rtn.type); break; case EXP_OP_FORCE_DEREF: rtn.seg = exp1.seg; - rtn.off = *(unsigned int *) exp1.off; + rtn.off = DEBUG_READ_MEM((void*)exp1.off, &rtn.off, sizeof(rtn.off)); break; case EXP_OP_ADDR: rtn.seg = 0; @@ -686,10 +704,6 @@ DEBUG_DisplayExpr(struct expr * exp) fprintf(stderr, ".%s", exp->un.structure.element_name); break; case EXPR_TYPE_CALL: - /* - * First, evaluate all of the arguments. If any of them are not - * evaluable, then bail. - */ fprintf(stderr, "%s(",exp->un.call.funcname); for(i=0; i < exp->un.call.nargs; i++) { @@ -841,10 +855,6 @@ DEBUG_CloneExpr(struct expr * exp) rtn->un.structure.element_name = DBG_strdup(exp->un.structure.element_name); break; case EXPR_TYPE_CALL: - /* - * First, evaluate all of the arguments. If any of them are not - * evaluable, then bail. - */ for(i=0; i < exp->un.call.nargs; i++) { rtn->un.call.arg[i] = DEBUG_CloneExpr(exp->un.call.arg[i]); @@ -898,10 +908,6 @@ DEBUG_FreeExpr(struct expr * exp) DBG_free((char *) exp->un.structure.element_name); break; case EXPR_TYPE_CALL: - /* - * First, evaluate all of the arguments. If any of them are not - * evaluable, then bail. - */ for(i=0; i < exp->un.call.nargs; i++) { DEBUG_FreeExpr(exp->un.call.arg[i]); diff --git a/debugger/hash.c b/debugger/hash.c index 8d791022584..35aaf6b283a 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 @@ BOOL DEBUG_Normalize(struct name_hash * nh ) * Get the address of a named symbol. */ BOOL DEBUG_GetSymbolValue( const char * name, const int lineno, - DBG_ADDR *addr, int bp_flag ) + DBG_ADDR *addr, int bp_flag ) { char buffer[256]; struct name_hash *nh; @@ -450,7 +449,7 @@ BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr ) if (!nh) return FALSE; nh->addr = *addr; nh->flags &= SYM_INVALID; - DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(&DEBUG_context) ); + DEBUG_FixAddress( &nh->addr, DEBUG_context.SegDs ); return TRUE; } @@ -477,6 +476,7 @@ const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, char * lineinfo, *sourcefile; int i; char linebuff[16]; + unsigned val; if( rtn != NULL ) { @@ -637,9 +637,9 @@ const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, { strcat(arglist, ", "); } + DEBUG_READ_MEM_VERBOSE(ptr, &val, sizeof(val)); + sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name, val); - sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name, - *ptr); strcat(arglist, argtmp); } if( arglist[0] == '(' ) @@ -1367,13 +1367,26 @@ BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr ) /* FIXME: what if regno == 0 ($eax) */ if( curr_func->local_vars[i].regno != 0 ) { +#if 0 + /* FIXME: NEWDBG NIY */ + /* this is a hack: addr points to the current processor context + * (as defined while entering the debugger), and uses a pointer + * to main memory (thus sharing the process address space *AND* + * the debugger address space, which is not good with address + * space separation in place) + */ /* * Register variable. Point to DEBUG_context field. */ addr->seg = 0; - addr->off = ((DWORD)&DEBUG_context) + reg_ofs[curr_func->local_vars[i].regno]; + addr->off = ((DWORD)DEBUG_context) + reg_ofs[curr_func->local_vars[i].regno]; addr->type = curr_func->local_vars[i].type; - +#else + fprintf(stderr, "No longer supported: value of register variable\n"); + addr->seg = 0; + addr->off = 0; + addr->type = NULL; +#endif return TRUE; } @@ -1395,7 +1408,7 @@ DEBUG_InfoLocals() unsigned int eip; int i; unsigned int * ptr; - int rtn = FALSE; + unsigned int val; if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE ) { @@ -1433,16 +1446,14 @@ DEBUG_InfoLocals() } else { - ptr = (unsigned int *) (ebp + curr_func->local_vars[i].offset); + DEBUG_READ_MEM_VERBOSE((void*)(ebp + curr_func->local_vars[i].offset), + &val, sizeof(val)); fprintf(stderr, "%s:%s == 0x%8.8x\n", - curr_func->name, curr_func->local_vars[i].name, - *ptr); + curr_func->name, curr_func->local_vars[i].name, val); } } - rtn = TRUE; - - return (rtn); + return TRUE; } int diff --git a/debugger/info.c b/debugger/info.c index ec1f0989596..2a6e00b33bf 100644 --- a/debugger/info.c +++ b/debugger/info.c @@ -8,6 +8,10 @@ #include "config.h" #include #include +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "toolhelp.h" #include "debugger.h" #include "expr.h" @@ -28,7 +32,7 @@ void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format ) } default_format = NULL; - value = DEBUG_GetExprValue((DBG_ADDR *) addr, &default_format); + value = DEBUG_GetExprValue(addr, &default_format); switch(format) { @@ -188,3 +192,264 @@ NULL while(infotext[i]) fprintf(stderr,"%s\n", infotext[i++]); } + +/* FIXME: merge InfoClass and InfoClass2 */ +void DEBUG_InfoClass(const char* name) +{ + WNDCLASSEXA wca; + + if (!GetClassInfoExA(0, name, &wca)) { + fprintf(stderr, "Cannot find class '%s'\n", name); + return; + } + + fprintf(stderr, "Class '%s':\n", name); + fprintf(stderr, + "style=%08x wndProc=%08lx\n" + "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n" + "clsExtra=%d winExtra=%d\n", + wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance, + wca.hIcon, wca.hCursor, wca.hbrBackground, + wca.cbClsExtra, wca.cbWndExtra); + + /* FIXME: + * + print #windows (or even list of windows...) + * + print extra bytes => this requires a window handle on this very class... + */ +} + +static void DEBUG_InfoClass2(HWND hWnd, const char* name) +{ + WNDCLASSEXA wca; + + if (!GetClassInfoExA(GetWindowLongA(hWnd, GWL_HINSTANCE), name, &wca)) { + fprintf(stderr, "Cannot find class '%s'\n", name); + return; + } + + fprintf(stderr, "Class '%s':\n", name); + fprintf(stderr, + "style=%08x wndProc=%08lx\n" + "inst=%04x icon=%04x cursor=%04x bkgnd=%04x\n" + "clsExtra=%d winExtra=%d\n", + wca.style, (DWORD)wca.lpfnWndProc, wca.hInstance, + wca.hIcon, wca.hCursor, wca.hbrBackground, + wca.cbClsExtra, wca.cbWndExtra); + + if (wca.cbClsExtra) { + int i; + WORD w; + + fprintf(stderr, "Extra bytes:" ); + for (i = 0; i < wca.cbClsExtra / 2; i++) { + w = GetClassWord(hWnd, i * 2); + /* FIXME: depends on i386 endian-ity */ + fprintf(stderr, " %02x", HIBYTE(w)); + fprintf(stderr, " %02x", LOBYTE(w)); + } + fprintf(stderr, "\n" ); + } + fprintf(stderr, "\n" ); +} + +struct class_walker { + ATOM* table; + int used; + int alloc; +}; + +static void DEBUG_WalkClassesHelper(HWND hWnd, struct class_walker* cw) +{ + char clsName[128]; + int i; + ATOM atom; + HWND child; + + if (!GetClassNameA(hWnd, clsName, sizeof(clsName))) + return; + if ((atom = FindAtomA(clsName)) == 0) + return; + + for (i = 0; i < cw->used; i++) { + if (cw->table[i] == atom) + break; + } + if (i == cw->used) { + if (cw->used >= cw->alloc) { + cw->alloc += 16; + cw->table = DBG_realloc(cw->table, cw->alloc * sizeof(ATOM)); + } + cw->table[cw->used++] = atom; + DEBUG_InfoClass2(hWnd, clsName); + } + do { + if ((child = GetWindow(hWnd, GW_CHILD)) != 0) + DEBUG_WalkClassesHelper(child, cw); + } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0); +} + +void DEBUG_WalkClasses(void) +{ + struct class_walker cw; + + cw.table = NULL; + cw.used = cw.alloc = 0; + DEBUG_WalkClassesHelper(GetDesktopWindow(), &cw); + DBG_free(cw.table); +} + +void DEBUG_DumpModule(DWORD mod) +{ + fprintf(stderr, "No longer doing info module '0x%08lx'\n", mod); +} + +void DEBUG_WalkModules(void) +{ + fprintf(stderr, "No longer walking modules list\n"); +} + +void DEBUG_DumpQueue(DWORD q) +{ + fprintf(stderr, "No longer doing info queue '0x%08lx'\n", q); +} + +void DEBUG_WalkQueues(void) +{ + fprintf(stderr, "No longer walking queues list\n"); +} + +void DEBUG_InfoWindow(HWND hWnd) +{ + char clsName[128]; + char wndName[128]; + RECT clientRect; + RECT windowRect; + int i; + WORD w; + + if (!GetClassNameA(hWnd, clsName, sizeof(clsName))) + strcpy(clsName, "-- Unknown --"); + if (!GetWindowTextA(hWnd, wndName, sizeof(wndName))) + strcpy(wndName, "-- Empty --"); + if (!GetClientRect(hWnd, &clientRect)) + SetRectEmpty(&clientRect); + if (!GetWindowRect(hWnd, &windowRect)) + SetRectEmpty(&windowRect); + + /* FIXME missing fields: hmemTaskQ, hrgnUpdate, dce, flags, pProp, scroll */ + fprintf(stderr, + "next=0x%04x child=0x%04x parent=0x%04x owner=0x%04x class='%s'\n" + "inst=%08lx active=%04x idmenu=%08lx\n" + "style=%08lx exstyle=%08lx wndproc=%08lx text='%s'\n" + "client=%d,%d-%d,%d window=%d,%d-%d,%d sysmenu=%04x\n", + GetWindow(hWnd, GW_HWNDNEXT), + GetWindow(hWnd, GW_CHILD), + GetParent(hWnd), + GetWindow(hWnd, GW_OWNER), + clsName, + GetWindowLongA(hWnd, GWL_HINSTANCE), + GetLastActivePopup(hWnd), + GetWindowLongA(hWnd, GWL_ID), + GetWindowLongA(hWnd, GWL_STYLE), + GetWindowLongA(hWnd, GWL_EXSTYLE), + GetWindowLongA(hWnd, GWL_WNDPROC), + wndName, + clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, + windowRect.left, windowRect.top, windowRect.right, windowRect.bottom, + GetSystemMenu(hWnd, FALSE)); + + if (GetClassLongA(hWnd, GCL_CBWNDEXTRA)) { + fprintf(stderr, "Extra bytes:" ); + for (i = 0; i < GetClassLongA(hWnd, GCL_CBWNDEXTRA) / 2; i++) { + w = GetWindowWord(hWnd, i * 2); + /* FIXME: depends on i386 endian-ity */ + fprintf(stderr, " %02x", HIBYTE(w)); + fprintf(stderr, " %02x", LOBYTE(w)); + } + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); +} + +void DEBUG_WalkWindows(HWND hWnd, int indent) +{ + char clsName[128]; + char wndName[128]; + HWND child; + + if (!IsWindow(hWnd)) + hWnd = GetDesktopWindow(); + + if (!indent) /* first time around */ + fprintf(stderr, + "%-16.16s %-17.17s %-8.8s %s\n", + "hwnd", "Class Name", " Style", " WndProc Text"); + + do { + if (!GetClassNameA(hWnd, clsName, sizeof(clsName))) + strcpy(clsName, "-- Unknown --"); + if (!GetWindowTextA(hWnd, wndName, sizeof(wndName))) + strcpy(wndName, "-- Empty --"); + + /* FIXME: missing hmemTaskQ */ + fprintf(stderr, "%*s%04x%*s", indent, "", hWnd, 13-indent,""); + fprintf(stderr, "%-17.17s %08lx %08lx %.14s\n", + clsName, GetWindowLongA(hWnd, GWL_STYLE), + GetWindowLongA(hWnd, GWL_WNDPROC), wndName); + + if ((child = GetWindow(hWnd, GW_CHILD)) != 0) + DEBUG_WalkWindows(child, indent + 1 ); + } while ((hWnd = GetWindow(hWnd, GW_HWNDNEXT)) != 0); +} + +void DEBUG_WalkProcess(void) +{ + fprintf(stderr, "No longer walking processes list\n"); +} + +void DEBUG_WalkModref(DWORD p) +{ + fprintf(stderr, "No longer walking module references list\n"); +} + +void DEBUG_InfoSegments(DWORD start, int length) +{ + char flags[3]; + DWORD i; + LDT_ENTRY le; + + if (length == -1) length = (8192 - start); + + for (i = start; i < start + length; i++) + { + if (!GetThreadSelectorEntry(DEBUG_CurrThread->handle, (i << 3)|7, &le)) + continue; + + if (le.HighWord.Bits.Type & 0x08) + { + flags[0] = (le.HighWord.Bits.Type & 0x2) ? 'r' : '-'; + flags[1] = '-'; + flags[2] = 'x'; + } + else + { + flags[0] = 'r'; + flags[1] = (le.HighWord.Bits.Type & 0x2) ? 'w' : '-'; + flags[2] = '-'; + } + fprintf(stderr, + "%04lx: sel=%04lx base=%08x limit=%08x %d-bit %c%c%c\n", + i, (i<<3)|7, + (le.HighWord.Bits.BaseHi << 24) + + (le.HighWord.Bits.BaseMid << 16) + le.BaseLow, + ((le.HighWord.Bits.LimitHi << 8) + le.LimitLow) << + (le.HighWord.Bits.Granularity ? 12 : 0), + le.HighWord.Bits.Default_Big ? 32 : 16, + flags[0], flags[1], flags[2] ); + } +} + +void DEBUG_InfoVirtual(void) +{ + fprintf(stderr, "No longer providing virtual mapping information\n"); +} diff --git a/debugger/memory.c b/debugger/memory.c index 63d1d52d02e..07759eee804 100644 --- a/debugger/memory.c +++ b/debugger/memory.c @@ -8,147 +8,126 @@ #include "config.h" #include #include -#include "wine/winbase16.h" +#include #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 seg)) - if (address->seg) /* segmented addr */ - { - if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off, - (WORD)address->seg ), size )) - return TRUE; - } -#endif - return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 1); -} +#include "wine/winbase16.h" +#define DBG_V86_MODULE(seg) ((seg)>>16) +#define IS_SELECTOR_V86(seg) DBG_V86_MODULE(seg) -/*********************************************************************** - * DEBUG_IsBadWritePtr - * - * Check if we are allowed to write memory at 'address'. - */ -BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size ) +static void DEBUG_Die(const char* msg) { -#ifdef __i386__ - if (!IS_SELECTOR_V86(address->seg)) - if (address->seg) /* segmented addr */ - { - /* Note: we use IsBadReadPtr here because we are */ - /* always allowed to write to read-only segments */ - if (IsBadReadPtr16( (SEGPTR)MAKELONG( (WORD)address->off, - (WORD)address->seg ), size )) - return TRUE; - } -#endif - return DEBUG_checkmap_bad( DBG_ADDR_TO_LIN(address), size, 0); + fprintf(stderr, msg); + exit(1); } +void* DEBUG_XMalloc(size_t size) +{ + void *res = malloc(size ? size : 1); + if (res == NULL) + DEBUG_Die("Memory exhausted.\n"); + memset(res, 0, size); + return res; +} + +void* DEBUG_XReAlloc(void *ptr, size_t size) +{ + void* res = realloc(ptr, size); + if ((res == NULL) && size) + DEBUG_Die("Memory exhausted.\n"); + return res; +} + +char* DEBUG_XStrDup(const char *str) +{ + char *res = strdup(str); + if (!res) + DEBUG_Die("Memory exhausted.\n"); + return res; +} + +void DEBUG_FixAddress( DBG_ADDR *addr, DWORD def) +{ + if (addr->seg == 0xffffffff) addr->seg = def; + if (!IS_SELECTOR_V86(addr->seg) && DEBUG_IsSelectorSystem(addr->seg)) addr->seg = 0; +} + +BOOL DEBUG_FixSegment( DBG_ADDR* addr ) +{ + /* V86 mode ? */ + if (DEBUG_context.EFlags & V86_FLAG) { + addr->seg |= (DWORD)(GetExePtr(GetCurrentTask())) << 16; + return TRUE; + } + return FALSE; +} + +DWORD DEBUG_ToLinear( const DBG_ADDR *addr ) +{ + LDT_ENTRY le; + + if (IS_SELECTOR_V86(addr->seg)) + return DOSMEM_MemoryBase(DBG_V86_MODULE(addr->seg)) + (((addr->seg)&0xFFFF)<<4) + addr->off; + if (DEBUG_IsSelectorSystem(addr->seg)) + return addr->off; + + if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, addr->seg, &le)) { + return (le.HighWord.Bits.BaseHi << 24) + (le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->off; + } + return 0; +} + +int DEBUG_GetSelectorType( WORD sel ) +{ + LDT_ENTRY le; + + if (sel == 0) + return 32; + if (IS_SELECTOR_V86(sel)) + return 16; + if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, sel, &le)) + return le.HighWord.Bits.Default_Big ? 32 : 16; + /* selector doesn't exist */ + return 0; +} + +/* Determine if sel is a system selector (i.e. not managed by Wine) */ +BOOL DEBUG_IsSelectorSystem(WORD sel) +{ + return !(sel & 4) || (((sel & 0xFFFF) >> 3) < 17); +} +#endif /* __i386__ */ + +void DEBUG_GetCurrentAddress( DBG_ADDR *addr ) +{ + addr->type = NULL; +#ifdef __i386__ + addr->seg = DEBUG_context.SegCs; + + if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg)) + addr->seg = 0; + addr->off = DEBUG_context.Eip; +#else + addr->seg = 0; + addr->off = 0; +#endif +} + +void DEBUG_InvalLinAddr( void* addr ) +{ + DBG_ADDR address; + + address.type = NULL; + address.seg = 0; + address.off = (unsigned long)addr; + + fprintf(stderr,"*** Invalid address "); + DEBUG_PrintAddress(&address, DEBUG_CurrThread->dbg_mode, FALSE); + fprintf(stderr,"\n"); +} /*********************************************************************** * DEBUG_ReadMemory @@ -157,11 +136,15 @@ BOOL DEBUG_IsBadWritePtr( const DBG_ADDR *address, int size ) */ int DEBUG_ReadMemory( const DBG_ADDR *address ) { - DBG_ADDR addr = *address; - - DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) ); - if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return 0; - return *(int *)DBG_ADDR_TO_LIN( &addr ); + DBG_ADDR addr = *address; + void* lin; + int value; + + DEBUG_FixAddress( &addr, DEBUG_context.SegDs ); + lin = (void*)DEBUG_ToLinear( &addr ); + if (!DEBUG_READ_MEM_VERBOSE(lin, &value, sizeof(value))) + value = 0; + return value; } @@ -172,11 +155,12 @@ int DEBUG_ReadMemory( const DBG_ADDR *address ) */ void DEBUG_WriteMemory( const DBG_ADDR *address, int value ) { - DBG_ADDR addr = *address; + DBG_ADDR addr = *address; + void* lin; - DBG_FIX_ADDR_SEG( &addr, DS_reg(&DEBUG_context) ); - if (!DBG_CHECK_WRITE_PTR( &addr, sizeof(int) )) return; - *(int *)DBG_ADDR_TO_LIN( &addr ) = value; + DEBUG_FixAddress( &addr, DEBUG_context.SegDs ); + lin = (void*)DEBUG_ToLinear( &addr ); + DEBUG_WRITE_MEM_VERBOSE(lin, &value, sizeof(value)); } @@ -188,15 +172,14 @@ void DEBUG_WriteMemory( const DBG_ADDR *address, int value ) void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) { DBG_ADDR addr = * address; - unsigned int * dump; int i; unsigned char * pnt; - unsigned int seg2; struct datatype * testtype; - unsigned short int * wdump; - DBG_FIX_ADDR_SEG( &addr, (format == 'i') ? - CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) ); + DEBUG_FixAddress( &addr, + (format == 'i') ? + DEBUG_context.SegCs : + DEBUG_context.SegDs ); /* * Dereference pointer to get actual memory address we need to be @@ -212,15 +195,15 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) * else in 32-bit space. Grab it, and we * should be all set. */ - seg2 = addr.seg; + unsigned int seg2 = addr.seg; addr.seg = 0; addr.off = DEBUG_GetExprValue(&addr, NULL); addr.seg = seg2; } else { - if (!DBG_CHECK_READ_PTR( &addr, 1 )) return; - DEBUG_TypeDerefPointer(&addr, &testtype); + if (DEBUG_TypeDerefPointer(&addr, &testtype) == 0) + return; if( testtype != NULL || addr.type == DEBUG_TypeIntConst ) { addr.off = DEBUG_GetExprValue(&addr, NULL); @@ -235,135 +218,71 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) if (format != 'i' && count > 1) { - DEBUG_PrintAddress( &addr, dbg_mode, FALSE ); + DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE ); fprintf(stderr,": "); } - pnt = DBG_ADDR_TO_LIN( &addr ); + pnt = (void*)DEBUG_ToLinear( &addr ); switch(format) { case 'u': { - WCHAR *ptr = (WCHAR*)pnt; + WCHAR wch; if (count == 1) count = 256; while (count--) { - if (!DBG_CHECK_READ_PTR( &addr, sizeof(WCHAR) )) return; - if (!*ptr) break; - addr.off++; - fputc( (char)*ptr++, stderr ); + if (!DEBUG_READ_MEM_VERBOSE(pnt, &wch, sizeof(wch))) + break; + pnt += sizeof(wch); + fputc( (char)wch, stderr ); } fprintf(stderr,"\n"); return; } - case 's': + case 's': { + char ch; + if (count == 1) count = 256; while (count--) { - if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return; - if (!*pnt) break; - addr.off++; - fputc( *pnt++, stderr ); + if (!DEBUG_READ_MEM_VERBOSE(pnt, &ch, sizeof(ch))) + break; + pnt++; + fputc( ch, stderr ); } fprintf(stderr,"\n"); return; - + } case 'i': while (count--) { - DEBUG_PrintAddress( &addr, dbg_mode, TRUE ); + DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE ); fprintf(stderr,": "); - if (!DBG_CHECK_READ_PTR( &addr, 1 )) return; DEBUG_Disasm( &addr, TRUE ); fprintf(stderr,"\n"); } return; - case 'x': - dump = (unsigned int *)pnt; - for(i=0; idbg_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 65f953af331..9f6610f6173 100644 --- a/debugger/registers.c +++ b/debugger/registers.c @@ -7,11 +7,8 @@ #include "config.h" #include #include -#include "selectors.h" #include "debugger.h" -CONTEXT DEBUG_context; - /*********************************************************************** * DEBUG_SetRegister * @@ -22,70 +19,73 @@ void DEBUG_SetRegister( enum debug_regs reg, int val ) #ifdef __i386__ switch(reg) { - case REG_EAX: EAX_reg(&DEBUG_context) = val; break; - case REG_EBX: EBX_reg(&DEBUG_context) = val; break; - case REG_ECX: ECX_reg(&DEBUG_context) = val; break; - case REG_EDX: EDX_reg(&DEBUG_context) = val; break; - case REG_ESI: ESI_reg(&DEBUG_context) = val; break; - case REG_EDI: EDI_reg(&DEBUG_context) = val; break; - case REG_EBP: EBP_reg(&DEBUG_context) = val; break; - case REG_EFL: EFL_reg(&DEBUG_context) = val; break; - case REG_EIP: EIP_reg(&DEBUG_context) = val; break; - case REG_ESP: ESP_reg(&DEBUG_context) = val; break; - case REG_CS: CS_reg(&DEBUG_context) = val; break; - case REG_DS: DS_reg(&DEBUG_context) = val; break; - case REG_ES: ES_reg(&DEBUG_context) = val; break; - case REG_SS: SS_reg(&DEBUG_context) = val; break; - case REG_FS: FS_reg(&DEBUG_context) = val; break; - case REG_GS: GS_reg(&DEBUG_context) = val; break; - case REG_AX: SET_LOWORD(EAX_reg(&DEBUG_context),val); break; - case REG_BX: SET_LOWORD(EBX_reg(&DEBUG_context),val); break; - case REG_CX: SET_LOWORD(ECX_reg(&DEBUG_context),val); break; - case REG_DX: SET_LOWORD(EDX_reg(&DEBUG_context),val); break; - case REG_SI: SET_LOWORD(ESI_reg(&DEBUG_context),val); break; - case REG_DI: SET_LOWORD(EDI_reg(&DEBUG_context),val); break; - case REG_BP: SET_LOWORD(EBP_reg(&DEBUG_context),val); break; - case REG_FL: SET_LOWORD(EFL_reg(&DEBUG_context),val); break; - case REG_IP: SET_LOWORD(EIP_reg(&DEBUG_context),val); break; - case REG_SP: SET_LOWORD(ESP_reg(&DEBUG_context),val); break; + case REG_EAX: DEBUG_context.Eax = val; break; + case REG_EBX: DEBUG_context.Ebx = val; break; + case REG_ECX: DEBUG_context.Ecx = val; break; + case REG_EDX: DEBUG_context.Edx = val; break; + case REG_ESI: DEBUG_context.Esi = val; break; + case REG_EDI: DEBUG_context.Edi = val; break; + case REG_EBP: DEBUG_context.Ebp = val; break; + case REG_EFL: DEBUG_context.EFlags = val; break; + case REG_EIP: DEBUG_context.Eip = val; break; + case REG_ESP: DEBUG_context.Esp = val; break; + case REG_CS: DEBUG_context.SegCs = val; break; + case REG_DS: DEBUG_context.SegDs = val; break; + case REG_ES: DEBUG_context.SegEs = val; break; + case REG_SS: DEBUG_context.SegSs = val; break; + case REG_FS: DEBUG_context.SegFs = val; break; + case REG_GS: DEBUG_context.SegGs = val; break; +#define SET_LOW_WORD(dw,lw) ((dw) = ((dw) & 0xFFFF0000) | LOWORD(lw)) + case REG_AX: SET_LOW_WORD(DEBUG_context.Eax,val); break; + case REG_BX: SET_LOW_WORD(DEBUG_context.Ebx,val); break; + case REG_CX: SET_LOW_WORD(DEBUG_context.Ecx,val); break; + case REG_DX: SET_LOW_WORD(DEBUG_context.Edx,val); break; + case REG_SI: SET_LOW_WORD(DEBUG_context.Esi,val); break; + case REG_DI: SET_LOW_WORD(DEBUG_context.Edi,val); break; + case REG_BP: SET_LOW_WORD(DEBUG_context.Ebp,val); break; + case REG_FL: SET_LOW_WORD(DEBUG_context.EFlags,val); break; + case REG_IP: SET_LOW_WORD(DEBUG_context.Eip,val); break; + case REG_SP: SET_LOW_WORD(DEBUG_context.Esp,val); break; +#undef SET_LOWORD } #endif } -int -DEBUG_PrintRegister(enum debug_regs reg) +int DEBUG_PrintRegister(enum debug_regs reg) { #ifdef __i386__ + char* val = NULL; switch(reg) { - case REG_EAX: fprintf(stderr, "%%eax"); break; - case REG_EBX: fprintf(stderr, "%%ebx"); break; - case REG_ECX: fprintf(stderr, "%%ecx"); break; - case REG_EDX: fprintf(stderr, "%%edx"); break; - case REG_ESI: fprintf(stderr, "%%esi"); break; - case REG_EDI: fprintf(stderr, "%%edi"); break; - case REG_EBP: fprintf(stderr, "%%ebp"); break; - case REG_EFL: fprintf(stderr, "%%efl"); break; - case REG_EIP: fprintf(stderr, "%%eip"); break; - case REG_ESP: fprintf(stderr, "%%esp"); break; - case REG_AX: fprintf(stderr, "%%ax"); break; - case REG_BX: fprintf(stderr, "%%bx"); break; - case REG_CX: fprintf(stderr, "%%cx"); break; - case REG_DX: fprintf(stderr, "%%dx"); break; - case REG_SI: fprintf(stderr, "%%si"); break; - case REG_DI: fprintf(stderr, "%%di"); break; - case REG_BP: fprintf(stderr, "%%bp"); break; - case REG_FL: fprintf(stderr, "%%fl"); break; - case REG_IP: fprintf(stderr, "%%ip"); break; - case REG_SP: fprintf(stderr, "%%sp"); break; - case REG_CS: fprintf(stderr, "%%cs"); break; - case REG_DS: fprintf(stderr, "%%ds"); break; - case REG_ES: fprintf(stderr, "%%es"); break; - case REG_SS: fprintf(stderr, "%%ss"); break; - case REG_FS: fprintf(stderr, "%%fs"); break; - case REG_GS: fprintf(stderr, "%%gs"); break; + case REG_EAX: val = "%%eax"; break; + case REG_EBX: val = "%%ebx"; break; + case REG_ECX: val = "%%ecx"; break; + case REG_EDX: val = "%%edx"; break; + case REG_ESI: val = "%%esi"; break; + case REG_EDI: val = "%%edi"; break; + case REG_EBP: val = "%%ebp"; break; + case REG_EFL: val = "%%efl"; break; + case REG_EIP: val = "%%eip"; break; + case REG_ESP: val = "%%esp"; break; + case REG_AX: val = "%%ax"; break; + case REG_BX: val = "%%bx"; break; + case REG_CX: val = "%%cx"; break; + case REG_DX: val = "%%dx"; break; + case REG_SI: val = "%%si"; break; + case REG_DI: val = "%%di"; break; + case REG_BP: val = "%%bp"; break; + case REG_FL: val = "%%fl"; break; + case REG_IP: val = "%%ip"; break; + case REG_SP: val = "%%sp"; break; + case REG_CS: val = "%%cs"; break; + case REG_DS: val = "%%ds"; break; + case REG_ES: val = "%%es"; break; + case REG_SS: val = "%%ss"; break; + case REG_FS: val = "%%fs"; break; + case REG_GS: val = "%%gs"; break; } + if (val) fprintf(stderr, val); return TRUE; #else return FALSE; @@ -102,32 +102,32 @@ int DEBUG_GetRegister( enum debug_regs reg ) #ifdef __i386__ switch(reg) { - case REG_EAX: return EAX_reg(&DEBUG_context); - case REG_EBX: return EBX_reg(&DEBUG_context); - case REG_ECX: return ECX_reg(&DEBUG_context); - case REG_EDX: return EDX_reg(&DEBUG_context); - case REG_ESI: return ESI_reg(&DEBUG_context); - case REG_EDI: return EDI_reg(&DEBUG_context); - case REG_EBP: return EBP_reg(&DEBUG_context); - case REG_EFL: return EFL_reg(&DEBUG_context); - case REG_EIP: return EIP_reg(&DEBUG_context); - case REG_ESP: return ESP_reg(&DEBUG_context); - case REG_CS: return CS_reg(&DEBUG_context); - case REG_DS: return DS_reg(&DEBUG_context); - case REG_ES: return ES_reg(&DEBUG_context); - case REG_SS: return SS_reg(&DEBUG_context); - case REG_FS: return FS_reg(&DEBUG_context); - case REG_GS: return GS_reg(&DEBUG_context); - case REG_AX: return LOWORD(EAX_reg(&DEBUG_context)); - case REG_BX: return LOWORD(EBX_reg(&DEBUG_context)); - case REG_CX: return LOWORD(ECX_reg(&DEBUG_context)); - case REG_DX: return LOWORD(EDX_reg(&DEBUG_context)); - case REG_SI: return LOWORD(ESI_reg(&DEBUG_context)); - case REG_DI: return LOWORD(EDI_reg(&DEBUG_context)); - case REG_BP: return LOWORD(EBP_reg(&DEBUG_context)); - case REG_FL: return LOWORD(EFL_reg(&DEBUG_context)); - case REG_IP: return LOWORD(EIP_reg(&DEBUG_context)); - case REG_SP: return LOWORD(ESP_reg(&DEBUG_context)); + case REG_EAX: return DEBUG_context.Eax; + case REG_EBX: return DEBUG_context.Ebx; + case REG_ECX: return DEBUG_context.Ecx; + case REG_EDX: return DEBUG_context.Edx; + case REG_ESI: return DEBUG_context.Esi; + case REG_EDI: return DEBUG_context.Edi; + case REG_EBP: return DEBUG_context.Ebp; + case REG_EFL: return DEBUG_context.EFlags; + case REG_EIP: return DEBUG_context.Eip; + case REG_ESP: return DEBUG_context.Esp; + case REG_CS: return DEBUG_context.SegCs; + case REG_DS: return DEBUG_context.SegDs; + case REG_ES: return DEBUG_context.SegEs; + case REG_SS: return DEBUG_context.SegSs; + case REG_FS: return DEBUG_context.SegFs; + case REG_GS: return DEBUG_context.SegGs; + case REG_AX: return LOWORD(DEBUG_context.Eax); + case REG_BX: return LOWORD(DEBUG_context.Ebx); + case REG_CX: return LOWORD(DEBUG_context.Ecx); + case REG_DX: return LOWORD(DEBUG_context.Edx); + case REG_SI: return LOWORD(DEBUG_context.Esi); + case REG_DI: return LOWORD(DEBUG_context.Edi); + case REG_BP: return LOWORD(DEBUG_context.Ebp); + case REG_FL: return LOWORD(DEBUG_context.EFlags); + case REG_IP: return LOWORD(DEBUG_context.Eip); + case REG_SP: return LOWORD(DEBUG_context.Esp); } #endif return 0; /* should not happen */ @@ -200,35 +200,35 @@ void DEBUG_InfoRegisters(void) #ifdef __i386__ /* First get the segment registers out of the way */ fprintf( stderr," CS:%04x SS:%04x DS:%04x ES:%04x FS:%04x GS:%04x", - (WORD)CS_reg(&DEBUG_context), (WORD)SS_reg(&DEBUG_context), - (WORD)DS_reg(&DEBUG_context), (WORD)ES_reg(&DEBUG_context), - (WORD)FS_reg(&DEBUG_context), (WORD)GS_reg(&DEBUG_context) ); - if (dbg_mode == 16) + (WORD)DEBUG_context.SegCs, (WORD)DEBUG_context.SegSs, + (WORD)DEBUG_context.SegDs, (WORD)DEBUG_context.SegEs, + (WORD)DEBUG_context.SegFs, (WORD)DEBUG_context.SegGs ); + if (DEBUG_CurrThread->dbg_mode == 16) { char flag[33]; fprintf( stderr,"\n IP:%04x SP:%04x BP:%04x FLAGS:%04x(%s)\n", - LOWORD(EIP_reg(&DEBUG_context)), LOWORD(ESP_reg(&DEBUG_context)), - LOWORD(EBP_reg(&DEBUG_context)), LOWORD(EFL_reg(&DEBUG_context)), - DEBUG_Flags(LOWORD(EFL_reg(&DEBUG_context)), flag)); + LOWORD(DEBUG_context.Eip), LOWORD(DEBUG_context.Esp), + LOWORD(DEBUG_context.Ebp), LOWORD(DEBUG_context.EFlags), + DEBUG_Flags(LOWORD(DEBUG_context.EFlags), flag)); fprintf( stderr," AX:%04x BX:%04x CX:%04x DX:%04x SI:%04x DI:%04x\n", - AX_reg(&DEBUG_context), BX_reg(&DEBUG_context), - CX_reg(&DEBUG_context), DX_reg(&DEBUG_context), - SI_reg(&DEBUG_context), DI_reg(&DEBUG_context) ); + LOWORD(DEBUG_context.Eax), LOWORD(DEBUG_context.Ebx), + LOWORD(DEBUG_context.Ecx), LOWORD(DEBUG_context.Edx), + LOWORD(DEBUG_context.Esi), LOWORD(DEBUG_context.Edi) ); } else /* 32-bit mode */ { char flag[33]; fprintf( stderr, "\n EIP:%08lx ESP:%08lx EBP:%08lx EFLAGS:%08lx(%s)\n", - EIP_reg(&DEBUG_context), ESP_reg(&DEBUG_context), - EBP_reg(&DEBUG_context), EFL_reg(&DEBUG_context), - DEBUG_Flags(EFL_reg(&DEBUG_context), flag)); + DEBUG_context.Eip, DEBUG_context.Esp, + DEBUG_context.Ebp, DEBUG_context.EFlags, + DEBUG_Flags(DEBUG_context.EFlags, flag)); fprintf( stderr, " EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\n", - EAX_reg(&DEBUG_context), EBX_reg(&DEBUG_context), - ECX_reg(&DEBUG_context), EDX_reg(&DEBUG_context) ); + DEBUG_context.Eax, DEBUG_context.Ebx, + DEBUG_context.Ecx, DEBUG_context.Edx ); fprintf( stderr, " ESI:%08lx EDI:%08lx\n", - ESI_reg(&DEBUG_context), EDI_reg(&DEBUG_context) ); + DEBUG_context.Esi, DEBUG_context.Edi ); } #endif } @@ -243,15 +243,12 @@ void DEBUG_InfoRegisters(void) BOOL DEBUG_ValidateRegisters(void) { #ifdef __i386__ - WORD cs, ds; - - if (ISV86(&DEBUG_context)) return TRUE; + if (DEBUG_context.EFlags & V86_FLAG) return TRUE; +#if 0 /* Check that a selector is a valid ring-3 LDT selector, or a NULL selector */ #define CHECK_SEG(seg,name) \ - if (((seg) & ~3) && \ - ((((seg) & 7) != 7) || IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(seg)))) \ - { \ + if (((seg) & ~3) && ((((seg) & 7) != 7) || !DEBUG_IsSelector(seg))) { \ fprintf( stderr, "*** Invalid value for %s register: %04x\n", \ (name), (WORD)(seg) ); \ return FALSE; \ @@ -259,26 +256,26 @@ BOOL DEBUG_ValidateRegisters(void) cs = __get_cs(); ds = __get_ds(); - if (CS_reg(&DEBUG_context) != cs) CHECK_SEG(CS_reg(&DEBUG_context), "CS"); - if (SS_reg(&DEBUG_context) != ds) CHECK_SEG(SS_reg(&DEBUG_context), "SS"); - if (DS_reg(&DEBUG_context) != ds) CHECK_SEG(DS_reg(&DEBUG_context), "DS"); - if (ES_reg(&DEBUG_context) != ds) CHECK_SEG(ES_reg(&DEBUG_context), "ES"); - if (FS_reg(&DEBUG_context) != ds) CHECK_SEG(FS_reg(&DEBUG_context), "FS"); - if (GS_reg(&DEBUG_context) != ds) CHECK_SEG(GS_reg(&DEBUG_context), "GS"); + if (CS_reg(DEBUG_context) != cs) CHECK_SEG(CS_reg(DEBUG_context), "CS"); + if (SS_reg(DEBUG_context) != ds) CHECK_SEG(SS_reg(DEBUG_context), "SS"); + if (DS_reg(DEBUG_context) != ds) CHECK_SEG(DS_reg(DEBUG_context), "DS"); + if (ES_reg(DEBUG_context) != ds) CHECK_SEG(ES_reg(DEBUG_context), "ES"); + if (FS_reg(DEBUG_context) != ds) CHECK_SEG(FS_reg(DEBUG_context), "FS"); + if (GS_reg(DEBUG_context) != ds) CHECK_SEG(GS_reg(DEBUG_context), "GS"); +#endif /* Check that CS and SS are not NULL */ - if (!ISV86(&DEBUG_context)) - if (!(CS_reg(&DEBUG_context) & ~3)) + if (!(DEBUG_context.SegCs & ~3)) { fprintf( stderr, "*** Invalid value for CS register: %04x\n", - (WORD)CS_reg(&DEBUG_context) ); + (WORD)DEBUG_context.SegCs ); return FALSE; } - if (!(SS_reg(&DEBUG_context) & ~3)) + if (!(DEBUG_context.SegSs & ~3)) { fprintf( stderr, "*** Invalid value for SS register: %04x\n", - (WORD)SS_reg(&DEBUG_context) ); + (WORD)DEBUG_context.SegSs ); return FALSE; } return TRUE; diff --git a/debugger/source.c b/debugger/source.c index 6ce1aee6c32..0b7e7c6ce18 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 @@ DEBUG_List(struct list_id * source1, struct list_id * source2, DBG_ADDR DEBUG_LastDisassemble={NULL,0,0}; -void DEBUG_GetCurrentAddress( DBG_ADDR *addr ) -{ -#ifdef __i386__ - TDB *pTask = (TDB*)GlobalLock16( GetCurrentTask() ); - - addr->type = NULL; - addr->seg = CS_reg(&DEBUG_context); - addr->off = EIP_reg(&DEBUG_context); - - if (ISV86(&DEBUG_context)) addr->seg |= (DWORD)(pTask? pTask->hModule : 0) << 16; - else if (IS_SELECTOR_SYSTEM(addr->seg)) addr->seg = 0; - - GlobalUnlock16( GetCurrentTask() ); -#else - addr->type = NULL; - addr->seg = 0; - addr->off = (DWORD)GET_IP(&DEBUG_context); -#endif -} - - static int _disassemble(DBG_ADDR *addr) { - DEBUG_PrintAddress( addr, dbg_mode, TRUE ); - fprintf(stderr,": "); - if (!DBG_CHECK_READ_PTR( addr, 1 )) return 0; - DEBUG_Disasm( addr, TRUE ); - fprintf(stderr,"\n"); - return 1; + char ch; + + DEBUG_PrintAddress( addr, DEBUG_CurrThread->dbg_mode, TRUE ); + fprintf(stderr,": "); + if (!DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(addr), &ch, sizeof(ch))) return 0; + DEBUG_Disasm( addr, TRUE ); + fprintf(stderr,"\n"); + return 1; } void @@ -465,7 +442,7 @@ _disassemble_fixaddr(DBG_ADDR *addr) { DWORD seg2; struct datatype *testtype; - DBG_FIX_ADDR_SEG(addr,CS_reg(&DEBUG_context)); + DEBUG_FixAddress(addr, DEBUG_context.SegCs); if( addr->type != NULL ) { if( addr->type == DEBUG_TypeIntConst ) @@ -482,7 +459,6 @@ _disassemble_fixaddr(DBG_ADDR *addr) { } else { - if (!DBG_CHECK_READ_PTR( addr, 1 )) return; DEBUG_TypeDerefPointer(addr, &testtype); if( testtype != NULL || addr->type == DEBUG_TypeIntConst ) addr->off = DEBUG_GetExprValue(addr, NULL); diff --git a/debugger/stabs.c b/debugger/stabs.c index e0376d8ec9d..7407847bf20 100644 --- a/debugger/stabs.c +++ b/debugger/stabs.c @@ -134,8 +134,6 @@ static void stab_strcpy(char * dest, const char * source) *dest++ = '\0'; } -extern void DEBUG_PrintAType(struct datatype*, int); - typedef struct { char* name; unsigned long value; diff --git a/debugger/stack.c b/debugger/stack.c index 4965e1bd073..62f9b431aae 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 @@ typedef struct DWORD ip; WORD cs; } FRAME32; - +#endif /*********************************************************************** @@ -57,18 +57,20 @@ void DEBUG_InfoStack(void) DBG_ADDR addr; addr.type = NULL; - addr.seg = SS_reg(&DEBUG_context); - addr.off = ESP_reg(&DEBUG_context); + addr.seg = DEBUG_context.SegSs; + addr.off = DEBUG_context.Esp; fprintf(stderr,"Stack dump:\n"); - if (IS_SELECTOR_32BIT(addr.seg)) - { /* 32-bit mode */ - DEBUG_ExamineMemory( &addr, 24, 'x' ); - } - else /* 16-bit mode */ - { + switch (DEBUG_GetSelectorType(addr.seg)) { + case 32: /* 32-bit mode */ + DEBUG_ExamineMemory( &addr, 24, 'x' ); + break; + case 16: /* 16-bit mode */ addr.off &= 0xffff; DEBUG_ExamineMemory( &addr, 24, 'w' ); + break; + default: + fprintf(stderr, "Bad segment (%ld)\n", addr.seg); } fprintf(stderr,"\n"); #endif @@ -79,7 +81,7 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b { int theframe = nframe++; frames = (struct bt_info *)DBG_realloc(frames, - nframe*sizeof(struct bt_info)); + nframe*sizeof(struct bt_info)); if (noisy) fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "), frameno); @@ -87,7 +89,7 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b frames[theframe].eip = code->off; if (noisy) frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, bits, - stack->off, TRUE ); + stack->off, TRUE ); else DEBUG_FindNearestSymbol( code, TRUE, &frames[theframe].frame.sym, stack->off, @@ -101,265 +103,284 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int b static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy) { - unsigned int ss = addr->seg, possible_cs = 0; - FRAME16 *frame = (FRAME16 *)DBG_ADDR_TO_LIN(addr); - int theframe = nframe; - - if (DEBUG_IsBadReadPtr( addr, sizeof(FRAME16) )) { - if (noisy) { - fprintf(stderr,"*** Invalid address "); - DEBUG_PrintAddress(addr, dbg_mode, FALSE); - fprintf(stderr,"\n"); - } - return FALSE; + unsigned int ss = addr->seg, possible_cs = 0; + FRAME16 frame; + int theframe = nframe; + void* p = (void*)DEBUG_ToLinear(addr); + + if (!p) return FALSE; + + if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) { + if (noisy) { + fprintf(stderr,"*** Invalid address "); + DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, FALSE); + fprintf(stderr,"\n"); + } + return FALSE; } - if (!frame->bp) return FALSE; + if (!frame.bp) return FALSE; nframe++; frames = (struct bt_info *)DBG_realloc(frames, - nframe*sizeof(struct bt_info)); + nframe*sizeof(struct bt_info)); if (noisy) - fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "), - frameno); - if (frame->bp & 1) *cs = frame->cs; + fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "), + frameno); + if (frame.bp & 1) *cs = frame.cs; else { - /* not explicitly marked as far call, - * but check whether it could be anyway */ - if (((frame->cs&7)==7) && (frame->cs != *cs) && !IS_SELECTOR_FREE(frame->cs)) { - ldt_entry tcs; - LDT_GetEntry( SELECTOR_TO_ENTRY(frame->cs), &tcs ); - if ( tcs.type == SEGMENT_CODE ) { - /* it is very uncommon to push a code segment cs as - * a parameter, so this should work in most cases */ - *cs = possible_cs = frame->cs; - } - } + /* not explicitly marked as far call, + * but check whether it could be anyway */ + if (((frame.cs&7)==7) && (frame.cs != *cs)) { + LDT_ENTRY le; + + if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, frame.cs, &le) && + (le.HighWord.Bits.Type & 0x08)) { /* code segment */ + /* it is very uncommon to push a code segment cs as + * a parameter, so this should work in most cases */ + *cs = possible_cs = frame.cs; + } + } } frames[theframe].cs = addr->seg = *cs; - frames[theframe].eip = addr->off = frame->ip; + frames[theframe].eip = addr->off = frame.ip; if (noisy) - frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16, - frame->bp, TRUE ); + frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16, + frame.bp, TRUE ); else - DEBUG_FindNearestSymbol( addr, TRUE, - &frames[theframe].frame.sym, frame->bp, - &frames[theframe].frame.list); + DEBUG_FindNearestSymbol( addr, TRUE, + &frames[theframe].frame.sym, frame.bp, + &frames[theframe].frame.list); frames[theframe].ss = addr->seg = ss; - frames[theframe].ebp = addr->off = frame->bp & ~1; + frames[theframe].ebp = addr->off = frame.bp & ~1; if (noisy) { - fprintf( stderr, " (bp=%04lx", addr->off ); - if (possible_cs) { - fprintf( stderr, ", far call assumed" ); - } - fprintf( stderr, ")\n" ); + fprintf( stderr, " (bp=%04lx", addr->off ); + if (possible_cs) { + fprintf( stderr, ", far call assumed" ); + } + fprintf( stderr, ")\n" ); } return TRUE; } static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy) { - unsigned int ss = addr->seg; - FRAME32 *frame = (FRAME32 *)DBG_ADDR_TO_LIN(addr); - int theframe = nframe; - - if (DEBUG_IsBadReadPtr( addr, sizeof(FRAME32) )) { + unsigned int ss = addr->seg; + FRAME32 frame; + int theframe = nframe; + void* p = (void*)DEBUG_ToLinear(addr); + + if (!p) return FALSE; + + if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) { if (noisy) { fprintf(stderr,"*** Invalid address "); - DEBUG_PrintAddress(addr, dbg_mode, FALSE); + DEBUG_PrintAddress(addr, DEBUG_CurrThread->dbg_mode, FALSE); fprintf(stderr,"\n"); } return FALSE; } - if (!frame->ip) return FALSE; + if (!frame.ip) return FALSE; + nframe++; frames = (struct bt_info *)DBG_realloc(frames, - nframe*sizeof(struct bt_info)); + nframe*sizeof(struct bt_info)); if (noisy) - fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "), - frameno); + fprintf(stderr,"%s%d ", (theframe == curr_frame ? "=>" : " "), + frameno); frames[theframe].cs = addr->seg = *cs; - frames[theframe].eip = addr->off = frame->ip; + frames[theframe].eip = addr->off = frame.ip; if (noisy) - frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32, - frame->bp, TRUE ); + frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32, + frame.bp, TRUE ); else - DEBUG_FindNearestSymbol( addr, TRUE, - &frames[theframe].frame.sym, frame->bp, - &frames[theframe].frame.list); - if (noisy) fprintf( stderr, " (ebp=%08lx)\n", frame->bp ); + DEBUG_FindNearestSymbol( addr, TRUE, + &frames[theframe].frame.sym, frame.bp, + &frames[theframe].frame.list); + if (noisy) fprintf( stderr, " (ebp=%08lx)\n", frame.bp ); frames[theframe].ss = addr->seg = ss; - frames[theframe].ebp = frame->bp; - if (addr->off == frame->bp) return FALSE; - addr->off = frame->bp; + frames[theframe].ebp = frame.bp; + if (addr->off == frame.bp) return FALSE; + addr->off = frame.bp; return TRUE; } - -static void DEBUG_DoBackTrace(int noisy) -{ - DBG_ADDR addr, sw_addr; - unsigned int ss = SS_reg(&DEBUG_context), cs = CS_reg(&DEBUG_context); - int frameno = 0, is16, ok; - DWORD next_switch, cur_switch; - - if (noisy) fprintf( stderr, "Backtrace:\n" ); - - nframe = 1; - if (frames) DBG_free( frames ); - frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); - if (noisy) - fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : " "), frameno); - - if (IS_SELECTOR_SYSTEM(ss)) ss = 0; - if (IS_SELECTOR_SYSTEM(cs)) cs = 0; - - /* first stack frame from registers */ - if (IS_SELECTOR_32BIT(ss)) - { - frames[0].cs = addr.seg = cs; - frames[0].eip = addr.off = EIP_reg(&DEBUG_context); - if (noisy) - frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE ); - else - DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, - &frames[0].frame.list); - frames[0].ss = addr.seg = ss; - frames[0].ebp = addr.off = EBP_reg(&DEBUG_context); - if (noisy) fprintf( stderr, " (ebp=%08x)\n", frames[0].ebp ); - is16 = FALSE; - } else { - frames[0].cs = addr.seg = cs; - frames[0].eip = addr.off = LOWORD(EIP_reg(&DEBUG_context)); - if (noisy) - frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE ); - else - DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, - &frames[0].frame.list); - frames[0].ss = addr.seg = ss; - frames[0].ebp = addr.off = BP_reg(&DEBUG_context); - if (noisy) fprintf( stderr, " (bp=%04x)\n", frames[0].ebp ); - is16 = TRUE; - } - - next_switch = NtCurrentTeb()->cur_stack; - if (is16) { - if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch ); - return; - } - cur_switch = (DWORD)((STACK32FRAME*)next_switch)->frame16; - sw_addr.seg = SELECTOROF(cur_switch); - sw_addr.off = OFFSETOF(cur_switch); - } else { - if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) ); - return; - } - cur_switch = (DWORD)((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch))->frame32; - sw_addr.seg = ss; - sw_addr.off = cur_switch; - } - if (DEBUG_IsBadReadPtr(&sw_addr,1)) { - sw_addr.seg = (DWORD)-1; - sw_addr.off = (DWORD)-1; - } - - for (ok = TRUE; ok;) { - if ((frames[frameno].ss == sw_addr.seg) && - (frames[frameno].ebp >= sw_addr.off)) { - /* 16<->32 switch... - * yes, I know this is confusing, it gave me a headache too */ - if (is16) { - STACK32FRAME *frame = (STACK32FRAME*)next_switch; - DBG_ADDR code; - - if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch ); - return; - } - code.type = NULL; - code.seg = 0; - code.off = frame->retaddr; - - cs = 0; - addr.seg = 0; - addr.off = frame->ebp; - DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy ); - - next_switch = cur_switch; - if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) ); - return; - } - cur_switch = (DWORD)((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch))->frame32; - sw_addr.seg = 0; - sw_addr.off = cur_switch; - - is16 = FALSE; - } else { - STACK16FRAME *frame = (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch); - DBG_ADDR code; - - if (IsBadReadPtr((STACK16FRAME*)PTR_SEG_TO_LIN(next_switch), sizeof(STACK16FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)PTR_SEG_TO_LIN(next_switch) ); - return; - } - - code.type = NULL; - code.seg = frame->cs; - code.off = frame->ip; - - cs = frame->cs; - addr.seg = SELECTOROF(next_switch); - addr.off = frame->bp; - DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy ); - - next_switch = cur_switch; - if (IsBadReadPtr((STACK32FRAME*)next_switch, sizeof(STACK32FRAME))) { - if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch ); - return; - } - cur_switch = (DWORD)((STACK32FRAME*)next_switch)->frame16; - sw_addr.seg = SELECTOROF(cur_switch); - sw_addr.off = OFFSETOF(cur_switch); - - is16 = TRUE; - } - if (DEBUG_IsBadReadPtr(&sw_addr,1)) { - sw_addr.seg = (DWORD)-1; - sw_addr.off = (DWORD)-1; - } - } else { - /* ordinary stack frame */ - ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy) - : DEBUG_Frame32( &addr, &cs, ++frameno, noisy); - } - } - if (noisy) fprintf( stderr, "\n" ); -} #endif - /*********************************************************************** * DEBUG_BackTrace * * Display a stack back-trace. */ -void DEBUG_BackTrace(void) +void DEBUG_BackTrace(BOOL noisy) { -#ifdef __i386__ - DEBUG_DoBackTrace( TRUE ); -#endif -} +#ifdef __i386 + DBG_ADDR addr, sw_addr, code, tmp; + unsigned int ss = DEBUG_context.SegSs; + unsigned int cs = DEBUG_context.SegCs; + int frameno = 0, is16, ok; + DWORD next_switch, cur_switch, p; + STACK16FRAME frame16; + STACK32FRAME frame32; + char ch; -/*********************************************************************** - * DEBUG_SilentBackTrace - * - * Display a stack back-trace. - */ -void DEBUG_SilentBackTrace(void) -{ -#ifdef __i386__ - DEBUG_DoBackTrace( FALSE ); + if (noisy) fprintf( stderr, "Backtrace:\n" ); + + nframe = 1; + if (frames) DBG_free( frames ); + frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); + if (noisy) + fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : " "), frameno); + + if (DEBUG_IsSelectorSystem(ss)) ss = 0; + if (DEBUG_IsSelectorSystem(cs)) cs = 0; + + /* first stack frame from registers */ + switch (DEBUG_GetSelectorType(ss)) + { + case 32: + frames[0].cs = addr.seg = cs; + frames[0].eip = addr.off = DEBUG_context.Eip; + if (noisy) + frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE ); + else + DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, + &frames[0].frame.list); + frames[0].ss = addr.seg = ss; + frames[0].ebp = addr.off = DEBUG_context.Ebp; + if (noisy) fprintf( stderr, " (ebp=%08x)\n", frames[0].ebp ); + is16 = FALSE; + break; + case 16: + frames[0].cs = addr.seg = cs; + frames[0].eip = addr.off = LOWORD(DEBUG_context.Eip); + if (noisy) + frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE ); + else + DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, + &frames[0].frame.list); + frames[0].ss = addr.seg = ss; + frames[0].ebp = addr.off = LOWORD(DEBUG_context.Ebp); + if (noisy) fprintf( stderr, " (bp=%04x)\n", frames[0].ebp ); + is16 = TRUE; + break; + default: + if (noisy) fprintf( stderr, "Bad segment '%u'\n", ss); + return; + } + + /* cur_switch holds address of curr_stack's field in TEB in debuggee + * address space + */ + cur_switch = (DWORD)DEBUG_CurrThread->teb + OFFSET_OF(TEB, cur_stack); + if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) { + if (noisy) fprintf( stderr, "Can't read TEB:cur_stack\n"); + return; + } + + if (is16) { + if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", + (STACK32FRAME*)next_switch ); + return; + } + cur_switch = (DWORD)frame32.frame16; + sw_addr.seg = SELECTOROF(cur_switch); + sw_addr.off = OFFSETOF(cur_switch); + } else { + tmp.seg = SELECTOROF(next_switch); + tmp.off = OFFSETOF(next_switch); + p = DEBUG_ToLinear(&tmp); + + if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK16FRAME*)p ); + return; + } + cur_switch = (DWORD)frame16.frame32; + sw_addr.seg = ss; + sw_addr.off = cur_switch; + } + if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) { + sw_addr.seg = (DWORD)-1; + sw_addr.off = (DWORD)-1; + } + + for (ok = TRUE; ok;) { + if ((frames[frameno].ss == sw_addr.seg) && + (frames[frameno].ebp >= sw_addr.off)) { + /* 16<->32 switch... + * yes, I know this is confusing, it gave me a headache too */ + if (is16) { + + if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch ); + return; + } + code.type = NULL; + code.seg = 0; + code.off = frame32.retaddr; + + cs = 0; + addr.seg = 0; + addr.off = frame32.ebp; + DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy ); + + next_switch = cur_switch; + tmp.seg = SELECTOROF(next_switch); + tmp.off = OFFSETOF(next_switch); + p = DEBUG_ToLinear(&tmp); + + if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", + (STACK16FRAME*)p ); + return; + } + cur_switch = (DWORD)frame16.frame32; + sw_addr.seg = 0; + sw_addr.off = cur_switch; + + is16 = FALSE; + } else { + tmp.seg = SELECTOROF(next_switch); + tmp.off = OFFSETOF(next_switch); + p = DEBUG_ToLinear(&tmp); + + if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", + (STACK16FRAME*)p ); + return; + } + + code.type = NULL; + code.seg = frame16.cs; + code.off = frame16.ip; + + cs = frame16.cs; + addr.seg = SELECTOROF(next_switch); + addr.off = frame16.bp; + DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy ); + + next_switch = cur_switch; + if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) { + if (noisy) fprintf( stderr, "Bad stack frame %p\n", + (STACK32FRAME*)next_switch ); + return; + } + cur_switch = (DWORD)frame32.frame16; + sw_addr.seg = SELECTOROF(cur_switch); + sw_addr.off = OFFSETOF(cur_switch); + + is16 = TRUE; + } + if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) { + sw_addr.seg = (DWORD)-1; + sw_addr.off = (DWORD)-1; + } + } else { + /* ordinary stack frame */ + ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy) + : DEBUG_Frame32( &addr, &cs, ++frameno, noisy); + } + } + if (noisy) fprintf( stderr, "\n" ); #endif } diff --git a/debugger/types.c b/debugger/types.c index 1719586e617..c827866c041 100644 --- a/debugger/types.c +++ b/debugger/types.c @@ -345,7 +345,7 @@ DEBUG_InitTypes() } long long int -DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) +DEBUG_GetExprValue(const DBG_ADDR * addr, char ** format) { DBG_ADDR address = *addr; unsigned int rtn; @@ -360,12 +360,10 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) switch(addr->type->type) { case DT_BASIC: - if (!DBG_CHECK_READ_PTR( &address, addr->type->un.basic.basic_size)) - { - return 0; - } + + if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, addr->type->un.basic.basic_size)) + return 0; - memcpy(&rtn, (char *) addr->off, addr->type->un.basic.basic_size); if( (addr->type->un.basic.b_signed) && ((addr->type->un.basic.basic_size & 3) != 0) && ((rtn >> (addr->type->un.basic.basic_size * 8 - 1)) != 0) ) @@ -388,8 +386,9 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) } break; case DT_POINTER: - if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0; - rtn = (unsigned int) *((unsigned char **)addr->off); + if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(void*))) + return 0; + type2 = addr->type->un.pointer.pointsto; if (!type2) @@ -402,9 +401,8 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) if( type2->type == DT_BASIC && type2->un.basic.basic_size == 1 ) { def_format = "\"%s\""; - address.off = rtn; - address.seg = 0; - if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0; + if (!DEBUG_READ_MEM_VERBOSE((void*)rtn, &rtn, 1)) + return 0; break; } else @@ -414,13 +412,13 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) break; case DT_ARRAY: case DT_STRUCT: - if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0; - rtn = (unsigned int) *((unsigned char **)addr->off); + if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(rtn))) + return 0; def_format = "0x%8.8x"; break; case DT_ENUM: - if (!DBG_CHECK_READ_PTR( &address, 1 )) return 0; - rtn = (unsigned int) *((unsigned char **)addr->off); + if (!DEBUG_READ_MEM_VERBOSE((void*)addr->off, &rtn, sizeof(rtn))) + return 0; for(e = addr->type->un.enumeration.members; e; e = e->next ) { if( e->value == rtn ) @@ -452,22 +450,23 @@ DEBUG_GetExprValue(DBG_ADDR * addr, char ** format) } unsigned int -DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype) +DEBUG_TypeDerefPointer(const DBG_ADDR * addr, struct datatype ** newtype) { DBG_ADDR address = *addr; + unsigned int val; /* * Make sure that this really makes sense. */ - if( addr->type->type != DT_POINTER ) + if( addr->type->type != DT_POINTER || !DEBUG_READ_MEM((void*)addr->off, &val, sizeof(val))) { *newtype = NULL; return 0; } *newtype = addr->type->un.pointer.pointsto; - address.off = *(unsigned int*) (addr->off); - return (unsigned int)DBG_ADDR_TO_LIN(&address); /* FIXME: is this right (or "better") ? */ + address.off = val; + return DEBUG_ToLinear(&address); /* FIXME: is this right (or "better") ? */ } unsigned int @@ -718,7 +717,7 @@ int DEBUG_GetObjectSize(struct datatype * dt) } unsigned int -DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index) +DEBUG_ArrayIndex(const DBG_ADDR * addr, DBG_ADDR * result, int index) { int size; diff --git a/debugger/winedbg.c b/debugger/winedbg.c new file mode 100644 index 00000000000..c5fe7d49a7d --- /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 +#include +#include +#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); +} + diff --git a/include/debugdefs.h b/include/debugdefs.h index 3d08eba0d07..fe0a3c095a0 100644 --- a/include/debugdefs.h +++ b/include/debugdefs.h @@ -163,6 +163,7 @@ char dbch_wave[] = "\003wave"; char dbch_win[] = "\003win"; char dbch_win16drv[] = "\003win16drv"; char dbch_win32[] = "\003win32"; +char dbch_winedbg[] = "\003winedbg"; char dbch_wing[] = "\003wing"; char dbch_winsock[] = "\003winsock"; char dbch_winspool[] = "\003winspool"; @@ -170,7 +171,7 @@ char dbch_wnet[] = "\003wnet"; char dbch_x11[] = "\003x11"; char dbch_x11drv[] = "\003x11drv"; -#define DEBUG_CHANNEL_COUNT 163 +#define DEBUG_CHANNEL_COUNT 164 static char * const debug_channels[DEBUG_CHANNEL_COUNT] = { dbch_accel, @@ -330,6 +331,7 @@ static char * const debug_channels[DEBUG_CHANNEL_COUNT] = { dbch_win, dbch_win16drv, dbch_win32, + dbch_winedbg, dbch_wing, dbch_winsock, dbch_winspool, diff --git a/miscemu/main.c b/miscemu/main.c index 09d4e6b6dd1..d20d3f4eeb6 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -7,7 +7,6 @@ #include #include "wine/winbase16.h" #include "callback.h" -#include "debugger.h" #include "main.h" #include "miscemu.h" #include "module.h" @@ -22,6 +21,7 @@ static int MAIN_argc; static char **MAIN_argv; +extern void DEBUG_StartDebugger(DWORD); /*********************************************************************** * Main loop of initial task @@ -29,7 +29,6 @@ static char **MAIN_argv; void MAIN_EmulatorRun( void ) { char startProg[256], defProg[256]; - HINSTANCE handle; int i, tasks = 0; MSG msg; BOOL err_msg = FALSE; @@ -71,18 +70,31 @@ void MAIN_EmulatorRun( void ) /* Load and run executables given on command line */ for (i = 1; i < MAIN_argc; i++) { - if ((handle = WinExec( MAIN_argv[i], SW_SHOWNORMAL )) < 32) - { + PROCESS_INFORMATION info; + STARTUPINFOA startup; + + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = SW_SHOWNORMAL; + + if (!CreateProcessA(NULL, MAIN_argv[i], NULL, NULL, FALSE, 0, + NULL, NULL, &startup, &info)) { err_msg = TRUE; - MESSAGE("wine: can't exec '%s': ", MAIN_argv[i]); - switch (handle) - { - case 2: MESSAGE("main executable or required DLL not found\n" ); break; - case 11: MESSAGE("invalid exe file\n" ); break; - default: MESSAGE("error=%d\n", handle ); break; - } + MESSAGE("wine: can't exec '%s': ", MAIN_argv[i]); + switch (GetLastError()) + { + case 2: MESSAGE("file not found\n" ); break; + case 11: MESSAGE("invalid exe file\n" ); break; + default: MESSAGE("error=%ld\n", GetLastError() ); break; + } } - else tasks++; + else + { + tasks++; + /* hack until wine debugger can be moved to a separate process */ + DEBUG_StartDebugger(info.dwProcessId); + } } if (!tasks)