blob: 950624077d16ae40045c314f851876f8c2b40aa0 [file] [log] [blame]
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001/*
2 * Wine debugger utility routines
3 * Eric Youngdale
4 * 9/93
5 */
6
7#include <stdio.h>
Alexandre Julliardecc37121994-11-22 16:31:29 +00008#include <stdlib.h>
Alexandre Julliarde2abbb11995-03-19 17:39:39 +00009#include "ldt.h"
Alexandre Julliard18506551995-01-24 16:21:01 +000010#include "db_disasm.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +000011#include "regpos.h"
12
13extern int * regval;
14extern unsigned int dbg_mask;
15extern unsigned int dbg_mode;
16
Alexandre Julliardd18872d1994-05-11 12:18:19 +000017void application_not_running()
18{
19 fprintf(stderr,"Application not running\n");
20}
21
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000022void 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 *);
Alexandre Julliard73450d61994-05-18 18:29:32 +000031
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000032 char * name = find_nearest_symbol((unsigned int *) addr);
Alexandre Julliardf0b23541993-09-29 12:21:49 +000033 if(name)
34 fprintf(outfile,"0x%8.8x(%s)", addr, name);
35 else
36 fprintf(outfile,"0x%8.8x", addr);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000037 }
Alexandre Julliardf0b23541993-09-29 12:21:49 +000038}
39
40
41void info_reg(){
Alexandre Julliardd18872d1994-05-11 12:18:19 +000042
43 if(!regval) {
44 application_not_running();
Alexandre Julliard73450d61994-05-18 18:29:32 +000045 return;
Alexandre Julliardd18872d1994-05-11 12:18:19 +000046 }
47
Alexandre Julliardf0b23541993-09-29 12:21:49 +000048 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
68void info_stack(){
69 unsigned int * dump;
70 int i;
71
Alexandre Julliardd18872d1994-05-11 12:18:19 +000072 if(!regval) {
73 application_not_running();
Alexandre Julliard73450d61994-05-18 18:29:32 +000074 return;
Alexandre Julliardd18872d1994-05-11 12:18:19 +000075 }
Alexandre Julliardf0b23541993-09-29 12:21:49 +000076
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
89void 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)
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000096 addr |= (format == 'i' ? SC_CS : SC_DS) << 16;
Alexandre Julliardf0b23541993-09-29 12:21:49 +000097
98 if(format != 'i' && count > 1) {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +000099 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000100 fprintf(stderr,": ");
101 };
102
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000103 switch(format){
104 case 's':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000105 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
106 : (char *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000107 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++) {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000117 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000118 fprintf(stderr,": ");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000119 addr = db_disasm( addr, 0, (dbg_mode == 16) );
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000120 fprintf(stderr,"\n");
121 };
122 return;
123 case 'x':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000124 dump = dbg_mode == 16 ? (unsigned int *)PTR_SEG_TO_LIN(addr)
125 : (unsigned int *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000126 for(i=0; i<count; i++)
127 {
128 fprintf(stderr," %8.8x", *dump++);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000129 addr += 4;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000130 if ((i % 8) == 7) {
131 fprintf(stderr,"\n");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000132 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000133 fprintf(stderr,": ");
134 };
135 }
136 fprintf(stderr,"\n");
137 return;
138
139 case 'd':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000140 dump = dbg_mode == 16 ? (unsigned int *)PTR_SEG_TO_LIN(addr)
141 : (unsigned int *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000142 for(i=0; i<count; i++)
143 {
144 fprintf(stderr," %d", *dump++);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000145 addr += 4;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000146 if ((i % 8) == 7) {
147 fprintf(stderr,"\n");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000148 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000149 fprintf(stderr,": ");
150 };
151 }
152 fprintf(stderr,"\n");
153 return;
154
155 case 'w':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000156 wdump = dbg_mode == 16 ? (unsigned short *)PTR_SEG_TO_LIN(addr)
157 : (unsigned short *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000158 for(i=0; i<count; i++)
159 {
Alexandre Julliard0e607781993-11-03 19:23:37 +0000160 fprintf(stderr," %x", *wdump++);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000161 addr += 2;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000162 if ((i % 10) == 7) {
163 fprintf(stderr,"\n");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000164 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000165 fprintf(stderr,": ");
166 };
167 }
168 fprintf(stderr,"\n");
169 return;
170
171 case 'c':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000172 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
173 : (char *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000174 for(i=0; i<count; i++)
175 {
176 if(*pnt < 0x20) {
177 fprintf(stderr," ");
178 pnt++;
179 } else
180 fprintf(stderr," %c", *pnt++);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000181 addr++;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000182 if ((i % 32) == 7) {
183 fprintf(stderr,"\n");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000184 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000185 fprintf(stderr,": ");
186 };
187 }
188 fprintf(stderr,"\n");
189 return;
190
191 case 'b':
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000192 pnt = dbg_mode == 16 ? (char *)PTR_SEG_TO_LIN(addr)
193 : (char *)addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000194 for(i=0; i<count; i++)
195 {
Alexandre Julliard234bc241994-12-10 13:02:28 +0000196 fprintf(stderr," %02x", (*pnt++) & 0xff);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000197 addr++;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000198 if ((i % 32) == 7) {
199 fprintf(stderr,"\n");
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000200 print_address(addr, stderr, dbg_mode);
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000201 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
213char * 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",
Alexandre Julliard18506551995-01-24 16:21:01 +0000217" 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>",
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000224" define <identifier> <expr>",
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000225"",
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"",
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000235NULL};
236
237void dbg_help(){
238 int i;
239 i = 0;
240 while(helptext[i]) fprintf(stderr,"%s\n", helptext[i++]);
241}
242
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000243
244struct 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
260void dbg_bt(){
261 struct frame * frame;
262 unsigned short cs;
263 int frameno = 0;
264
265 if(!regval) {
266 application_not_running();
Alexandre Julliard73450d61994-05-18 18:29:32 +0000267 return;
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000268 }
269
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000270 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);
Alexandre Julliard18506551995-01-24 16:21:01 +0000274
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000275 fprintf(stderr,"Backtrace:\n");
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000276 cs = SC_CS;
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000277 while((cs & 3) == 3) {
278 /* See if in 32 bit mode or not. Assume GDT means 32 bit. */
279 if ((cs & 7) != 7) {
Alexandre Julliardaca05781994-10-17 18:12:41 +0000280 void CallTo32();
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000281 fprintf(stderr,"%d ",frameno++);
282 print_address(frame->u.win32.saved_ip,stderr,32);
283 fprintf( stderr, "\n" );
Alexandre Julliard18506551995-01-24 16:21:01 +0000284 if(frame->u.win32.saved_ip<((unsigned long)CallTo32+1000))break;
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000285 frame = (struct frame *) frame->u.win32.saved_bp;
286 } else {
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000287 if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000288 fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, cs,
289 frame->u.win16.saved_ip);
Alexandre Julliarde2abbb11995-03-19 17:39:39 +0000290 frame = (struct frame *) PTR_SEG_OFF_TO_LIN( SC_SS, frame->u.win16.saved_bp & ~1);
291 if ((cs & 7) != 7) /* switching to 32-bit mode */
292 {
293 extern int IF1632_Saved32_ebp;
294 frame = (struct frame *)IF1632_Saved32_ebp;
295 }
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000296 }
297 }
Alexandre Julliardaca05781994-10-17 18:12:41 +0000298 putchar('\n');
Alexandre Julliardd18872d1994-05-11 12:18:19 +0000299}
300