blob: b892a0e8995483ec3263d90ba0d05cbe6b1dd30a [file] [log] [blame]
Alexandre Julliardded30381995-07-06 17:18:27 +00001/*
2 * Debugger stack handling
3 *
4 * Copyright 1995 Alexandre Julliard
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00005 * Copyright 1996 Eric Youngdale
Ove Kaavenb4a5db51999-05-08 12:38:20 +00006 * Copyright 1999 Ove Kåven
Alexandre Julliardded30381995-07-06 17:18:27 +00007 */
8
Marcus Meissnerb0d52b01999-02-28 19:59:00 +00009#include "config.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000010
Alexandre Julliard84c70f51997-05-09 08:40:27 +000011#include <stdlib.h>
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000012
Alexandre Julliardded30381995-07-06 17:18:27 +000013#include "debugger.h"
Ove Kaavenb4a5db51999-05-08 12:38:20 +000014#include "stackframe.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000015#include "winbase.h"
Alexandre Julliardded30381995-07-06 17:18:27 +000016
Eric Pouech527eea92000-03-08 16:44:54 +000017#ifdef __i386__
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000018/*
19 * We keep this info for each frame, so that we can
20 * find local variable information correctly.
21 */
22struct bt_info
23{
Ove Kaavenb4a5db51999-05-08 12:38:20 +000024 unsigned int cs;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000025 unsigned int eip;
Ove Kaavenb4a5db51999-05-08 12:38:20 +000026 unsigned int ss;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000027 unsigned int ebp;
Alexandre Julliardc6c09441997-01-12 18:32:19 +000028 struct symbol_info frame;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000029};
30
31static int nframe;
32static struct bt_info * frames = NULL;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000033
Alexandre Julliardded30381995-07-06 17:18:27 +000034typedef struct
35{
36 WORD bp;
37 WORD ip;
38 WORD cs;
39} FRAME16;
40
41typedef struct
42{
43 DWORD bp;
44 DWORD ip;
45 WORD cs;
46} FRAME32;
Eric Pouech527eea92000-03-08 16:44:54 +000047#endif
Alexandre Julliardded30381995-07-06 17:18:27 +000048
49
50/***********************************************************************
51 * DEBUG_InfoStack
52 *
53 * Dump the top of the stack
54 */
55void DEBUG_InfoStack(void)
56{
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +000057#ifdef __i386__
Eric Pouechd33bcb62000-03-15 19:57:20 +000058 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;
Alexandre Julliard808cb041995-08-17 17:11:36 +000064
Eric Poueche5efa0c2000-04-13 19:31:58 +000065 DEBUG_Printf(DBG_CHN_MESG,"Stack dump:\n");
Alexandre Julliard954a4132000-09-24 03:15:50 +000066 switch (DEBUG_GetSelectorType(value.addr.seg))
67 {
68 case MODE_32: /* 32-bit mode */
Eric Pouechd33bcb62000-03-15 19:57:20 +000069 DEBUG_ExamineMemory( &value, 24, 'x' );
Eric Pouech527eea92000-03-08 16:44:54 +000070 break;
Alexandre Julliard954a4132000-09-24 03:15:50 +000071 case MODE_16: /* 16-bit mode */
72 case MODE_VM86:
Eric Pouechd33bcb62000-03-15 19:57:20 +000073 value.addr.off &= 0xffff;
74 DEBUG_ExamineMemory( &value, 24, 'w' );
Eric Pouech527eea92000-03-08 16:44:54 +000075 break;
76 default:
Eric Poueche5efa0c2000-04-13 19:31:58 +000077 DEBUG_Printf(DBG_CHN_MESG, "Bad segment (%ld)\n", value.addr.seg);
Alexandre Julliardded30381995-07-06 17:18:27 +000078 }
Eric Poueche5efa0c2000-04-13 19:31:58 +000079 DEBUG_Printf(DBG_CHN_MESG,"\n");
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +000080#endif
Alexandre Julliardded30381995-07-06 17:18:27 +000081}
82
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +000083#ifdef __i386__
Alexandre Julliard954a4132000-09-24 03:15:50 +000084static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, enum dbg_mode mode,
85 int noisy, const char *caveat)
Ove Kaavenb4a5db51999-05-08 12:38:20 +000086{
87 int theframe = nframe++;
88 frames = (struct bt_info *)DBG_realloc(frames,
Eric Pouech527eea92000-03-08 16:44:54 +000089 nframe*sizeof(struct bt_info));
Ove Kaavenb4a5db51999-05-08 12:38:20 +000090 if (noisy)
Eric Poueche5efa0c2000-04-13 19:31:58 +000091 DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : " "),
Ove Kaavenb4a5db51999-05-08 12:38:20 +000092 frameno);
93 frames[theframe].cs = code->seg;
94 frames[theframe].eip = code->off;
95 if (noisy)
Alexandre Julliard954a4132000-09-24 03:15:50 +000096 frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, mode, stack->off, TRUE );
Ove Kaavenb4a5db51999-05-08 12:38:20 +000097 else
98 DEBUG_FindNearestSymbol( code, TRUE,
99 &frames[theframe].frame.sym, stack->off,
100 &frames[theframe].frame.list);
101 frames[theframe].ss = stack->seg;
102 frames[theframe].ebp = stack->off;
103 if (noisy) {
Alexandre Julliard954a4132000-09-24 03:15:50 +0000104 DEBUG_Printf( DBG_CHN_MESG, (mode != MODE_32) ? " (bp=%04lx%s)\n" : " (ebp=%08lx%s)\n",
105 stack->off, caveat?caveat:"" );
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000106 }
107}
108
Eric Pouech800773f2001-08-06 17:51:52 +0000109static BOOL DEBUG_Frame16(DBG_THREAD* thread, DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000110{
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000111 unsigned int possible_cs = 0;
Eric Pouech527eea92000-03-08 16:44:54 +0000112 FRAME16 frame;
Eric Pouech527eea92000-03-08 16:44:54 +0000113 void* p = (void*)DEBUG_ToLinear(addr);
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000114 DBG_ADDR code;
Eric Pouech527eea92000-03-08 16:44:54 +0000115
116 if (!p) return FALSE;
117
118 if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000119 if (noisy) DEBUG_InvalAddr(addr);
Eric Pouech527eea92000-03-08 16:44:54 +0000120 return FALSE;
Eric Pouech99b15131999-08-21 12:56:15 +0000121 }
Eric Pouech527eea92000-03-08 16:44:54 +0000122 if (!frame.bp) return FALSE;
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000123
Eric Pouech527eea92000-03-08 16:44:54 +0000124 if (frame.bp & 1) *cs = frame.cs;
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000125 else {
Eric Pouech527eea92000-03-08 16:44:54 +0000126 /* not explicitly marked as far call,
127 * but check whether it could be anyway */
128 if (((frame.cs&7)==7) && (frame.cs != *cs)) {
129 LDT_ENTRY le;
130
Eric Pouech800773f2001-08-06 17:51:52 +0000131 if (GetThreadSelectorEntry( thread->handle, frame.cs, &le) &&
Eric Pouech527eea92000-03-08 16:44:54 +0000132 (le.HighWord.Bits.Type & 0x08)) { /* code segment */
133 /* it is very uncommon to push a code segment cs as
134 * a parameter, so this should work in most cases */
135 *cs = possible_cs = frame.cs;
136 }
137 }
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000138 }
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000139 code.seg = *cs;
140 code.off = frame.ip;
141 addr->off = frame.bp & ~1;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000142 DEBUG_ForceFrame(addr, &code, frameno, MODE_16, noisy,
143 possible_cs ? ", far call assumed" : NULL );
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000144 return TRUE;
145}
146
147static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
148{
Eric Pouech527eea92000-03-08 16:44:54 +0000149 FRAME32 frame;
Eric Pouech527eea92000-03-08 16:44:54 +0000150 void* p = (void*)DEBUG_ToLinear(addr);
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000151 DBG_ADDR code;
152 DWORD old_bp = addr->off;
Eric Pouech527eea92000-03-08 16:44:54 +0000153
154 if (!p) return FALSE;
155
156 if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000157 if (noisy) DEBUG_InvalAddr(addr);
Eric Pouech99b15131999-08-21 12:56:15 +0000158 return FALSE;
159 }
Eric Pouech527eea92000-03-08 16:44:54 +0000160 if (!frame.ip) return FALSE;
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000161
162 code.seg = *cs;
163 code.off = frame.ip;
Eric Pouech527eea92000-03-08 16:44:54 +0000164 addr->off = frame.bp;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000165 DEBUG_ForceFrame(addr, &code, frameno, MODE_32, noisy, NULL);
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000166 if (addr->off == old_bp) return FALSE;
Ove Kaavenb4a5db51999-05-08 12:38:20 +0000167 return TRUE;
168}
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +0000169#endif
170
171
Alexandre Julliardded30381995-07-06 17:18:27 +0000172/***********************************************************************
173 * DEBUG_BackTrace
174 *
175 * Display a stack back-trace.
176 */
Eric Pouech800773f2001-08-06 17:51:52 +0000177void DEBUG_BackTrace(DWORD tid, BOOL noisy)
Alexandre Julliardded30381995-07-06 17:18:27 +0000178{
Eric Pouech527eea92000-03-08 16:44:54 +0000179#ifdef __i386
180 DBG_ADDR addr, sw_addr, code, tmp;
Eric Pouech800773f2001-08-06 17:51:52 +0000181 unsigned int ss, cs;
Eric Pouech527eea92000-03-08 16:44:54 +0000182 int frameno = 0, is16, ok;
183 DWORD next_switch, cur_switch, p;
184 STACK16FRAME frame16;
185 STACK32FRAME frame32;
186 char ch;
Eric Pouech800773f2001-08-06 17:51:52 +0000187 CONTEXT ctx;
188 DBG_THREAD* thread;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000189
Eric Pouech800773f2001-08-06 17:51:52 +0000190 int copy_nframe = 0;
191 int copy_curr_frame = 0;
192 struct bt_info* copy_frames = NULL;
193
Eric Poueche5efa0c2000-04-13 19:31:58 +0000194 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Backtrace:\n" );
Eric Pouech527eea92000-03-08 16:44:54 +0000195
Eric Pouech800773f2001-08-06 17:51:52 +0000196 if (tid == DEBUG_CurrTid)
197 {
198 ctx = DEBUG_context;
199 thread = DEBUG_CurrThread;
200
201 if (frames) DBG_free( frames );
202 /* frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); */
203 }
204 else
205 {
206 thread = DEBUG_GetThread(DEBUG_CurrProcess, tid);
207
208 if (!thread)
209 {
210 DEBUG_Printf( DBG_CHN_MESG, "Unknown thread id (0x%08lx) in current process\n", tid);
211 return;
212 }
213 memset(&ctx, 0, sizeof(ctx));
214 ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_SEGMENTS;
215
216 if ( SuspendThread( thread->handle ) == -1 ||
217 !GetThreadContext( thread->handle, &ctx ))
218 {
219 DEBUG_Printf( DBG_CHN_MESG, "Can't get context for thread id (0x%08lx) in current process\n", tid);
220 return;
221 }
222 /* need to avoid trashing stack frame for current thread */
223 copy_nframe = nframe;
224 copy_frames = frames;
225 copy_curr_frame = curr_frame;
226 curr_frame = 0;
227 }
228
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000229 nframe = 0;
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000230 frames = NULL;
Eric Pouech527eea92000-03-08 16:44:54 +0000231
Eric Pouech800773f2001-08-06 17:51:52 +0000232 cs = ctx.SegCs;
233 ss = ctx.SegSs;
234
Eric Pouech527eea92000-03-08 16:44:54 +0000235 if (DEBUG_IsSelectorSystem(ss)) ss = 0;
236 if (DEBUG_IsSelectorSystem(cs)) cs = 0;
237
238 /* first stack frame from registers */
239 switch (DEBUG_GetSelectorType(ss))
240 {
Alexandre Julliard954a4132000-09-24 03:15:50 +0000241 case MODE_32:
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000242 code.seg = cs;
Eric Pouech800773f2001-08-06 17:51:52 +0000243 code.off = ctx.Eip;
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000244 addr.seg = ss;
Eric Pouech800773f2001-08-06 17:51:52 +0000245 addr.off = ctx.Ebp;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000246 DEBUG_ForceFrame( &addr, &code, frameno, MODE_32, noisy, NULL );
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000247 if (!(code.seg || code.off)) {
248 /* trying to execute a null pointer... yuck...
249 * if it was a call to null, the return EIP should be
250 * available at SS:ESP, so let's try to retrieve it */
251 tmp.seg = ss;
Eric Pouech800773f2001-08-06 17:51:52 +0000252 tmp.off = ctx.Esp;
Patrik Stridvallb4c74992000-08-04 21:08:01 +0000253 if (DEBUG_READ_MEM((void *)DEBUG_ToLinear(&tmp), &code.off, sizeof(code.off))) {
Alexandre Julliard954a4132000-09-24 03:15:50 +0000254 DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, ", null call assumed" );
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000255 }
256 }
Eric Pouech527eea92000-03-08 16:44:54 +0000257 is16 = FALSE;
258 break;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000259 case MODE_16:
260 case MODE_VM86:
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000261 code.seg = cs;
Eric Pouech800773f2001-08-06 17:51:52 +0000262 code.off = LOWORD(ctx.Eip);
Ove Kaaven2ce9ad82000-07-31 23:27:20 +0000263 addr.seg = ss;
Eric Pouech800773f2001-08-06 17:51:52 +0000264 addr.off = LOWORD(ctx.Ebp);
Alexandre Julliard954a4132000-09-24 03:15:50 +0000265 DEBUG_ForceFrame( &addr, &code, frameno, MODE_16, noisy, NULL );
Eric Pouech527eea92000-03-08 16:44:54 +0000266 is16 = TRUE;
267 break;
268 default:
Alexandre Julliard954a4132000-09-24 03:15:50 +0000269 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad segment '%x'\n", ss);
Eric Pouech527eea92000-03-08 16:44:54 +0000270 return;
271 }
272
273 /* cur_switch holds address of curr_stack's field in TEB in debuggee
274 * address space
275 */
Eric Pouech800773f2001-08-06 17:51:52 +0000276 cur_switch = (DWORD)thread->teb + OFFSET_OF(TEB, cur_stack);
Eric Pouech527eea92000-03-08 16:44:54 +0000277 if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000278 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Can't read TEB:cur_stack\n");
Eric Pouech527eea92000-03-08 16:44:54 +0000279 return;
280 }
281
282 if (is16) {
283 if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000284 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
285 (unsigned long)(STACK32FRAME*)next_switch );
Eric Pouech527eea92000-03-08 16:44:54 +0000286 return;
287 }
288 cur_switch = (DWORD)frame32.frame16;
289 sw_addr.seg = SELECTOROF(cur_switch);
290 sw_addr.off = OFFSETOF(cur_switch);
291 } else {
292 tmp.seg = SELECTOROF(next_switch);
293 tmp.off = OFFSETOF(next_switch);
294 p = DEBUG_ToLinear(&tmp);
295
296 if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000297 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
298 (unsigned long)(STACK16FRAME*)p );
Eric Pouech527eea92000-03-08 16:44:54 +0000299 return;
300 }
301 cur_switch = (DWORD)frame16.frame32;
302 sw_addr.seg = ss;
303 sw_addr.off = cur_switch;
304 }
305 if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
306 sw_addr.seg = (DWORD)-1;
307 sw_addr.off = (DWORD)-1;
308 }
309
310 for (ok = TRUE; ok;) {
311 if ((frames[frameno].ss == sw_addr.seg) &&
Alexandre Julliarddf12a0d2000-10-02 22:17:07 +0000312 sw_addr.off && (frames[frameno].ebp >= sw_addr.off))
313 {
Eric Pouech527eea92000-03-08 16:44:54 +0000314 /* 16<->32 switch...
315 * yes, I know this is confusing, it gave me a headache too */
316 if (is16) {
317
318 if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000319 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
320 (unsigned long)(STACK32FRAME*)next_switch );
Eric Pouech527eea92000-03-08 16:44:54 +0000321 return;
322 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000323
Eric Pouech527eea92000-03-08 16:44:54 +0000324 code.seg = 0;
325 code.off = frame32.retaddr;
326
327 cs = 0;
328 addr.seg = 0;
329 addr.off = frame32.ebp;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000330 DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, NULL );
Eric Pouech527eea92000-03-08 16:44:54 +0000331
332 next_switch = cur_switch;
333 tmp.seg = SELECTOROF(next_switch);
334 tmp.off = OFFSETOF(next_switch);
335 p = DEBUG_ToLinear(&tmp);
336
337 if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000338 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
339 (unsigned long)(STACK16FRAME*)p );
Eric Pouech527eea92000-03-08 16:44:54 +0000340 return;
341 }
342 cur_switch = (DWORD)frame16.frame32;
343 sw_addr.seg = 0;
344 sw_addr.off = cur_switch;
345
346 is16 = FALSE;
347 } else {
348 tmp.seg = SELECTOROF(next_switch);
349 tmp.off = OFFSETOF(next_switch);
350 p = DEBUG_ToLinear(&tmp);
351
352 if (!DEBUG_READ_MEM((void*)p, &frame16, sizeof(STACK16FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000353 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
354 (unsigned long)(STACK16FRAME*)p );
Eric Pouech527eea92000-03-08 16:44:54 +0000355 return;
356 }
357
Eric Pouech527eea92000-03-08 16:44:54 +0000358 code.seg = frame16.cs;
359 code.off = frame16.ip;
360
361 cs = frame16.cs;
362 addr.seg = SELECTOROF(next_switch);
363 addr.off = frame16.bp;
Alexandre Julliard954a4132000-09-24 03:15:50 +0000364 DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_16, noisy, NULL );
Eric Pouech527eea92000-03-08 16:44:54 +0000365
366 next_switch = cur_switch;
367 if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) {
Eric Pouechf1822352000-05-11 21:43:43 +0000368 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n",
369 (unsigned long)(STACK32FRAME*)next_switch );
Eric Pouech527eea92000-03-08 16:44:54 +0000370 return;
371 }
372 cur_switch = (DWORD)frame32.frame16;
373 sw_addr.seg = SELECTOROF(cur_switch);
374 sw_addr.off = OFFSETOF(cur_switch);
375
376 is16 = TRUE;
377 }
378 if (!DEBUG_READ_MEM((void*)DEBUG_ToLinear(&sw_addr), &ch, sizeof(ch))) {
379 sw_addr.seg = (DWORD)-1;
380 sw_addr.off = (DWORD)-1;
381 }
382 } else {
383 /* ordinary stack frame */
Eric Pouech800773f2001-08-06 17:51:52 +0000384 ok = is16 ? DEBUG_Frame16( thread, &addr, &cs, ++frameno, noisy)
Eric Pouech527eea92000-03-08 16:44:54 +0000385 : DEBUG_Frame32( &addr, &cs, ++frameno, noisy);
386 }
387 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000388 if (noisy) DEBUG_Printf( DBG_CHN_MESG, "\n" );
Eric Pouech800773f2001-08-06 17:51:52 +0000389
390 if (tid != DEBUG_CurrTid)
391 {
392 ResumeThread( thread->handle );
393 /* restore stack frame for current thread */
394 if (frames) DBG_free( frames );
395 frames = copy_frames;
396 nframe = copy_nframe;
397 curr_frame = copy_curr_frame;
398 }
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +0000399#endif
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000400}
401
402int
403DEBUG_SetFrame(int newframe)
404{
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000405#ifdef __i386__
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000406 int rtn = FALSE;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000407
408 curr_frame = newframe;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000409
410 if( curr_frame >= nframe )
411 {
412 curr_frame = nframe - 1;
413 }
414
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000415 if( curr_frame < 0 )
416 {
417 curr_frame = 0;
418 }
419
Eric Pouech761e3141999-02-20 16:40:47 +0000420 if( frames && frames[curr_frame].frame.list.sourcefile != NULL )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000421 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000422 DEBUG_List(&frames[curr_frame].frame.list, NULL, 0);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000423 }
424
425 rtn = TRUE;
426 return (rtn);
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000427#else /* __i386__ */
428 return FALSE;
429#endif /* __i386__ */
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000430}
431
432int
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000433DEBUG_GetCurrentFrame(struct name_hash ** name, unsigned int * eip,
434 unsigned int * ebp)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000435{
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000436#ifdef __i386__
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000437 /*
438 * If we don't have a valid backtrace, then just return.
439 */
440 if( frames == NULL )
441 {
442 return FALSE;
443 }
444
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000445 /*
446 * If we don't know what the current function is, then we also have
447 * nothing to report here.
448 */
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000449 if( frames[curr_frame].frame.sym == NULL )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000450 {
451 return FALSE;
452 }
453
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000454 *name = frames[curr_frame].frame.sym;
455 *eip = frames[curr_frame].eip;
456 *ebp = frames[curr_frame].ebp;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000457
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000458 return TRUE;
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000459#else /* __i386__ */
460 return FALSE;
461#endif /* __i386__ */
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000462}
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000463