Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Debugger stack handling |
| 3 | * |
| 4 | * Copyright 1995 Alexandre Julliard |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 5 | * Copyright 1996 Eric Youngdale |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 6 | * Copyright 1999 Ove Kåven |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 7 | */ |
| 8 | |
Marcus Meissner | b0d52b0 | 1999-02-28 19:59:00 +0000 | [diff] [blame] | 9 | #include "config.h" |
Patrik Stridvall | 6cc47d4 | 2000-03-08 18:26:56 +0000 | [diff] [blame] | 10 | |
Alexandre Julliard | 84c70f5 | 1997-05-09 08:40:27 +0000 | [diff] [blame] | 11 | #include <stdlib.h> |
Patrik Stridvall | 6cc47d4 | 2000-03-08 18:26:56 +0000 | [diff] [blame] | 12 | |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 13 | #include "debugger.h" |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 14 | #include "stackframe.h" |
Patrik Stridvall | 6cc47d4 | 2000-03-08 18:26:56 +0000 | [diff] [blame] | 15 | #include "winbase.h" |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 16 | |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 17 | #ifdef __i386__ |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 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 | { |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 24 | unsigned int cs; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 25 | unsigned int eip; |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 26 | unsigned int ss; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 27 | unsigned int ebp; |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 28 | struct symbol_info frame; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 29 | }; |
| 30 | |
| 31 | static int nframe; |
| 32 | static struct bt_info * frames = NULL; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 33 | |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 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; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 47 | #endif |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 48 | |
| 49 | |
| 50 | /*********************************************************************** |
| 51 | * DEBUG_InfoStack |
| 52 | * |
| 53 | * Dump the top of the stack |
| 54 | */ |
| 55 | void DEBUG_InfoStack(void) |
| 56 | { |
Ulrich Weigand | b3ec4b9 | 1999-11-13 20:58:45 +0000 | [diff] [blame] | 57 | #ifdef __i386__ |
Eric Pouech | d33bcb6 | 2000-03-15 19:57:20 +0000 | [diff] [blame] | 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; |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 64 | |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 65 | DEBUG_Printf(DBG_CHN_MESG,"Stack dump:\n"); |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 66 | switch (DEBUG_GetSelectorType(value.addr.seg)) |
| 67 | { |
| 68 | case MODE_32: /* 32-bit mode */ |
Eric Pouech | d33bcb6 | 2000-03-15 19:57:20 +0000 | [diff] [blame] | 69 | DEBUG_ExamineMemory( &value, 24, 'x' ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 70 | break; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 71 | case MODE_16: /* 16-bit mode */ |
| 72 | case MODE_VM86: |
Eric Pouech | d33bcb6 | 2000-03-15 19:57:20 +0000 | [diff] [blame] | 73 | value.addr.off &= 0xffff; |
| 74 | DEBUG_ExamineMemory( &value, 24, 'w' ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 75 | break; |
| 76 | default: |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 77 | DEBUG_Printf(DBG_CHN_MESG, "Bad segment (%ld)\n", value.addr.seg); |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 78 | } |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 79 | DEBUG_Printf(DBG_CHN_MESG,"\n"); |
Ulrich Weigand | b3ec4b9 | 1999-11-13 20:58:45 +0000 | [diff] [blame] | 80 | #endif |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 81 | } |
| 82 | |
Ulrich Weigand | b3ec4b9 | 1999-11-13 20:58:45 +0000 | [diff] [blame] | 83 | #ifdef __i386__ |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 84 | static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, enum dbg_mode mode, |
| 85 | int noisy, const char *caveat) |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 86 | { |
| 87 | int theframe = nframe++; |
| 88 | frames = (struct bt_info *)DBG_realloc(frames, |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 89 | nframe*sizeof(struct bt_info)); |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 90 | if (noisy) |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 91 | DEBUG_Printf(DBG_CHN_MESG,"%s%d ", (theframe == curr_frame ? "=>" : " "), |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 92 | frameno); |
| 93 | frames[theframe].cs = code->seg; |
| 94 | frames[theframe].eip = code->off; |
| 95 | if (noisy) |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 96 | frames[theframe].frame = DEBUG_PrintAddressAndArgs( code, mode, stack->off, TRUE ); |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 97 | 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 Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 104 | DEBUG_Printf( DBG_CHN_MESG, (mode != MODE_32) ? " (bp=%04lx%s)\n" : " (ebp=%08lx%s)\n", |
| 105 | stack->off, caveat?caveat:"" ); |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 106 | } |
| 107 | } |
| 108 | |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 109 | static BOOL DEBUG_Frame16(DBG_THREAD* thread, DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy) |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 110 | { |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 111 | unsigned int possible_cs = 0; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 112 | FRAME16 frame; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 113 | void* p = (void*)DEBUG_ToLinear(addr); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 114 | DBG_ADDR code; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 115 | |
| 116 | if (!p) return FALSE; |
| 117 | |
| 118 | if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) { |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 119 | if (noisy) DEBUG_InvalAddr(addr); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 120 | return FALSE; |
Eric Pouech | 99b1513 | 1999-08-21 12:56:15 +0000 | [diff] [blame] | 121 | } |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 122 | if (!frame.bp) return FALSE; |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 123 | |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 124 | if (frame.bp & 1) *cs = frame.cs; |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 125 | else { |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 126 | /* 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 Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 131 | if (GetThreadSelectorEntry( thread->handle, frame.cs, &le) && |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 132 | (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 Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 138 | } |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 139 | code.seg = *cs; |
| 140 | code.off = frame.ip; |
| 141 | addr->off = frame.bp & ~1; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 142 | DEBUG_ForceFrame(addr, &code, frameno, MODE_16, noisy, |
| 143 | possible_cs ? ", far call assumed" : NULL ); |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 144 | return TRUE; |
| 145 | } |
| 146 | |
| 147 | static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy) |
| 148 | { |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 149 | FRAME32 frame; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 150 | void* p = (void*)DEBUG_ToLinear(addr); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 151 | DBG_ADDR code; |
| 152 | DWORD old_bp = addr->off; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 153 | |
| 154 | if (!p) return FALSE; |
| 155 | |
| 156 | if (!DEBUG_READ_MEM(p, &frame, sizeof(frame))) { |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 157 | if (noisy) DEBUG_InvalAddr(addr); |
Eric Pouech | 99b1513 | 1999-08-21 12:56:15 +0000 | [diff] [blame] | 158 | return FALSE; |
| 159 | } |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 160 | if (!frame.ip) return FALSE; |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 161 | |
| 162 | code.seg = *cs; |
| 163 | code.off = frame.ip; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 164 | addr->off = frame.bp; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 165 | DEBUG_ForceFrame(addr, &code, frameno, MODE_32, noisy, NULL); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 166 | if (addr->off == old_bp) return FALSE; |
Ove Kaaven | b4a5db5 | 1999-05-08 12:38:20 +0000 | [diff] [blame] | 167 | return TRUE; |
| 168 | } |
Ulrich Weigand | b3ec4b9 | 1999-11-13 20:58:45 +0000 | [diff] [blame] | 169 | #endif |
| 170 | |
| 171 | |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 172 | /*********************************************************************** |
| 173 | * DEBUG_BackTrace |
| 174 | * |
| 175 | * Display a stack back-trace. |
| 176 | */ |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 177 | void DEBUG_BackTrace(DWORD tid, BOOL noisy) |
Alexandre Julliard | ded3038 | 1995-07-06 17:18:27 +0000 | [diff] [blame] | 178 | { |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 179 | #ifdef __i386 |
| 180 | DBG_ADDR addr, sw_addr, code, tmp; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 181 | unsigned int ss, cs; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 182 | int frameno = 0, is16, ok; |
| 183 | DWORD next_switch, cur_switch, p; |
| 184 | STACK16FRAME frame16; |
| 185 | STACK32FRAME frame32; |
| 186 | char ch; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 187 | CONTEXT ctx; |
| 188 | DBG_THREAD* thread; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 189 | |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 190 | int copy_nframe = 0; |
| 191 | int copy_curr_frame = 0; |
| 192 | struct bt_info* copy_frames = NULL; |
| 193 | |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 194 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Backtrace:\n" ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 195 | |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 196 | 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 Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 229 | nframe = 0; |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 230 | frames = NULL; |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 231 | |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 232 | cs = ctx.SegCs; |
| 233 | ss = ctx.SegSs; |
| 234 | |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 235 | 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 Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 241 | case MODE_32: |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 242 | code.seg = cs; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 243 | code.off = ctx.Eip; |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 244 | addr.seg = ss; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 245 | addr.off = ctx.Ebp; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 246 | DEBUG_ForceFrame( &addr, &code, frameno, MODE_32, noisy, NULL ); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 247 | 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 Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 252 | tmp.off = ctx.Esp; |
Patrik Stridvall | b4c7499 | 2000-08-04 21:08:01 +0000 | [diff] [blame] | 253 | if (DEBUG_READ_MEM((void *)DEBUG_ToLinear(&tmp), &code.off, sizeof(code.off))) { |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 254 | DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, ", null call assumed" ); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 255 | } |
| 256 | } |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 257 | is16 = FALSE; |
| 258 | break; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 259 | case MODE_16: |
| 260 | case MODE_VM86: |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 261 | code.seg = cs; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 262 | code.off = LOWORD(ctx.Eip); |
Ove Kaaven | 2ce9ad8 | 2000-07-31 23:27:20 +0000 | [diff] [blame] | 263 | addr.seg = ss; |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 264 | addr.off = LOWORD(ctx.Ebp); |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 265 | DEBUG_ForceFrame( &addr, &code, frameno, MODE_16, noisy, NULL ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 266 | is16 = TRUE; |
| 267 | break; |
| 268 | default: |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 269 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad segment '%x'\n", ss); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 270 | return; |
| 271 | } |
| 272 | |
| 273 | /* cur_switch holds address of curr_stack's field in TEB in debuggee |
| 274 | * address space |
| 275 | */ |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 276 | cur_switch = (DWORD)thread->teb + OFFSET_OF(TEB, cur_stack); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 277 | if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) { |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 278 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Can't read TEB:cur_stack\n"); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 279 | return; |
| 280 | } |
| 281 | |
| 282 | if (is16) { |
| 283 | if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) { |
Eric Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 284 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 285 | (unsigned long)(STACK32FRAME*)next_switch ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 286 | 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 Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 297 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 298 | (unsigned long)(STACK16FRAME*)p ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 299 | 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 Julliard | df12a0d | 2000-10-02 22:17:07 +0000 | [diff] [blame] | 312 | sw_addr.off && (frames[frameno].ebp >= sw_addr.off)) |
| 313 | { |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 314 | /* 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 Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 319 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 320 | (unsigned long)(STACK32FRAME*)next_switch ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 321 | return; |
| 322 | } |
Eric Pouech | d33bcb6 | 2000-03-15 19:57:20 +0000 | [diff] [blame] | 323 | |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 324 | code.seg = 0; |
| 325 | code.off = frame32.retaddr; |
| 326 | |
| 327 | cs = 0; |
| 328 | addr.seg = 0; |
| 329 | addr.off = frame32.ebp; |
Alexandre Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 330 | DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, NULL ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 331 | |
| 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 Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 338 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 339 | (unsigned long)(STACK16FRAME*)p ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 340 | 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 Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 353 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 354 | (unsigned long)(STACK16FRAME*)p ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 355 | return; |
| 356 | } |
| 357 | |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 358 | 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 Julliard | 954a413 | 2000-09-24 03:15:50 +0000 | [diff] [blame] | 364 | DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_16, noisy, NULL ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 365 | |
| 366 | next_switch = cur_switch; |
| 367 | if (!DEBUG_READ_MEM((void*)next_switch, &frame32, sizeof(STACK32FRAME))) { |
Eric Pouech | f182235 | 2000-05-11 21:43:43 +0000 | [diff] [blame] | 368 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Bad stack frame 0x%08lx\n", |
| 369 | (unsigned long)(STACK32FRAME*)next_switch ); |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 370 | 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 Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 384 | ok = is16 ? DEBUG_Frame16( thread, &addr, &cs, ++frameno, noisy) |
Eric Pouech | 527eea9 | 2000-03-08 16:44:54 +0000 | [diff] [blame] | 385 | : DEBUG_Frame32( &addr, &cs, ++frameno, noisy); |
| 386 | } |
| 387 | } |
Eric Pouech | e5efa0c | 2000-04-13 19:31:58 +0000 | [diff] [blame] | 388 | if (noisy) DEBUG_Printf( DBG_CHN_MESG, "\n" ); |
Eric Pouech | 800773f | 2001-08-06 17:51:52 +0000 | [diff] [blame] | 389 | |
| 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 Weigand | b3ec4b9 | 1999-11-13 20:58:45 +0000 | [diff] [blame] | 399 | #endif |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 400 | } |
| 401 | |
| 402 | int |
| 403 | DEBUG_SetFrame(int newframe) |
| 404 | { |
Ulrich Weigand | 1cbf27a | 2000-06-04 01:33:21 +0000 | [diff] [blame] | 405 | #ifdef __i386__ |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 406 | int rtn = FALSE; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 407 | |
| 408 | curr_frame = newframe; |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 409 | |
| 410 | if( curr_frame >= nframe ) |
| 411 | { |
| 412 | curr_frame = nframe - 1; |
| 413 | } |
| 414 | |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 415 | if( curr_frame < 0 ) |
| 416 | { |
| 417 | curr_frame = 0; |
| 418 | } |
| 419 | |
Eric Pouech | 761e314 | 1999-02-20 16:40:47 +0000 | [diff] [blame] | 420 | if( frames && frames[curr_frame].frame.list.sourcefile != NULL ) |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 421 | { |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 422 | DEBUG_List(&frames[curr_frame].frame.list, NULL, 0); |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 423 | } |
| 424 | |
| 425 | rtn = TRUE; |
| 426 | return (rtn); |
Ulrich Weigand | 1cbf27a | 2000-06-04 01:33:21 +0000 | [diff] [blame] | 427 | #else /* __i386__ */ |
| 428 | return FALSE; |
| 429 | #endif /* __i386__ */ |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 430 | } |
| 431 | |
| 432 | int |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 433 | DEBUG_GetCurrentFrame(struct name_hash ** name, unsigned int * eip, |
| 434 | unsigned int * ebp) |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 435 | { |
Ulrich Weigand | 1cbf27a | 2000-06-04 01:33:21 +0000 | [diff] [blame] | 436 | #ifdef __i386__ |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 437 | /* |
| 438 | * If we don't have a valid backtrace, then just return. |
| 439 | */ |
| 440 | if( frames == NULL ) |
| 441 | { |
| 442 | return FALSE; |
| 443 | } |
| 444 | |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 445 | /* |
| 446 | * If we don't know what the current function is, then we also have |
| 447 | * nothing to report here. |
| 448 | */ |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 449 | if( frames[curr_frame].frame.sym == NULL ) |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 450 | { |
| 451 | return FALSE; |
| 452 | } |
| 453 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 454 | *name = frames[curr_frame].frame.sym; |
| 455 | *eip = frames[curr_frame].eip; |
| 456 | *ebp = frames[curr_frame].ebp; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 457 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 458 | return TRUE; |
Ulrich Weigand | 1cbf27a | 2000-06-04 01:33:21 +0000 | [diff] [blame] | 459 | #else /* __i386__ */ |
| 460 | return FALSE; |
| 461 | #endif /* __i386__ */ |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 462 | } |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 463 | |