%{ /* Parser for command lines in the Wine debugger * * Version 1.0 * Eric Youngdale * 9/93 */ #include #include #include "ldt.h" #include "windows.h" #include "wine.h" #define YYSTYPE int #include "regpos.h" extern FILE * yyin; unsigned int * regval = NULL; unsigned int dbg_mask = 0; unsigned int dbg_mode = 0; void issue_prompt(void); void mode_command(int); %} %token CONT %token QUIT %token HELP %token BACKTRACE %token INFO %token STACK %token SEGMENTS %token REG %token REGS %token NUM %token ENABLE %token DISABLE %token BREAK %token SET %token MODE %token PRINT %token FILE_IDENTIFIER %token IDENTIFIER %token NO_SYMBOL %token SYMBOLFILE %token DEFINE %token ABORT %% input: /* empty */ | input line { issue_prompt(); } line: '\n' | infocmd '\n' | error '\n' { yyerrok; } | QUIT '\n' { exit(0); } | 'q' '\n' { exit(0); } | HELP '\n' { dbg_help(); } | CONT '\n' { return 0; } | 'c' '\n' { return 0; } | ABORT '\n' { kill(getpid(), SIGABRT); } | SYMBOLFILE FILE_IDENTIFIER '\n' { read_symboltable($2); } | DEFINE IDENTIFIER expr '\n' { add_hash($2, 0, $3); } | MODE NUM { mode_command($2); } | ENABLE NUM { enable_break($2); } | DISABLE NUM { disable_break($2); } | BREAK '*' expr { add_break($3); } | x_command | BACKTRACE '\n' { dbg_bt(); } | print_command | deposit_command deposit_command: SET REG '=' expr '\n' { if(regval) regval[$2] = $4; else application_not_running();} | SET '*' expr '=' expr '\n' { *((unsigned int *) $3) = $5; } | SET symbol '=' expr '\n' { *((unsigned int *) $2) = $4; } x_command: 'x' expr '\n' { examine_memory($2, 1, 'x'); } | 'x' '/' fmt expr '\n' { examine_memory($4, 1, $3); } | 'x' '/' NUM fmt expr '\n' { examine_memory($5, $3, $4); } print: 'p' | PRINT print_command: print expr '\n' { examine_memory(((unsigned int) &$2 ), 1, 'x'); } | print '/' fmt expr '\n' { examine_memory((unsigned int) &$4, 1, $3); } | print '/' NUM fmt expr '\n' { examine_memory((unsigned int) &$5, $3, $4); } fmt: 'x' { $$ = 'x'; } | 'd' { $$ = 'd'; } | 'i' { $$ = 'i'; } | 'w' { $$ = 'w'; } | 's' { $$ = 's'; } | 'c' { $$ = 'c'; } | 'b' { $$ = 'b'; } symbol: IDENTIFIER { $$ = find_hash($1); if($$ == 0xffffffff) { fprintf(stderr,"Symbol %s not found\n", $1); YYERROR; } } expr: NUM { $$ = $1; } | REG { if(regval) $$ = regval[$1]; else application_not_running();} | symbol { $$ = $1; } | expr '+' NUM { $$ = $1 + $3; } | expr '-' NUM { $$ = $1 - $3; } | '(' expr ')' { $$ = $2; } | '*' expr { $$ = *((unsigned int *) $2); } infocmd: INFO REGS { info_reg(); } | INFO STACK { info_stack(); } | INFO SEGMENTS { LDT_Print(); } | INFO BREAK { info_break(); } %% void issue_prompt(){ #ifndef USE_READLINE fprintf(stderr,"Wine-dbg>"); #endif } void mode_command(int newmode) { if(newmode == 16){ dbg_mask = 0xffff; dbg_mode = 16; return; } if(newmode == 32){ dbg_mask = 0xffffffff; dbg_mode = 32; return; } fprintf(stderr,"Invalid mode (use 16 or 32)\n"); } static int loaded_symbols = 0; void wine_debug(int signal, int * regs) { static int dummy_regs[32]; char SymbolTableFile[256]; #ifdef YYDEBUG yydebug = 0; #endif yyin = stdin; regval = regs ? regs : dummy_regs; if (SC_CS == WINE_CODE_SELECTOR) { dbg_mask = 0xffffffff; dbg_mode = 32; } else { dbg_mask = 0xffff; dbg_mode = 16; } fprintf(stderr,"In %d bit mode.\n", dbg_mode); if(dbg_mode == 32 && !loaded_symbols) { loaded_symbols++; GetPrivateProfileString("wine", "SymbolTableFile", "wine.sym", SymbolTableFile, sizeof(SymbolTableFile), WINE_INI); read_symboltable(SymbolTableFile); } /* Remove the breakpoints from memory... */ insert_break(0); /* If we stopped on a breakpoint, report this fact */ if(signal == SIGTRAP) { unsigned int addr; int bpnum; addr = SC_EIP(dbg_mask); if((addr & 0xffff0000) == 0 && dbg_mode == 16) addr = PTR_SEG_OFF_TO_LIN( SC_CS, addr ); if(should_continue(bpnum=get_bpnum(addr))){ insert_break(1); return; } fprintf(stderr,"Stopped on breakpoint %d\n", bpnum); } /* Show where we crashed */ if(regs) examine_memory(SC_EIP(dbg_mask), 1, 'i'); issue_prompt(); yyparse(); flush_symbols(); /* Re-insert the breakpoints from memory... */ insert_break(1); fprintf(stderr,"Returning to Wine...\n"); } int yyerror(char * s) { fprintf(stderr,"%s\n", s); return 0; }