Commit d33bcb61 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

Introduced DBG_VALUE struct to manipulate debugger/debuggee address space.

Added watch (hardware assisted debugging) and whatis (type of expr) commands. Fixed some issues in local vars handling (stabs parsing & registers optimization).
parent 38828c4e
...@@ -1011,7 +1011,6 @@ static void db_task_printsym(unsigned int addr, int size) ...@@ -1011,7 +1011,6 @@ static void db_task_printsym(unsigned int addr, int size)
{ {
DBG_ADDR address; DBG_ADDR address;
address.type = NULL;
address.seg = 0; address.seg = 0;
address.off = addr; address.off = addr;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Copyright 1993 Eric Youngdale * Copyright 1993 Eric Youngdale
* Copyright 1995 Morten Welinder * Copyright 1995 Morten Welinder
* Copyright 2000 Eric Pouech
*/ */
#include "config.h" #include "config.h"
...@@ -21,8 +22,8 @@ ...@@ -21,8 +22,8 @@
extern FILE * yyin; extern FILE * yyin;
int curr_frame = 0; int curr_frame = 0;
void issue_prompt(void); static void issue_prompt(void);
void mode_command(int); static void mode_command(int);
void flush_symbols(void); void flush_symbols(void);
int yylex(void); int yylex(void);
int yyerror(char *); int yyerror(char *);
...@@ -31,7 +32,7 @@ int yyerror(char *); ...@@ -31,7 +32,7 @@ int yyerror(char *);
%union %union
{ {
DBG_ADDR address; DBG_VALUE value;
enum debug_regs reg; enum debug_regs reg;
char * string; char * string;
int integer; int integer;
...@@ -46,7 +47,7 @@ int yyerror(char *); ...@@ -46,7 +47,7 @@ int yyerror(char *);
%token tPROCESS tMODREF %token tPROCESS tMODREF
%token tEOL tSTRING tDEBUGSTR %token tEOL tSTRING tDEBUGSTR
%token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
%token tSTEPI tNEXTI tFINISH tSHOW tDIR %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS
%token <string> tPATH %token <string> tPATH
%token <string> tIDENTIFIER tSTRING tDEBUGSTR %token <string> tIDENTIFIER tSTRING tDEBUGSTR
%token <integer> tNUM tFORMAT %token <integer> tNUM tFORMAT
...@@ -77,7 +78,7 @@ int yyerror(char *); ...@@ -77,7 +78,7 @@ int yyerror(char *);
%type <expression> expr lval lvalue %type <expression> expr lval lvalue
%type <type> type_cast type_expr %type <type> type_cast type_expr
%type <address> expr_addr lval_addr %type <value> expr_addr lval_addr
%type <integer> expr_value %type <integer> expr_value
%type <string> pathname %type <string> pathname
...@@ -144,19 +145,21 @@ command: ...@@ -144,19 +145,21 @@ command:
| tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); } | tCOND tNUM tEOL { DEBUG_AddBPCondition($2, NULL); }
| tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); } | tCOND tNUM expr tEOL { DEBUG_AddBPCondition($2, $3); }
| tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); } | tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); }
| tWHATIS expr_addr tEOL { DEBUG_PrintType(&$2); DEBUG_FreeExprMem(); }
| list_command | list_command
| disassemble_command | disassemble_command
| set_command | set_command
| x_command | x_command
| print_command | print_command
| break_command | break_command
| watch_command
| info_command | info_command
| walk_command | walk_command
set_command: set_command:
tSET tREG '=' expr_value tEOL { DEBUG_SetRegister( $2, $4 ); tSET tREG '=' expr_value tEOL { DEBUG_SetRegister( $2, $4 );
DEBUG_FreeExprMem(); } DEBUG_FreeExprMem(); }
| tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory( &$2, $4 ); | tSET lval_addr '=' expr_value tEOL { DEBUG_WriteMemory( &$2.addr, $4 );
DEBUG_FreeExprMem(); } DEBUG_FreeExprMem(); }
pathname: pathname:
...@@ -180,7 +183,7 @@ list_arg: ...@@ -180,7 +183,7 @@ list_arg:
| pathname ':' tNUM { $$.sourcefile = $1; $$.line = $3; } | pathname ':' tNUM { $$.sourcefile = $1; $$.line = $3; }
| tIDENTIFIER { DEBUG_GetFuncInfo( & $$, NULL, $1); } | tIDENTIFIER { DEBUG_GetFuncInfo( & $$, NULL, $1); }
| pathname ':' tIDENTIFIER { DEBUG_GetFuncInfo( & $$, $1, $3); } | pathname ':' tIDENTIFIER { DEBUG_GetFuncInfo( & $$, $1, $3); }
| '*' expr_addr { DEBUG_FindNearestSymbol( & $2, FALSE, NULL, | '*' expr_addr { DEBUG_FindNearestSymbol( & $2.addr, FALSE, NULL,
0, & $$ ); 0, & $$ );
DEBUG_FreeExprMem(); } DEBUG_FreeExprMem(); }
...@@ -199,20 +202,20 @@ print_command: ...@@ -199,20 +202,20 @@ print_command:
break_command: break_command:
tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3 ); tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3 );
DEBUG_FreeExprMem(); } DEBUG_FreeExprMem(); }
| tBREAK tIDENTIFIER tEOL { DBG_ADDR addr; | tBREAK tIDENTIFIER tEOL { DBG_VALUE value;
if( DEBUG_GetSymbolValue($2, -1, &addr, TRUE) ) if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
{ {
DEBUG_AddBreakpoint( &addr ); DEBUG_AddBreakpoint( &value );
} }
else else
{ {
fprintf(stderr,"Unable to add breakpoint\n"); fprintf(stderr,"Unable to add breakpoint\n");
} }
} }
| tBREAK tIDENTIFIER ':' tNUM tEOL { DBG_ADDR addr; | tBREAK tIDENTIFIER ':' tNUM tEOL { DBG_VALUE value;
if( DEBUG_GetSymbolValue($2, $4, &addr, TRUE) ) if( DEBUG_GetSymbolValue($2, $4, &value, TRUE) )
{ {
DEBUG_AddBreakpoint( &addr ); DEBUG_AddBreakpoint( &value );
} }
else else
{ {
...@@ -220,15 +223,16 @@ break_command: ...@@ -220,15 +223,16 @@ break_command:
} }
} }
| tBREAK tNUM tEOL { struct name_hash *nh; | tBREAK tNUM tEOL { struct name_hash *nh;
DBG_ADDR addr; DBG_VALUE value;
DEBUG_GetCurrentAddress( &addr ); DEBUG_GetCurrentAddress( &value.addr );
DEBUG_FindNearestSymbol(&addr, TRUE, DEBUG_FindNearestSymbol(&value.addr, TRUE,
&nh, 0, NULL); &nh, 0, NULL);
if( nh != NULL ) if( nh != NULL )
{ {
DEBUG_GetLineNumberAddr(nh, DEBUG_GetLineNumberAddr(nh, $2, &value.addr, TRUE);
$2, &addr, TRUE); value.type = NULL;
DEBUG_AddBreakpoint( &addr ); value.cookie = DV_TARGET;
DEBUG_AddBreakpoint( &value );
} }
else else
{ {
...@@ -236,19 +240,29 @@ break_command: ...@@ -236,19 +240,29 @@ break_command:
} }
} }
| tBREAK tEOL { DBG_ADDR addr; | tBREAK tEOL { DBG_VALUE value;
DEBUG_GetCurrentAddress( &addr ); DEBUG_GetCurrentAddress( &value.addr );
DEBUG_AddBreakpoint( &addr ); value.type = NULL;
value.cookie = DV_TARGET;
DEBUG_AddBreakpoint( &value );
} }
watch_command:
tWATCH '*' expr_addr tEOL { DEBUG_AddWatchpoint( &$3, 1 );
DEBUG_FreeExprMem(); }
| tWATCH tIDENTIFIER tEOL { DBG_VALUE value;
if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
DEBUG_AddWatchpoint( &value, 1 );
else
fprintf(stderr,"Unable to add breakpoint\n");
}
info_command: info_command:
tINFO tBREAK tEOL { DEBUG_InfoBreakpoints(); } tINFO tBREAK tEOL { DEBUG_InfoBreakpoints(); }
| tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); } | tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); }
| tINFO tSHARE tEOL { DEBUG_InfoShare(); } | tINFO tSHARE tEOL { DEBUG_InfoShare(); }
| tINFO tMODULE expr_value tEOL { DEBUG_DumpModule( $3 ); | tINFO tMODULE expr_value tEOL { DEBUG_DumpModule( $3 ); DEBUG_FreeExprMem(); }
DEBUG_FreeExprMem(); } | tINFO tQUEUE expr_value tEOL { DEBUG_DumpQueue( $3 ); DEBUG_FreeExprMem(); }
| tINFO tQUEUE expr_value tEOL { DEBUG_DumpQueue( $3 );
DEBUG_FreeExprMem(); }
| tINFO tREGS tEOL { DEBUG_InfoRegisters(); } | tINFO tREGS tEOL { DEBUG_InfoRegisters(); }
| tINFO tSEGMENTS expr_value tEOL { DEBUG_InfoSegments( $3, 1 ); DEBUG_FreeExprMem(); } | tINFO tSEGMENTS expr_value tEOL { DEBUG_InfoSegments( $3, 1 ); DEBUG_FreeExprMem(); }
| tINFO tSEGMENTS tEOL { DEBUG_InfoSegments( 0, -1 ); } | tINFO tSEGMENTS tEOL { DEBUG_InfoSegments( 0, -1 ); }
...@@ -296,9 +310,10 @@ expr_addr: ...@@ -296,9 +310,10 @@ expr_addr:
expr { $$ = DEBUG_EvalExpr($1); } expr { $$ = DEBUG_EvalExpr($1); }
expr_value: expr_value:
expr { DBG_ADDR addr = DEBUG_EvalExpr($1); expr { DBG_VALUE value = DEBUG_EvalExpr($1);
/* expr_value is typed as an integer */ /* expr_value is typed as an integer */
if (!addr.off || !DEBUG_READ_MEM((void*)addr.off, &$$, sizeof($$))) if (!value.addr.off ||
!DEBUG_READ_MEM((void*)value.addr.off, &$$, sizeof($$)))
$$ = 0; } $$ = 0; }
/* /*
* The expr rule builds an expression tree. When we are done, we call * The expr rule builds an expression tree. When we are done, we call
...@@ -315,8 +330,7 @@ expr: ...@@ -315,8 +330,7 @@ expr:
| expr '.' tIDENTIFIER { $$ = DEBUG_StructExpr($1, $3); } | expr '.' tIDENTIFIER { $$ = DEBUG_StructExpr($1, $3); }
| tIDENTIFIER '(' ')' { $$ = DEBUG_CallExpr($1, 0); } | tIDENTIFIER '(' ')' { $$ = DEBUG_CallExpr($1, 0); }
| tIDENTIFIER '(' expr ')' { $$ = DEBUG_CallExpr($1, 1, $3); } | tIDENTIFIER '(' expr ')' { $$ = DEBUG_CallExpr($1, 1, $3); }
| tIDENTIFIER '(' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 2, $3, | tIDENTIFIER '(' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 2, $3, $5); }
$5); }
| tIDENTIFIER '(' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7); } | tIDENTIFIER '(' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7); }
| tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9); } | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9); }
| tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9, $11); } | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ',' expr ')' { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9, $11); }
...@@ -370,24 +384,39 @@ lvalue: ...@@ -370,24 +384,39 @@ lvalue:
%% %%
void static void issue_prompt(void)
issue_prompt(){ {
#ifdef DONT_USE_READLINE #ifdef DONT_USE_READLINE
fprintf(stderr,"Wine-dbg>"); fprintf(stderr, "Wine-dbg>");
#endif #endif
} }
void mode_command(int newmode) static void mode_command(int newmode)
{ {
if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode; if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode;
else fprintf(stderr,"Invalid mode (use 16 or 32)\n"); else fprintf(stderr,"Invalid mode (use 16 or 32)\n");
} }
static WINE_EXCEPTION_FILTER(no_symbol) static WINE_EXCEPTION_FILTER(wine_dbg)
{ {
if (GetExceptionCode() == DEBUG_STATUS_NO_SYMBOL) switch (GetExceptionCode()) {
return EXCEPTION_EXECUTE_HANDLER; case DEBUG_STATUS_INTERNAL_ERROR:
return EXCEPTION_CONTINUE_SEARCH; fprintf(stderr, "WineDbg internal error\n");
break;
case DEBUG_STATUS_NO_SYMBOL:
fprintf(stderr, "Undefined symbol\n");
break;
case DEBUG_STATUS_DIV_BY_ZERO:
fprintf(stderr, "Division by zero\n");
break;
case DEBUG_STATUS_BAD_TYPE:
fprintf(stderr, "No type or type mismatch\n");
break;
default:
fprintf(stderr, "Exception %lx\n", GetExceptionCode());
break;
}
return EXCEPTION_EXECUTE_HANDLER;
} }
/*********************************************************************** /***********************************************************************
...@@ -444,8 +473,6 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code ) ...@@ -444,8 +473,6 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code )
DBG_ADDR addr; DBG_ADDR addr;
DEBUG_GetCurrentAddress( &addr ); DEBUG_GetCurrentAddress( &addr );
/* EPP if (USER_Driver) USER_Driver->pBeginDebugging(); */
#ifdef __i386__ #ifdef __i386__
switch (newmode = DEBUG_GetSelectorType(addr.seg)) { switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
case 16: case 32: break; case 16: case 32: break;
...@@ -509,9 +536,8 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code ) ...@@ -509,9 +536,8 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code )
if ((ret_ok = DEBUG_ValidateRegisters())) if ((ret_ok = DEBUG_ValidateRegisters()))
ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 ); ret_ok = DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear( &addr ), &ch, 1 );
} }
__EXCEPT(no_symbol) __EXCEPT(wine_dbg)
{ {
fprintf(stderr, "Undefined symbol\n");
ret_ok = 0; ret_ok = 0;
} }
__ENDTRY; __ENDTRY;
...@@ -527,13 +553,12 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code ) ...@@ -527,13 +553,12 @@ BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code )
*/ */
if ((DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT) || (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)) if ((DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT) || (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS))
DEBUG_CurrThread->dbg_exec_count = 0; DEBUG_CurrThread->dbg_exec_count = 0;
/* EPP if (USER_Driver) USER_Driver->pEndDebugging(); */
return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE; return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? 0 : DBG_CONTINUE;
} }
int yyerror(char* s) int yyerror(char* s)
{ {
fprintf(stderr,"%s\n", s); fprintf(stderr,"%s\n", s);
return 0; return 0;
} }
...@@ -32,7 +32,7 @@ XFlush(Display * d ) ...@@ -32,7 +32,7 @@ XFlush(Display * d )
return(0); return(0);
} }
HTASK16 GetCurrentTask() HTASK16 GetCurrentTask(void)
{ {
exit(0); exit(0);
} }
...@@ -70,17 +70,17 @@ void WIN_DumpWindow( HWND hwnd ) ...@@ -70,17 +70,17 @@ void WIN_DumpWindow( HWND hwnd )
} }
void CLASS_WalkClasses() void CLASS_WalkClasses(void)
{ {
exit(0); exit(0);
} }
void MODULE_WalkModules() void MODULE_WalkModules(void)
{ {
exit(0); exit(0);
} }
void QUEUE_WalkQueues() void QUEUE_WalkQueues(void)
{ {
exit(0); exit(0);
} }
...@@ -173,7 +173,7 @@ struct CodeViewDebug ...@@ -173,7 +173,7 @@ struct CodeViewDebug
char cv_name[1]; char cv_name[1];
}; };
test_pdbstuff() test_pdbstuff(void)
{ {
struct deferred_debug_info deefer; struct deferred_debug_info deefer;
IMAGE_DEBUG_DIRECTORY dinfo; IMAGE_DEBUG_DIRECTORY dinfo;
......
...@@ -131,7 +131,7 @@ $gs { yylval.reg = REG_GS; return tREG; } ...@@ -131,7 +131,7 @@ $gs { yylval.reg = REG_GS; return tREG; }
<INITIAL>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; } <INITIAL>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; }
<INITIAL>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; } <INITIAL>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; }
<INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; } <INITIAL>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
<INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; } <INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; }
<INITIAL>pass|pas|pa { BEGIN(NOCMD); return tPASS; } <INITIAL>pass|pas|pa { BEGIN(NOCMD); return tPASS; }
...@@ -151,14 +151,15 @@ $gs { yylval.reg = REG_GS; return tREG; } ...@@ -151,14 +151,15 @@ $gs { yylval.reg = REG_GS; return tREG; }
<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; }
<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>modref|modre|modr { return tMODREF; } <INFO_CMD,WALK_CMD>modref|modre|modr { return tMODREF; }
<INFO_CMD>registers|regs|reg|re { return tREGS; } <INFO_CMD>registers|regs|reg|re { return tREGS; }
<INFO_CMD>segments|segment|segm|seg|se { return tSEGMENTS; } <INFO_CMD>segments|segment|segm|seg|se { return tSEGMENTS; }
<INFO_CMD>stack|stac|sta|st { return tSTACK; } <INFO_CMD>stack|stac|sta|st { return tSTACK; }
......
...@@ -8,11 +8,12 @@ ...@@ -8,11 +8,12 @@
#define __WINE_DEBUGGER_H #define __WINE_DEBUGGER_H
#include <sys/types.h> /* u_long ... */ #include <sys/types.h> /* u_long ... */
#include <assert.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#ifdef __i386__ #ifdef __i386__
#define STEP_FLAG 0x100 /* single step flag */ #define STEP_FLAG 0x00000100 /* single step flag */
#define V86_FLAG 0x00020000 #define V86_FLAG 0x00020000
#endif #endif
...@@ -46,11 +47,20 @@ extern struct datatype * DEBUG_TypeString; ...@@ -46,11 +47,20 @@ extern struct datatype * DEBUG_TypeString;
typedef struct typedef struct
{ {
struct datatype * type; DWORD seg; /* 0xffffffff means current default segment (cs or ds) */
DWORD seg; /* 0xffffffff means current default segment (cs or ds) */ DWORD off;
DWORD off;
} DBG_ADDR; } DBG_ADDR;
#define DV_TARGET 0xF00D
#define DV_HOST 0x50DA
typedef struct
{
struct datatype* type;
int cookie; /* DV_??? */
DBG_ADDR addr;
} DBG_VALUE;
struct list_id struct list_id
{ {
char * sourcefile; char * sourcefile;
...@@ -101,15 +111,27 @@ enum exec_mode ...@@ -101,15 +111,27 @@ enum exec_mode
* instr just after the call. * instr just after the call.
*/ */
}; };
#define DBG_BREAK 0
#define DBG_WATCH 1
typedef struct typedef struct
{ {
DBG_ADDR addr; DBG_ADDR addr;
BYTE addrlen;
BYTE opcode;
WORD skipcount;
WORD enabled : 1, WORD enabled : 1,
refcount; type : 1,
is32 : 1,
refcount : 13;
WORD skipcount;
union {
BYTE opcode;
struct {
BYTE rw : 1,
len : 2;
BYTE reg;
DWORD oldval;
} w;
} u;
struct expr * condition; struct expr * condition;
} BREAKPOINT; } BREAKPOINT;
...@@ -171,8 +193,8 @@ enum debug_regs ...@@ -171,8 +193,8 @@ enum debug_regs
/* debugger/break.c */ /* debugger/break.c */
extern void DEBUG_SetBreakpoints( BOOL set ); extern void DEBUG_SetBreakpoints( BOOL set );
extern int DEBUG_FindBreakpoint( const DBG_ADDR *addr ); extern void DEBUG_AddBreakpoint( const DBG_VALUE *addr );
extern void DEBUG_AddBreakpoint( const DBG_ADDR *addr ); extern void DEBUG_AddWatchpoint( const DBG_VALUE *addr, int is_write );
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);
...@@ -181,6 +203,7 @@ extern BOOL DEBUG_ShouldContinue( DWORD code, enum exec_mode mode, int * count ) ...@@ -181,6 +203,7 @@ 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);
/* 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 );
...@@ -200,15 +223,11 @@ struct expr * DEBUG_StructExpr(struct expr *, const char * element); ...@@ -200,15 +223,11 @@ struct expr * DEBUG_StructExpr(struct expr *, const char * element);
struct expr * DEBUG_ArrayExpr(struct expr *, struct expr * index); struct expr * DEBUG_ArrayExpr(struct expr *, struct expr * index);
struct expr * DEBUG_CallExpr(const char *, int nargs, ...); struct expr * DEBUG_CallExpr(const char *, int nargs, ...);
struct expr * DEBUG_TypeCastExpr(struct datatype *, struct expr *); struct expr * DEBUG_TypeCastExpr(struct datatype *, struct expr *);
extern int DEBUG_ExprValue(const DBG_ADDR *, unsigned int *); extern DBG_VALUE DEBUG_EvalExpr(struct expr *);
extern DBG_ADDR DEBUG_EvalExpr(struct expr *);
extern int DEBUG_DelDisplay(int displaynum); extern int DEBUG_DelDisplay(int displaynum);
extern struct expr * DEBUG_CloneExpr(struct expr * exp); 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(struct expr * exp); extern int DEBUG_DisplayExpr(const struct expr * exp);
/* more debugger/break.c */
extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
/* debugger/display.c */ /* debugger/display.c */
extern int DEBUG_DoDisplay(void); extern int DEBUG_DoDisplay(void);
...@@ -219,15 +238,12 @@ extern int DEBUG_InfoDisplay(void); ...@@ -219,15 +238,12 @@ extern int DEBUG_InfoDisplay(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_ADDR *addr, const DBG_VALUE *addr,
const char * sourcefile, const char *sourcefile,
int flags); int flags);
extern struct name_hash * DEBUG_AddInvSymbol( const char *name,
const DBG_ADDR *addr,
const char * sourcefile);
extern BOOL DEBUG_GetSymbolValue( const char * name, const int lineno, extern BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
DBG_ADDR *addr, int ); DBG_VALUE *addr, int );
extern BOOL DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr ); extern BOOL DEBUG_SetSymbolValue( const char * name, const DBG_VALUE *addr );
extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
struct name_hash ** rtn, struct name_hash ** rtn,
unsigned int ebp, unsigned int ebp,
...@@ -235,7 +251,7 @@ extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag, ...@@ -235,7 +251,7 @@ extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
extern void DEBUG_ReadSymbolTable( const char * filename ); extern void DEBUG_ReadSymbolTable( const char * filename );
extern int DEBUG_LoadEntryPoints( const char * prefix ); extern int DEBUG_LoadEntryPoints( const char * prefix );
extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num, extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num,
unsigned long offset ); unsigned long offset );
extern struct wine_locals * extern struct wine_locals *
DEBUG_AddLocal( struct name_hash * func, int regno, DEBUG_AddLocal( struct name_hash * func, int regno,
int offset, int offset,
...@@ -250,14 +266,14 @@ extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len); ...@@ -250,14 +266,14 @@ extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len);
extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr); extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr);
extern int DEBUG_cmp_sym(const void * p1, const void * p2); extern int DEBUG_cmp_sym(const void * p1, const void * p2);
extern BOOL DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno, extern BOOL DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno,
DBG_ADDR *addr, int bp_flag ); DBG_ADDR *addr, int bp_flag );
extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym, extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym,
struct datatype * type); struct datatype * type);
BOOL DEBUG_Normalize(struct name_hash * nh ); BOOL DEBUG_Normalize(struct name_hash * nh );
/* debugger/info.c */ /* debugger/info.c */
extern void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format ); extern void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format );
extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr, extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr,
int addrlen, int flag ); int addrlen, int flag );
extern void DEBUG_Help(void); extern void DEBUG_Help(void);
...@@ -282,7 +298,7 @@ extern void DEBUG_WalkWindows(HWND hWnd, int indent); ...@@ -282,7 +298,7 @@ extern void DEBUG_WalkWindows(HWND hWnd, int indent);
/* debugger/memory.c */ /* debugger/memory.c */
extern int DEBUG_ReadMemory( const DBG_ADDR *address ); extern int DEBUG_ReadMemory( const DBG_ADDR *address );
extern void DEBUG_WriteMemory( const DBG_ADDR *address, int value ); 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_ExamineMemory( const DBG_VALUE *addr, int count, char format);
extern void DEBUG_InvalLinAddr( void* addr ); extern void DEBUG_InvalLinAddr( void* addr );
#ifdef __i386__ #ifdef __i386__
extern void DEBUG_GetCurrentAddress( DBG_ADDR * ); extern void DEBUG_GetCurrentAddress( DBG_ADDR * );
...@@ -311,7 +327,8 @@ extern int DEBUG_GetCurrentFrame(struct name_hash ** name, ...@@ -311,7 +327,8 @@ extern int DEBUG_GetCurrentFrame(struct name_hash ** name,
/* debugger/stabs.c */ /* debugger/stabs.c */
extern int DEBUG_ReadExecutableDbgInfo(void); extern int DEBUG_ReadExecutableDbgInfo(void);
extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff, int stablen, unsigned int strtaboff, int strtablen); extern int DEBUG_ParseStabs(char * addr, unsigned int load_offset, unsigned int staboff,
int stablen, unsigned int strtaboff, int strtablen);
/* debugger/msc.c */ /* debugger/msc.c */
extern int DEBUG_RegisterDebugInfo( HMODULE, const char *); extern int DEBUG_RegisterDebugInfo( HMODULE, const char *);
...@@ -325,8 +342,7 @@ extern int DEBUG_nchar; ...@@ -325,8 +342,7 @@ extern int DEBUG_nchar;
extern void DEBUG_InitTypes(void); extern void DEBUG_InitTypes(void);
extern struct datatype * DEBUG_NewDataType(enum debug_type xtype, extern struct datatype * DEBUG_NewDataType(enum debug_type xtype,
const char * typename); const char * typename);
extern unsigned int extern unsigned int DEBUG_TypeDerefPointer(const DBG_VALUE *value, struct datatype ** newtype);
DEBUG_TypeDerefPointer(const DBG_ADDR * addr, struct datatype ** newtype);
extern int DEBUG_AddStructElement(struct datatype * dt, extern int DEBUG_AddStructElement(struct datatype * dt,
char * name, struct datatype * type, char * name, struct datatype * type,
int offset, int size); int offset, int size);
...@@ -334,20 +350,21 @@ extern int DEBUG_SetStructSize(struct datatype * dt, int size); ...@@ -334,20 +350,21 @@ extern int DEBUG_SetStructSize(struct datatype * dt, int size);
extern int DEBUG_SetPointerType(struct datatype * dt, struct datatype * dt2); extern int DEBUG_SetPointerType(struct datatype * dt, struct datatype * dt2);
extern int DEBUG_SetArrayParams(struct datatype * dt, int min, int max, extern int DEBUG_SetArrayParams(struct datatype * dt, int min, int max,
struct datatype * dt2); struct datatype * dt2);
extern void DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level ); extern void DEBUG_Print( const DBG_VALUE *addr, int count, char format, int level );
extern unsigned int DEBUG_FindStructElement(DBG_ADDR * addr, extern unsigned int DEBUG_FindStructElement(DBG_VALUE * addr,
const char * ele_name, int * tmpbuf); const char * ele_name, int * tmpbuf);
extern struct datatype * DEBUG_GetPointerType(struct datatype * dt); extern struct datatype * DEBUG_GetPointerType(struct datatype * dt);
extern int DEBUG_GetObjectSize(struct datatype * dt); extern int DEBUG_GetObjectSize(struct datatype * dt);
extern unsigned int DEBUG_ArrayIndex(const DBG_ADDR * addr, DBG_ADDR * result, int index); extern unsigned int DEBUG_ArrayIndex(const DBG_VALUE * addr, DBG_VALUE * result, int index);
extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype); extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
extern long long int DEBUG_GetExprValue(const DBG_ADDR * addr, char ** format); extern long long int DEBUG_GetExprValue(const DBG_VALUE * addr, char ** format);
extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset, extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset,
int nbits, struct datatype * dt2); int nbits, struct datatype * dt2);
extern int DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2); extern int DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2);
extern enum debug_type DEBUG_GetType(struct datatype * dt); extern enum debug_type DEBUG_GetType(struct datatype * dt);
extern struct datatype * DEBUG_TypeCast(enum debug_type, const char *); extern struct datatype * DEBUG_TypeCast(enum debug_type, const char *);
extern int DEBUG_PrintTypeCast(struct datatype *); extern int DEBUG_PrintTypeCast(const struct datatype *);
extern int DEBUG_PrintType( const DBG_VALUE* addr );
/* debugger/source.c */ /* debugger/source.c */
extern void DEBUG_ShowDir(void); extern void DEBUG_ShowDir(void);
...@@ -355,7 +372,7 @@ extern void DEBUG_AddPath(const char * path); ...@@ -355,7 +372,7 @@ extern void DEBUG_AddPath(const char * path);
extern void DEBUG_List(struct list_id * line1, struct list_id * line2, extern void DEBUG_List(struct list_id * line1, struct list_id * line2,
int delta); int delta);
extern void DEBUG_NukePath(void); extern void DEBUG_NukePath(void);
extern void DEBUG_Disassemble( const DBG_ADDR *, const DBG_ADDR*, int offset ); extern void DEBUG_Disassemble( const DBG_VALUE *, const DBG_VALUE*, int offset );
/* debugger/external.c */ /* debugger/external.c */
extern void DEBUG_ExternalDebugger(void); extern void DEBUG_ExternalDebugger(void);
...@@ -390,6 +407,10 @@ extern char* DEBUG_XStrDup(const char *str); ...@@ -390,6 +407,10 @@ extern char* DEBUG_XStrDup(const char *str);
extern HANDLE dbg_heap; extern HANDLE dbg_heap;
#endif #endif
#define DEBUG_STATUS_NO_SYMBOL 0x80003000 #define DEBUG_STATUS_OFFSET 0x80003000
#define DEBUG_STATUS_INTERNAL_ERROR (DEBUG_STATUS_OFFSET+0)
#define DEBUG_STATUS_NO_SYMBOL (DEBUG_STATUS_OFFSET+1)
#define DEBUG_STATUS_DIV_BY_ZERO (DEBUG_STATUS_OFFSET+2)
#define DEBUG_STATUS_BAD_TYPE (DEBUG_STATUS_OFFSET+3)
#endif /* __WINE_DEBUGGER_H */ #endif /* __WINE_DEBUGGER_H */
...@@ -49,7 +49,7 @@ DEBUG_AddDisplay(struct expr * exp, int count, char format) ...@@ -49,7 +49,7 @@ DEBUG_AddDisplay(struct expr * exp, int count, char format)
} }
int int
DEBUG_InfoDisplay() DEBUG_InfoDisplay(void)
{ {
int i; int i;
...@@ -70,10 +70,10 @@ DEBUG_InfoDisplay() ...@@ -70,10 +70,10 @@ DEBUG_InfoDisplay()
} }
int int
DEBUG_DoDisplay() DEBUG_DoDisplay(void)
{ {
DBG_ADDR addr; DBG_VALUE value;
int i; int i;
/* /*
* First find a slot where we can store this display. * First find a slot where we can store this display.
...@@ -82,8 +82,8 @@ DEBUG_DoDisplay() ...@@ -82,8 +82,8 @@ DEBUG_DoDisplay()
{ {
if( displaypoints[i].exp != NULL ) if( displaypoints[i].exp != NULL )
{ {
addr = DEBUG_EvalExpr(displaypoints[i].exp); value = DEBUG_EvalExpr(displaypoints[i].exp);
if( addr.type == NULL ) if( value.type == NULL )
{ {
fprintf(stderr, "Unable to evaluate expression "); fprintf(stderr, "Unable to evaluate expression ");
DEBUG_DisplayExpr(displaypoints[i].exp); DEBUG_DisplayExpr(displaypoints[i].exp);
...@@ -97,13 +97,13 @@ DEBUG_DoDisplay() ...@@ -97,13 +97,13 @@ DEBUG_DoDisplay()
fprintf(stderr, " = "); fprintf(stderr, " = ");
if( displaypoints[i].format == 'i' ) if( displaypoints[i].format == 'i' )
{ {
DEBUG_ExamineMemory( &addr, DEBUG_ExamineMemory( &value,
displaypoints[i].count, displaypoints[i].count,
displaypoints[i].format); displaypoints[i].format);
} }
else else
{ {
DEBUG_Print( &addr, DEBUG_Print( &value,
displaypoints[i].count, displaypoints[i].count,
displaypoints[i].format, 0); displaypoints[i].format, 0);
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
#include "winuser.h" #include "winuser.h"
...@@ -20,40 +21,41 @@ ...@@ -20,40 +21,41 @@
* *
* Implementation of the 'print' command. * Implementation of the 'print' command.
*/ */
void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format ) void DEBUG_PrintBasic( const DBG_VALUE* value, int count, char format )
{ {
char * default_format; char * default_format;
long long int value; long long int res;
if( addr->type == NULL ) assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
if( value->type == NULL )
{ {
fprintf(stderr, "Unable to evaluate expression\n"); fprintf(stderr, "Unable to evaluate expression\n");
return; return;
} }
default_format = NULL; default_format = NULL;
value = DEBUG_GetExprValue(addr, &default_format); res = DEBUG_GetExprValue(value, &default_format);
switch(format) switch(format)
{ {
case 'x': case 'x':
if (addr->seg) if (value->addr.seg)
{ {
DEBUG_nchar += fprintf( stderr, "0x%04lx", (long unsigned int) value ); DEBUG_nchar += fprintf( stderr, "0x%04lx", (long unsigned int) res );
} }
else else
{ {
DEBUG_nchar += fprintf( stderr, "0x%08lx", (long unsigned int) value ); DEBUG_nchar += fprintf( stderr, "0x%08lx", (long unsigned int) res );
} }
break; break;
case 'd': case 'd':
DEBUG_nchar += fprintf( stderr, "%ld\n", (long int) value ); DEBUG_nchar += fprintf( stderr, "%ld\n", (long int) res );
break; break;
case 'c': case 'c':
DEBUG_nchar += fprintf( stderr, "%d = '%c'", DEBUG_nchar += fprintf( stderr, "%d = '%c'",
(char)(value & 0xff), (char)(value & 0xff) ); (char)(res & 0xff), (char)(res & 0xff) );
break; break;
case 'i': case 'i':
...@@ -64,7 +66,51 @@ void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format ) ...@@ -64,7 +66,51 @@ void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format )
case 0: case 0:
if( default_format != NULL ) if( default_format != NULL )
{ {
DEBUG_nchar += fprintf( stderr, default_format, value ); if (strstr(default_format, "%S") == NULL)
{
DEBUG_nchar += fprintf( stderr, default_format, res );
}
else
{
char* ptr;
int state = 0;
/* FIXME: simplistic implementation for default_format being
* foo%Sbar => will print foo, then string then bar
*/
for (ptr = default_format; *ptr; ptr++)
{
fprintf(stderr, "[%c]", *ptr);
if (*ptr == '%') state++;
else if (state == 1)
{
if (*ptr == 'S')
{
char ch;
char* str = (char*)(long)res;
for (; DEBUG_READ_MEM(str, &ch, 1) && ch; str++) {
fputc(ch, stderr);
DEBUG_nchar++;
}
}
else
{
/* shouldn't happen */
fputc('%', stderr);
fputc(*ptr, stderr);
DEBUG_nchar += 2;
}
state = 0;
}
else
{
fputc(*ptr, stderr);
DEBUG_nchar++;
}
}
}
} }
break; break;
} }
...@@ -144,7 +190,7 @@ void DEBUG_Help(void) ...@@ -144,7 +190,7 @@ void DEBUG_Help(void)
" display <expr> undisplay <disnum>", " display <expr> undisplay <disnum>",
" delete display <disnum> debugmsg <class>[-+]<type>\n", " delete display <disnum> debugmsg <class>[-+]<type>\n",
" mode [16,32] walk [wnd,class,queue,module,", " mode [16,32] walk [wnd,class,queue,module,",
" process,modref <pid>]", " whatis process,modref <pid>]",
" info (see 'help info' for options)\n", " info (see 'help info' for options)\n",
"The 'x' command accepts repeat counts and formats (including 'i') in the", "The 'x' command accepts repeat counts and formats (including 'i') in the",
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright 1993 Eric Youngdale * Copyright 1993 Eric Youngdale
* Copyright 1995 Alexandre Julliard * Copyright 1995 Alexandre Julliard
* Copyright 2000 Eric Pouech
*/ */
#include "config.h" #include "config.h"
...@@ -103,7 +104,6 @@ BOOL DEBUG_IsSelectorSystem(WORD sel) ...@@ -103,7 +104,6 @@ BOOL DEBUG_IsSelectorSystem(WORD sel)
void DEBUG_GetCurrentAddress( DBG_ADDR *addr ) void DEBUG_GetCurrentAddress( DBG_ADDR *addr )
{ {
addr->type = NULL;
#ifdef __i386__ #ifdef __i386__
addr->seg = DEBUG_context.SegCs; addr->seg = DEBUG_context.SegCs;
...@@ -120,7 +120,6 @@ void DEBUG_InvalLinAddr( void* addr ) ...@@ -120,7 +120,6 @@ void DEBUG_InvalLinAddr( void* addr )
{ {
DBG_ADDR address; DBG_ADDR address;
address.type = NULL;
address.seg = 0; address.seg = 0;
address.off = (unsigned long)addr; address.off = (unsigned long)addr;
...@@ -169,14 +168,16 @@ void DEBUG_WriteMemory( const DBG_ADDR *address, int value ) ...@@ -169,14 +168,16 @@ void DEBUG_WriteMemory( const DBG_ADDR *address, int value )
* *
* Implementation of the 'x' command. * Implementation of the 'x' command.
*/ */
void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) void DEBUG_ExamineMemory( const DBG_VALUE *_value, int count, char format )
{ {
DBG_ADDR addr = * address; DBG_VALUE value = *_value;
int i; int i;
unsigned char * pnt; unsigned char * pnt;
struct datatype * testtype; struct datatype * testtype;
DEBUG_FixAddress( &addr, assert(_value->cookie == DV_TARGET || _value->cookie == DV_HOST);
DEBUG_FixAddress( &value.addr,
(format == 'i') ? (format == 'i') ?
DEBUG_context.SegCs : DEBUG_context.SegCs :
DEBUG_context.SegDs ); DEBUG_context.SegDs );
...@@ -186,31 +187,31 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) ...@@ -186,31 +187,31 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
* reading. We will use the same segment as what we have already, * reading. We will use the same segment as what we have already,
* and hope that this is a sensible thing to do. * and hope that this is a sensible thing to do.
*/ */
if( addr.type != NULL ) if( value.type != NULL )
{ {
if( addr.type == DEBUG_TypeIntConst ) if( value.type == DEBUG_TypeIntConst )
{ {
/* /*
* We know that we have the actual offset stored somewhere * We know that we have the actual offset stored somewhere
* else in 32-bit space. Grab it, and we * else in 32-bit space. Grab it, and we
* should be all set. * should be all set.
*/ */
unsigned int seg2 = addr.seg; unsigned int seg2 = value.addr.seg;
addr.seg = 0; value.addr.seg = 0;
addr.off = DEBUG_GetExprValue(&addr, NULL); value.addr.off = DEBUG_GetExprValue(&value, NULL);
addr.seg = seg2; value.addr.seg = seg2;
} }
else else
{ {
if (DEBUG_TypeDerefPointer(&addr, &testtype) == 0) if (DEBUG_TypeDerefPointer(&value, &testtype) == 0)
return; return;
if( testtype != NULL || addr.type == DEBUG_TypeIntConst ) if( testtype != NULL || value.type == DEBUG_TypeIntConst )
{ {
addr.off = DEBUG_GetExprValue(&addr, NULL); value.addr.off = DEBUG_GetExprValue(&value, NULL);
} }
} }
} }
else if (!addr.seg && !addr.off) else if (!value.addr.seg && !value.addr.off)
{ {
fprintf(stderr,"Invalid expression\n"); fprintf(stderr,"Invalid expression\n");
return; return;
...@@ -218,11 +219,11 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) ...@@ -218,11 +219,11 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
if (format != 'i' && count > 1) if (format != 'i' && count > 1)
{ {
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE ); DEBUG_PrintAddress( &value.addr, DEBUG_CurrThread->dbg_mode, FALSE );
fprintf(stderr,": "); fprintf(stderr,": ");
} }
pnt = (void*)DEBUG_ToLinear( &addr ); pnt = (void*)DEBUG_ToLinear( &value.addr );
switch(format) switch(format)
{ {
...@@ -256,9 +257,9 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) ...@@ -256,9 +257,9 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
case 'i': case 'i':
while (count--) while (count--)
{ {
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE ); DEBUG_PrintAddress( &value.addr, DEBUG_CurrThread->dbg_mode, TRUE );
fprintf(stderr,": "); fprintf(stderr,": ");
DEBUG_Disasm( &addr, TRUE ); DEBUG_Disasm( &value.addr, TRUE );
fprintf(stderr,"\n"); fprintf(stderr,"\n");
} }
return; return;
...@@ -267,10 +268,10 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format ) ...@@ -267,10 +268,10 @@ void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
for(i=0; i<count; i++) { \ for(i=0; i<count; i++) { \
if (!DEBUG_READ_MEM_VERBOSE(pnt, &_v, sizeof(_t))) break; \ if (!DEBUG_READ_MEM_VERBOSE(pnt, &_v, sizeof(_t))) break; \
fprintf(stderr,_f,(_vv)); \ fprintf(stderr,_f,(_vv)); \
pnt += sizeof(_t); addr.off += sizeof(_t); \ pnt += sizeof(_t); value.addr.off += sizeof(_t); \
if ((i % (_l)) == (_l)-1) { \ if ((i % (_l)) == (_l)-1) { \
fprintf(stderr,"\n"); \ fprintf(stderr,"\n"); \
DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, FALSE );\ DEBUG_PrintAddress( &value.addr, DEBUG_CurrThread->dbg_mode, FALSE );\
fprintf(stderr,": ");\ fprintf(stderr,": ");\
} \ } \
} \ } \
......
...@@ -49,7 +49,7 @@ static int DEBUG_start_sourceline = -1; ...@@ -49,7 +49,7 @@ static int DEBUG_start_sourceline = -1;
static int DEBUG_end_sourceline = -1; static int DEBUG_end_sourceline = -1;
void void
DEBUG_ShowDir() DEBUG_ShowDir(void)
{ {
struct searchlist * sl; struct searchlist * sl;
...@@ -78,7 +78,7 @@ DEBUG_AddPath(const char * path) ...@@ -78,7 +78,7 @@ DEBUG_AddPath(const char * path)
} }
void void
DEBUG_NukePath() DEBUG_NukePath(void)
{ {
struct searchlist * sl; struct searchlist * sl;
struct searchlist * nxt; struct searchlist * nxt;
...@@ -422,7 +422,7 @@ DEBUG_List(struct list_id * source1, struct list_id * source2, ...@@ -422,7 +422,7 @@ DEBUG_List(struct list_id * source1, struct list_id * source2,
DEBUG_end_sourceline = end; DEBUG_end_sourceline = end;
} }
DBG_ADDR DEBUG_LastDisassemble={NULL,0,0}; DBG_ADDR DEBUG_LastDisassemble={0,0};
static int static int
_disassemble(DBG_ADDR *addr) _disassemble(DBG_ADDR *addr)
...@@ -438,33 +438,36 @@ _disassemble(DBG_ADDR *addr) ...@@ -438,33 +438,36 @@ _disassemble(DBG_ADDR *addr)
} }
void void
_disassemble_fixaddr(DBG_ADDR *addr) { _disassemble_fixaddr(DBG_VALUE *value) {
DWORD seg2; DWORD seg2;
struct datatype *testtype; struct datatype *testtype;
DEBUG_FixAddress(addr, DEBUG_context.SegCs); assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
if( addr->type != NULL )
DEBUG_FixAddress(&value->addr, DEBUG_context.SegCs);
if( value->type != NULL )
{ {
if( addr->type == DEBUG_TypeIntConst ) if( value->type == DEBUG_TypeIntConst )
{ {
/* /*
* We know that we have the actual offset stored somewhere * We know that we have the actual offset stored somewhere
* else in 32-bit space. Grab it, and we * else in 32-bit space. Grab it, and we
* should be all set. * should be all set.
*/ */
seg2 = addr->seg; seg2 = value->addr.seg;
addr->seg = 0; value->addr.seg = 0;
addr->off = DEBUG_GetExprValue(addr, NULL); value->addr.off = DEBUG_GetExprValue(value, NULL);
addr->seg = seg2; value->addr.seg = seg2;
} }
else else
{ {
DEBUG_TypeDerefPointer(addr, &testtype); DEBUG_TypeDerefPointer(value, &testtype);
if( testtype != NULL || addr->type == DEBUG_TypeIntConst ) if( testtype != NULL || value->type == DEBUG_TypeIntConst )
addr->off = DEBUG_GetExprValue(addr, NULL); value->addr.off = DEBUG_GetExprValue(value, NULL);
} }
} }
else if (!addr->seg && !addr->off) else if (!value->addr.seg && !value->addr.off)
{ {
fprintf(stderr,"Invalid expression\n"); fprintf(stderr,"Invalid expression\n");
return; return;
...@@ -472,18 +475,18 @@ _disassemble_fixaddr(DBG_ADDR *addr) { ...@@ -472,18 +475,18 @@ _disassemble_fixaddr(DBG_ADDR *addr) {
} }
void void
DEBUG_Disassemble(const DBG_ADDR *xstart,const DBG_ADDR *xend,int offset) DEBUG_Disassemble(const DBG_VALUE *xstart,const DBG_VALUE *xend,int offset)
{ {
int i; int i;
DBG_ADDR last; DBG_ADDR last;
DBG_ADDR end,start; DBG_VALUE end,start;
if (xstart) { if (xstart) {
start=*xstart; start = *xstart;
_disassemble_fixaddr(&start); _disassemble_fixaddr(&start);
} }
if (xend) { if (xend) {
end=*xend; end = *xend;
_disassemble_fixaddr(&end); _disassemble_fixaddr(&end);
} }
if (!xstart && !xend) { if (!xstart && !xend) {
...@@ -493,26 +496,26 @@ DEBUG_Disassemble(const DBG_ADDR *xstart,const DBG_ADDR *xend,int offset) ...@@ -493,26 +496,26 @@ DEBUG_Disassemble(const DBG_ADDR *xstart,const DBG_ADDR *xend,int offset)
for (i=0;i<offset;i++) for (i=0;i<offset;i++)
if (!_disassemble(&last)) break; if (!_disassemble(&last)) break;
memcpy(&DEBUG_LastDisassemble,&last,sizeof(last)); DEBUG_LastDisassemble = last;
return; return;
} }
last = start; last = start.addr;
if (!xend) { if (!xend) {
for (i=0;i<offset;i++) for (i=0;i<offset;i++)
if (!_disassemble(&last)) break; if (!_disassemble(&last)) break;
memcpy(&DEBUG_LastDisassemble,&last,sizeof(last)); DEBUG_LastDisassemble = last;
return; return;
} }
while (last.off <= end.off) while (last.off <= end.addr.off)
if (!_disassemble(&last)) break; if (!_disassemble(&last)) break;
memcpy(&DEBUG_LastDisassemble,&last,sizeof(last)); DEBUG_LastDisassemble = last;
return; return;
} }
#if 0 #if 0
main() main(void)
{ {
int i, j; int i, j;
DEBUG_AddPath("../../de"); DEBUG_AddPath("../../de");
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "config.h" #include "config.h"
#include <assert.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -426,7 +425,7 @@ DEBUG_HandlePreviousTypedef(const char * name, const char * stab) ...@@ -426,7 +425,7 @@ DEBUG_HandlePreviousTypedef(const char * name, const char * stab)
return TRUE; return TRUE;
} }
static int DEBUG_FreeRegisteredTypedefs() static int DEBUG_FreeRegisteredTypedefs(void)
{ {
int count; int count;
int j; int j;
...@@ -775,10 +774,10 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -775,10 +774,10 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
struct name_hash * curr_sym = NULL; struct name_hash * curr_sym = NULL;
char currpath[PATH_MAX]; char currpath[PATH_MAX];
int i; int i;
int ignore = FALSE; int in_external_file = FALSE;
int last_nso = -1; int last_nso = -1;
int len; int len;
DBG_ADDR new_addr; DBG_VALUE new_value;
int nstab; int nstab;
char * ptr; char * ptr;
char * stabbuff; char * stabbuff;
...@@ -855,16 +854,17 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -855,16 +854,17 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
* *
* With a.out, they actually do make some amount of sense. * With a.out, they actually do make some amount of sense.
*/ */
new_addr.seg = 0; new_value.addr.seg = 0;
new_addr.type = DEBUG_ParseStabType(ptr); new_value.type = DEBUG_ParseStabType(ptr);
new_addr.off = load_offset + stab_ptr->n_value; new_value.addr.off = load_offset + stab_ptr->n_value;
new_value.cookie = DV_TARGET;
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
#ifdef __ELF__ #ifdef __ELF__
curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath, curr_sym = DEBUG_AddSymbol( symname, &new_value, currpath,
SYM_WINE | SYM_DATA | SYM_INVALID); SYM_WINE | SYM_DATA | SYM_INVALID);
#else #else
curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath, curr_sym = DEBUG_AddSymbol( symname, &new_value, currpath,
SYM_WINE | SYM_DATA ); SYM_WINE | SYM_DATA );
#endif #endif
break; break;
...@@ -883,20 +883,20 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -883,20 +883,20 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
/* /*
* These are static symbols and BSS symbols. * These are static symbols and BSS symbols.
*/ */
new_addr.seg = 0; new_value.addr.seg = 0;
new_addr.type = DEBUG_ParseStabType(ptr); new_value.type = DEBUG_ParseStabType(ptr);
new_addr.off = load_offset + stab_ptr->n_value; new_value.addr.off = load_offset + stab_ptr->n_value;
new_value.cookie = DV_TARGET;
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath, curr_sym = DEBUG_AddSymbol( symname, &new_value, currpath,
SYM_WINE | SYM_DATA ); SYM_WINE | SYM_DATA );
break; break;
case N_PSYM: case N_PSYM:
/* /*
* These are function parameters. * These are function parameters.
*/ */
if( (curr_func != NULL) if( curr_func != NULL && !in_external_file )
&& (stab_ptr->n_value != 0) )
{ {
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
curr_loc = DEBUG_AddLocal( curr_func, 0, curr_loc = DEBUG_AddLocal( curr_func, 0,
...@@ -905,34 +905,29 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -905,34 +905,29 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
} }
break; break;
case N_RSYM: case N_RSYM:
if( curr_func != NULL ) if( curr_func != NULL && !in_external_file )
{ {
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
curr_loc = DEBUG_AddLocal( curr_func, stab_ptr->n_value, curr_loc = DEBUG_AddLocal( curr_func, stab_ptr->n_value + 1,
0, 0, 0, symname ); 0, 0, 0, symname );
DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) ); DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) );
} }
break; break;
case N_LSYM: case N_LSYM:
if( (curr_func != NULL) if( curr_func != NULL && !in_external_file )
&& (stab_ptr->n_value != 0) )
{ {
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
curr_loc = DEBUG_AddLocal( curr_func, 0, curr_loc = DEBUG_AddLocal( curr_func, 0,
stab_ptr->n_value, 0, 0, symname ); stab_ptr->n_value, 0, 0, symname );
DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) ); DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr) );
} }
else if (curr_func == NULL)
{
stab_strcpy(symname, ptr);
}
break; break;
case N_SLINE: case N_SLINE:
/* /*
* This is a line number. These are always relative to the start * This is a line number. These are always relative to the start
* of the function (N_FUN), and this makes the lookup easier. * of the function (N_FUN), and this makes the lookup easier.
*/ */
if( curr_func != NULL ) if( curr_func != NULL && !in_external_file )
{ {
#ifdef __ELF__ #ifdef __ELF__
DEBUG_AddLineNumber(curr_func, stab_ptr->n_desc, DEBUG_AddLineNumber(curr_func, stab_ptr->n_desc,
...@@ -961,11 +956,12 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -961,11 +956,12 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
* on, we will add the line number information and the * on, we will add the line number information and the
* local symbols. * local symbols.
*/ */
if( !ignore ) if( !in_external_file )
{ {
new_addr.seg = 0; new_value.addr.seg = 0;
new_addr.type = DEBUG_ParseStabType(ptr); new_value.type = DEBUG_ParseStabType(ptr);
new_addr.off = load_offset + stab_ptr->n_value; new_value.addr.off = load_offset + stab_ptr->n_value;
new_value.cookie = DV_TARGET;
/* /*
* Copy the string to a temp buffer so we * Copy the string to a temp buffer so we
* can kill everything after the ':'. We do * can kill everything after the ':'. We do
...@@ -974,7 +970,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -974,7 +970,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
* sucks up swap space like crazy. * sucks up swap space like crazy.
*/ */
stab_strcpy(symname, ptr); stab_strcpy(symname, ptr);
curr_func = DEBUG_AddSymbol( symname, &new_addr, currpath, curr_func = DEBUG_AddSymbol( symname, &new_value, currpath,
SYM_WINE | SYM_FUNC); SYM_WINE | SYM_FUNC);
} }
else else
...@@ -1031,16 +1027,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset, ...@@ -1031,16 +1027,7 @@ DEBUG_ParseStabs(char * addr, unsigned int load_offset,
* If this is the main source, enable the debug stuff, otherwise * If this is the main source, enable the debug stuff, otherwise
* ignore it. * ignore it.
*/ */
if( subpath == NULL || strcmp(ptr, subpath) == 0 ) in_external_file = !(subpath == NULL || strcmp(ptr, subpath) == 0);
{
ignore = FALSE;
}
else
{
ignore = TRUE;
DEBUG_Normalize(curr_func);
curr_func = NULL;
}
break; break;
case N_UNDF: case N_UNDF:
strs += strtabinc; strs += strtabinc;
...@@ -1106,7 +1093,7 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset, ...@@ -1106,7 +1093,7 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
struct name_hash * curr_sym = NULL; struct name_hash * curr_sym = NULL;
int flags; int flags;
int i; int i;
DBG_ADDR new_addr; DBG_VALUE new_value;
int nsym; int nsym;
char * strp; char * strp;
char * symname; char * symname;
...@@ -1148,19 +1135,20 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset, ...@@ -1148,19 +1135,20 @@ DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
* we will have to keep the darned thing, because there can be * we will have to keep the darned thing, because there can be
* multiple local symbols by the same name. * multiple local symbols by the same name.
*/ */
if( (DEBUG_GetSymbolValue(symname, -1, &new_addr, FALSE ) == TRUE) if( (DEBUG_GetSymbolValue(symname, -1, &new_value, FALSE ) == TRUE)
&& (new_addr.off == (load_offset + symp->st_value)) ) && (new_value.addr.off == (load_offset + symp->st_value)) )
continue; continue;
new_addr.seg = 0; new_value.addr.seg = 0;
new_addr.type = NULL; new_value.type = NULL;
new_addr.off = load_offset + symp->st_value; new_value.addr.off = load_offset + symp->st_value;
new_value.cookie = DV_TARGET;
flags = SYM_WINE | (ELF32_ST_BIND(symp->st_info) == STT_FUNC flags = SYM_WINE | (ELF32_ST_BIND(symp->st_info) == STT_FUNC
? SYM_FUNC : SYM_DATA); ? SYM_FUNC : SYM_DATA);
if( ELF32_ST_BIND(symp->st_info) == STB_GLOBAL ) if( ELF32_ST_BIND(symp->st_info) == STB_GLOBAL )
curr_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, flags ); curr_sym = DEBUG_AddSymbol( symname, &new_value, NULL, flags );
else else
curr_sym = DEBUG_AddSymbol( symname, &new_addr, curfile, flags ); curr_sym = DEBUG_AddSymbol( symname, &new_value, curfile, flags );
/* /*
* Record the size of the symbol. This can come in handy in * Record the size of the symbol. This can come in handy in
......
...@@ -57,23 +57,24 @@ typedef struct ...@@ -57,23 +57,24 @@ typedef struct
void DEBUG_InfoStack(void) void DEBUG_InfoStack(void)
{ {
#ifdef __i386__ #ifdef __i386__
DBG_ADDR addr; DBG_VALUE value;
addr.type = NULL; value.type = NULL;
addr.seg = DEBUG_context.SegSs; value.cookie = DV_TARGET;
addr.off = DEBUG_context.Esp; value.addr.seg = DEBUG_context.SegSs;
value.addr.off = DEBUG_context.Esp;
fprintf(stderr,"Stack dump:\n"); fprintf(stderr,"Stack dump:\n");
switch (DEBUG_GetSelectorType(addr.seg)) { switch (DEBUG_GetSelectorType(value.addr.seg)) {
case 32: /* 32-bit mode */ case 32: /* 32-bit mode */
DEBUG_ExamineMemory( &addr, 24, 'x' ); DEBUG_ExamineMemory( &value, 24, 'x' );
break; break;
case 16: /* 16-bit mode */ case 16: /* 16-bit mode */
addr.off &= 0xffff; value.addr.off &= 0xffff;
DEBUG_ExamineMemory( &addr, 24, 'w' ); DEBUG_ExamineMemory( &value, 24, 'w' );
break; break;
default: default:
fprintf(stderr, "Bad segment (%ld)\n", addr.seg); fprintf(stderr, "Bad segment (%ld)\n", value.addr.seg);
} }
fprintf(stderr,"\n"); fprintf(stderr,"\n");
#endif #endif
...@@ -317,7 +318,7 @@ void DEBUG_BackTrace(BOOL noisy) ...@@ -317,7 +318,7 @@ void DEBUG_BackTrace(BOOL noisy)
if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch ); if (noisy) fprintf( stderr, "Bad stack frame %p\n", (STACK32FRAME*)next_switch );
return; return;
} }
code.type = NULL;
code.seg = 0; code.seg = 0;
code.off = frame32.retaddr; code.off = frame32.retaddr;
...@@ -352,7 +353,6 @@ void DEBUG_BackTrace(BOOL noisy) ...@@ -352,7 +353,6 @@ void DEBUG_BackTrace(BOOL noisy)
return; return;
} }
code.type = NULL;
code.seg = frame16.cs; code.seg = frame16.cs;
code.off = frame16.ip; code.off = frame16.ip;
......
...@@ -176,12 +176,14 @@ static void DEBUG_InitCurrThread(void) ...@@ -176,12 +176,14 @@ static void DEBUG_InitCurrThread(void)
if (!Options.debug) return; if (!Options.debug) return;
if (DEBUG_CurrThread->start) { if (DEBUG_CurrThread->start) {
DBG_ADDR addr; DBG_VALUE value;
DEBUG_SetBreakpoints(FALSE); DEBUG_SetBreakpoints(FALSE);
addr.seg = 0; value.type = NULL;
addr.off = (DWORD)DEBUG_CurrThread->start; value.cookie = DV_TARGET;
DEBUG_AddBreakpoint(&addr); value.addr.seg = 0;
value.addr.off = (DWORD)DEBUG_CurrThread->start;
DEBUG_AddBreakpoint(&value);
DEBUG_SetBreakpoints(TRUE); DEBUG_SetBreakpoints(TRUE);
} else { } else {
DEBUG_CurrThread->wait_for_first_exception = 1; DEBUG_CurrThread->wait_for_first_exception = 1;
...@@ -386,6 +388,11 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid) ...@@ -386,6 +388,11 @@ static DWORD CALLBACK DEBUG_MainLoop(DWORD pid)
DEBUG_InitCurrProcess(); DEBUG_InitCurrProcess();
DEBUG_InitCurrThread(); DEBUG_InitCurrThread();
#ifdef _WE_SUPPORT_THE_STAB_TYPES_USED_BY_MINGW_TOO
/* so far, process name is not set */
DEBUG_RegisterDebugInfo((DWORD)de.u.CreateProcessInfo.lpBaseOfImage,
"wine-exec");
#endif
break; break;
case EXIT_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT:
......
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