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

📄 vunwind.c

📁 wince下的源代码集合打包
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++Copyright (c) 1993-2000 Microsoft Corporation.  All rights reserved.Module Name:    vunwind.cAbstract:    This module contains the instruction classifying and virtual    unwinding routines for structured exception handling on PowerPC.    Virtual Unwind was moved to this file from exdsptch.c so that it    can be used directly in the kernel debugger. --*/#include "kernel.h"typedef double *PDOUBLE;#define READ_ULONG(addr,dest) ((dest) = (*(PULONG)(addr)))#define READ_DOUBLE(addr,dest) ((dest) = (*(PDOUBLE)(addr)))#if 0 ///ifdef _IMAGEHLP_SOURCE_#define FUNCTION_ENTRY_IS_IMAGE_STYLE#define NOT_IMAGEHLP(E)#else#define NOT_IMAGEHLP(E) E#endifextern PRUNTIME_FUNCTION NKLookupFunctionEntry(    IN PPROCESS pProc,    IN ULONG ControlPc,    PRUNTIME_FUNCTION prf);//// The `ClassifyInstruction' function returns an enum that identifies// the type of processing needed for an instruction.//typedef enum _INSTR_CLASS {    InstrIgnore,        // Do not process    InstrMFLR,          // Move from Link Register    InstrMFCR,          // Move from Condition Register    InstrSTW,           // Store word    InstrSTWU,          // Store word with update    InstrSTWUr12,       // Store word with update during UnwindR12    InstrSTFD,          // Store float double    InstrMR,            // Move register    InstrMRr12,         // Move register during UnwindR12    InstrMRfwd,         // Move register during UnwindForward    InstrADDIr12,       // Add immediate during UnwindR12    InstrADDIfwd,       // Add immediate during UnwindForward    InstrSaveCode,      // Branch and link to GPR or FPR saving millicode    InstrRestoreCode,   // Branch to GPR or FPR saving millicode    InstrGlue,          // Branch or Branch and link to glue code    InstrBLR,           // Branch to Link Register    InstrSetEstablisher // Special instruction used to set establisher frame} INSTR_CLASS;//// If `ClassifyInstruction' returns `InstrSaveCode' or `InstrRestoreCode',// the following information is completed.//typedef struct _MILLICODE_INFO {    ULONG  TargetPc;    // Millicode entry point    PRUNTIME_FUNCTION FunctionEntry; // Millicode function table entry    RUNTIME_FUNCTION  FETemp;       // storage to hold FE if using compressed PData} MILLICODE_INFO, *PMILLICODE_INFO;//// `ClassifyInstruction' interprets the instruction based on the intent.//typedef enum _UNWIND_INTENT {    UnwindForward,      // Performing a forward execution    UnwindR12,          // Performing a reverse execution to get r.12    UnwindReverse,      // Performing a reverse execution    UnwindReverseR12    // Performing a reverse execution allowing r.12} UNWIND_INTENT;//// The simulated execution by `RtlVirtualUnwind' is controlled by this// data type.//typedef struct _ITERATOR {    ULONG BeginPc;      // Address of first instruction to simulate    ULONG EndPc;        // Address after the last instruction to simulate    LONG  Increment;    // Simulation direction    UNWIND_INTENT Intent; // Simulation intent} ITERATOR, *PITERATOR;#define GPR1     1      // GPR 1 in an RA, RB, RT, etc. field#define GPR2     2      // GPR 2 in an RA, RB, RT, etc. field#define GPR12    12     // GPR 12 in an RA, RB, RT, etc. field#define LINKREG  0x100  // Link Reg in a MFSPR instructionstatic INSTR_CLASSClassifyInstruction (PPC_INSTRUCTION *I,                     UNWIND_INTENT Intent,                     ULONG Pc,                     PMILLICODE_INFO Info)/*++Routine description:    This function inspects the instruction identified by the "Pc"    argument and determines what sort of processing is needed in order    to simulate its execution.  Some instructions can be safely    ignored altogether, in which case "InstrIgnore" is returned.  For    others, a value is returned indicating what kind of instruction    was found.  The interpreation depends on the value of "Intent".Arguments:    I - Address of a struct containing the instruction to be examined.    Intent - Type of unwinding being performed.    Pc - Address of the instruction, used for computing relative branch        addresses.    Info - Address to store a description of the register save/restore        millicode.Return value:    One of the enum values defined above is returned. --*/{// Unique value combining an opcode and an UNWIND_INTENT value.#define OP_INTENT(OP,INTENT) ((OP) << 2 | (INTENT))    switch (OP_INTENT (I->Primary_Op, Intent)) {      //      // Store word: recognize "stw r.n, disp(r.1)".  Allow a base of      // r.12 if we have computed its value.      //      case OP_INTENT (STW_OP, UnwindReverseR12):        if (I->Dform_RA == GPR12)            return InstrSTW;        // fall thru      case OP_INTENT (STW_OP, UnwindReverse):        if (I->Dform_RA == GPR1)            return InstrSTW;        break;      //      // Load word:  recognize "lwz r.n, disp(r.x)" in epilogue millicode.      //      case OP_INTENT (LWZ_OP, UnwindForward):        return InstrSTW;      //      // Store word with update:  recognize "stwu r.1, r.1, disp"      //      case OP_INTENT (STWU_OP, UnwindReverse):      case OP_INTENT (STWU_OP, UnwindReverseR12):      case OP_INTENT (STWU_OP, UnwindR12):        if (I->Dform_RS == GPR1 &&            I->Dform_RA == GPR1)            return (Intent == UnwindR12 ? InstrSTWUr12 : InstrSTWU);        break;      //      // Store float double: recognize "stfd f.n, disp(r.1)".  Allow a      // base of r.12 if we have computed its value.      //      case OP_INTENT (STFD_OP, UnwindReverseR12):        if (I->Dform_RA == GPR12)            return InstrSTFD;        // fall thru      case OP_INTENT (STFD_OP, UnwindReverse):        if (I->Dform_RA == GPR1)            return InstrSTFD;        break;      //      // Load float double:  recognize "lfd f.n, disp(r.x)"      //      case OP_INTENT (LFD_OP, UnwindForward):        return InstrSTFD;      //      // Add immediate:  recognize "addi r.12, r.1, delta"      //      case OP_INTENT (ADDI_OP, UnwindR12):        if (I->Dform_RS == GPR12 &&            I->Dform_RA == GPR1)            return InstrADDIr12;        break;      case OP_INTENT (ADDI_OP, UnwindForward):        return InstrADDIfwd;      //      // Branch (long form):  recognize "bl[a] saveregs"and "b[a] restregs"      //      case OP_INTENT (B_OP, UnwindReverse):        //        // Compute branch target address, allowing for branch-relative        // and branch-absolute.        //        Pc = ((LONG)(I->Iform_LI) << 2) + (I->Iform_AA ? 0 : Pc);        //        // Determine whether the target address is part of a register        // save or register restore sequence or is a direct branch out        // by checking it's function table entry.        //        if ((Info->FunctionEntry = NKLookupFunctionEntry(pCurProc, Pc, &Info->FETemp)) != NULL                && Info->FunctionEntry->ExceptionHandler == 0) {            Info->TargetPc = Pc;            switch ((ULONG)Info->FunctionEntry->HandlerData) {            case 1:                if (I->Iform_LK)                    return InstrSaveCode;                break;            case 2:                if (!I->Iform_LK)                    return InstrRestoreCode;                break;            case 3:                return InstrGlue;            }        }        break; // unrecognized entry point      //      // Extended ops -- primary opcode 19      //      case OP_INTENT (X19_OP, UnwindForward):        //        // BLR: recognized "bclr 20,0".        //        if (I->Long == RETURN_INSTR)            return InstrBLR;        break;      case OP_INTENT (X19_OP, UnwindR12):      case OP_INTENT (X19_OP, UnwindReverse):      case OP_INTENT (X19_OP, UnwindReverseR12):        //        // RFI: this instruction is used in special kernel fake prologues        //      to indicate that the establisher frame address should be        //      updated using the current value of sp.        //        if (I->Xform_XO == RFI_OP)            return InstrSetEstablisher;        break;      //      // Extended ops -- primary opcode 31      //      case OP_INTENT (X31_OP, UnwindForward):      case OP_INTENT (X31_OP, UnwindR12):      case OP_INTENT (X31_OP, UnwindReverse):      case OP_INTENT (X31_OP, UnwindReverseR12):        switch (OP_INTENT (I->Xform_XO, Intent)) {          //          // OR register: recognize "or r.x, r.y, r.y" as move-reg          //          case OP_INTENT (OR_OP, UnwindReverse):            if (I->Xform_RS == I->Xform_RB)                return InstrMR;            break;          case OP_INTENT (OR_OP, UnwindForward):            if (I->Xform_RS == I->Xform_RB)                return InstrMRfwd;            break;          //          // Store word with update indexed:  recognize "stwux r.1, r.1, r.x"          //          case OP_INTENT (STWUX_OP, UnwindReverse):          case OP_INTENT (STWUX_OP, UnwindReverseR12):          case OP_INTENT (STWUX_OP, UnwindR12):            if (I->Xform_RS == GPR1 && I->Xform_RA == GPR1)                return (Intent == UnwindR12 ? InstrSTWUr12 : InstrSTWU);            break;          //          // Move to/from special-purpose reg:  recognize "mflr", "mtlr"          //          case OP_INTENT (MFSPR_OP, UnwindReverse):          case OP_INTENT (MTSPR_OP, UnwindForward):            if (I->XFXform_spr == LINKREG)                return InstrMFLR;            break;          //          // Move from Condition Register:  "mfcr r.x"          //          case OP_INTENT (MFCR_OP, UnwindReverse):          case OP_INTENT (MFCR_OP, UnwindReverseR12):            return InstrMFCR;          //          // Move to Condition Register:  "mtcrf 255,r.x"          //          case OP_INTENT (MTCRF_OP, UnwindForward):            if (I->XFXform_FXM == 255)                return InstrMFCR;            break;          default:              // unrecognized            break;        }      default:                  // unrecognized        break;    }    //    // Instruction not recognized; just ignore it and carry on    //    return InstrIgnore;#undef OP_INTENT}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.    If the function is register save millicode, it is treated as a leaf    function.  If the function is register restore millicode, the remaining    body is executed forwards and the address where control left the    previous frame is obtained from the final blr instruction.    If the function was called via glue code and is not that glue code,    the prologe of the glue code is executed backwards in addition to the    above actions.    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

⌨️ 快捷键说明

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