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

📄 exdsptch.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    // If the registration pointer is equal to the target frame
    // pointer, then continue execution. Otherwise, an exit unwind was
    // performed or the target of the unwind did not exist and the
    // debugger and subsystem are given a second chance to handle the
    // unwind.
    if ((TargetFrame && RegistrationPointer == TargetFrame)
            || (TargetCStk && pcstk == TargetCStk)) {
        DEBUGMSG(ZONE_SEH, (TEXT("NKUnwind: continuing @%8.8lx\r\n"),
                CONTEXT_TO_PROGRAM_COUNTER(ContextRecord)));
        return TRUE;
    }
    return FALSE;
}
#endif

#ifndef x86

extern void MD_CBRtn (void);
extern void MDRestoreCalleeSavedRegisters (PCALLSTACK pcstk, PCONTEXT pCtx);

#if MIPS
#define COMBINED_PDATA           // define to enable combined pdata format

#define INST_SIZE   4
#define STK_ALIGN   0x7
#define RetValue    IntV0

#define RESTORE_EXTRA_INFO(Context, extra) ((Context)->IntGp = (extra))
#define FIXTOC(Context)
#endif

#if SHx
#define COMPRESSED_PDATA        // define to enable compressed pdata format

#define INST_SIZE   2
#define STK_ALIGN   0x3
#define IntRa       PR
#define IntSp       R15
#define RetValue    R0

#define RESTORE_EXTRA_INFO(Context, extra)
#define FIXTOC(Context)
#endif

#if ARM
#define COMPRESSED_PDATA        // define to enable compressed pdata format

#define INST_SIZE   4
#define STK_ALIGN   0x3
#define IntRa       Lr
#define IntSp       Sp
#define RetValue    R0
#define RESTORE_EXTRA_INFO(Context, extra) ((Context)->R9 = (extra))
#define FIXTOC(Context)

#endif


#ifdef INST_SIZE
//
// Define private function prototypes.
//

ULONG
RtlpVirtualUnwind(
    IN ULONG ControlPc,
    IN PRUNTIME_FUNCTION FunctionEntry,
    IN PCONTEXT ContextRecord,
    OUT PBOOLEAN InFunction,
    OUT PULONG EstablisherFrame);

EXCEPTION_DISPOSITION RtlpExecuteHandlerForException(
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN ULONG EstablisherFrame,
    IN OUT PCONTEXT ContextRecord,
    IN OUT PDISPATCHER_CONTEXT DispatcherContext,
    IN PEXCEPTION_ROUTINE ExceptionRoutine,
    IN OUT PCALLSTACK pcstk,
    IN ULONG ExceptionMode);

EXCEPTION_DISPOSITION RtlpExecuteHandlerForUnwind(
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN ULONG EstablisherFrame,
    IN OUT PCONTEXT ContextRecord,
    IN OUT PDISPATCHER_CONTEXT DispatcherContext,
    IN PEXCEPTION_ROUTINE ExceptionRoutine,
    IN OUT PCALLSTACK pcstk);

BOOLEAN NKUnwind(
    IN PTHREAD pth,
    IN PCALLSTACK TargetCStk OPTIONAL,
    IN ULONG TargetFrame OPTIONAL,
    IN ULONG TargetIp OPTIONAL,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN ULONG ReturnValue,
    IN PCONTEXT ContextRecord,
    IN PCALLSTACK NewStkTop);

PRUNTIME_FUNCTION NKLookupFunctionEntry(
    IN PPROCESS pProc,
    IN ULONG ControlPc,
    PRUNTIME_FUNCTION prf);

void UpdateASID(IN PTHREAD pth, IN PPROCESS pProc, IN ACCESSKEY aky);

extern EXCEPTION_ROUTINE KPSLExceptionRoutine;

#if defined(COMPRESSED_PDATA) || defined(COMBINED_PDATA)
typedef struct PDATA {
    ULONG pFuncStart;
    ULONG PrologLen : 8;        // low order bits
    ULONG FuncLen   : 22;       // high order bits
    ULONG ThirtyTwoBits : 1;    // 0/1 == 16/32 bit instructions
    ULONG ExceptionFlag : 1;    // highest bit
} PDATA, *PPDATA;
#endif

