|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: walk.c
8:
9: Abstract:
10:
11: This file provides support for stack walking.
12:
13: Author:
14:
15: Wesley Witt (wesw) 1-May-1993
16:
17: Environment:
18:
19: User Mode
20:
21: --*/
22:
23: #include <windows.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
27:
28: #include "drwatson.h"
29: #include "proto.h"
30:
31:
32: #ifdef MIPSEB
33: typedef union _MIPS_INSTRUCTION {
34: ULONG Long;
35: UCHAR Byte[4];
36:
37: struct {
38: ULONG Opcode : 6;
39: ULONG Target : 26;
40: } j_format;
41:
42: struct {
43: ULONG Opcode : 6;
44: ULONG Rs : 5;
45: ULONG Rt : 5;
46: LONG Simmediate : 16;
47: } i_format;
48:
49: struct {
50: ULONG Opcode : 6;
51: ULONG Rs : 5;
52: ULONG Rt : 5;
53: ULONG Uimmediate : 16;
54: } u_format;
55:
56: struct {
57: ULONG Opcode : 6;
58: ULONG Rs : 5;
59: ULONG Rt : 5;
60: ULONG Rd : 5;
61: ULONG Re : 5;
62: ULONG Function : 6;
63: } r_format;
64:
65: struct {
66: ULONG Opcode : 6;
67: ULONG Fill1 : 1;
68: ULONG Format : 4;
69: ULONG Rt : 5;
70: ULONG Rd : 5;
71: ULONG Re : 5;
72: ULONG Function : 6;
73: } f_format;
74:
75: struct {
76: ULONG Opcode : 6;
77: ULONG Fill1 : 1;
78: ULONG Format : 4;
79: ULONG Ft : 5;
80: ULONG Fs : 5;
81: ULONG Fd : 5;
82: ULONG Function : 6;
83: } c_format;
84:
85: } MIPS_INSTRUCTION, *PMIPS_INSTRUCTION;
86:
87: #else
88:
89: typedef union _MIPS_INSTRUCTION {
90: ULONG Long;
91: UCHAR Byte[4];
92:
93: struct {
94: ULONG Target : 26;
95: ULONG Opcode : 6;
96: } j_format;
97:
98: struct {
99: LONG Simmediate : 16;
100: ULONG Rt : 5;
101: ULONG Rs : 5;
102: ULONG Opcode : 6;
103: } i_format;
104:
105: struct {
106: ULONG Uimmediate : 16;
107: ULONG Rt : 5;
108: ULONG Rs : 5;
109: ULONG Opcode : 6;
110: } u_format;
111:
112: struct {
113: ULONG Function : 6;
114: ULONG Re : 5;
115: ULONG Rd : 5;
116: ULONG Rt : 5;
117: ULONG Rs : 5;
118: ULONG Opcode : 6;
119: } r_format;
120:
121: struct {
122: ULONG Function : 6;
123: ULONG Re : 5;
124: ULONG Rd : 5;
125: ULONG Rt : 5;
126: ULONG Format : 4;
127: ULONG Fill1 : 1;
128: ULONG Opcode : 6;
129: } f_format;
130:
131: struct {
132: ULONG Function : 6;
133: ULONG Fd : 5;
134: ULONG Fs : 5;
135: ULONG Ft : 5;
136: ULONG Format : 4;
137: ULONG Fill1 : 1;
138: ULONG Opcode : 6;
139: } c_format;
140:
141: } MIPS_INSTRUCTION, *PMIPS_INSTRUCTION;
142:
143: #endif // MIPSEB
144:
145: /* Define MIPS nonvolatile register test macros. */
146: #define IS_FLOATING_SAVED(Register) ((SAVED_FLOATING_MASK >> Register) & 1L) /*
147: */
148: #define IS_INTEGER_SAVED(Register) ((SAVED_INTEGER_MASK >> Register) & 1L)
149:
150: //
151: /* Define MIPS instruction opcode values. */
152: //
153: #define ORI_OP 0xd /* or unsigned immediate integer */
154: #define ADDIU_OP 0x9 /* add immediate unsigned integer register */
155: #define ADDU_OP 0x21 /* add unsigned integer register */
156: #define JUMP_RA 0x3e00008 /* jump indirect return address register */
157: #define LUI_OP 0xf /* load upper immediate integer register */
158: #define SD_OP 0x2f /* store double integer register */
159: #define SW_OP 0x2b /* store word integer register */
160: #define SDC1_OP 0x3d /* store double floating register */
161: #define SWC1_OP 0x39 /* store word floating register */
162: #define SPEC_OP 0x0 /* special opcode - use function field */
163: #define SUBU_OP 0x23 /* subtract unsigned integer register */
164:
165: /* Define stack register and zero register numbers. */
166:
167: #define RA 0x1f /* integer register 31 */
168: #define SP 0x1d /* integer register 29 */
169: #define ZERO 0x0 /* integer register 0 */
170:
171: /* Define saved register masks. */
172:
173: #define SAVED_FLOATING_MASK 0xfff00000 /* saved floating registers */
174: #define SAVED_INTEGER_MASK 0xf3ffff02 /* saved integer registers */
175:
176:
177:
178: DWORD
179: VirtualUnwind (
180: PDEBUGPACKET dp,
181: DWORD ControlPc,
182: PRUNTIME_FUNCTION FunctionEntry,
183: PCONTEXT ContextRecord
184: )
185:
186: /*++
187:
188: Routine Description:
189:
190: This function virtually unwinds the specfified function by executing its
191: prologue code backwards.
192:
193: If the function is a leaf function, then the address where control left
194: the previous frame is obtained from the context record. If the function
195: is a nested function, but not an exception or interrupt frame, then the
196: prologue code is executed backwards and the address where control left
197: the previous frame is obtained from the updated context record.
198:
199: Otherwise, an exception or interrupt entry to the system is being unwound
200: and a specially coded prologue restores the return address twice. Once
201: from the fault instruction address and once from the saved return address
202: register. The first restore is returned as the function value and the
203: second restore is place in the updated context record.
204:
205: If a context pointers record is specified, then the address where each
206: nonvolatile registers is restored from is recorded in the appropriate
207: element of the context pointers record.
208:
209: Arguments:
210:
211: ControlPc - Supplies the address where control left the specified
212: function.
213:
214: FunctionEntry - Supplies the address of the function table entry for the
215: specified function.
216:
217: ContextRecord - Supplies the address of a context record.
218:
219: ContextPointers - Supplies an optional pointer to a context pointers
220: record.
221:
222: Return Value:
223:
224: The address where control left the previous frame is returned as the
225: function value.
226:
227: --*/
228:
229: {
230: DWORD Address;
231: DWORD DecrementOffset;
232: DWORD DecrementRegister;
233: LPDWORD FloatingRegister;
234: MIPS_INSTRUCTION Instruction;
235: LPDWORD IntegerRegister;
236: DWORD NextPc;
237: LONG Offset;
238: DWORD Opcode;
239: DWORD Rd;
240: BOOL Restored;
241: DWORD Rs;
242: DWORD Rt;
243: DWORD instrProlog;
244: DWORD addrPC;
245: DWORD addrT;
246:
247:
248: addrPC = ControlPc;
249:
250: if (!ReadProcessMemory( dp->hProcess,
251: (LPVOID)ControlPc,
252: (LPVOID)&instrProlog,
253: 4,
254: NULL
255: )) {
256: return 0;
257: }
258:
259: if (instrProlog == JUMP_RA) {
260: ControlPc += 4;
261: addrPC += 4;
262: if (!ReadProcessMemory( dp->hProcess,
263: (LPVOID)addrPC,
264: (LPVOID)&Instruction.Long,
265: 4,
266: NULL
267: )) {
268: return 0;
269: }
270: addrPC -= 4;
271: ControlPc -= 4;
272: Opcode = Instruction.i_format.Opcode;
273: if (((Opcode != ADDIU_OP) &&
274: ((Opcode != SPEC_OP) ||
275: (Instruction.r_format.Function != ADDU_OP))) ||
276: ((Opcode == ADDIU_OP) &&
277: (Instruction.i_format.Rt != SP)) ||
278: ((Opcode == SPEC_OP) &&
279: (Instruction.r_format.Function == ADDU_OP) &&
280: (Instruction.r_format.Rd != SP))) {
281: return ContextRecord->IntRa;
282: }
283: }
284:
285: if (ControlPc > FunctionEntry->PrologEndAddress) {
286: addrPC = FunctionEntry->PrologEndAddress;
287: ControlPc = FunctionEntry->PrologEndAddress;
288: }
289:
290: FloatingRegister = &ContextRecord->FltF0;
291: IntegerRegister = &ContextRecord->IntZero;
292:
293: DecrementRegister = 0;
294: NextPc = ContextRecord->IntRa;
295: Restored = FALSE;
296: while (ControlPc > FunctionEntry->BeginAddress) {
297: ControlPc -= 4;
298: addrPC -= 4;
299: if (!ReadProcessMemory( dp->hProcess,
300: (LPVOID)addrPC,
301: (LPVOID)&Instruction.Long,
302: 4,
303: NULL
304: )) {
305: return 0;
306: }
307: Opcode = Instruction.i_format.Opcode;
308: Offset = Instruction.i_format.Simmediate;
309: Rd = Instruction.r_format.Rd;
310: Rs = Instruction.i_format.Rs;
311: Rt = Instruction.i_format.Rt;
312: Address = Offset + IntegerRegister[Rs];
313: addrT = Offset + IntegerRegister[Rs];
314: if (Opcode == SW_OP) {
315:
316: if ((Rs == SP) && (IS_INTEGER_SAVED(Rt))) {
317: if (!ReadProcessMemory( dp->hProcess,
318: (LPVOID)addrT,
319: (LPVOID)&IntegerRegister[Rt],
320: 4,
321: NULL
322: )) {
323: return 0;
324: }
325: if ((Rt == RA) && (Restored == FALSE)) {
326: NextPc = ContextRecord->IntRa;
327: Restored = TRUE;
328: }
329:
330: }
331:
332: } else if (Opcode == SWC1_OP) {
333:
334: if ((Rs == SP) && (IS_FLOATING_SAVED(Rt))) {
335: if (!ReadProcessMemory( dp->hProcess,
336: (LPVOID)addrT,
337: (LPVOID)&FloatingRegister[Rt],
338: 4,
339: NULL
340: )) {
341: return 0;
342: }
343: }
344:
345: } else if (Opcode == SDC1_OP) {
346:
347: if ((Rs == SP) && (IS_FLOATING_SAVED(Rt))) {
348: if (!ReadProcessMemory( dp->hProcess,
349: (LPVOID)addrT,
350: (LPVOID)&(FloatingRegister[Rt]),
351: 4,
352: NULL
353: )) {
354: return 0;
355: }
356: Address += 4;
357: addrT += 4;
358: if (!ReadProcessMemory( dp->hProcess,
359: (LPVOID)addrT,
360: (LPVOID)&(FloatingRegister[Rt+1]),
361: 4,
362: NULL
363: )) {
364: return 0;
365: }
366: Address -= 4;
367: addrT -= 4;
368: }
369:
370: } else if (Opcode == ADDIU_OP) {
371:
372: if ((Rs == SP) && (Rt == SP)) {
373: IntegerRegister[SP] -= Offset;
374:
375: } else if ((Rt == DecrementRegister) && (Rs == ZERO)) {
376: IntegerRegister[SP] += Offset;
377: }
378:
379: } else if (Opcode == ORI_OP) {
380:
381: if ((Rs == DecrementRegister) && (Rt == DecrementRegister)) {
382: DecrementOffset = (Offset & 0xffff);
383:
384: } else if ((Rt == DecrementRegister) && (Rs == ZERO)) {
385: IntegerRegister[SP] += (Offset & 0xffff);
386: }
387:
388: } else if (Opcode == SPEC_OP) {
389:
390: Opcode = Instruction.r_format.Function;
391: if (Opcode == ADDU_OP) {
392:
393: if (IS_INTEGER_SAVED(Rd)) {
394: if ((IS_INTEGER_SAVED(Rs)) && (Rt == ZERO)) {
395: IntegerRegister[Rs] = IntegerRegister[Rd];
396: if ((Rs == RA) && (Restored == FALSE)) {
397: NextPc = ContextRecord->IntRa;
398: Restored = TRUE;
399: }
400:
401: } else if ((Rs == ZERO) && (IS_INTEGER_SAVED(Rt))) {
402: IntegerRegister[Rt] = IntegerRegister[Rd];
403: if ((Rt == RA) && (Restored == FALSE)) {
404: NextPc = ContextRecord->IntRa;
405: Restored = TRUE;
406: }
407: }
408: }
409:
410: } else if (Opcode == SUBU_OP) {
411:
412: if ((Rd == SP) && (Rs == SP)) {
413: DecrementRegister = Rt;
414: }
415: }
416:
417: } else if (Opcode == LUI_OP) {
418:
419: if (Rt == DecrementRegister) {
420: IntegerRegister[SP] += (DecrementOffset + (Offset << 16));
421: DecrementRegister = 0;
422: }
423: }
424: }
425: return NextPc;
426: }
427:
428: BOOL
429: StackWalkInit( PSTACKWALK pstk, PDEBUGPACKET dp )
430: {
431: pstk->pc = dp->tctx->context.Fir;
432: pstk->frame = dp->tctx->context.IntSp;
433: pstk->params[0] = dp->tctx->context.IntA0;
434: pstk->params[1] = dp->tctx->context.IntA1;
435: pstk->params[2] = dp->tctx->context.IntA2;
436: pstk->params[3] = dp->tctx->context.IntA3;
437:
438: return TRUE;
439: }
440:
441: BOOL
442: StackWalkNext( PSTACKWALK pstk, PDEBUGPACKET dp )
443: {
444: DWORD fir;
445: LONG begin=0, end, test;
446: CONTEXT context;
447: DWORD dwRa;
448: PMODULEINFO mi;
449:
450:
451: fir = pstk->pc;
452:
453: mi = GetModuleForPC( dp, fir );
454: if (mi == NULL) {
455: return FALSE;
456: }
457:
458: /*
459: * Do a binary search to determine which function contains this FIR
460: */
461:
462: for(end=mi->dwEntries,test=(begin+end)/2; begin<=end; test=(begin+end)/2) {
463: if (fir<mi->pExceptionData[test].BeginAddress) {
464: end = test-1;
465: }
466: else
467: if (fir>=mi->pExceptionData[test].EndAddress) {
468: begin = test+1;
469: }
470: else {
471: break;
472: }
473: }
474:
475: /*
476: * No function was found to include this FIR. Therefore this
477: * is a leaf function
478: */
479:
480: if (begin>end) {
481: dp->tctx->stackBase = dp->tctx->context.IntSp;
482: dp->tctx->stackRA = dp->tctx->context.IntRa;
483:
484: pstk->frame = dp->tctx->context.IntSp;
485: pstk->pc = dp->tctx->context.IntRa;
486:
487: if (!ReadProcessMemory( dp->hProcess,
488: (LPVOID)pstk->frame,
489: (LPVOID)pstk->params,
490: 12,
491: NULL
492: )) {
493: pstk->params[0] =
494: pstk->params[1] =
495: pstk->params[2] = 0;
496: }
497:
498: return TRUE;
499: }
500:
501: // Virtually unwind the stack to determine base and caller
502:
503: context = dp->tctx->context;
504: context.IntSp = pstk->frame;
505:
506: dwRa = VirtualUnwind(dp, fir, &mi->pExceptionData[test], &context);
507:
508: if (((dp->tctx->stackBase == context.IntSp) && (dwRa == dp->tctx->stackRA)) ||
509: (dwRa == 1)) {
510: return FALSE;
511: }
512:
513: dp->tctx->stackBase = context.IntSp;
514: dp->tctx->stackRA = dwRa;
515:
516: pstk->frame = context.IntSp;
517: pstk->pc = dwRa;
518:
519: if (!ReadProcessMemory( dp->hProcess,
520: (LPVOID)pstk->frame,
521: (LPVOID)pstk->params,
522: 12,
523: NULL
524: )) {
525: pstk->params[0] =
526: pstk->params[1] =
527: pstk->params[2] = 0;
528: }
529:
530: return TRUE;
531: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.