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