typedef struct PDATA_EH {
    PEXCEPTION_ROUTINE pHandler;
    PVOID pHandlerData;
} PDATA_EH, *PPDATA_EH;

#if defined(COMBINED_PDATA)
typedef struct COMBINED_HEADER {
    DWORD zero1;               // must be zero if header present
    DWORD zero2;               // must be zero if header present
    DWORD Uncompressed;        // count of uncompressed entries
    DWORD Compressed;          // count of compressed entries
} COMBINED_HEADER, *PCOMBINED_HEADER;
#endif



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOLEAN
NKDispatchException(
    IN PTHREAD pth,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PCONTEXT ContextRecord
    )
/*++
Routine Description:
    This function attempts to dispatch an exception to a frame based
    handler by searching backwards through the stack based call frames.
    The search begins with the frame specified in the context record and
    continues backward until either a handler is found that handles the
    exception, the stack is found to be invalid (i.e., out of limits or
    unaligned), or the end of the call hierarchy is reached.

    As each frame is encounter, the PC where control left the corresponding
    function is determined and used to lookup exception handler information
    in the runtime function table built by the linker. If the respective
    routine has an exception handler, then the handler is called. If the
    handler does not handle the exception, then the prologue of the routine
    is executed backwards to "unwind" the effect of the prologue and then
    the next frame is examined.

Arguments:
    pth - Supplies a pointer to thread structure
    ExceptionRecord - Supplies a pointer to an exception record.
    ContextRecord - Supplies a pointer to a context record.

Return Value:
    If the exception is handled by one of the frame based handlers, then
    a value of TRUE is returned. Otherwise a value of FALSE is returned.
--*/
{
    CONTEXT ContextRecord1;
    CONTEXT LocalContext;
    PCONTEXT OriginalContext;
    ULONG ControlPc;
    DISPATCHER_CONTEXT DispatcherContext;
    EXCEPTION_DISPOSITION Disposition;
    ULONG EstablisherFrame;
    ULONG ExceptionFlags;
    PRUNTIME_FUNCTION FunctionEntry;
    BOOLEAN InFunction;
    BOOLEAN Handled;
    ULONG HighLimit;
    ULONG LowLimit;
    ULONG NestedFrame;
    ULONG NextPc;
    ULONG PrevSp;
    PCALLSTACK pcstk, pcstkForHandler;
    PCALLSTACK TargetCStk;
    PPROCESS pprcSave;
    ACCESSKEY akySave;
    RUNTIME_FUNCTION TempFunctionEntry;
    LPDWORD tlsSave;

    // Get current stack limits, copy the context record, get the initial
    // PC value, capture the exception flags, and set the nested exception
    // frame pointer.
    NKGetStackLimits(pth, &LowLimit, &HighLimit);

    //
    // Redirect ContextRecord to a local copy of the incoming context. The
    // exception dispatch process modifies the PC of this context. Unwinding
    // of nested exceptions will fail when unwinding through CaptureContext
    // with a modified PC.
    //

    OriginalContext = ContextRecord;
    ContextRecord = &LocalContext;
    memcpy(ContextRecord, OriginalContext, sizeof(CONTEXT));

    memcpy(&ContextRecord1, ContextRecord, sizeof(CONTEXT));
    ControlPc = CONTEXT_TO_PROGRAM_COUNTER(&ContextRecord1);
    ExceptionFlags = ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE;
    NestedFrame = 0;

    pcstk = pth->pcstkTop;

    akySave = pth->aky;
    pprcSave = pCurProc;
    tlsSave = pth->tlsPtr;

    // Start with the frame specified by the context record and search
    // backwards through the call frame hierarchy attempting to find an
    // exception handler that will handle the exception.
    do { 
        // Lookup the function table entry using the point at which control
        // left the procedure.
        DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException(%08x): Proc=%8.8lx ControlPc=%8.8lx SP=%8.8lx, PSR = %8.8lx\r\n"),
                ContextRecord, pCurProc, ControlPc, ContextRecord1.IntSp, ContextRecord1.Psr));
        PrevSp = (ULONG) ContextRecord1.IntSp;
        TargetCStk = 0;
        ControlPc = ZeroPtr(ControlPc);
        FunctionEntry = NKLookupFunctionEntry(pCurProc, ControlPc, &TempFunctionEntry);

        // If there is a function table entry for the routine, then virtually
        // unwind to the caller of the current routine to obtain the virtual
        // frame pointer of the establisher and check if there is an exception
        // handler for the frame.
        if (FunctionEntry != NULL) {
            NextPc = RtlVirtualUnwind(ControlPc,
                                      FunctionEntry,
                                      &ContextRecord1,
                                      &InFunction,
                                      &EstablisherFrame,
                                      pCurProc);

            // If the virtual frame pointer is not within the specified stack
            // limits or the virtual frame pointer is unaligned, then set the
            // stack invalid flag in the exception record and return exception
            // not handled. Otherwise, check if the current routine has an
            // exception handler.
            if ((EstablisherFrame < LowLimit) 
                    || (EstablisherFrame > HighLimit)
                    || ((EstablisherFrame & STK_ALIGN) != 0)) {
                DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException: Bad stack frame=%8.8lx Low=%8.8lx High=%8.8lx\r\n"),
                    EstablisherFrame, LowLimit, HighLimit));
                ExceptionFlags |= EXCEPTION_STACK_INVALID;
                break;

            } else if ((FunctionEntry->ExceptionHandler != NULL) && InFunction) {
                // The frame has an exception handler. The handler must be
                // executed by calling another routine that is written in
                // assembler. This is required because up level addressing
                // of the handler information is required when a nested
                // exception is encountered.
invokeHandler:
                DispatcherContext.ControlPc = ControlPc;
                DispatcherContext.FunctionEntry = FunctionEntry;
                DispatcherContext.EstablisherFrame = EstablisherFrame;
                DispatcherContext.ContextRecord = ContextRecord;

                ExceptionRecord->ExceptionFlags = ExceptionFlags;
                DEBUGMSG(ZONE_SEH, (TEXT("Calling exception handler @%8.8lx(%8.8lx) Frame=%8.8lx\r\n"),
                        FunctionEntry->ExceptionHandler, FunctionEntry->HandlerData,
                        EstablisherFrame));
                pcstkForHandler = 0;
                if (KERNEL_MODE != GetContextMode (&ContextRecord1)) {
                    if (!(pcstkForHandler = (PCALLSTACK) AllocMem (HEAP_CALLSTACK))) {
                        // we're completely out of memory, can't do much about it
                        ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
                        break;
                    }
                    SetupCSTK (pcstkForHandler);
                }
                Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
                        EstablisherFrame, ContextRecord, &DispatcherContext,
                        FunctionEntry->ExceptionHandler, pcstkForHandler, ContextRecord1.Psr);
                // don't need to free pcstkForHandler since it'll be freed at callback return
                ExceptionFlags |=
                    (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE);
                DEBUGMSG(ZONE_SEH, (TEXT("exception dispostion = %d\r\n"), Disposition));

                // If the current scan is within a nested context and the frame
                // just examined is the end of the nested region, then clear
                // the nested context frame and the nested exception flag in
                // the exception flags.
                if (NestedFrame == EstablisherFrame) {
                    ExceptionFlags &= (~EXCEPTION_NESTED_CALL);
                    NestedFrame = 0;
                }

                // Case on the handler disposition.
                switch (Disposition) {
                    // The disposition is to execute a frame based handler. The
                    // target handler address is in DispatcherContext.ControlPc.
                    // Reset to the original context and switch to unwind mode.
                case ExceptionExecuteHandler:
                    DEBUGMSG(ZONE_SEH, (TEXT("Unwinding to %8.8lx Frame=%8.8lx\r\n"),
                            DispatcherContext.ControlPc, EstablisherFrame));
                    KPlpvTls = pth->tlsPtr = tlsSave;
                    UpdateASID(pth, pprcSave, akySave);
                    Handled =  NKUnwind(pth, TargetCStk, EstablisherFrame,
                                DispatcherContext.ControlPc, ExceptionRecord,
                                ExceptionRecord->ExceptionCode, ContextRecord, pcstk);

⌨️ 快捷键说明

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