|
|
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.