⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mipsuwnd.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                IntRegs [Op->Rd] -= Op->Imm;
            }
            break;
        case OP_STORE:
            FindValue (Op-1, NumOps, Op->Rs, IntRegs);
            IntRegs [Op->Rt] = *(PLONG) (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_STORE64:
            FindValue (Op-1, NumOps, Op->Rs, IntRegs);
            IntRegs [Op->Rt] = *(REG_TYPE *) (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:
            FindValue (Op-1, NumOps, Op->Rs, IntRegs);
            FpRegs [Op->Rt] = *(PULONG) (Op->Imm + IntRegs [Op->Rs]);
            break;
        case OP_DSTORE:
            FindValue (Op-1, NumOps, Op->Rs, IntRegs);
            FpRegs [Op->Rt] = *(FREG_TYPE *) (Op->Imm + IntRegs [Op->Rs]);
#ifndef _MIPS64
            FpRegs [Op->Rt+1] = *(PULONG) (Op->Imm + IntRegs [Op->Rs] + 4);
#endif  //  _MIPS64
            break;
        case OP_IMM:
            IntRegs [Op->Rd] = Op->Imm;
            break;
        case OP_MOVE:
            IntRegs [Op->Rs] = IntRegs [Op->Rd];
            if (Op->Rs == RA) {
                if (RestoredRa == FALSE) {
                    NextPc = MIPS_PREV_INSTR(IntRegs[RA]);
                    RestoredRa = TRUE;
                } else {
                    NextPc = MIPS_NEXT_INSTR(NextPc);
                }
            }
            break;
        }
        Op--;
    }
    return RestoredRa ? NextPc : MIPS_PREV_INSTR(IntRegs[RA]);
}

ULONG
RtlVirtualUnwind(
    IN ULONG ControlPc,
    IN PRUNTIME_FUNCTION FunctionEntry,
    IN OUT PCONTEXT ContextRecord,
    OUT PBOOLEAN InFunction,
    OUT PULONG EstablisherFrame,
    IN PPROCESS pprc
    )
/*++
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;
    FREG_TYPE * FloatingRegister;
    REG_TYPE * IntegerRegister;
    MIPS_INSTRUCTION I32;
    MIPS16_INSTRUCTION I16;
    ULONG Rs;
    ULONG NextPc;
    INT OpCount;
    BOOL WithinHelper;
    POPERATION Ops;
    DWORD pcOfst = ControlPc - (DWORD) ZeroPtr (ControlPc);
    DWORD BeginAddress, PrologEndAddress;

    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 = (ULONG)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 (pprc, (ULONG)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);
            // Replace any break instruction introduced by the debugger, as 
            // a result of a breakpoint, with its original instruction
            if (I16.rr_format.Function == BREAK_OP16 &&
                I16.rr_format.Opcode == RR_OP16) {
                (*KDSanitize)((BYTE *)&I16.Short, (void *)(ControlPc - 1),
                           sizeof(I16.Short), FALSE);
            }
            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);

                // Could a user insert a breakpoint in the delay slot 
                // of a return instruction?
                // If yes, replace any break instruction introduced in the 
                // delay slot by the debugger with its original instruction
                if (I16.rr_format.Function == BREAK_OP16 &&
                    I16.rr_format.Opcode == RR_OP16) {
                    (*KDSanitize)((BYTE *)&I16.Short, (void *)(ControlPc + 1), 
                               sizeof(I16.Short), FALSE);
                }

                // 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 = (ULONG)ContextRecord->IntSp;
                return MIPS_PREV_INSTR(IntegerRegister [Rs]);
            }
        } else {
            DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: MIPS32 code\r\n"));
            I32.Long = *(PULONG) ControlPc;
            // Replace any break instruction introduced by the debugger, as 
            // a result of a breakpoint, with its original instruction
            if (I32.r_format.Function == BREAK_OP &&
                I32.r_format.Opcode == SPEC_OP) {
                (*KDSanitize)((BYTE *)&I32.Long, (void *)(ControlPc),
                           sizeof(I32.Long), FALSE);
            }
            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);

                // Could a user insert a breakpoint in the delay slot
                // of a return instruction?
                // If yes, replace any break instruction introduced in the 
                // delay slot by the debugger with its original instruction
                if (I32.r_format.Function == BREAK_OP &&
                    I32.r_format.Opcode == SPEC_OP) {
                    (*KDSanitize)((BYTE *)&I32.Long, (void *)(ControlPc + 4), 
                               sizeof(I32.Long), FALSE);
                }

                // 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 = (ULONG)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 (pprc, (ULONG)ContextRecord->IntRa - 4, &rf);
        if (FunctionEntry == NULL) {
            return 0;
        }

        // Reverse execute to the end of the prologue
        ControlPc = FunctionEntry->PrologEndAddress;

        // map slot 0 address to the process
        if (ControlPc < (1 << VA_SECTION))
            ControlPc += pcOfst;
    }

    BeginAddress = FunctionEntry->BeginAddress;
    PrologEndAddress = FunctionEntry->PrologEndAddress;

    // map slot 0 address to the process
    if (BeginAddress < (1 << VA_SECTION)) {
        BeginAddress += pcOfst;
        PrologEndAddress += pcOfst;
    }


    // 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 < BeginAddress ||
         ControlPc >= PrologEndAddress) &&
        !WithinHelper) {
        *InFunction = TRUE;
        ControlPc = PrologEndAddress;
        DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: within function, new ControPc=%x\r\n", ControlPc));
    }

    // Allocate an array of OPERATION's that will hold the entire prologue.
    // Note that the prologue may include the body of a helper function. If this is the case,
    // the call and return won't be stored in Ops, so we add the size of the largest
    // prologue helper, minus the call to and return from the helper.
    OpCount = BYTES_TO_OPCOUNT(BeginAddress, ControlPc) + MIPS_PROLHELPER_OPCOUNT(ControlPc) - 2;
    Ops = (POPERATION) _alloca(OpCount * sizeof(OPERATION));

    // Build an operation list of all instructions from the function start
    // to the control PC.
    OpCount = BuildOps (Ops, OpCount, BeginAddress, ControlPc, pcOfst);
    DEBUGMSG(ZONE_SEH,(L"RtlVirtualUnwind: build op list with %d elements\r\n", OpCount));

    // We were unable to build the op list
    if (OpCount < 0) {
        return 0;
    }

    NextPc = Reverse (Ops, OpCount, ContextRecord);
    DEBUGMSG(ZONE_SEH,(L"Reverse executed RA=%x SP=%x\r\n", ContextRecord->IntRa, ContextRecord->IntSp));
    
    *EstablisherFrame = (ULONG)ContextRecord->IntSp;
    // Make sure that integer register zero is really zero.
    ContextRecord->IntZero = 0;
    return NextPc;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -