Release 950403
[wine] / debugger / info.c
1 /*
2  * Wine debugger utility routines
3  * Eric Youngdale
4  * 9/93
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "ldt.h"
10 #include "db_disasm.h"
11 #include "regpos.h"
12
13 extern int * regval;
14 extern unsigned int dbg_mask;
15 extern unsigned int dbg_mode;
16
17 void application_not_running()
18 {
19   fprintf(stderr,"Application not running\n");
20 }
21
22 void print_address(unsigned int addr, FILE * outfile, int addrlen)
23 {
24     if (addrlen == 16)
25     {
26         fprintf( outfile, "%4.4x:%4.4x", addr >> 16, addr & 0xffff );
27     }
28     else
29     {
30         extern char * find_nearest_symbol(unsigned int *);
31
32         char * name = find_nearest_symbol((unsigned int *) addr);
33         if(name)
34                 fprintf(outfile,"0x%8.8x(%s)", addr, name);
35         else
36                 fprintf(outfile,"0x%8.8x", addr);
37     }
38 }
39
40
41 void info_reg(){
42
43           if(!regval) {
44             application_not_running();
45             return;
46           }
47
48         fprintf(stderr,"Register dump:\n");
49         /* First get the segment registers out of the way */
50         fprintf(stderr," CS:%4.4x SS:%4.4x DS:%4.4x ES:%4.4x GS:%4.4x FS:%4.4x\n", 
51                 SC_CS, SC_SS, SC_DS, SC_ES, SC_GS, SC_FS);
52
53         /* Now dump the main registers */
54         fprintf(stderr," EIP:%8.8x ESP:%8.8x EBP:%8.8x EFLAGS:%8.8x\n", 
55                 SC_EIP(dbg_mask), SC_ESP(dbg_mask), SC_EBP(dbg_mask), SC_EFLAGS);
56
57         /* And dump the regular registers */
58
59         fprintf(stderr," EAX:%8.8x EBX:%8.8x ECX:%8.8x EDX:%8.8x\n", 
60                 SC_EAX(dbg_mask), SC_EBX(dbg_mask), SC_ECX(dbg_mask), SC_EDX(dbg_mask));
61
62         /* Finally dump these main registers */
63         fprintf(stderr," EDI:%8.8x ESI:%8.8x\n", 
64                 SC_EDI(dbg_mask), SC_ESI(dbg_mask));
65
66 }
67
68 void info_stack(){
69         unsigned int * dump;
70         int i;
71
72         if(!regval) {
73           application_not_running();
74           return;
75         }
76
77         fprintf(stderr,"Stack dump:\n");
78         dump = (int*) SC_EIP(dbg_mask);
79         for(i=0; i<22; i++) 
80         {
81             fprintf(stderr," %8.8x", *dump++);
82             if ((i % 8) == 7)
83                 fprintf(stderr,"\n");
84         }
85         fprintf(stderr,"\n");
86 }
87
88
89 void examine_memory(int addr, int count, char format){
90         char * pnt;
91         unsigned int * dump;
92         unsigned short int * wdump;
93         int i;
94
95         if((addr & 0xffff0000) == 0 && dbg_mode == 16)
96             addr |= (format == 'i' ? SC_CS : SC_DS) << 16;
97
98         if(format != 'i' && count > 1) {
99                 print_address(addr, stderr, dbg_mode);
100                 fprintf(stderr,":  ");
101         };
102
103         switch(format){
104         case 's':
105                 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
106                                      : (char *)addr;
107                 if (count == 1) count = 256;
108                 while(*pnt && count) {
109                         fputc( *pnt++, stderr);
110                         count--;
111                 };
112                 fprintf(stderr,"\n");
113                 return;
114
115         case 'i':
116                 for(i=0; i<count; i++) {
117                         print_address(addr, stderr, dbg_mode);
118                         fprintf(stderr,":  ");
119                         addr = db_disasm( addr, 0, (dbg_mode == 16) );
120                         fprintf(stderr,"\n");
121                 };
122                 return;
123         case 'x':
124                 dump = dbg_mode == 16 ? (unsigned int *)PTR_SEG_TO_LIN(addr)
125                                       : (unsigned int *)addr;
126                 for(i=0; i<count; i++) 
127                 {
128                         fprintf(stderr," %8.8x", *dump++);
129                         addr += 4;
130                         if ((i % 8) == 7) {
131                                 fprintf(stderr,"\n");
132                                 print_address(addr, stderr, dbg_mode);
133                                 fprintf(stderr,":  ");
134                         };
135                 }
136                 fprintf(stderr,"\n");
137                 return;
138         
139         case 'd':
140                 dump = dbg_mode == 16 ? (unsigned int *)PTR_SEG_TO_LIN(addr)
141                                       : (unsigned int *)addr;
142                 for(i=0; i<count; i++) 
143                 {
144                         fprintf(stderr," %d", *dump++);
145                         addr += 4;
146                         if ((i % 8) == 7) {
147                                 fprintf(stderr,"\n");
148                                 print_address(addr, stderr, dbg_mode);
149                                 fprintf(stderr,":  ");
150                         };
151                 }
152                 fprintf(stderr,"\n");
153                 return;
154         
155         case 'w':
156                 wdump = dbg_mode == 16 ? (unsigned short *)PTR_SEG_TO_LIN(addr)
157                                        : (unsigned short *)addr;
158                 for(i=0; i<count; i++) 
159                 {
160                         fprintf(stderr," %x", *wdump++);
161                         addr += 2;
162                         if ((i % 10) == 7) {
163                                 fprintf(stderr,"\n");
164                                 print_address(addr, stderr, dbg_mode);
165                                 fprintf(stderr,":  ");
166                         };
167                 }
168                 fprintf(stderr,"\n");
169                 return;
170         
171         case 'c':
172                 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
173                                      : (char *)addr;
174                 for(i=0; i<count; i++) 
175                 {
176                         if(*pnt < 0x20) {
177                                 fprintf(stderr,"  ");
178                                 pnt++;
179                         } else
180                                 fprintf(stderr," %c", *pnt++);
181                         addr++;
182                         if ((i % 32) == 7) {
183                                 fprintf(stderr,"\n");
184                                 print_address(addr, stderr, dbg_mode);
185                                 fprintf(stderr,":  ");
186                         };
187                 }
188                 fprintf(stderr,"\n");
189                 return;
190         
191         case 'b':
192                 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
193                                      : (char *)addr;
194                 for(i=0; i<count; i++) 
195                 {
196                         fprintf(stderr," %02x", (*pnt++) & 0xff);
197                         addr++;
198                         if ((i % 32) == 7) {
199                                 fprintf(stderr,"\n");
200                                 print_address(addr, stderr, dbg_mode);
201                                 fprintf(stderr,":  ");
202                         };
203                 }
204                 fprintf(stderr,"\n");
205                 return;
206         };
207         
208         /* The rest are fairly straightforward */
209
210         fprintf(stderr,"examine mem: %x %d %c\n", addr, count, format);
211 }
212
213 char * helptext[] = {
214 "The commands accepted by the Wine debugger are a small subset",
215 "of the commands that gdb would accept.  The commands currently",
216 "are:\n",
217 "  break *<addr>                        bt",
218 "  disable bpnum                        enable bpnum",
219 "  help                                 quit",
220 "  x <expr>                             cont",
221 "  mode [16,32]                         print <expr>",
222 "  set <reg> = <expr>                   set *<expr> = <expr>",
223 "  info [reg,stack,break,segments]      symbolfile <filename>",
224 "  define <identifier> <expr>",
225 "",
226 "The 'x' command accepts repeat counts and formats (including 'i') in the",
227 "same way that gdb does.",
228 "",
229 " The following are examples of legal expressions:",
230 " $eax     $eax+0x3   0x1000   ($eip + 256)  *$eax   *($esp + 3)",
231 " Also, a nm format symbol table can be read from a file using the",
232 " symbolfile command.  Symbols can also be defined individually with",
233 " the define command.",
234 "",
235 NULL};
236
237 void dbg_help(){
238         int i;
239         i = 0;
240         while(helptext[i]) fprintf(stderr,"%s\n", helptext[i++]);
241 }
242
243
244 struct frame{
245   union{
246     struct {
247       unsigned short saved_bp;
248       unsigned short saved_ip;
249       unsigned short saved_cs;
250     } win16;
251     struct {
252       unsigned long saved_bp;
253       unsigned long saved_ip;
254       unsigned short saved_cs;
255     } win32;
256   } u;
257 };
258
259
260 void dbg_bt(){
261   struct frame * frame;
262   unsigned short cs;
263   int frameno = 0;
264
265   if(!regval) {
266     application_not_running();
267     return;
268   }
269
270   if (dbg_mode == 16)
271       frame = (struct frame *)PTR_SEG_OFF_TO_LIN( SC_SS, SC_BP & ~1 );
272   else
273       frame = (struct frame *)SC_EBP(dbg_mask);
274
275   fprintf(stderr,"Backtrace:\n");
276   cs = SC_CS;
277   while((cs & 3) == 3) {
278     /* See if in 32 bit mode or not.  Assume GDT means 32 bit. */
279     if ((cs & 7) != 7) {
280       extern int main();
281       fprintf(stderr,"%d ",frameno++);
282       print_address(frame->u.win32.saved_ip,stderr,32);
283       fprintf( stderr, "\n" );
284       if (frame->u.win32.saved_ip >= ((unsigned long)main) &&
285           frame->u.win32.saved_ip <= ((unsigned long)main+1000)) break;
286       frame = (struct frame *) frame->u.win32.saved_bp;
287     } else {
288       if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
289       fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, cs, 
290               frame->u.win16.saved_ip);
291       frame = (struct frame *) PTR_SEG_OFF_TO_LIN( SC_SS, frame->u.win16.saved_bp & ~1);
292       if ((cs & 7) != 7)  /* switching to 32-bit mode */
293       {
294           extern int IF1632_Saved32_ebp;
295           frame = (struct frame *)IF1632_Saved32_ebp;
296       }
297     }
298   }
299   putchar('\n');
300 }
301