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