Release 970101
[wine] / debugger / stack.c
1 /*
2  * Debugger stack handling
3  *
4  * Copyright 1995 Alexandre Julliard
5  * Copyright 1996 Eric Youngdale
6  */
7
8 #include <stdio.h>
9 #include <malloc.h>
10 #include "xmalloc.h"
11 #include "windows.h"
12 #include "debugger.h"
13
14
15 /*
16  * We keep this info for each frame, so that we can
17  * find local variable information correctly.
18  */
19 struct bt_info
20 {
21   unsigned int       eip;
22   unsigned int       ebp;
23   struct name_hash * frame;
24 };
25
26 static int nframe;
27 static struct bt_info * frames = NULL;
28 int curr_frame;
29 static char * reg_name[] =
30 {
31   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
32 };
33
34 typedef struct
35 {
36     WORD bp;
37     WORD ip;
38     WORD cs;
39 } FRAME16;
40
41 typedef struct
42 {
43     DWORD bp;
44     DWORD ip;
45     WORD cs;
46 } FRAME32;
47
48
49
50 /***********************************************************************
51  *           DEBUG_InfoStack
52  *
53  * Dump the top of the stack
54  */
55 void DEBUG_InfoStack(void)
56 {
57     DBG_ADDR addr;
58
59     fprintf(stderr,"Stack dump:\n");
60     if ((SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR) ||
61         (GET_SEL_FLAGS(SS_reg(&DEBUG_context)) & LDT_FLAGS_32BIT))
62     {  /* 32-bit mode */
63         addr.seg = 0;
64         addr.off = ESP_reg(&DEBUG_context);
65         DEBUG_ExamineMemory( &addr, 24, 'x' );
66     }
67     else  /* 16-bit mode */
68     {
69         addr.seg = SS_reg(&DEBUG_context);
70         addr.off = SP_reg(&DEBUG_context);
71         DEBUG_ExamineMemory( &addr, 24, 'w' );
72     }
73     fprintf(stderr,"\n");
74 }
75
76
77 /***********************************************************************
78  *           DEBUG_BackTrace
79  *
80  * Display a stack back-trace.
81  */
82 void DEBUG_BackTrace(void)
83 {
84     DBG_ADDR addr;
85     int frameno = 0;
86
87     fprintf(stderr,"Backtrace:\n");
88     if (SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR)  /* 32-bit mode */
89     {
90         nframe = 1;
91         if (frames) free( frames );
92         frames = (struct bt_info *) xmalloc( sizeof(struct bt_info) );
93         fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : "  "), frameno++);
94
95         addr.seg = 0;
96         addr.off = EIP_reg(&DEBUG_context);
97         frames[0].eip = addr.off;
98         frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
99         fprintf( stderr, "\n" );
100         frames[0].ebp = addr.off = EBP_reg(&DEBUG_context);
101
102         while (addr.off)
103         {
104             FRAME32 *frame = (FRAME32 *)addr.off;
105             if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME32) )) return;
106             if (!frame->ip) break;
107             nframe++;
108             frames = (struct bt_info *)xrealloc(frames,
109                                                 nframe*sizeof(struct bt_info));
110             fprintf(stderr,"%s%d ", (frameno == curr_frame ? "=>" : "  "),
111                     frameno);
112             addr.off = frame->ip;
113             frames[frameno].eip = addr.off;
114             frames[frameno].ebp = frame->bp;
115             frames[frameno].frame = DEBUG_PrintAddressAndArgs( &addr, 32, 
116                                                         frame->bp, TRUE );
117             frameno++;
118             fprintf( stderr, "\n" );
119             addr.off = frame->bp;
120         }
121     }
122     else  /* 16-bit mode */
123     {
124       WORD ss = SS_reg(&DEBUG_context), cs = CS_reg(&DEBUG_context);
125       if (GET_SEL_FLAGS(ss) & LDT_FLAGS_32BIT)
126       {
127           fprintf( stderr, "Not implemented: 32-bit backtrace on a different stack segment.\n" );
128           return;
129       }
130       fprintf( stderr,"%d ", frameno++ );
131       addr.seg = cs;
132       addr.off = IP_reg(&DEBUG_context);
133       DEBUG_PrintAddress( &addr, 16, TRUE );
134       fprintf( stderr, "\n" );
135       addr.seg = ss;
136       addr.off = BP_reg(&DEBUG_context) & ~1;
137       for (;;)
138       {
139           FRAME16 *frame = (FRAME16 *)DBG_ADDR_TO_LIN(&addr);
140           if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME16) )) return;
141           if (!frame->bp) break;
142           if (frame->bp & 1) cs = frame->cs;
143           fprintf( stderr,"%d ", frameno++ );
144           addr.seg = cs;
145           addr.off = frame->ip;
146           DEBUG_PrintAddress( &addr, 16, TRUE );
147           fprintf( stderr, "\n" );
148           addr.seg = ss;
149           addr.off = frame->bp & ~1;
150       }
151   }
152   fprintf( stderr, "\n" );
153 }
154
155 /***********************************************************************
156  *           DEBUG_GetSymbolValue
157  *
158  * Get the address of a named symbol from the current stack frame.
159  */
160 BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
161 {
162   struct name_hash * curr_func;
163   int                i;
164
165   /*
166    * If we don't have a valid backtrace, then just return.
167    */
168   if( frames == NULL )
169     {
170       return FALSE;
171     }
172
173   curr_func = frames[curr_frame].frame;
174
175   /*
176    * If we don't know what the current function is, then we also have
177    * nothing to report here.
178    */
179   if( curr_func == NULL )
180     {
181       return FALSE;
182     }
183
184   for(i=0; i < curr_func->n_locals; i++ )
185     {
186       /*
187        * Test the range of validity of the local variable.  This
188        * comes up with RBRAC/LBRAC stabs in particular.
189        */
190       if(    (curr_func->local_vars[i].pc_start != 0)
191           && ((frames[curr_frame].eip - curr_func->addr.off) 
192               < curr_func->local_vars[i].pc_start) )
193         {
194           continue;
195         }
196
197       if(    (curr_func->local_vars[i].pc_end != 0)
198           && ((frames[curr_frame].eip - curr_func->addr.off) 
199               > curr_func->local_vars[i].pc_end) )
200         {
201           continue;
202         }
203
204       if( strcmp(name, curr_func->local_vars[i].name) == 0 )
205         {
206           /*
207            * OK, we found it.  Now figure out what to do with this.
208            */
209           if( curr_func->local_vars[i].regno != 0 )
210             {
211               /*
212                * Register variable.  We don't know how to treat
213                * this yet.
214                */
215               return FALSE;
216             }
217
218           addr->seg = 0;
219           addr->off = frames[curr_frame].ebp + curr_func->local_vars[i].offset;
220
221           return TRUE;
222         }
223     }
224   return FALSE;
225 }
226
227 int
228 DEBUG_SetFrame(int newframe)
229 {
230   int           rtn = FALSE;
231   /*
232    * Nothing for now.  Add support later.
233    */
234
235   curr_frame = newframe;
236   if( curr_frame < 0 )
237     {
238       curr_frame = 0;
239     }
240
241   if( curr_frame >= nframe )
242     {
243       curr_frame = nframe - 1;
244     }
245
246   rtn = TRUE;
247   return (rtn);
248 }
249
250 int
251 DEBUG_InfoLocals()
252 {
253   struct name_hash * curr_func;
254   int                i;
255   int           rtn = FALSE;
256   unsigned      int * ptr;
257
258   /*
259    * If we don't have a valid backtrace, then just return.
260    */
261   if( frames == NULL )
262     {
263       return FALSE;
264     }
265
266   curr_func = frames[curr_frame].frame;
267
268   /*
269    * If we don't know what the current function is, then we also have
270    * nothing to report here.
271    */
272   if( curr_func == NULL )
273     {
274       return FALSE;
275     }
276
277   for(i=0; i < curr_func->n_locals; i++ )
278     {
279       /*
280        * Test the range of validity of the local variable.  This
281        * comes up with RBRAC/LBRAC stabs in particular.
282        */
283       if(    (curr_func->local_vars[i].pc_start != 0)
284           && ((frames[curr_frame].eip - curr_func->addr.off) 
285               < curr_func->local_vars[i].pc_start) )
286         {
287           continue;
288         }
289
290       if(    (curr_func->local_vars[i].pc_end != 0)
291           && ((frames[curr_frame].eip - curr_func->addr.off) 
292               > curr_func->local_vars[i].pc_end) )
293         {
294           continue;
295         }
296       
297       if( curr_func->local_vars[i].offset == 0 )
298         {
299           fprintf(stderr, "%s:%s optimized into register $%s \n",
300                   curr_func->name, curr_func->local_vars[i].name,
301                   reg_name[curr_func->local_vars[i].regno]);
302         }
303       else
304         {
305           ptr = (unsigned int *) (frames[curr_frame].ebp 
306                                    + curr_func->local_vars[i].offset);
307           fprintf(stderr, "%s:%s == 0x%8.8x\n",
308                   curr_func->name, curr_func->local_vars[i].name,
309                   *ptr);
310         }
311     }
312
313   rtn = TRUE;
314
315   return (rtn);
316 }