📄 mipsuwnd.c
字号:
I16.Short = *((PUSHORT) (Address - 1)); switch (I16.i_format.Opcode) { case EXTEND_OP16: Extend = (I16.ei_format.Simmediate11 << 11) | (I16.ei_format.Immediate5 << 5); PCAddress = Address; Address += 2; break; case B_OP16: if (Extend == (ULONG) -1) { Address += (I16.b_format.Simmediate << 1) + 2; } else { Address += (I16.rri_format.Immediate | Extend) + 4; } PCAddress = Address; Extend = (ULONG) -1; break; case JALX_OP16: Op = BuildSimpleOp16 (Op, Address + 3, Address, (ULONG) -1); RetAddress = Address + 6; Address = (I16.j_format.Target16 << 18) | (I16.j_format.Target21 << 23) | (*(PUSHORT) (Address+1) << 2) | ((Address+3) & 0xf0000000); Address |= (I16.j_format.Ext == 0); PCAddress = Address; Extend = (ULONG) -1; break; case RR_OP16: switch (I16.rr_format.Function) { case JR_OP16: if (I16.rr_format.Ry == 1 && I16.rr_format.Rx == 0) { // If this is a "JR RA" and we've nested then decode from return address if (RetAddress != (ULONG) -1) { Op = BuildSimpleOp16 (Op, Address + 1, PCAddress, (ULONG) -1); PCAddress = Address = RetAddress; RetAddress = (ULONG) -1; Extend = (ULONG) -1; continue; } } // Anything other than JR RA is not acceptable in helper functions return -1; } Address += 2; PCAddress = Address; Extend = (ULONG) -1; break; default: Op = BuildSimpleOp16 (Op, Address - 1, PCAddress, Extend); Address += 2; PCAddress = Address; Extend = (ULONG) -1; break; } } else { // Get MIPS32 instruction I32.Long = *(PULONG) Address; switch (I32.i_format.Opcode) { case JAL_OP: Op = BuildSimpleOp32 (Op, Address + 4, (BOOLEAN)(Op != Operations)); RetAddress = Address + 8; Address = (I32.j_format.Target << 2) | ((Address + 4) & 0xf0000000); if (I32.j_format.Target >> 26) Address |= 1; PCAddress = Address; break; case SPEC_OP: if (I32.Long == JUMP_RA && RetAddress != (ULONG) -1) { Op = BuildSimpleOp32 (Op, Address + 4, (BOOLEAN)(Op != Operations)); Address = PCAddress = RetAddress; RetAddress = (ULONG) -1; continue; } // Note fallthrough default: Op = BuildSimpleOp32 (Op, Address, (BOOLEAN)(Op != Operations)); Address += 4; break; } } } if (Address != EndAddress) { return -1; } return Op - Operations;} voidFindImmed ( IN POPERATION Ops, IN DWORD NumOps, IN DWORD RegNum, IN OUT PULONG Regs)/*++Routine Description This function searches backwards through the Op array looking for OP_IMM assignments to a given register.Arguments Op - A pointer to an interpreter operation array. NumOps - Number of operations in the array. RegNum - Register to search for. Regs - Register value array to update.--*/{ while (NumOps-- > 0) { if (Ops->Opcode == OP_IMM && Ops->Rd == RegNum) { Regs [RegNum] = Ops->Imm; return; } Ops--; }}ULONGReverse ( IN POPERATION Op, IN DWORD NumOps, IN OUT PCONTEXT Context)/*++Routine DescriptionArguments--*/{ PULONG IntRegs = &Context->IntZero; PULONG FpRegs = &Context->FltF0; ULONG NextPc; BOOL RestoredRa = FALSE; Op += NumOps - 1; while (NumOps-- > 0) { switch (Op->Opcode) { case OP_ADD: FindImmed (Op-1, NumOps, Op->Rt, IntRegs); IntRegs [Op->Rd] -= IntRegs [Op->Rt]; break; case OP_SUB: FindImmed (Op-1, NumOps, Op->Rt, IntRegs); IntRegs [Op->Rd] += IntRegs [Op->Rt]; break; case OP_ADDI: IntRegs [Op->Rd] -= Op->Imm; break; case OP_STORE: IntRegs [Op->Rt] = *(PULONG) (Op->Imm + IntRegs [Op->Rs]); if (Op->Rt == RA) { if (RestoredRa == FALSE) { NextPc = MIPS_PREV_INSTR(IntRegs[RA]); RestoredRa = TRUE; } else NextPc = MIPS_NEXT_INSTR(NextPc); } break; case OP_FSTORE: FpRegs [Op->Rt] = *(PULONG) (Op->Imm + IntRegs [Op->Rs]); break; case OP_DSTORE: FpRegs [Op->Rt] = *(PULONG) (Op->Imm + IntRegs [Op->Rs]); FpRegs [Op->Rt+1] = *(PULONG) (Op->Imm + IntRegs [Op->Rs] + 4); break; case OP_IMM: IntRegs [Op->Rd] = Op->Imm; break; case OP_MOVE: IntRegs [Op->Rs] = IntRegs [Op->Rd]; break; } Op--; } return RestoredRa ? NextPc : MIPS_PREV_INSTR(IntRegs[RA]);}ULONGRtlVirtualUnwind( IN ULONG ControlPc, IN PRUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PBOOLEAN InFunction, OUT PULONG EstablisherFrame)/*++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. ContextRecord - Supplies the address of a context record. InFunction - Supplies a pointer to a variable that receives whether the control PC is within the current function. EstablisherFrame - Supplies a pointer to a variable that receives the the establisher frame pointer value. ContextPointers - Supplies an optional pointer to a context pointers record.Return Value: The address where control left the previous frame is returned as the function value.--*/{ RUNTIME_FUNCTION rf; PULONG FloatingRegister; PULONG IntegerRegister; MIPS_INSTRUCTION I32; MIPS16_INSTRUCTION I16; ULONG Rs; ULONG NextPc; INT OpCount; BOOL WithinHelper; POPERATION Ops; DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: (ControlPc=%x)\r\n", ControlPc)); DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: entry RA=%x SP=%x\r\n", ContextRecord->IntRa, ContextRecord->IntSp)); // Set the base address of the integer and floating register arrays. FloatingRegister = &ContextRecord->FltF0; IntegerRegister = &ContextRecord->IntZero; WithinHelper = FALSE; *InFunction = FALSE; // If the function is a frameless leaf function, then RA holds // the control PC for the previous function if (FunctionEntry == NULL) { *EstablisherFrame = ContextRecord->IntSp; DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: returning due to NULL function entry RA=%x\r\n", ContextRecord->IntRa)); return MIPS_PREV_INSTR(ContextRecord->IntRa); } // Determine if the PC is within a prolog helper. If it is then // the RA register will hold the address that we left the prolog // within the calling function. Get the function entry for this // function. if (FunctionEntry->ExceptionHandler == 0 && (ULONG)FunctionEntry->HandlerData == 2) { // Get function entry based upon ContextRecord->IntRA DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: in prolog helper RA=%x\r\n", ContextRecord->IntRa)); WithinHelper = TRUE; FunctionEntry = NKLookupFunctionEntry (pCurProc, ContextRecord->IntRa, &rf); if (FunctionEntry == NULL) { DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: returning due to NULL function entry RA=%x\r\n", ContextRecord->IntRa)); return 0; } } else { // If we are currently pointing at a return, then any saved registers // have been restored with the possible exception of the stack pointer. // The control PC is considered to be in the calling function. If the // instruction in the delay slot is a stack pointer restore then it is // executed. if (ControlPc & 1) { DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: MIPS16 code\r\n")); I16.Short = *(PUSHORT) (ControlPc - 1); if (IS_MIPS16_RETURN (I16.Short)) { // Determine return address (RA or Rx) Rs = RA; if (IS_MIPS16_JR (I16.Short)) { Rs = FIX_MIPS16_REG (I16.rr_format.Rx); } // Get MIPS16 instruction in delay slot I16.Short = *(PUSHORT)(ControlPc + 1); // Handle: MOV32R SP, Rx // ADDIU SP, Imm if (IS_MIPS16_MOV32RSP (I16.Short)) { IntegerRegister[SP] = IntegerRegister[FIX_MIPS16_REG (I16.mov32r_format.Rz)]; } else if (IS_MIPS16_ADDIUSP (I16.Short)) { IntegerRegister[SP] += (I16.rsi_format.Simmediate << 3); } *EstablisherFrame = ContextRecord->IntSp; return MIPS_PREV_INSTR(IntegerRegister [Rs]); } } else { DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: MIPS32 code\r\n")); I32.Long = *(PULONG) ControlPc; if (IS_MIPS32_RETURN (I32.Long)) { DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: at return instruction\r\n")); // Get MIPS32 instruction in delay slot I32.Long = *((PULONG)ControlPc + 1); // Handle: ADDIU SP, SP, Imm // ADDU SP, SP, Rt if (IS_MIPS32_ADDIUSP (I32.Long)) { IntegerRegister[SP] += I32.i_format.Simmediate; } else if (IS_MIPS32_ADDUSP (I32.Long)) { IntegerRegister[SP] += IntegerRegister [I32.i_format.Rt]; } *EstablisherFrame = ContextRecord->IntSp; return MIPS_PREV_INSTR(ContextRecord->IntRa); } } } // If the PC is within an epilog helper then the RA register will // hold the address that we left the calling function. Use this // to get the function entry. if (FunctionEntry->ExceptionHandler == 0 && (ULONG)FunctionEntry->HandlerData == 3) { DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: within epilog helper\r\n")); // Get function entry based upon ContextRecord->IntRA - 4; FunctionEntry = NKLookupFunctionEntry (pCurProc, ContextRecord->IntRa - 4, &rf); if (FunctionEntry == NULL) { return 0; } // Reverse execute to the end of the prologue ControlPc = FunctionEntry->PrologEndAddress; } // If the address where control left the specified function is outside // the limits of the prologue, then the control PC is considered to be // within the function and the control address is set to the end of // the prologue. Otherwise, the control PC is not considered to be // within the function (i.e., it is within the prologue). if ((ControlPc < FunctionEntry->BeginAddress || ControlPc >= FunctionEntry->PrologEndAddress) && !WithinHelper) { *InFunction = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -