| |
| %{ |
| |
| /* Parser for command lines in the Wine debugger |
| * |
| * Version 1.0 |
| * Eric Youngdale |
| * 9/93 |
| */ |
| |
| #include <stdio.h> |
| #include <signal.h> |
| #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; |
| } |
| |