Release 970914
[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 <stdlib.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       ess;
23   unsigned int       ebp;
24   struct symbol_info frame;
25 };
26
27 static int nframe;
28 static struct bt_info * frames = NULL;
29 int curr_frame;
30
31 typedef struct
32 {
33     WORD bp;
34     WORD ip;
35     WORD cs;
36 } FRAME16;
37
38 typedef struct
39 {
40     DWORD bp;
41     DWORD ip;
42     WORD cs;
43 } FRAME32;
44
45
46
47 /***********************************************************************
48  *           DEBUG_InfoStack
49  *
50  * Dump the top of the stack
51  */
52 void DEBUG_InfoStack(void)
53 {
54     DBG_ADDR addr;
55
56     fprintf(stderr,"Stack dump:\n");
57     if ((SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR) ||
58         (GET_SEL_FLAGS(SS_reg(&DEBUG_context)) & LDT_FLAGS_32BIT))
59     {  /* 32-bit mode */
60         addr.seg = 0;
61         addr.off = ESP_reg(&DEBUG_context);
62         addr.type = NULL;
63         DEBUG_ExamineMemory( &addr, 24, 'x' );
64     }
65     else  /* 16-bit mode */
66     {
67         addr.seg = SS_reg(&DEBUG_context);
68         addr.off = SP_reg(&DEBUG_context);
69         addr.type = NULL;
70         DEBUG_ExamineMemory( &addr, 24, 'w' );
71     }
72     fprintf(stderr,"\n");
73 }
74
75
76 /***********************************************************************
77  *           DEBUG_BackTrace
78  *
79  * Display a stack back-trace.
80  */
81 void DEBUG_BackTrace(void)
82 {
83     DBG_ADDR addr;
84     int frameno = 0;
85
86     fprintf(stderr,"Backtrace:\n");
87     if (SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR)  /* 32-bit mode */
88     {
89         nframe = 1;
90         if (frames) free( frames );
91         frames = (struct bt_info *) xmalloc( sizeof(struct bt_info) );
92         fprintf(stderr,"%s%d ",(curr_frame == 0 ? "=>" : "  "), frameno++);
93
94         addr.seg = 0;
95         addr.off = EIP_reg(&DEBUG_context);
96         frames[0].eip = addr.off;
97         frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
98         fprintf( stderr, "\n" );
99         frames[0].ebp = addr.off = EBP_reg(&DEBUG_context);
100
101         while (addr.off)
102         {
103             FRAME32 *frame = (FRAME32 *)addr.off;
104             if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME32) )) return;
105             if (!frame->ip) break;
106             nframe++;
107             frames = (struct bt_info *)xrealloc(frames,
108                                                 nframe*sizeof(struct bt_info));
109             fprintf(stderr,"%s%d ", (frameno == curr_frame ? "=>" : "  "),
110                     frameno);
111             addr.off = frame->ip;
112             frames[frameno].eip = addr.off;
113             frames[frameno].ebp = frame->bp;
114             frames[frameno].frame = DEBUG_PrintAddressAndArgs( &addr, 32, 
115                                                         frame->bp, TRUE );
116             frameno++;
117             fprintf( stderr, "\n" );
118             addr.off = frame->bp;
119         }
120     }
121     else  /* 16-bit mode */
122     {
123       WORD ss = SS_reg(&DEBUG_context), cs = CS_reg(&DEBUG_context);
124       if (GET_SEL_FLAGS(ss) & LDT_FLAGS_32BIT)
125       {
126           fprintf( stderr, "Not implemented: 32-bit backtrace on a different stack segment.\n" );
127           return;
128       }
129       fprintf( stderr,"%d ", frameno++ );
130       addr.seg = cs;
131       addr.off = IP_reg(&DEBUG_context);
132       DEBUG_PrintAddress( &addr, 16, TRUE );
133       fprintf( stderr, "\n" );
134       addr.seg = ss;
135       addr.off = BP_reg(&DEBUG_context) & ~1;
136       for (;;)
137       {
138           FRAME16 *frame = (FRAME16 *)DBG_ADDR_TO_LIN(&addr);
139           if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME16) )) return;
140           if (!frame->bp) break;
141           if (frame->bp & 1) cs = frame->cs;
142           fprintf( stderr,"%d ", frameno++ );
143           addr.seg = cs;
144           addr.off = frame->ip;
145           DEBUG_PrintAddress( &addr, 16, TRUE );
146           fprintf( stderr, "\n" );
147           addr.seg = ss;
148           addr.off = frame->bp & ~1;
149       }
150   }
151   fprintf( stderr, "\n" );
152 }
153
154 /***********************************************************************
155  *           DEBUG_SilentBackTrace
156  *
157  * Display a stack back-trace.
158  */
159 void DEBUG_SilentBackTrace(void)
160 {
161     DBG_ADDR addr;
162     int frameno = 0;
163
164     nframe = 1;
165     if (frames) free( frames );
166     frames = (struct bt_info *) xmalloc( sizeof(struct bt_info) );
167
168     if (SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR)  /* 32-bit mode */
169     {
170         addr.seg = 0;
171         addr.off = EIP_reg(&DEBUG_context);
172         frames[0].eip = addr.off;
173         DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
174                                                 &frames[0].frame.list);
175         frames[0].ebp = addr.off = EBP_reg(&DEBUG_context);
176         frameno++;
177
178         while (addr.off)
179         {
180             FRAME32 *frame = (FRAME32 *)addr.off;
181             if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME32) )) return;
182             if (!frame->ip) break;
183             nframe++;
184             frames = (struct bt_info *)xrealloc(frames,
185                                                 nframe*sizeof(struct bt_info));
186             addr.off = frame->ip;
187             frames[frameno].eip = addr.off;
188             frames[frameno].ebp = frame->bp;
189             DEBUG_FindNearestSymbol( &addr, TRUE, 
190                                      &frames[frameno].frame.sym, frame->bp, 
191                                      &frames[frameno].frame.list);
192             frameno++;
193             addr.off = frame->bp;
194         }
195     }
196     else  /* 16-bit mode */
197     {
198       /*
199        * Not implemented here.  I am not entirely sure how best to handle
200        * this stuff.
201        */
202     }
203 }
204
205 int
206 DEBUG_SetFrame(int newframe)
207 {
208   int           rtn = FALSE;
209
210   curr_frame = newframe;
211
212   if( curr_frame >= nframe )
213     {
214       curr_frame = nframe - 1;
215     }
216
217   if( curr_frame < 0 )
218     {
219       curr_frame = 0;
220     }
221
222    if( frames[curr_frame].frame.list.sourcefile != NULL )
223     {
224       DEBUG_List(&frames[curr_frame].frame.list, NULL, 0);
225     }
226
227   rtn = TRUE;
228   return (rtn);
229 }
230
231 int
232 DEBUG_GetCurrentFrame(struct name_hash ** name, unsigned int * eip,
233                       unsigned int * ebp)
234 {
235   /*
236    * If we don't have a valid backtrace, then just return.
237    */
238   if( frames == NULL )
239     {
240       return FALSE;
241     }
242
243   /*
244    * If we don't know what the current function is, then we also have
245    * nothing to report here.
246    */
247   if( frames[curr_frame].frame.sym == NULL )
248     {
249       return FALSE;
250     }
251
252   *name = frames[curr_frame].frame.sym;
253   *eip = frames[curr_frame].eip;
254   *ebp = frames[curr_frame].ebp;
255
256   return TRUE;
257 }
258