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

📄 vunwind.c

📁 wince下的源代码集合打包
💻 C
📖 第 1 页 / 共 2 页
字号:
        specified function or NULL if the function is a leaf 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.Return Value:    The address where control left the previous frame is returned as the    function value. --*/{    ITERATOR Iterator[8];    PITERATOR Piterator;    ULONG Address;    PDOUBLE FloatingRegister;    PPC_INSTRUCTION I;    PULONG IntegerRegister;    ULONG NextPc, Pc;    BOOLEAN RestoredLr = FALSE;    BOOLEAN RestoredSp = FALSE;    BOOLEAN ComputedSp = FALSE;    ULONG Rt;    MILLICODE_INFO Info;    INSTR_CLASS InstrClass;    ULONG EstablisherFrameValue;	//    // Set the base address of the integer and floating register arrays.    //    FloatingRegister = &ContextRecord->Fpr0;    IntegerRegister = &ContextRecord->Gpr0;    //    // If the function is a leaf function, perform the default unwinding    // action and check to see if the function was called via glue.    //    if (FunctionEntry == NULL) {        //        // Set point at which control left the previous routine.        //        return( ContextRecord->Lr - 4 );    }    //    // Set initial values for EstablisherFrame and Offset.    // (this may need more careful planning IBMPLJ).    //    NOT_IMAGEHLP (*EstablisherFrame =                  EstablisherFrameValue = ContextRecord->Gpr1);    READ_ULONG (ControlPc, I.Long);    if (I.Long == RETURN_INSTR) {        //        // If the instruction at the point where control left the specified        // function is a return, then any saved registers have been restored        // and the control PC is not considered to be in the function        // (i.e., in an epilogue).        //        NOT_IMAGEHLP(*InFunction = FALSE);        return( ContextRecord->Lr );    }    InstrClass = ClassifyInstruction(&I, UnwindReverse, ControlPc, &Info);    if (InstrClass == InstrRestoreCode) {        //        // If the instruction at the point where control left the        // specified function is a branch to register restore        // millicode, the state is restored by simulating the        // execution of the restore millicode.  The control PC is in        // an epilogue.        //        Iterator[0].BeginPc = Info.TargetPc;        Iterator[0].EndPc = Info.FunctionEntry->EndAddress;        Iterator[0].Increment = 4;        Iterator[0].Intent = UnwindForward;        NOT_IMAGEHLP(*InFunction = FALSE);    } else if (FunctionEntry->ExceptionHandler == 0 &&               (ULONG)FunctionEntry->HandlerData == 2) {        //        // If the address is in register restore millicode, the state        // is restored by completing the execution of the restore        // millicode.  The control PC is in an epilogue.        //        Iterator[0].BeginPc = ControlPc;        Iterator[0].EndPc = FunctionEntry->EndAddress;        Iterator[0].Increment = 4;        Iterator[0].Intent = UnwindForward;        NOT_IMAGEHLP(*InFunction = FALSE);    } else {        //        // 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., in the prologue).        //        Iterator[0].EndPc = FunctionEntry->BeginAddress - 4;        Iterator[0].Increment = -4;        Iterator[0].Intent = UnwindReverse;        if (ControlPc < FunctionEntry->BeginAddress                || ControlPc >= (FunctionEntry->PrologEndAddress & ~3)) {            NOT_IMAGEHLP(*InFunction = TRUE);            Iterator[0].BeginPc = ((FunctionEntry->PrologEndAddress & ~3) - 4);        } else {            NOT_IMAGEHLP(*InFunction = FALSE);            Iterator[0].BeginPc = ControlPc - 4;        }    }    //    // Scan through the given instructions and reload callee registers    // as indicated.    //    NextPc = ContextRecord->Lr - 4;    for (Piterator = Iterator; Piterator >= Iterator; Piterator--) {        for (Pc = Piterator->BeginPc;             Pc != Piterator->EndPc;             Pc += Piterator->Increment) {            READ_ULONG (Pc, I.Long);            Address = IntegerRegister[I.Dform_RA] + I.Dform_D;            Rt = I.Dform_RT;            switch (ClassifyInstruction (&I, Piterator->Intent, Pc, &Info)) {              //              // Move from Link Register (save LR in a GPR)              //              // In the usual case, the link register gets set by a call              // instruction so the PC value should point to the              // instruction that sets the link register.  In an interrupt              // or exception frame, the link register and PC value are              // independent.  By convention, fake prologues for these              // frames store the link register twice: once to the link              // register location, once to the faulting PC location.              //              // If this is the first time that RA is being restored,              // then set the address of where control left the previous              // frame. Otherwise, this is an interrupt or exception and              // the return PC should be biased by 4 and the link register              // value should be updated.              //              case InstrMFLR:                ContextRecord->Lr = IntegerRegister[Rt];                if ( RestoredLr == FALSE ) {                    NextPc = ContextRecord->Lr - 4;                    RestoredLr = TRUE;                } else {                    NextPc += 4;                }                continue; // Next PC              //              // Branch to Link Register (forward execution).              //              case InstrBLR:                NextPc = ContextRecord->Lr - 4;                break; // Terminate simulation--start next iterator.              //              // Move from Condition Register (save CR in a GPR)              //              case InstrMFCR:                ContextRecord->Cr = IntegerRegister[Rt];                continue; // Next PC              //              // Store word (save a GPR)              //              case InstrSTW:              //              // Even though a stw  r.sp, xxxx in general is an invalid              // proloque instruction there are places in the kernel              // fake prologues (KiExceptionExit) where we must use this,              // so handle it.              //				READ_ULONG (Address, IntegerRegister[Rt]);				// Check for an SP update				if ( Rt == GPR1 )					RestoredSp = TRUE;                continue; // Next PC              //              // Store word with update, Store word with update indexed              // (buy stack frame, updating stack pointer and link              // cell in storage)              //              case InstrSTWU:				// STWU should only be used for updating SP				DEBUGCHK(I.Dform_RT == GPR1);				DEBUGCHK(I.Dform_RA == GPR1);				  				// Do not update SP twice.  CaptureContext is an example of 				// a prolog where only the last sp update (the first one the 				// unwinder encounters) should be unwound.				if ( RestoredSp == FALSE )				{					Address = IntegerRegister[GPR1];					READ_ULONG(Address,IntegerRegister[GPR1]);					                    *EstablisherFrame = ContextRecord->Gpr1;					EstablisherFrameValue = ContextRecord->Gpr1;                    RestoredSp = TRUE;				}                continue; // Next PC              //              // Store floating point double (save an FPR)              //              case InstrSTFD:                READ_DOUBLE (Address, FloatingRegister[Rt]);                continue; // Next PC              //              // Move register.  Certain forms are ignored based on the intent.              //              case InstrMR:                IntegerRegister[Rt] = IntegerRegister[I.Xform_RA];                continue; // Next PC              case InstrMRfwd:                IntegerRegister[I.Xform_RA] = IntegerRegister[Rt];                continue; // Next PC              //              // Add immediate.  Certain forms are ignored based on the intent.              //              case InstrADDIfwd:                IntegerRegister[Rt] = Address;                continue; // Next PC              case InstrADDIr12:                if (!ComputedSp) {                  // No intervening instruction changes r.1, so compute                  // addi r.12,r.1,N instead of addi r.12,r.12,N.                  IntegerRegister[Rt] = IntegerRegister[GPR1];                }                IntegerRegister[Rt] += I.Dform_SI;                break; // Terminate search--start next iterator.              //              // Store with update while searching for the value of r.12              //              case InstrSTWUr12:                ComputedSp = TRUE;                Address = IntegerRegister[GPR1];                READ_ULONG(Address,IntegerRegister[GPR12]);                continue; // Next PC              //              // A call to a register save millicode.              //              case InstrSaveCode:                //                // Push an iterator to incorporate the actions of the                // millicode.                //                Piterator++;                Piterator->BeginPc = Info.FunctionEntry->EndAddress - 4;                Piterator->EndPc = Info.TargetPc - 4;                Piterator->Increment = -4;                Piterator->Intent = UnwindReverseR12;                //                // Push an iterator to determine the current value of r.12                //                Piterator++;                Piterator->BeginPc = Pc - 4;                Piterator->EndPc = Piterator[-2].EndPc;                Piterator->Increment = -4;                Piterator->Intent = UnwindR12;                ComputedSp = FALSE;                //                // Update the start of the original iterator so it can later                // resume where it left off.                //                Piterator[-2].BeginPc = Pc - 4;                Piterator++;                break; // Start the next iterator.              //              // A branch was encountered in the prologue to a routine              // identified as glue code.  This should only happen from              // fake prologues such as those in the system exception              // handler.              //              // We handle it by pushing an iterator to incorporate              // the actions of the glue code prologue.              //             case InstrGlue:                //                // Check that we don't nest too deeply.  Verify that                // we can push this iterator and the iterators for a                // glue sequence.  There's no need to make this check                // elsewhere because B_OP is only recognized during                // UnwindReverse.  Returing zero is the only error action                // we have.                //                if (Piterator - Iterator + 4                    > sizeof (Iterator) / sizeof (Iterator[0]))                    return 0;                //                // Push an iterator to incorporate the actions of the glue                // code's prologue.  Check that we don't nest too deeply.                // Verify that we can push this iterator and the iterators                // for a glue sequence.                //                Piterator++;                Piterator->BeginPc                  = (Info.FunctionEntry->PrologEndAddress & ~3) - 4;                Piterator->EndPc = Info.FunctionEntry->BeginAddress - 4;                Piterator->Increment = -4;                Piterator->Intent = UnwindReverse;                //                // Update the start of the original iterator so it can later                // resume where it left off.                //                Piterator[-1].BeginPc = Pc - 4;                Piterator++;                break; // Start the next iterator.              //              // Special "set establisher" instruction (rfi).              //              // Kernel fake prologues that can't use stwu (KiExceptionExit,              // KiAlternateExit) use an rfi instruction to tell the              // unwinder to update the establisher frame pointer using              // the current value of sp.              //              case InstrSetEstablisher:                NOT_IMAGEHLP (*EstablisherFrame =                                  EstablisherFrameValue = ContextRecord->Gpr1);                continue; // Next PC              //              // None of the above.  Just ignore the instruction.  It              // is presumed to be non-prologue code that has been              // merged into the prologue for scheduling purposes.  It              // may also be improper code in a register save/restore              // millicode routine or unimportant code when              // determining the value of r.12.              //              case InstrIgnore:              default:                continue; // Next PC            }            break; // Start the next iterator.        } // end foreach Pc    } // end foreach Iterator    return NextPc;}#undef NOT_IMAGEHLP

⌨️ 快捷键说明

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