mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
855 lines
26 KiB
855 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
walkmip.c
|
|
|
|
Abstract:
|
|
|
|
This file implements the MIPS stack walking api.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 1-Oct-1993
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#define TARGET_MIPS
|
|
#define _IMAGEHLP_SOURCE_
|
|
#define _CROSS_PLATFORM_
|
|
#include "walk.h"
|
|
#include "private.h"
|
|
#include <stdlib.h>
|
|
|
|
BOOL
|
|
WalkMipsInit(
|
|
HANDLE hProcess,
|
|
LPSTACKFRAME StackFrame,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine
|
|
);
|
|
|
|
BOOL
|
|
WalkMipsNext(
|
|
HANDLE hProcess,
|
|
LPSTACKFRAME StackFrame,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
GetStackFrame(
|
|
HANDLE hProcess,
|
|
LPDWORD ReturnAddress,
|
|
LPDWORD FramePointer,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccess,
|
|
PKDHELP KdHelp
|
|
);
|
|
|
|
#define ZERO 0x0 /* integer register 0 */
|
|
#define SP 0x1d /* integer register 29 */
|
|
#define RA 0x1f /* integer register 31 */
|
|
#define CALLBACK_STACK(f) (f->KdHelp.ThCallbackStack)
|
|
#define CALLBACK_NEXT(f) (f->KdHelp.NextCallback)
|
|
#define CALLBACK_FUNC(f) (f->KdHelp.KiCallUserMode)
|
|
#define CALLBACK_THREAD(f) (f->KdHelp.Thread)
|
|
|
|
|
|
BOOL
|
|
WalkMips(
|
|
HANDLE hProcess,
|
|
LPSTACKFRAME StackFrame,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccess
|
|
)
|
|
{
|
|
BOOL rval;
|
|
|
|
if (StackFrame->Virtual) {
|
|
|
|
rval = WalkMipsNext( hProcess,
|
|
StackFrame,
|
|
Context,
|
|
ReadMemory,
|
|
FunctionTableAccess
|
|
);
|
|
|
|
} else {
|
|
|
|
rval = WalkMipsInit( hProcess,
|
|
StackFrame,
|
|
Context,
|
|
ReadMemory,
|
|
FunctionTableAccess
|
|
);
|
|
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
|
|
static DWORD
|
|
VirtualUnwind (
|
|
HANDLE hProcess,
|
|
DWORD ControlPc,
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function virtually unwinds the specfified function by executing its
|
|
prologue code backwards.
|
|
|
|
If the function is a leaf function, then the address where control left
|
|
the previous frame is obtained from the context record. If the function
|
|
is a nested function, but not an exception or interrupt frame, then the
|
|
prologue code is executed backwards and the address where control left
|
|
the previous frame is obtained from the updated context record.
|
|
|
|
Otherwise, an exception or interrupt entry to the system is being unwound
|
|
and a specially coded prologue restores the return address twice. Once
|
|
from the fault instruction address and once from the saved return address
|
|
register. The first restore is returned as the function value and the
|
|
second restore is place in the updated context record.
|
|
|
|
If a context pointers record is specified, then the address where each
|
|
nonvolatile registers is restored from is recorded in the appropriate
|
|
element of the context pointers record.
|
|
|
|
Arguments:
|
|
|
|
ControlPc - Supplies the address where control left the specified
|
|
function.
|
|
|
|
FunctionEntry - Supplies the address of the function table entry for the
|
|
specified function.
|
|
|
|
Context - Supplies the address of a context record.
|
|
|
|
|
|
Return Value:
|
|
|
|
The address where control left the previous frame is returned as the
|
|
function value.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Address;
|
|
DWORD DecrementOffset;
|
|
DWORD DecrementRegister;
|
|
DWORD Function;
|
|
MIPS_INSTRUCTION Instruction;
|
|
DWORD NextPc;
|
|
LONG Offset;
|
|
DWORD Opcode;
|
|
DWORD Rd;
|
|
BOOL Restored;
|
|
DWORD Rs;
|
|
DWORD Rt;
|
|
DWORD instrProlog;
|
|
DWORD cb;
|
|
PVOID Prolog;
|
|
DWORD dwData;
|
|
ULONGLONG dwlData;
|
|
PULONGLONG XIntegerRegister;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
BOOL Use32 = (Context->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER;
|
|
LPDWORD IntegerRegister;
|
|
LPDWORD FloatingRegister;
|
|
#else // SUPPORT_MIXED_INTEGER
|
|
PULONGLONG XFloatingRegister;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
|
|
//
|
|
// perf hack: fill cache with prolog
|
|
//
|
|
if (FunctionEntry) {
|
|
cb = FunctionEntry->PrologEndAddress - FunctionEntry->BeginAddress;
|
|
Prolog = (PVOID) MemAlloc( cb );
|
|
if (!ReadMemory( hProcess, (LPVOID)FunctionEntry->BeginAddress,
|
|
Prolog, cb, &cb )) {
|
|
return 0;
|
|
}
|
|
|
|
MemFree(Prolog);
|
|
}
|
|
|
|
if (!ReadMemory( hProcess, (LPVOID)ControlPc, &instrProlog, 4L, &cb )) {
|
|
return 0;
|
|
}
|
|
|
|
#ifndef SUPPORT_MIXED_INTEGER
|
|
XFloatingRegister = &Context->XFltF0;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
FloatingRegister = &Context->FltF0;
|
|
if (Use32) {
|
|
IntegerRegister = &Context->IntZero;
|
|
XIntegerRegister = NULL;
|
|
} else
|
|
{
|
|
IntegerRegister = NULL;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister = &Context->XIntZero;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
if (instrProlog == JUMP_RA) {
|
|
if (!ReadMemory(hProcess, (LPVOID)(ControlPc + 4), &Instruction.Long, 4L, &cb)) {
|
|
return 0;
|
|
}
|
|
|
|
Opcode = Instruction.i_format.Opcode;
|
|
Offset = Instruction.i_format.Simmediate;
|
|
Rd = Instruction.r_format.Rd;
|
|
Rs = Instruction.i_format.Rs;
|
|
Rt = Instruction.i_format.Rt;
|
|
Function = Instruction.r_format.Function;
|
|
if ((Opcode == ADDIU_OP) && (Rt == SP) && (Rs == SP)) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[SP] += Offset;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[SP] += Offset;
|
|
|
|
} else if ((Opcode == SPEC_OP) && (Function == ADDU_OP) &&
|
|
(Rd == SP) && (Rs == SP)) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[SP] += IntegerRegister[Rt];
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[SP] += XIntegerRegister[Rt];
|
|
}
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
return Context->IntRa;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
return (DWORD)Context->XIntRa;
|
|
}
|
|
|
|
if ((ControlPc < FunctionEntry->BeginAddress) ||
|
|
(ControlPc >= FunctionEntry->PrologEndAddress)) {
|
|
ControlPc = FunctionEntry->PrologEndAddress;
|
|
}
|
|
|
|
DecrementRegister = 0;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
NextPc = Context->IntRa;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
NextPc = (DWORD)Context->XIntRa;
|
|
Restored = FALSE;
|
|
while (ControlPc > FunctionEntry->BeginAddress) {
|
|
|
|
ControlPc -= 4;
|
|
if (!ReadMemory(hProcess, (LPVOID)ControlPc, &Instruction.Long, 4L, &cb)) {
|
|
return 0;
|
|
}
|
|
|
|
Opcode = Instruction.i_format.Opcode;
|
|
Offset = Instruction.i_format.Simmediate;
|
|
Rd = Instruction.r_format.Rd;
|
|
Rs = Instruction.i_format.Rs;
|
|
Rt = Instruction.i_format.Rt;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
Address = (DWORD)(Offset + IntegerRegister[Rs]);
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
Address = (DWORD)(Offset + XIntegerRegister[Rs]);
|
|
if (Opcode == SW_OP) {
|
|
|
|
if (Rs == SP) {
|
|
if (!ReadMemory(hProcess,
|
|
(LPVOID)Address,
|
|
&dwData,
|
|
4L,
|
|
&cb)) {
|
|
return 0;
|
|
}
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[Rt] = dwData;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[Rt] = (LONG)dwData;
|
|
|
|
if ((Rt == RA) && (Restored == FALSE)) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
NextPc = Context->IntRa;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
NextPc = (DWORD)Context->XIntRa;
|
|
Restored = TRUE;
|
|
}
|
|
}
|
|
|
|
} else if (Opcode == SD_OP) {
|
|
|
|
if (Rs == SP) {
|
|
if (!ReadMemory(hProcess,
|
|
(LPVOID)Address,
|
|
&dwlData,
|
|
8L,
|
|
&cb)) {
|
|
return 0;
|
|
}
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[Rt] = (DWORD)dwlData;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[Rt] = dwlData;
|
|
|
|
if ((Rt == RA) && (Restored == FALSE)) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
NextPc = Context->IntRa;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
NextPc = (DWORD)Context->XIntRa;
|
|
Restored = TRUE;
|
|
}
|
|
}
|
|
|
|
} else if (Opcode == SWC1_OP) {
|
|
|
|
if (Rs == SP) {
|
|
if (!ReadMemory(hProcess,
|
|
(LPVOID)Address,
|
|
&dwData,
|
|
4L,
|
|
&cb)) {
|
|
return 0;
|
|
}
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
FloatingRegister[Rt] = dwData;
|
|
#else // SUPPORT_MIXED_INTEGER
|
|
XFloatingRegister[Rt] = (LONG)dwData;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
}
|
|
|
|
|
|
} else if (Opcode == SDC1_OP) {
|
|
|
|
if (Rs == SP) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (!ReadMemory( hProcess, (LPVOID)Address,
|
|
&(FloatingRegister[Rt]), 8L, &cb)) {
|
|
return 0;
|
|
}
|
|
#else // SUPPORT_MIXED_INTEGER
|
|
if (!ReadMemory( hProcess, (LPVOID)Address,
|
|
&(XFloatingRegister[Rt]), 8L, &cb)) {
|
|
return 0;
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
}
|
|
|
|
} else if (Opcode == ADDIU_OP) {
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if ((Rs == SP) && (Rt == SP)) {
|
|
IntegerRegister[SP] -= Offset;
|
|
} else if ((Rt == DecrementRegister) && (Rs == ZERO)) {
|
|
IntegerRegister[SP] += Offset;
|
|
}
|
|
} else {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
if ((Rs == SP) && (Rt == SP)) {
|
|
XIntegerRegister[SP] -= Offset;
|
|
} else if ((Rt == DecrementRegister) && (Rs == ZERO)) {
|
|
XIntegerRegister[SP] += Offset;
|
|
}
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
} else if (Opcode == ORI_OP) {
|
|
|
|
if ((Rs == DecrementRegister) && (Rt == DecrementRegister)) {
|
|
DecrementOffset = (Offset & 0xffff);
|
|
|
|
} else if ((Rt == DecrementRegister) && (Rs == ZERO)) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[SP] += (Offset & 0xffff);
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[SP] += (Offset & 0xffff);
|
|
}
|
|
|
|
} else if (Opcode == SPEC_OP) {
|
|
|
|
Opcode = Instruction.r_format.Function;
|
|
if (Opcode == ADDU_OP || Opcode == OR_OP) {
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if (Rt == ZERO) {
|
|
IntegerRegister[Rs] = IntegerRegister[Rd];
|
|
if ((Rs == RA) && (Restored == FALSE)) {
|
|
NextPc = Context->IntRa;
|
|
Restored = TRUE;
|
|
}
|
|
|
|
} else if (Rs == ZERO) {
|
|
IntegerRegister[Rt] = IntegerRegister[Rd];
|
|
if ((Rt == RA) && (Restored == FALSE)) {
|
|
NextPc = Context->IntRa;
|
|
Restored = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
if (Rt == ZERO) {
|
|
XIntegerRegister[Rs] = XIntegerRegister[Rd];
|
|
if ((Rs == RA) && (Restored == FALSE)) {
|
|
NextPc = (DWORD)Context->XIntRa;
|
|
Restored = TRUE;
|
|
}
|
|
|
|
} else if (Rs == ZERO) {
|
|
XIntegerRegister[Rt] = XIntegerRegister[Rd];
|
|
if ((Rt == RA) && (Restored == FALSE)) {
|
|
NextPc = (DWORD)Context->XIntRa;
|
|
Restored = TRUE;
|
|
}
|
|
}
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
} else if (Opcode == SUBU_OP) {
|
|
|
|
if ((Rd == SP) && (Rs == SP)) {
|
|
DecrementRegister = Rt;
|
|
}
|
|
}
|
|
|
|
} else if (Opcode == LUI_OP) {
|
|
|
|
if (Rt == DecrementRegister) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
IntegerRegister[SP] += (LONG)(DecrementOffset + (Offset << 16));
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
XIntegerRegister[SP] += (LONG)(DecrementOffset + (Offset << 16));
|
|
DecrementRegister = 0;
|
|
}
|
|
}
|
|
}
|
|
return NextPc;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WalkMipsGetStackFrame(
|
|
HANDLE hProcess,
|
|
LPDWORD ReturnAddress,
|
|
LPDWORD FramePointer,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccess,
|
|
PKDHELP KdHelp
|
|
)
|
|
{
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
|
|
BOOL rval = TRUE;
|
|
DWORD cb;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
BOOL Use32 = (Context->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER;
|
|
DWORD dwRa = Use32 ? Context->IntRa : (DWORD)Context->XIntRa;
|
|
#else // SUPPORT_MIXED_INTEGER
|
|
DWORD dwRa = Context->XIntRa;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
|
|
rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY) FunctionTableAccess( hProcess, *ReturnAddress );
|
|
|
|
if (rf) {
|
|
|
|
dwRa = VirtualUnwind( hProcess, *ReturnAddress, rf, Context, ReadMemory );
|
|
if (!dwRa) {
|
|
rval = FALSE;
|
|
}
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if ((dwRa == *ReturnAddress && *FramePointer == Context->IntSp) || (dwRa == 1)) {
|
|
rval = FALSE;
|
|
}
|
|
|
|
*ReturnAddress = dwRa;
|
|
*FramePointer = Context->IntSp;
|
|
} else {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
if ((dwRa == *ReturnAddress && *FramePointer == (DWORD)Context->XIntSp) || (dwRa == 1)) {
|
|
rval = FALSE;
|
|
}
|
|
|
|
*ReturnAddress = dwRa;
|
|
*FramePointer = (DWORD)Context->XIntSp;
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
} else {
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if ((dwRa == *ReturnAddress && *FramePointer == Context->IntSp) || (dwRa == 1)) {
|
|
rval = FALSE;
|
|
}
|
|
|
|
*ReturnAddress = Context->IntRa;
|
|
*FramePointer = Context->IntSp;
|
|
} else {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
if ((dwRa == *ReturnAddress && *FramePointer == (DWORD)Context->XIntSp) || (dwRa == 1)) {
|
|
rval = FALSE;
|
|
}
|
|
|
|
*ReturnAddress = (DWORD)Context->XIntRa;
|
|
*FramePointer = (DWORD)Context->XIntSp;
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WalkMipsInit(
|
|
HANDLE hProcess,
|
|
LPSTACKFRAME StackFrame,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccess
|
|
)
|
|
{
|
|
KEXCEPTION_FRAME ExceptionFrame;
|
|
CONTEXT ContextSave;
|
|
DWORD PcOffset;
|
|
DWORD FrameOffset;
|
|
DWORD cb;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
BOOL Use32 = (Context->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
|
|
if (StackFrame->AddrFrame.Offset) {
|
|
if (ReadMemory( hProcess,
|
|
(LPVOID) StackFrame->AddrFrame.Offset,
|
|
&ExceptionFrame,
|
|
sizeof(KEXCEPTION_FRAME),
|
|
&cb )) {
|
|
//
|
|
// successfully read an exception frame from the stack
|
|
//
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
Context->IntSp = StackFrame->AddrFrame.Offset;
|
|
Context->Psr = 0x2000fc01;
|
|
Context->Fir = ExceptionFrame.SwapReturn;
|
|
Context->IntRa = ExceptionFrame.SwapReturn;
|
|
Context->IntS3 = ExceptionFrame.IntS3;
|
|
Context->IntS4 = ExceptionFrame.IntS4;
|
|
Context->IntS5 = ExceptionFrame.IntS5;
|
|
Context->IntS6 = ExceptionFrame.IntS6;
|
|
Context->IntS7 = ExceptionFrame.IntS7;
|
|
Context->IntS8 = ExceptionFrame.IntS8;
|
|
} else {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
Context->XIntSp = (LONG)StackFrame->AddrFrame.Offset;
|
|
Context->Psr = 0x2000fc01;
|
|
Context->Fir = ExceptionFrame.SwapReturn;
|
|
Context->XIntRa = (LONG)ExceptionFrame.SwapReturn;
|
|
Context->XIntS3 = (LONG)ExceptionFrame.IntS3;
|
|
Context->XIntS4 = (LONG)ExceptionFrame.IntS4;
|
|
Context->XIntS5 = (LONG)ExceptionFrame.IntS5;
|
|
Context->XIntS6 = (LONG)ExceptionFrame.IntS6;
|
|
Context->XIntS7 = (LONG)ExceptionFrame.IntS7;
|
|
Context->XIntS8 = (LONG)ExceptionFrame.IntS8;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
//
|
|
// Don't zero the KdHelp part of the stackframe:
|
|
// 1) it will trash data in old apps
|
|
// 2) we don't want to discard KdHelp if it is there.
|
|
//
|
|
ZeroMemory( StackFrame, FIELD_OFFSET(STACKFRAME, KdHelp));
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
StackFrame->Virtual = TRUE;
|
|
|
|
if (!StackFrame->AddrPC.Offset) {
|
|
StackFrame->AddrPC.Offset = Context->Fir;
|
|
StackFrame->AddrPC.Mode = AddrModeFlat;
|
|
}
|
|
|
|
if (!StackFrame->AddrFrame.Offset) {
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
StackFrame->AddrFrame.Offset = Context->IntSp;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
StackFrame->AddrFrame.Offset = (DWORD)Context->XIntSp;
|
|
StackFrame->AddrFrame.Mode = AddrModeFlat;
|
|
}
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (!Use32) {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
ContextSave = *Context;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
} else {
|
|
memcpy(&ContextSave,
|
|
Context,
|
|
FIELD_OFFSET(CONTEXT, ContextFlags) + 4);
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
PcOffset = StackFrame->AddrPC.Offset;
|
|
FrameOffset = StackFrame->AddrFrame.Offset;
|
|
|
|
if (!WalkMipsGetStackFrame( hProcess,
|
|
&PcOffset,
|
|
&FrameOffset,
|
|
&ContextSave,
|
|
ReadMemory,
|
|
FunctionTableAccess,
|
|
&StackFrame->KdHelp ) ) {
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
StackFrame->AddrReturn.Offset = Context->IntRa;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
StackFrame->AddrReturn.Offset = (DWORD)Context->XIntRa;
|
|
|
|
} else {
|
|
|
|
StackFrame->AddrReturn.Offset = PcOffset;
|
|
}
|
|
|
|
StackFrame->AddrReturn.Mode = AddrModeFlat;
|
|
|
|
//
|
|
// get the arguments to the function
|
|
//
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if (!ReadMemory( hProcess, (LPVOID)ContextSave.IntSp,
|
|
StackFrame->Params, 16, &cb )) {
|
|
StackFrame->Params[0] =
|
|
StackFrame->Params[1] =
|
|
StackFrame->Params[2] =
|
|
StackFrame->Params[3] = 0;
|
|
}
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
if (!ReadMemory( hProcess, (LPVOID)(DWORD)ContextSave.XIntSp,
|
|
StackFrame->Params, 16, &cb )) {
|
|
StackFrame->Params[0] =
|
|
StackFrame->Params[1] =
|
|
StackFrame->Params[2] =
|
|
StackFrame->Params[3] = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WalkMipsNext(
|
|
HANDLE hProcess,
|
|
LPSTACKFRAME StackFrame,
|
|
PCONTEXT Context,
|
|
PREAD_PROCESS_MEMORY_ROUTINE ReadMemory,
|
|
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccess
|
|
)
|
|
{
|
|
DWORD cb;
|
|
CONTEXT ContextSave;
|
|
BOOL rval = TRUE;
|
|
DWORD Address;
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
BOOL Use32 = (Context->ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER;
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
|
|
|
|
if (!WalkMipsGetStackFrame( hProcess,
|
|
&StackFrame->AddrPC.Offset,
|
|
&StackFrame->AddrFrame.Offset,
|
|
Context,
|
|
ReadMemory,
|
|
FunctionTableAccess,
|
|
&StackFrame->KdHelp ) ) {
|
|
|
|
rval = FALSE;
|
|
|
|
//
|
|
// If the frame could not be unwound or is terminal, see if
|
|
// there is a callback frame:
|
|
//
|
|
|
|
if (AppVersion.Revision >= 4 && CALLBACK_STACK(StackFrame)) {
|
|
|
|
if (CALLBACK_STACK(StackFrame) & 0x80000000) {
|
|
|
|
//
|
|
// it is the pointer to the stack frame that we want,
|
|
// or -1.
|
|
|
|
Address = CALLBACK_STACK(StackFrame);
|
|
|
|
} else {
|
|
|
|
//
|
|
// if it is a positive integer, it is the offset to
|
|
// the address in the thread.
|
|
// Look up the pointer:
|
|
//
|
|
|
|
rval = ReadMemory(hProcess,
|
|
(PVOID)(CALLBACK_THREAD(StackFrame) +
|
|
CALLBACK_STACK(StackFrame)),
|
|
&Address,
|
|
sizeof(DWORD),
|
|
&cb);
|
|
|
|
if (!rval || Address == 0) {
|
|
Address = 0xffffffff;
|
|
CALLBACK_STACK(StackFrame) = 0xffffffff;
|
|
}
|
|
|
|
}
|
|
|
|
if ((Address == 0xffffffff) ||
|
|
!(rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY)
|
|
FunctionTableAccess(hProcess, CALLBACK_FUNC(StackFrame))) ) {
|
|
|
|
rval = FALSE;
|
|
|
|
} else {
|
|
|
|
ReadMemory(hProcess,
|
|
(PVOID)(Address + CALLBACK_NEXT(StackFrame)),
|
|
&CALLBACK_STACK(StackFrame),
|
|
sizeof(DWORD),
|
|
&cb);
|
|
|
|
StackFrame->AddrPC.Offset = rf->PrologEndAddress;
|
|
StackFrame->AddrFrame.Offset = Address;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
Context->IntSp = Address;
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
Context->XIntSp = (LONG)Address;
|
|
|
|
rval = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// get the return address
|
|
//
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (!Use32) {
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
ContextSave = *Context;
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
} else {
|
|
memcpy(&ContextSave,
|
|
Context,
|
|
FIELD_OFFSET(CONTEXT, ContextFlags) + 4);
|
|
}
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
cb = 0;
|
|
StackFrame->AddrReturn.Offset = StackFrame->AddrPC.Offset;
|
|
|
|
if (!WalkMipsGetStackFrame( hProcess,
|
|
&StackFrame->AddrReturn.Offset,
|
|
&cb,
|
|
&ContextSave,
|
|
ReadMemory,
|
|
FunctionTableAccess,
|
|
&StackFrame->KdHelp ) ) {
|
|
StackFrame->AddrReturn.Offset = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// get the arguments to the function
|
|
//
|
|
|
|
#ifdef SUPPORT_MIXED_INTEGER
|
|
if (Use32) {
|
|
if (!ReadMemory( hProcess, (LPVOID)ContextSave.IntSp,
|
|
StackFrame->Params, 16, &cb )) {
|
|
StackFrame->Params[0] =
|
|
StackFrame->Params[1] =
|
|
StackFrame->Params[2] =
|
|
StackFrame->Params[3] = 0;
|
|
}
|
|
} else
|
|
#endif // SUPPORT_MIXED_INTEGER
|
|
if (!ReadMemory( hProcess, (LPVOID)(DWORD)ContextSave.XIntSp,
|
|
StackFrame->Params, 16, &cb )) {
|
|
StackFrame->Params[0] =
|
|
StackFrame->Params[1] =
|
|
StackFrame->Params[2] =
|
|
StackFrame->Params[3] = 0;
|
|
}
|
|
|
|
return rval;
|
|
}
|