Commit 911436bf authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- cleaned-up break handling

- better integration of debugger inner loops (parser & events) - added attach command - improved parser so that it can be entered without any process loaded - added BreakOnFirstChance internal variable - disabled NE module symbol module (which is broken with ASS) - misc portability cleanups
parent fb949605
...@@ -369,6 +369,47 @@ void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) ) ...@@ -369,6 +369,47 @@ void DEBUG_AddBreakpoint( const DBG_VALUE *_value, BOOL (*func)(void) )
DEBUG_Printf( DBG_CHN_MESG, "\n" ); DEBUG_Printf( DBG_CHN_MESG, "\n" );
} }
/***********************************************************************
* DEBUG_AddBreakpointFromId
*
* Add a breakpoint from a function name (and eventually a line #)
*/
void DEBUG_AddBreakpointFromId(const char *name, int lineno)
{
DBG_VALUE value;
if (DEBUG_GetSymbolValue(name, lineno, &value, TRUE))
DEBUG_AddBreakpoint(&value, NULL);
else
DEBUG_Printf(DBG_CHN_MESG, "Unable to add breakpoint\n");
}
/***********************************************************************
* DEBUG_AddBreakpointFromLineno
*
* Add a breakpoint from a line number in current file
*/
void DEBUG_AddBreakpointFromLineno(int lineno)
{
DBG_VALUE value;
DEBUG_GetCurrentAddress(&value.addr);
if (lineno != -1) {
struct name_hash* nh;
DEBUG_FindNearestSymbol(&value.addr, TRUE, &nh, 0, NULL);
if (nh == NULL) {
DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
return;
}
DEBUG_GetLineNumberAddr(nh, lineno, &value.addr, TRUE);
}
value.type = NULL;
value.cookie = DV_TARGET;
DEBUG_AddBreakpoint( &value, NULL );
}
/*********************************************************************** /***********************************************************************
* DEBUG_AddWatchpoint * DEBUG_AddWatchpoint
...@@ -439,6 +480,21 @@ void DEBUG_AddWatchpoint( const DBG_VALUE *_value, BOOL is_write ) ...@@ -439,6 +480,21 @@ void DEBUG_AddWatchpoint( const DBG_VALUE *_value, BOOL is_write )
} }
/*********************************************************************** /***********************************************************************
* DEBUG_AddWathpointFromId
*
* Add a watchpoint from a symbol name (and eventually a line #)
*/
void DEBUG_AddWatchpointFromId(const char *name, int lineno)
{
DBG_VALUE value;
if( DEBUG_GetSymbolValue(name, lineno, &value, TRUE) )
DEBUG_AddWatchpoint( &value, 1 );
else
DEBUG_Printf(DBG_CHN_MESG, "Unable to add watchpoint\n");
}
/***********************************************************************
* DEBUG_DelBreakpoint * DEBUG_DelBreakpoint
* *
* Delete a breakpoint. * Delete a breakpoint.
...@@ -921,8 +977,6 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ) ...@@ -921,8 +977,6 @@ enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
DEBUG_context.EFlags |= STEP_FLAG; DEBUG_context.EFlags |= STEP_FLAG;
#endif #endif
break; break;
case EXEC_KILL:
break;
default: default:
RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Lexical scanner for command line parsing * Lexical scanner for command line parsing
* *
* Copyright 1993 Eric Youngdale * Copyright 1993 Eric Youngdale
* 2000 Eric Pouech
*/ */
%{ %{
...@@ -10,12 +11,6 @@ ...@@ -10,12 +11,6 @@
#include "debugger.h" #include "debugger.h"
#include "y.tab.h" #include "y.tab.h"
#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
#ifndef DONT_USE_READLINE #ifndef DONT_USE_READLINE
#undef YY_INPUT #undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
...@@ -23,7 +18,7 @@ ...@@ -23,7 +18,7 @@
YY_FATAL_ERROR( "read() in flex scanner failed" ); YY_FATAL_ERROR( "read() in flex scanner failed" );
static int dbg_read(char * buf, int size); static int dbg_read(char * buf, int size);
static char * make_symbol(char *); static char * DEBUG_MakeSymbol(char *);
#endif /* DONT_USE_READLINE */ #endif /* DONT_USE_READLINE */
...@@ -47,40 +42,42 @@ STRING \"[^\n"]+\" ...@@ -47,40 +42,42 @@ STRING \"[^\n"]+\"
%s WALK_CMD %s WALK_CMD
%s SHOW_CMD %s SHOW_CMD
%s NOCMD %s NOCMD
%s DEBUGSTR
%x ASTRING_EXPECTED
%x NOPROCESS
%% %%
/* set to special state when no process is loaded. */
\n { BEGIN(0); syntax_error = 0; if (!DEBUG_CurrProcess && YYSTATE == INITIAL) {BEGIN(NOPROCESS);}
return tEOL; } /*Indicates end of command. Reset state. */
<*>\n { BEGIN(INITIAL); syntax_error = 0; return tEOL; }
"||" { return OP_LOR; } /* Indicates end of command. Reset state. */
"&&" { return OP_LAND; }
"==" { return OP_EQ; } "||" { return OP_LOR; }
"!=" { return OP_NE; } "&&" { return OP_LAND; }
"<=" { return OP_LE; } "==" { return OP_EQ; }
">=" { return OP_GE; } "!=" { return OP_NE; }
"<<" { return OP_SHL; } "<=" { return OP_LE; }
">>" { return OP_SHR; } ">=" { return OP_GE; }
"->" { return OP_DRF; } "<<" { return OP_SHL; }
[-+<=>|&^()*/%:!~,\.] { return *yytext; } ">>" { return OP_SHR; }
"[" { return *yytext; } "->" { return OP_DRF; }
"]" { return *yytext; } [-+<=>|&^()*/%:!~,\.] { return *yytext; }
"[" { return *yytext; }
"0x"{HEXDIGIT}+ { sscanf(yytext, "%x", &yylval.integer); return tNUM; } "]" { return *yytext; }
{DIGIT}+ { sscanf(yytext, "%d", &yylval.integer); return tNUM; }
"0x"{HEXDIGIT}+ { sscanf(yytext, "%x", &yylval.integer); return tNUM; }
{DIGIT}+ { sscanf(yytext, "%d", &yylval.integer); return tNUM; }
<FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT} { char * last;
yylval.integer = strtol( yytext+1, &last, NULL ); <FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT} { char* last;
yylval.integer = (yylval.integer << 8) | *last; yylval.integer = strtol( yytext+1, &last, NULL ) << 8;
return tFORMAT; } yylval.integer |= *last;
return tFORMAT; }
<FORMAT_EXPECTED>"/"{FORMAT} { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; } <FORMAT_EXPECTED>"/"{FORMAT} { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
{STRING} { yylval.string = make_symbol(yytext); return tSTRING; } {STRING} { yylval.string = DEBUG_MakeSymbol(yytext); return tSTRING; }
<DEBUGSTR>[a-z+\-,]* { yylval.string = yytext; return tDEBUGSTR; } <ASTRING_EXPECTED>[^\n]+ { char* p = yytext; while (*p == ' ' || *p == '\t') p++;
yylval.string = DEBUG_MakeSymbol(p); return tSTRING; }
<INITIAL>info|inf|in { BEGIN(INFO_CMD); return tINFO; } <INITIAL>info|inf|in { BEGIN(INFO_CMD); return tINFO; }
<INITIAL>up { BEGIN(NOCMD); return tUP; } <INITIAL>up { BEGIN(NOCMD); return tUP; }
...@@ -93,9 +90,9 @@ STRING \"[^\n"]+\" ...@@ -93,9 +90,9 @@ STRING \"[^\n"]+\"
<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; } <INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; }
<INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und { BEGIN(NOCMD); return tUNDISPLAY; } <INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und { BEGIN(NOCMD); return tUNDISPLAY; }
<INITIAL>delete|delet|dele|del { BEGIN(DEL_CMD); return tDELETE; } <INITIAL>delete|delet|dele|del { BEGIN(DEL_CMD); return tDELETE; }
<INITIAL>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; } <INITIAL,NOPROCESS>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; }
<INITIAL>set|se { BEGIN(NOCMD); return tSET; } <INITIAL>set|se { BEGIN(NOCMD); return tSET; }
<INITIAL>walk|w { BEGIN(WALK_CMD); return tWALK; } <INITIAL,NOPROCESS>walk|w { BEGIN(WALK_CMD); return tWALK; }
<INITIAL>x { BEGIN(FORMAT_EXPECTED); return tEXAM; } <INITIAL>x { BEGIN(FORMAT_EXPECTED); return tEXAM; }
<INITIAL>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; } <INITIAL>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; }
...@@ -121,11 +118,12 @@ STRING \"[^\n"]+\" ...@@ -121,11 +118,12 @@ STRING \"[^\n"]+\"
<INITIAL,INFO_CMD,DEL_CMD>break|brea|bre|br|b { BEGIN(PATH_EXPECTED); return tBREAK; } <INITIAL,INFO_CMD,DEL_CMD>break|brea|bre|br|b { BEGIN(PATH_EXPECTED); return tBREAK; }
<INITIAL>watch|watc|wat { BEGIN(PATH_EXPECTED); return tWATCH; } <INITIAL>watch|watc|wat { BEGIN(PATH_EXPECTED); return tWATCH; }
<INITIAL>whatis|whati|what { BEGIN(PATH_EXPECTED); return tWHATIS; } <INITIAL>whatis|whati|what { BEGIN(PATH_EXPECTED); return tWHATIS; }
<INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;}
<NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; }
<INFO_CMD>share|shar|sha { return tSHARE; } <INFO_CMD>share|shar|sha { return tSHARE; }
<INFO_CMD>locals|local|loca|loc { return tLOCAL; } <INFO_CMD>locals|local|loca|loc { return tLOCAL; }
<INFO_CMD,WALK_CMD>class|clas|cla { return tCLASS; } <INFO_CMD,WALK_CMD>class|clas|cla { return tCLASS; }
<INFO_CMD,WALK_CMD>module|modul|modu|mod { return tMODULE; } <INFO_CMD,WALK_CMD>module|modul|modu|mod { return tMODULE; }
<INFO_CMD,WALK_CMD>queue|queu|que { return tQUEUE; } <INFO_CMD,WALK_CMD>queue|queu|que { return tQUEUE; }
<INFO_CMD,WALK_CMD>process|proces|proce|proc { return tPROCESS; } <INFO_CMD,WALK_CMD>process|proces|proce|proc { return tPROCESS; }
<INFO_CMD,WALK_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; } <INFO_CMD,WALK_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
...@@ -138,7 +136,7 @@ STRING \"[^\n"]+\" ...@@ -138,7 +136,7 @@ STRING \"[^\n"]+\"
<HELP_CMD>info|inf|in { return tINFO; } <HELP_CMD>info|inf|in { return tINFO; }
<INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir { <INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir {
BEGIN(PATH_EXPECTED); return tDIR; } BEGIN(PATH_EXPECTED); return tDIR; }
char { return tCHAR; } char { return tCHAR; }
short { return tSHORT; } short { return tSHORT; }
...@@ -152,20 +150,18 @@ struct { return tSTRUCT; } ...@@ -152,20 +150,18 @@ struct { return tSTRUCT; }
union { return tUNION; } union { return tUNION; }
enum { return tENUM; } enum { return tENUM; }
{IDENTIFIER} { yylval.string = make_symbol(yytext); return tIDENTIFIER; } {IDENTIFIER} { yylval.string = DEBUG_MakeSymbol(yytext); return tIDENTIFIER; }
"$"{IDENTIFIER} { yylval.string = make_symbol(yytext+1); return tINTVAR; } "$"{IDENTIFIER} { yylval.string = DEBUG_MakeSymbol(yytext+1); return tINTVAR; }
<PATH_EXPECTED>{PATHNAME} { yylval.string = make_symbol(yytext); return tPATH; } <PATH_EXPECTED>{PATHNAME} { yylval.string = DEBUG_MakeSymbol(yytext); return tPATH; }
[ \t]+ /* Eat up whitespace */
. { if (syntax_error == 0)
{
syntax_error ++; DEBUG_Printf(DBG_CHN_MESG, "Syntax Error\n");
}
}
<*>[ \t]+ /* Eat up whitespace */
<NOPROCESS>. { BEGIN(ASTRING_EXPECTED); yyless(0); return tNOPROCESS;}
<*>. { if (syntax_error == 0) {
syntax_error++;
DEBUG_Printf(DBG_CHN_MESG, "Syntax Error (%s)\n", yytext); }
}
%% %%
#ifndef yywrap #ifndef yywrap
...@@ -206,7 +202,7 @@ static int dbg_read(char * buf, int size) ...@@ -206,7 +202,7 @@ static int dbg_read(char * buf, int size)
for (;;) for (;;)
{ {
flush_symbols(); DEBUG_FlushSymbols();
line = readline ("Wine-dbg>"); line = readline ("Wine-dbg>");
if (!line) if (!line)
{ {
...@@ -226,7 +222,7 @@ static int dbg_read(char * buf, int size) ...@@ -226,7 +222,7 @@ static int dbg_read(char * buf, int size)
add_history( line ); add_history( line );
strncpy( last_line, line, 255 ); strncpy( last_line, line, 255 );
last_line[255] = '\0'; last_line[255] = '\0';
} }
free( line ); free( line );
line = last_line; line = last_line;
...@@ -249,14 +245,15 @@ static int dbg_read(char * buf, int size) ...@@ -249,14 +245,15 @@ static int dbg_read(char * buf, int size)
static char *local_symbols[30]; static char *local_symbols[30];
static int next_symbol; static int next_symbol;
static char * make_symbol(char * symbol) static char * DEBUG_MakeSymbol(char * symbol)
{ {
return local_symbols[next_symbol++] = DBG_strdup(symbol); assert(0 <= next_symbol && next_symbol < (sizeof(local_symbols) / sizeof(local_symbols[0])));
return local_symbols[next_symbol++] = DBG_strdup(symbol);
} }
void flush_symbols(void) void DEBUG_FlushSymbols(void)
{ {
while(--next_symbol>= 0) DBG_free(local_symbols[next_symbol]); while(--next_symbol >= 0) DBG_free(local_symbols[next_symbol]);
next_symbol = 0; next_symbol = 0;
} }
......
...@@ -112,7 +112,6 @@ enum exec_mode ...@@ -112,7 +112,6 @@ enum exec_mode
* and set breakpoint there - not at the * and set breakpoint there - not at the
* instr just after the call. * instr just after the call.
*/ */
EXEC_KILL /* terminate debugging session */
}; };
#define DBG_BREAK 0 #define DBG_BREAK 0
...@@ -224,24 +223,16 @@ typedef struct { ...@@ -224,24 +223,16 @@ typedef struct {
#define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0))) #define OFFSET_OF(__c,__f) ((int)(((char*)&(((__c*)0)->__f))-((char*)0)))
/* from winelib.so */
extern void DEBUG_ExternalDebugger(void);
#ifdef __i386__
# define GET_IP(context) ((DWORD)(context)->Eip)
#endif
#ifdef __sparc__
# define GET_IP(context) ((DWORD)(context)->pc)
#endif
#if !defined(GET_IP)
# error You must define GET_IP for this CPU
#endif
/* debugger/break.c */ /* debugger/break.c */
extern void DEBUG_SetBreakpoints( BOOL set ); extern void DEBUG_SetBreakpoints( BOOL set );
extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void) ); extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr, BOOL (*func)(void) );
extern void DEBUG_AddBreakpointFromId( const char *name, int lineno );
extern void DEBUG_AddBreakpointFromLineno( int lineno );
extern void DEBUG_AddWatchpoint( const DBG_VALUE *addr, int is_write ); extern void DEBUG_AddWatchpoint( const DBG_VALUE *addr, int is_write );
extern void DEBUG_AddWatchpointFromId( const char *name, int lineno );
extern void DEBUG_DelBreakpoint( int num ); extern void DEBUG_DelBreakpoint( int num );
extern void DEBUG_EnableBreakpoint( int num, BOOL enable ); extern void DEBUG_EnableBreakpoint( int num, BOOL enable );
extern void DEBUG_InfoBreakpoints(void); extern void DEBUG_InfoBreakpoints(void);
...@@ -250,17 +241,17 @@ extern BOOL DEBUG_ShouldContinue( DWORD code, enum exec_mode mode, int * count ) ...@@ -250,17 +241,17 @@ extern BOOL DEBUG_ShouldContinue( DWORD code, enum exec_mode mode, int * count )
extern void DEBUG_SuspendExecution( void ); extern void DEBUG_SuspendExecution( void );
extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count ); extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
extern BOOL DEBUG_IsFctReturn(void); extern BOOL DEBUG_IsFctReturn(void);
extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp); extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
/* debugger/db_disasm.c */ /* debugger/db_disasm.c */
extern void DEBUG_Disasm( DBG_ADDR *addr, int display ); extern void DEBUG_Disasm( DBG_ADDR *addr, int display );
/* debugger/dbg.y */ /* debugger/dbg.y */
extern BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code ); extern BOOL DEBUG_Parser(void);
extern void DEBUG_Exit( DWORD ); extern void DEBUG_Exit( DWORD );
/* debugger/debug.l */ /* debugger/debug.l */
extern void flush_symbols(void); extern void DEBUG_FlushSymbols(void);
/* debugger/display.c */ /* debugger/display.c */
extern int DEBUG_DoDisplay(void); extern int DEBUG_DoDisplay(void);
...@@ -294,9 +285,6 @@ extern struct expr * DEBUG_CloneExpr(const struct expr * exp); ...@@ -294,9 +285,6 @@ extern struct expr * DEBUG_CloneExpr(const struct expr * exp);
extern int DEBUG_FreeExpr(struct expr * exp); extern int DEBUG_FreeExpr(struct expr * exp);
extern int DEBUG_DisplayExpr(const struct expr * exp); extern int DEBUG_DisplayExpr(const struct expr * exp);
/* debugger/external.c */
extern void DEBUG_ExternalDebugger(void);
/* debugger/hash.c */ /* debugger/hash.c */
extern struct name_hash * DEBUG_AddSymbol( const char *name, extern struct name_hash * DEBUG_AddSymbol( const char *name,
const DBG_VALUE *addr, const DBG_VALUE *addr,
...@@ -378,6 +366,7 @@ extern DBG_MODULE* DEBUG_AddModule(const char* name, int type, ...@@ -378,6 +366,7 @@ extern DBG_MODULE* DEBUG_AddModule(const char* name, int type,
void* mod_addr, HMODULE hmod); void* mod_addr, HMODULE hmod);
extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type); extern DBG_MODULE* DEBUG_FindModuleByName(const char* name, int type);
extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type); extern DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type);
extern DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process);
extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name); extern DBG_MODULE* DEBUG_RegisterPEModule(HMODULE, u_long load_addr, const char* name);
extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name); extern DBG_MODULE* DEBUG_RegisterELFModule(u_long load_addr, const char* name);
extern void DEBUG_InfoShare(void); extern void DEBUG_InfoShare(void);
...@@ -456,8 +445,11 @@ extern int DEBUG_Printf(int chn, const char* format, ...) __attribute__((format ...@@ -456,8 +445,11 @@ extern int DEBUG_Printf(int chn, const char* format, ...) __attribute__((format
extern int DEBUG_Printf(int chn, const char* format, ...); extern int DEBUG_Printf(int chn, const char* format, ...);
#endif #endif
extern DBG_INTVAR* DEBUG_GetIntVar(const char*); extern DBG_INTVAR* DEBUG_GetIntVar(const char*);
extern BOOL DEBUG_Attach(DWORD pid, BOOL cofe);
extern void DEBUG_Run(const char* args);
extern int curr_frame;
/* Choose your allocator! */ /* Choose your allocator! */
#if 1 #if 1
/* this one is libc's fast one */ /* this one is libc's fast one */
extern void* DEBUG_XMalloc(size_t size); extern void* DEBUG_XMalloc(size_t size);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
INTERNAL_VAR(BreakAllThreadsStartup, FALSE, NULL, DEBUG_TypeIntConst) INTERNAL_VAR(BreakAllThreadsStartup, FALSE, NULL, DEBUG_TypeIntConst)
INTERNAL_VAR(BreakOnCritSectTimeOut, FALSE, NULL, DEBUG_TypeIntConst) INTERNAL_VAR(BreakOnCritSectTimeOut, FALSE, NULL, DEBUG_TypeIntConst)
INTERNAL_VAR(BreakOnAttach, FALSE, NULL, DEBUG_TypeIntConst) INTERNAL_VAR(BreakOnAttach, FALSE, NULL, DEBUG_TypeIntConst)
INTERNAL_VAR(BreakOnFirstChance, TRUE, NULL, DEBUG_TypeIntConst)
/* output handling */ /* output handling */
INTERNAL_VAR(ConChannelMask, DBG_CHN_MESG, NULL, DEBUG_TypeIntConst) INTERNAL_VAR(ConChannelMask, DBG_CHN_MESG, NULL, DEBUG_TypeIntConst)
......
...@@ -117,9 +117,11 @@ void DEBUG_GetCurrentAddress( DBG_ADDR *addr ) ...@@ -117,9 +117,11 @@ void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg)) if (!DEBUG_FixSegment( addr ) && DEBUG_IsSelectorSystem(addr->seg))
addr->seg = 0; addr->seg = 0;
addr->off = DEBUG_context.Eip; addr->off = DEBUG_context.Eip;
#elif defined(__sparc__)
addr->seg = 0;
addr->off = DEBUG_context.pc;
#else #else
addr->seg = 0; # error You must define GET_IP for this CPU
addr->off = GET_IP( &DEBUG_context );
#endif #endif
} }
......
...@@ -92,6 +92,21 @@ DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type) ...@@ -92,6 +92,21 @@ DBG_MODULE* DEBUG_FindModuleByHandle(HANDLE handle, int type)
} }
/*********************************************************************** /***********************************************************************
* DEBUG_GetProcessMainModule
*/
DBG_MODULE* DEBUG_GetProcessMainModule(DBG_PROCESS* process)
{
DBG_MODULE* wmod;
if (!process) return NULL;
/* main module is the first to be loaded on a given process, so it's the last on
* the list */
for (wmod = process->modules; wmod && wmod->next; wmod = wmod->next);
return wmod;
}
/***********************************************************************
* DEBUG_RegisterELFModule * DEBUG_RegisterELFModule
* *
* ELF modules are also entered into the list - this is so that we * ELF modules are also entered into the list - this is so that we
...@@ -139,6 +154,7 @@ DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char ...@@ -139,6 +154,7 @@ DBG_MODULE* DEBUG_RegisterNEModule(HMODULE hModule, void* load_addr, const char
return wmod; return wmod;
} }
#if 0
/*********************************************************************** /***********************************************************************
* DEBUG_GetEP16 * DEBUG_GetEP16
* *
...@@ -230,6 +246,7 @@ static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleA ...@@ -230,6 +246,7 @@ static void DEBUG_LoadModule16(HMODULE hModule, NE_MODULE* module, char* moduleA
} }
GlobalUnlock16(module->nrname_handle); GlobalUnlock16(module->nrname_handle);
} }
#endif
/*********************************************************************** /***********************************************************************
* DEBUG_LoadModule32 * DEBUG_LoadModule32
...@@ -355,10 +372,14 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base) ...@@ -355,10 +372,14 @@ void DEBUG_LoadModule32(const char* name, HANDLE hFile, DWORD base)
*/ */
int DEBUG_LoadEntryPoints(const char* pfx) int DEBUG_LoadEntryPoints(const char* pfx)
{ {
int first = 0;
/* FIXME: with address space separation in space, this is plain wrong
* it requires the 16 bit WOW debugging interface...
*/
#if 0
MODULEENTRY entry; MODULEENTRY entry;
NE_MODULE module; NE_MODULE module;
void* moduleAddr; void* moduleAddr;
int first = 0;
int rowcount = 0; int rowcount = 0;
int len; int len;
...@@ -390,6 +411,7 @@ int DEBUG_LoadEntryPoints(const char* pfx) ...@@ -390,6 +411,7 @@ int DEBUG_LoadEntryPoints(const char* pfx)
DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule); DEBUG_LoadModule16(entry.hModule, &module, moduleAddr, entry.szModule);
} while (ModuleNext16(&entry)); } while (ModuleNext16(&entry));
#endif
if (first) DEBUG_Printf(DBG_CHN_MESG, "\n"); if (first) DEBUG_Printf(DBG_CHN_MESG, "\n");
return first; return first;
......
...@@ -121,6 +121,9 @@ void DEBUG_InfoRegisters(void) ...@@ -121,6 +121,9 @@ void DEBUG_InfoRegisters(void)
*/ */
BOOL DEBUG_ValidateRegisters(void) BOOL DEBUG_ValidateRegisters(void)
{ {
DBG_ADDR addr;
char ch;
#ifdef __i386__ #ifdef __i386__
if (DEBUG_context.EFlags & V86_FLAG) return TRUE; if (DEBUG_context.EFlags & V86_FLAG) return TRUE;
...@@ -157,9 +160,13 @@ BOOL DEBUG_ValidateRegisters(void) ...@@ -157,9 +160,13 @@ BOOL DEBUG_ValidateRegisters(void)
(WORD)DEBUG_context.SegSs ); (WORD)DEBUG_context.SegSs );
return FALSE; return FALSE;
} }
return TRUE;
#undef CHECK_SEG #undef CHECK_SEG
#else #else
return TRUE; /* to be written */
#endif #endif
/* check if PC is correct */
DEBUG_GetCurrentAddress(&addr);
return DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(&addr), &ch, 1);
} }
...@@ -30,7 +30,6 @@ struct bt_info ...@@ -30,7 +30,6 @@ struct bt_info
static int nframe; static int nframe;
static struct bt_info * frames = NULL; static struct bt_info * frames = NULL;
int curr_frame;
typedef struct typedef struct
{ {
......
...@@ -897,7 +897,11 @@ DEBUG_Print( const DBG_VALUE *value, int count, char format, int level ) ...@@ -897,7 +897,11 @@ DEBUG_Print( const DBG_VALUE *value, int count, char format, int level )
} }
} }
break; break;
case DT_FUNC:
DEBUG_Printf(DBG_CHN_MESG, "Function at ???\n");
break;
default: default:
DEBUG_Printf(DBG_CHN_MESG, "Unknown type (%d)\n", value->type->type);
assert(FALSE); assert(FALSE);
break; break;
} }
......
...@@ -10,9 +10,7 @@ point of view and processes/threads from a Windows point of view. ...@@ -10,9 +10,7 @@ point of view and processes/threads from a Windows point of view.
Each Windows' thread is implemented as a Unix process (under Linux Each Windows' thread is implemented as a Unix process (under Linux
using the clone syscall), meaning that all threads of a same Windows' using the clone syscall), meaning that all threads of a same Windows'
process share the same (unix) address space (currently, one of wine process share the same (unix) address space.
limitation is that several windows processes run in the same (unix)
address space. it's being worked on).
In the following: In the following:
+ W-process means a process in Windows' terminology + W-process means a process in Windows' terminology
...@@ -69,22 +67,13 @@ winedbg "hl.exe -windowed" ...@@ -69,22 +67,13 @@ winedbg "hl.exe -windowed"
II.2 Attaching II.2 Attaching
-------------- --------------
WineDbg can also launched without any command line argument: WineDbg can also launched without any command line argument:
- if a wineserver is running, WineDbg lists the running W-processes - WineDbg is started without any attached process. You can get a list
(and their wpid:s), and let you pick up the wpid of the W-process you of running W-processes (and their wpid:s) using 'walk process'
want to debug. command, and then, with the attach command, pick up the wpid of the
W-process you want to debug.
This is (for now) a neat feature for the following reasons: This is (for now) a neat feature for the following reasons:
* debug an already started application * debug an already started application
+ launching WineDbg this way let WineDbg and the debugged process run
in a *separate address space* (launching with 'winedbg myprog.exe'
doesn't), and most of the deadlocks seen when running the debugger
disappear (because there is no crit sect shared by both
processes). That's the best (but far from being acceptable) current
way to debug an application
This last advantage shall disappear when address space separation is
in place. At that time, only the ability to debug an already started
process will remain.
II.3 On exception II.3 On exception
----------------- -----------------
...@@ -188,6 +177,9 @@ modifications to those options are automatically saved when WineDbg ...@@ -188,6 +177,9 @@ modifications to those options are automatically saved when WineDbg
terminates). terminates).
Here's the list of all options: Here's the list of all options:
III.2.1 Controling when the debugger is entered
BreakAllThreadsStartup set to TRUE if at all threads start-up the BreakAllThreadsStartup set to TRUE if at all threads start-up the
debugger stops debugger stops
set to FALSE if only at the first thread set to FALSE if only at the first thread
...@@ -204,11 +196,30 @@ BreakOnAttach, set to TRUE if when WineDbg attaches to an ...@@ -204,11 +196,30 @@ BreakOnAttach, set to TRUE if when WineDbg attaches to an
context of an exception event (the next event context of an exception event (the next event
which is the exception event is of course which is the exception event is of course
relevant), that option is likely to be FALSE. relevant), that option is likely to be FALSE.
BreakOnFirstChance an exception can generate two debug events.
The first one is passed to the debugger (known
as a first chance) just after the
exception. The debugger can then decides
either to resume execution (see winedbg's cont
command) or pass the exception up to the
exception handler chain in the program (if it
exists) (winedbg implements this thru the pass
command). If none of the exception handlers
takes care of the exception, the exception
event is sent again to the debugger (known as
last chance exception). You cannot pass on a
last exception. When the BreakOnFirstChance
exception is TRUE, then winedbg is entered for
both first and last chance execptions (to
FALSE, it's only entered for last chance exceptions).
III.2.1 Output handling
ConChannelMask mask of active debugger output channels on ConChannelMask mask of active debugger output channels on
console console
StdChannelMask mask of active debugger output channels on StdChannelMask mask of active debugger output channels on
stderr stderr
UseXTerm set to TRUE if the debugger uses its own xterm UseXTerm set to TRUE if the debugger uses its own xterm
window for console input/output window for console input/output
set to FALSE is the debugger uses the current set to FALSE is the debugger uses the current
...@@ -241,6 +252,17 @@ example >& shell redirect command), you'll get in that file both ...@@ -241,6 +252,17 @@ example >& shell redirect command), you'll get in that file both
outputs. It may be interesting to look in the relay trace for specific outputs. It may be interesting to look in the relay trace for specific
values which the process segv:ed on. values which the process segv:ed on.
III.2.3 Context information
ThreadId ID of the W-thread currently examined by the
debugger
ProcessId ID of the W-thread currently examined by the
debugger
<registers> All CPU registers are also available
The ThreadId and ProcessId variables can be handy to set conditional
breakpoints on a given thread or process.
IV WineDbg commands IV WineDbg commands
=================== ===================
...@@ -249,6 +271,9 @@ IV.1 Misc ...@@ -249,6 +271,9 @@ IV.1 Misc
abort aborts the debugger abort aborts the debugger
quit exits the debugger quit exits the debugger
attach N attach to a W-process (N is its ID). IDs can be
obtained thru walk process command
help prints some help on the commands help prints some help on the commands
help info prints some help on info commands help info prints some help on info commands
...@@ -417,8 +442,7 @@ V.2 Using other Windows debuggers ...@@ -417,8 +442,7 @@ V.2 Using other Windows debuggers
You can use any Windows' debugging API compliant debugger with You can use any Windows' debugging API compliant debugger with
Wine. Some reports have been made of success with VisualStudio Wine. Some reports have been made of success with VisualStudio
debugger (in remote mode, only the hub runs in Wine). debugger (in remote mode, only the hub runs in Wine).
GoVest fully runs in Wine, but is plagued with the same address space GoVest fully runs in Wine.
issues as WineDbg as stated in II.2
V.3 Main differences between winedbg and regular Unix debuggers V.3 Main differences between winedbg and regular Unix debuggers
--------------------------------------------------------------- ---------------------------------------------------------------
...@@ -444,6 +468,5 @@ VI Limitations ...@@ -444,6 +468,5 @@ VI Limitations
16 bit processes are not supported (but calls to 16 bit code in 32 bit 16 bit processes are not supported (but calls to 16 bit code in 32 bit
applications is). applications is).
Lack of address space separation exhibits some deadlocks.
Last updated: 5/21/2000 by ericP Last updated: 6/14/2000 by ericP
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment