Release 960225
[wine.git] / debugger / dbg.y
blobd42eac74288e41d44003c7868d4087f29e22c3dd
1 %{
2 /*
3 * Parser for command lines in the Wine debugger
5 * Copyright 1993 Eric Youngdale
6 * Copyright 1995 Morten Welinder
7 */
9 #include <stdio.h>
10 #include <signal.h>
11 #include <unistd.h>
12 #include "windows.h"
13 #include "debugger.h"
15 extern FILE * yyin;
16 unsigned int dbg_mode = 0;
18 static enum exec_mode dbg_exec_mode = EXEC_CONT;
20 void issue_prompt(void);
21 void mode_command(int);
22 void flush_symbols(void);
23 int yylex(void);
24 int yyerror(char *);
28 %union
30 DBG_ADDR address;
31 enum debug_regs reg;
32 char * string;
33 int integer;
36 %token CONT STEP LIST NEXT QUIT HELP BACKTRACE INFO STACK SEGMENTS REGS
37 %token ENABLE DISABLE BREAK DELETE SET MODE PRINT EXAM DEFINE ABORT
38 %token NO_SYMBOL EOL
39 %token SYMBOLFILE
41 %token <string> IDENTIFIER
42 %token <integer> NUM FORMAT
43 %token <reg> REG
45 /* %left ',' */
46 /* %left '=' OP_OR_EQUAL OP_XOR_EQUAL OP_AND_EQUAL OP_SHL_EQUAL \
47 OP_SHR_EQUAL OP_PLUS_EQUAL OP_MINUS_EQUAL \
48 OP_TIMES_EQUAL OP_DIVIDE_EQUAL OP_MODULO_EQUAL */
49 /* %left OP_COND */ /* ... ? ... : ... */
50 %left OP_LOR
51 %left OP_LAND
52 %left '|'
53 %left '^'
54 %left '&'
55 %left OP_EQ OP_NE
56 %left '<' '>' OP_LE OP_GE
57 %left OP_SHL OP_SHR
58 %left '+' '-'
59 %left '*' '/' '%'
60 %left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
61 %nonassoc ':'
63 %type <integer> expr
64 %type <address> addr segaddr symbol
68 input: line { issue_prompt(); }
69 | input line { issue_prompt(); }
71 line: command
72 | EOL
73 | error EOL { yyerrok; }
75 command: QUIT EOL { exit(0); }
76 | HELP EOL { DEBUG_Help(); }
77 | CONT EOL { dbg_exec_mode = EXEC_CONT; return 0; }
78 | STEP EOL { dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
79 | NEXT EOL { dbg_exec_mode = EXEC_STEP_OVER; return 0; }
80 | LIST EOL { DEBUG_List( NULL, 15 ); }
81 | LIST addr EOL { DEBUG_List( &$2, 15 ); }
82 | ABORT EOL { kill(getpid(), SIGABRT); }
83 | SYMBOLFILE IDENTIFIER EOL { DEBUG_ReadSymbolTable( $2 ); }
84 | DEFINE IDENTIFIER addr EOL { DEBUG_AddSymbol( $2, &$3 ); }
85 | MODE NUM EOL { mode_command($2); }
86 | ENABLE NUM EOL { DEBUG_EnableBreakpoint( $2, TRUE ); }
87 | DISABLE NUM EOL { DEBUG_EnableBreakpoint( $2, FALSE ); }
88 | BREAK '*' addr EOL { DEBUG_AddBreakpoint( &$3 ); }
89 | BREAK symbol EOL { DEBUG_AddBreakpoint( &$2 ); }
90 | BREAK EOL { DBG_ADDR addr = { CS_reg(DEBUG_context),
91 EIP_reg(DEBUG_context) };
92 DEBUG_AddBreakpoint( &addr );
94 | DELETE BREAK NUM EOL { DEBUG_DelBreakpoint( $3 ); }
95 | BACKTRACE EOL { DEBUG_BackTrace(); }
96 | infocmd
97 | x_command
98 | print_command
99 | deposit_command
101 deposit_command:
102 SET REG '=' expr EOL { DEBUG_SetRegister( $2, $4 ); }
103 | SET '*' addr '=' expr EOL { DEBUG_WriteMemory( &$3, $5 ); }
104 | SET IDENTIFIER '=' addr EOL { if (!DEBUG_SetSymbolValue( $2, &$4 ))
106 fprintf( stderr,
107 "Symbol %s not found\n", $2 );
108 YYERROR;
113 x_command:
114 EXAM addr EOL { DEBUG_ExamineMemory( &$2, 1, 'x'); }
115 | EXAM FORMAT addr EOL { DEBUG_ExamineMemory( &$3, $2>>8, $2&0xff ); }
117 print_command:
118 PRINT addr EOL { DEBUG_Print( &$2, 1, 'x' ); }
119 | PRINT FORMAT addr EOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff ); }
121 symbol: IDENTIFIER { if (!DEBUG_GetSymbolValue( $1, &$$ ))
123 fprintf( stderr, "Symbol %s not found\n", $1 );
124 YYERROR;
128 addr: expr { $$.seg = 0xffffffff; $$.off = $1; }
129 | segaddr { $$ = $1; }
131 segaddr: expr ':' expr { $$.seg = $1; $$.off = $3; }
132 | symbol { $$ = $1; }
134 expr: NUM { $$ = $1; }
135 | REG { $$ = DEBUG_GetRegister($1); }
136 | expr OP_LOR expr { $$ = $1 || $3; }
137 | expr OP_LAND expr { $$ = $1 && $3; }
138 | expr '|' expr { $$ = $1 | $3; }
139 | expr '&' expr { $$ = $1 & $3; }
140 | expr '^' expr { $$ = $1 ^ $3; }
141 | expr OP_EQ expr { $$ = $1 == $3; }
142 | expr '>' expr { $$ = $1 > $3; }
143 | expr '<' expr { $$ = $1 < $3; }
144 | expr OP_GE expr { $$ = $1 >= $3; }
145 | expr OP_LE expr { $$ = $1 <= $3; }
146 | expr OP_NE expr { $$ = $1 != $3; }
147 | expr OP_SHL expr { $$ = (unsigned)$1 << $3; }
148 | expr OP_SHR expr { $$ = (unsigned)$1 >> $3; }
149 | expr '+' expr { $$ = $1 + $3; }
150 | expr '-' expr { $$ = $1 - $3; }
151 | expr '*' expr { $$ = $1 * $3; }
152 | expr '/' expr
153 { if ($3)
154 if ($3 == -1 && $1 == 0x80000000l)
155 yyerror ("Division overflow");
156 else
157 $$ = $1 / $3;
158 else
159 yyerror ("Division by zero"); }
160 | expr '%' expr
161 { if ($3)
162 if ($3 == -1 && $1 == 0x80000000l)
163 $$ = 0; /* A sensible result in this case. */
164 else
165 $$ = $1 % $3;
166 else
167 yyerror ("Division by zero"); }
168 | '-' expr %prec OP_SIGN { $$ = -$2; }
169 | '+' expr %prec OP_SIGN { $$ = $2; }
170 | '!' expr { $$ = !$2; }
171 | '~' expr { $$ = ~$2; }
172 | '(' expr ')' { $$ = $2; }
173 /* For parser technical reasons we can't use "addr" here. */
174 | '*' expr %prec OP_DEREF { DBG_ADDR addr = { 0xffffffff, $2 };
175 $$ = DEBUG_ReadMemory( &addr ); }
176 | '*' segaddr %prec OP_DEREF { $$ = DEBUG_ReadMemory( &$2 ); }
178 infocmd: INFO REGS EOL { DEBUG_InfoRegisters(); }
179 | INFO STACK EOL { DEBUG_InfoStack(); }
180 | INFO BREAK EOL { DEBUG_InfoBreakpoints(); }
181 | INFO SEGMENTS EOL { LDT_Print( 0, -1 ); }
182 | INFO SEGMENTS expr EOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 ); }
187 void
188 issue_prompt(){
189 #ifndef USE_READLINE
190 fprintf(stderr,"Wine-dbg>");
191 #endif
194 void mode_command(int newmode)
196 if ((newmode == 16) || (newmode == 32)) dbg_mode = newmode;
197 else fprintf(stderr,"Invalid mode (use 16 or 32)\n");
201 void wine_debug( int signal, struct sigcontext_struct *regs )
203 static int loaded_symbols = 0;
204 char SymbolTableFile[256];
205 int instr_len = 0, newmode;
206 #ifdef YYDEBUG
207 yydebug = 0;
208 #endif
210 yyin = stdin;
211 DEBUG_context = (struct sigcontext_struct *)regs;
213 DEBUG_SetBreakpoints( FALSE );
215 if (!loaded_symbols)
217 loaded_symbols++;
218 PROFILE_GetWineIniString( "wine", "SymbolTableFile", "wine.sym",
219 SymbolTableFile, sizeof(SymbolTableFile) );
220 DEBUG_ReadSymbolTable( SymbolTableFile );
221 DEBUG_LoadEntryPoints();
224 if ((signal != SIGTRAP) || !DEBUG_ShouldContinue( regs, dbg_exec_mode ))
226 DBG_ADDR addr;
228 addr.seg = CS_reg(DEBUG_context);
229 addr.off = EIP_reg(DEBUG_context);
230 DBG_FIX_ADDR_SEG( &addr, 0 );
232 if (!addr.seg) newmode = 32;
233 else newmode = (GET_SEL_FLAGS(addr.seg) & LDT_FLAGS_32BIT) ? 32 : 16;
235 if (newmode != dbg_mode)
236 fprintf(stderr,"In %d bit mode.\n", dbg_mode = newmode);
238 if (signal != SIGTRAP) /* This is a real crash, dump some info */
240 DEBUG_InfoRegisters();
241 DEBUG_InfoStack();
242 if (dbg_mode == 16)
244 LDT_Print( SELECTOR_TO_ENTRY(DS_reg(DEBUG_context)), 1 );
245 if (ES_reg(DEBUG_context) != DS_reg(DEBUG_context))
246 LDT_Print( SELECTOR_TO_ENTRY(ES_reg(DEBUG_context)), 1 );
248 DEBUG_BackTrace();
251 /* Show where we crashed */
252 DEBUG_PrintAddress( &addr, dbg_mode );
253 fprintf(stderr,": ");
254 if (DBG_CHECK_READ_PTR( &addr, 1 ))
256 DEBUG_Disasm( &addr );
257 fprintf(stderr,"\n");
258 instr_len = addr.off - EIP_reg(DEBUG_context);
263 issue_prompt();
264 yyparse();
265 flush_symbols();
266 addr.seg = CS_reg(DEBUG_context);
267 addr.off = EIP_reg(DEBUG_context);
268 DBG_FIX_ADDR_SEG( &addr, 0 );
269 } while (!DBG_CHECK_READ_PTR( &addr, 1 ));
272 DEBUG_RestartExecution( regs, dbg_exec_mode, instr_len );
276 int yyerror(char * s)
278 fprintf(stderr,"%s\n", s);
279 return 0;