Fixed background redrawing when control is covered. Fixed a really
[wine] / debugger / stack.c
1 /*
2  * Debugger stack handling
3  *
4  * Copyright 1995 Alexandre Julliard
5  * Copyright 1996 Eric Youngdale
6  * Copyright 1999 Ove Kåven
7  */
8
9 #include "config.h"
10
11 #include <stdlib.h>
12
13 #include "debugger.h"
14 #include "stackframe.h"
15 #include "winbase.h"
16
17 #ifdef __i386__
18 /*
19  * We keep this info for each frame, so that we can
20  * find local variable information correctly.
21  */
22 struct bt_info
23 {
24   unsigned int       cs;
25   unsigned int       eip;
26   unsigned int       ss;
27   unsigned int       ebp;
28   struct symbol_info frame;
29 };
30
31 static int nframe;
32 static struct bt_info * frames = NULL;
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 #endif
48
49
50 /***********************************************************************
51  *           DEBUG_InfoStack
52  *
53  * Dump the top of the stack
54  */
55 void DEBUG_InfoStack(void)
56 {
57 #ifdef __i386__
58     DBG_VALUE   value;
59     
60     value.type = NULL;
61     value.cookie = DV_TARGET;
62     value.addr.seg = DEBUG_context.SegSs;
63     value.addr.off = DEBUG_context.Esp;
64
65     DEBUG_Printf(DBG_CHN_MESG,"Stack dump:\n");
66     switch (DEBUG_GetSelectorType(value.addr.seg)) {
67     case 32: /* 32-bit mode */
68        DEBUG_ExamineMemory( &value, 24, 'x' );
69        break;
70     case 16:  /* 16-bit mode */
71         value.addr.off &= 0xffff;
72         DEBUG_ExamineMemory( &value, 24, 'w' );
73         break;
74     default:
75        DEBUG_Printf(DBG_CHN_MESG, "Bad segment (%ld)\n", value.addr.seg);
76     }
77     DEBUG_Printf(DBG_CHN_MESG,"\n");
78 #endif
79 }
80
81 #ifdef __i386__
82 static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, int bits, int noisy)
83 {
84     int theframe = nframe++;
85     frames = (struct bt_info *)DBG_realloc(frames,
86                                            nframe*sizeof(struct bt_info));
87     if (noisy)
88       DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : "  "),
89               frameno);
90     frames[theframe].cs = code->seg;
91     frames[theframe].eip = code->off;
92     if (noisy)
93       frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, bits, 
94                                                           stack->off, TRUE );
95     else
96       DEBUG_FindNearestSymbol( code, TRUE, 
97                                &frames[theframe].frame.sym, stack->off, 
98                                &frames[theframe].frame.list);
99     frames[theframe].ss = stack->seg;
100     frames[theframe].ebp = stack->off;
101     if (noisy) {
102       DEBUG_Printf( DBG_CHN_MESG, (bits == 16) ? " (bp=%04lx)\n" : " (ebp=%08lx)\n", stack->off );
103     }
104 }
105
106 static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
107 {
108     unsigned int        ss = addr->seg, possible_cs = 0;
109     FRAME16             frame;
110     int                 theframe = nframe;
111     void*               p = (void*)DEBUG_ToLinear(addr);
112     
113     if (!p) return FALSE;
114     
115     if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
116         if (noisy) DEBUG_InvalAddr(addr);
117         return FALSE;
118     }
119     if (!frame.bp) return FALSE;
120     nframe++;
121     frames = (struct bt_info *)DBG_realloc(frames,
122                                            nframe*sizeof(struct bt_info));
123     if (noisy)
124         DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : "  "),
125                      frameno);
126     if (frame.bp & 1) *cs = frame.cs;
127     else {
128         /* not explicitly marked as far call,
129          * but check whether it could be anyway */
130         if (((frame.cs&7)==7) && (frame.cs != *cs)) {
131             LDT_ENTRY   le;
132          
133             if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, frame.cs, &le) &&
134                 (le.HighWord.Bits.Type & 0x08)) { /* code segment */
135                 /* it is very uncommon to push a code segment cs as
136                  * a parameter, so this should work in most cases */
137                 *cs = possible_cs = frame.cs;
138             }
139         }
140     }
141     frames[theframe].cs = addr->seg = *cs;
142     frames[theframe].eip = addr->off = frame.ip;
143     if (noisy)
144         frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 16, 
145                                                             frame.bp, TRUE );
146     else
147         DEBUG_FindNearestSymbol( addr, TRUE, 
148                                  &frames[theframe].frame.sym, frame.bp, 
149                                  &frames[theframe].frame.list);
150     frames[theframe].ss = addr->seg = ss;
151     frames[theframe].ebp = addr->off = frame.bp & ~1;
152     if (noisy) {
153         DEBUG_Printf( DBG_CHN_MESG, " (bp=%04lx", addr->off );
154         if (possible_cs) {
155             DEBUG_Printf( DBG_CHN_MESG, ", far call assumed" );
156         }
157         DEBUG_Printf( DBG_CHN_MESG, ")\n" );
158     }
159     return TRUE;
160 }
161
162 static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
163 {
164     unsigned int        ss = addr->seg;
165     FRAME32             frame;
166     int                 theframe = nframe;
167     void*               p = (void*)DEBUG_ToLinear(addr);
168     
169     if (!p) return FALSE;
170     
171     if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
172        if (noisy) DEBUG_InvalAddr(addr);
173        return FALSE;
174     }
175     if (!frame.ip) return FALSE;
176     
177     nframe++;
178     frames = (struct bt_info *)DBG_realloc(frames,
179                                            nframe*sizeof(struct bt_info));
180     if (noisy)
181        DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : "  "),
182                     frameno);
183     frames[theframe].cs = addr->seg = *cs;
184     frames[theframe].eip = addr->off = frame.ip;
185     if (noisy)
186         frames[theframe].frame = DEBUG_PrintAddressAndArgs( addr, 32, 
187                                                             frame.bp, TRUE );
188     else
189         DEBUG_FindNearestSymbol( addr, TRUE, 
190                                  &frames[theframe].frame.sym, frame.bp, 
191                                  &frames[theframe].frame.list);
192     if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (ebp=%08lx)\n", frame.bp );
193     frames[theframe].ss = addr->seg = ss;
194     frames[theframe].ebp = frame.bp;
195     if (addr->off == frame.bp) return FALSE;
196     addr->off = frame.bp;
197     return TRUE;
198 }
199 #endif
200
201
202 /***********************************************************************
203  *           DEBUG_BackTrace
204  *
205  * Display a stack back-trace.
206  */
207 void DEBUG_BackTrace(BOOL noisy)
208 {
209 #ifdef __i386
210     DBG_ADDR            addr, sw_addr, code, tmp;
211     unsigned int        ss = DEBUG_context.SegSs;
212     unsigned int        cs = DEBUG_context.SegCs;
213     int                 frameno = 0, is16, ok;
214     DWORD               next_switch, cur_switch, p;
215     STACK16FRAME        frame16;
216     STACK32FRAME        frame32;
217     char                ch;
218
219     if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Backtrace:\n" );
220
221     nframe = 1;
222     if (frames) DBG_free( frames );
223     frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) );
224     if (noisy)
225         DEBUG_Printf(DBG_CHN_MESG,"%s%d ",(curr_frame == 0 ? "=>" : "  "), frameno);
226
227     if (DEBUG_IsSelectorSystem(ss)) ss = 0;
228     if (DEBUG_IsSelectorSystem(cs)) cs = 0;
229
230     /* first stack frame from registers */
231     switch (DEBUG_GetSelectorType(ss))
232     {
233     case 32:
234         frames[0].cs = addr.seg = cs;
235         frames[0].eip = addr.off = DEBUG_context.Eip;
236         if (noisy)
237             frames[0].frame = DEBUG_PrintAddress( &addr, 32, TRUE );
238         else
239             DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
240                                      &frames[0].frame.list);
241         frames[0].ss = addr.seg = ss;
242         frames[0].ebp = addr.off = DEBUG_context.Ebp;
243         if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (ebp=%08x)\n", frames[0].ebp );
244         is16 = FALSE;
245         break;
246     case 16:
247         frames[0].cs = addr.seg = cs;
248         frames[0].eip = addr.off = LOWORD(DEBUG_context.Eip);
249         if (noisy)
250             frames[0].frame = DEBUG_PrintAddress( &addr, 16, TRUE );
251         else
252             DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
253                                      &frames[0].frame.list);
254         frames[0].ss = addr.seg = ss;
255         frames[0].ebp = addr.off = LOWORD(DEBUG_context.Ebp);
256         if (noisy) DEBUG_Printf( DBG_CHN_MESG, " (bp=%04x)\n", frames[0].ebp );
257         is16 = TRUE;
258         break;
259     default:
260         if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad segment '%u'\n", ss);
261         return;
262     }
263
264     /* cur_switch holds address of curr_stack's field in TEB in debuggee 
265      * address space 
266      */
267     cur_switch = (DWORD)DEBUG_CurrThread->teb + OFFSET_OF(TEB, cur_stack);
268     if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) {
269         if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Can't read TEB:cur_stack\n");
270         return;
271     }
272
273     if (is16) {
274         if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
275             if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", 
276                                      (unsigned long)(STACK32FRAME*)next_switch );
277             return;
278         }
279         cur_switch = (DWORD)frame32.frame16;
280         sw_addr.seg = SELECTOROF(cur_switch);
281         sw_addr.off = OFFSETOF(cur_switch);
282     } else {
283         tmp.seg = SELECTOROF(next_switch);
284         tmp.off = OFFSETOF(next_switch);
285         p = DEBUG_ToLinear(&tmp);
286         
287         if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
288             if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", 
289                                      (unsigned long)(STACK16FRAME*)p );
290             return;
291         }
292         cur_switch = (DWORD)frame16.frame32;
293         sw_addr.seg = ss;
294         sw_addr.off = cur_switch;
295     }
296     if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
297         sw_addr.seg = (DWORD)-1;
298         sw_addr.off = (DWORD)-1;
299     }
300     
301     for (ok = TRUE; ok;) {
302         if ((frames[frameno].ss == sw_addr.seg) &&
303             (frames[frameno].ebp >= sw_addr.off)) {
304            /* 16<->32 switch...
305             * yes, I know this is confusing, it gave me a headache too */
306            if (is16) {
307               
308                if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
309                   if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", 
310                                            (unsigned long)(STACK32FRAME*)next_switch );
311                   return;
312                }
313
314                code.seg  = 0;
315                code.off  = frame32.retaddr;
316                
317                cs = 0;
318                addr.seg = 0;
319                addr.off = frame32.ebp;
320                DEBUG_ForceFrame( &addr, &code, ++frameno, 32, noisy );
321                
322                next_switch = cur_switch;
323                tmp.seg = SELECTOROF(next_switch);
324                tmp.off = OFFSETOF(next_switch);
325                p = DEBUG_ToLinear(&tmp);
326                
327                if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
328                    if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", 
329                                             (unsigned long)(STACK16FRAME*)p );
330                    return;
331                }
332                cur_switch = (DWORD)frame16.frame32;
333                sw_addr.seg = 0;
334                sw_addr.off = cur_switch;
335                
336                is16 = FALSE;
337            } else {
338               tmp.seg = SELECTOROF(next_switch);
339               tmp.off = OFFSETOF(next_switch);
340               p = DEBUG_ToLinear(&tmp);
341               
342               if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
343                   if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
344                                            (unsigned long)(STACK16FRAME*)p );
345                   return;
346               }
347               
348               code.seg  = frame16.cs;
349               code.off  = frame16.ip;
350               
351               cs = frame16.cs;
352               addr.seg = SELECTOROF(next_switch);
353               addr.off = frame16.bp;
354               DEBUG_ForceFrame( &addr, &code, ++frameno, 16, noisy );
355               
356               next_switch = cur_switch;
357               if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
358                  if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", 
359                                           (unsigned long)(STACK32FRAME*)next_switch );
360                  return;
361               }
362               cur_switch = (DWORD)frame32.frame16;
363               sw_addr.seg = SELECTOROF(cur_switch);
364               sw_addr.off = OFFSETOF(cur_switch);
365               
366               is16 = TRUE;
367            }
368            if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
369               sw_addr.seg = (DWORD)-1;
370               sw_addr.off = (DWORD)-1;
371            }
372         } else {
373             /* ordinary stack frame */
374            ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy)
375               : DEBUG_Frame32( &addr, &cs, ++frameno, noisy);
376         }
377     }
378     if (noisy) DEBUG_Printf( DBG_CHN_MESG, "\n" );
379 #endif
380 }
381
382 int
383 DEBUG_SetFrame(int newframe)
384 {
385 #ifdef __i386__
386   int           rtn = FALSE;
387
388   curr_frame = newframe;
389
390   if( curr_frame >= nframe )
391     {
392       curr_frame = nframe - 1;
393     }
394
395   if( curr_frame < 0 )
396     {
397       curr_frame = 0;
398     }
399
400    if( frames && frames[curr_frame].frame.list.sourcefile != NULL )
401     {
402       DEBUG_List(&frames[curr_frame].frame.list, NULL, 0);
403     }
404
405   rtn = TRUE;
406   return (rtn);
407 #else /* __i386__ */
408   return FALSE;
409 #endif /* __i386__ */
410 }
411
412 int
413 DEBUG_GetCurrentFrame(struct name_hash ** name, unsigned int * eip,
414                       unsigned int * ebp)
415 {
416 #ifdef __i386__
417   /*
418    * If we don't have a valid backtrace, then just return.
419    */
420   if( frames == NULL )
421     {
422       return FALSE;
423     }
424
425   /*
426    * If we don't know what the current function is, then we also have
427    * nothing to report here.
428    */
429   if( frames[curr_frame].frame.sym == NULL )
430     {
431       return FALSE;
432     }
433
434   *name = frames[curr_frame].frame.sym;
435   *eip = frames[curr_frame].eip;
436   *ebp = frames[curr_frame].ebp;
437
438   return TRUE;
439 #else /* __i386__ */
440   return FALSE;
441 #endif /* __i386__ */
442 }
443