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

📄 mdx86.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        _asm {
            mov eax, lpv
            mov dr0, eax
            mov eax, lpvZero
            mov dr1, eax
            mov eax, dr7
            and eax, dwMask
            or  eax, dwFlags
            mov dr7, eax
        }
        pOwnerProc = pCurProc;
        KCALLPROFOFF(73);
        return 1;
    }

    KCALLPROFOFF(73);
}
    


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
ExceptionDispatch(
    PCONTEXT pctx
    ) 
{
    PTHREAD pth;
    PEXCINFO pexi;
    int id;
    ULONG info = 0;
    PEXCARGS pea;
    EXCEPTION_RECORD er;
    DWORD dwThrdInfo = KTHRDINFO (pCurThread);  // need to save it since it might get changed during exception handling
    BOOL  fInKMode;
    pth = pCurThread;
    pexi = (PEXCINFO)pth->pcstkTop;
    DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Eip=%8.8lx id=%x\r\n"),
            pexi, pexi->oldEip, pexi->id));
    // Update CONTEXT with infomation saved in the EXCINFO structure
    pctx->Eip = pexi->oldEip;
    pctx->Esp = (DWORD)pctx + sizeof(CONTEXT);
    SetContextMode(pctx, (((PCALLSTACK)pexi)->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE);
    memset(&er, 0, sizeof(er));
    er.ExceptionAddress = (PVOID)pctx->Eip;
    // Check for RaiseException call versus a CPU detected exception.
    // RaiseException just becomes a call to CaptureContext as a KPSL.
    // HandleExcepion sets the LSB of the callstack linkage but ObjectCall
    // does not.
    if (!(pexi->linkage & 1)) {
        NK_PCR *pcr = (NK_PCR *)((char *)pth->tlsPtr - offsetof(NK_PCR, tls));
        // Fill in exception record information from the parameters passed to
        // the RaiseException call.
        // Restore exception list linkage.
        DEBUGCHK(pcr->ExceptionList == -2);
        pcr->ExceptionList = ((PCALLSTACK)pexi)->extra;
                pea = (PEXCARGS)(pctx->Esp + 4);
        id = -1;
        pctx->Esp += 4;     // Remove return address from the stack
        DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
                pea->dwExceptionCode, pea->dwExceptionFlags, pea->cArguments, pexi));
        er.ExceptionCode = pea->dwExceptionCode;
        er.ExceptionFlags = pea->dwExceptionFlags;
        if (pea->lpArguments && pea->cArguments) {
            if (pea->cArguments > EXCEPTION_MAXIMUM_PARAMETERS) {
                er.ExceptionCode = STATUS_INVALID_PARAMETER;
                er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
            } else {
                memcpy(er.ExceptionInformation, pea->lpArguments,
                        pea->cArguments*sizeof(DWORD));
                er.NumberParameters = pea->cArguments;
            }
        }
    } else {
        // CPU detected exception. Extract some additional information about
        // the cause of the exception from the EXCINFO (CALLSTACK) structure.
        id = pexi->id;
        info = pexi->info;
        pctx->EFlags |= pexi->oldTFlag << 8;
        pctx->Esp += pexi->lowSp + sizeof(CALLSTACK);
        if ((id == 14) && AutoCommit(info)) {
            pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
            goto continueExecution;
        }
        // Construct an EXCEPTION_RECORD from the EXCINFO structure
        er.ExceptionInformation[1] = info;
        switch (id) {
        case 14:    // Page fault
            er.ExceptionInformation[0] = (pexi->error >> 1) & 1;
            goto accessError;
        case 13:        // General Protection Fault
            er.ExceptionInformation[0] = 1; accessError:
            fInKMode = (GetContextMode(pctx) == KERNEL_MODE);
            // er.ExceptionInformation[0] == read or write (1 for write)
            if (!InSysCall ()
                && (!(info & 0x80000000) || fInKMode)
                // writing to shared section require KMode access
                && (!IsInSharedSection(info) || !er.ExceptionInformation[0] || fInKMode)
                && ProcessPageFault(er.ExceptionInformation[0], info)) {
                pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
                goto continueExecution;
            }
            er.ExceptionCode = STATUS_ACCESS_VIOLATION;
            er.NumberParameters = 2;
            break;

        case 3:     // Breakpoint
            er.ExceptionInformation[0] = 1; // DEBUGBREAK_STOP_BREAKPOINT
            er.ExceptionCode = STATUS_BREAKPOINT;
            break;

        case 2: // Stop thread breakpoint
            er.ExceptionInformation[0] = 3; // DEBUG_THREAD_SWITCH_BREAKPOINT
            er.ExceptionCode = STATUS_BREAKPOINT;
            break;


        case 1:     // Breakpoint
            er.ExceptionInformation[0] = 0;
            er.ExceptionCode = STATUS_SINGLE_STEP;
            // If you are using the SetCPUHardware watch function you will probably 
            // want to uncomment the following lines so that it will clear the register
            // automatically on exception
/*          
            if(!SetCPUHardwareWatch(0, (DWORD)-1)) {
                pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
                goto continueExecution;
            }
*/          
            break;

        case 0:     // Divide by zero
            er.ExceptionInformation[0] = 0;
            er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
            break;

        case 6: // Reserved instruction
            er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
            break;

        case 16: {
            if (pexi->error & 0x01)
                er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
            else if (pexi->error & 0x4)
                er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
            else if (pexi->error & 0x8)
                er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
            else if (pexi->error & 0x10)
                er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
            else if (pexi->error & 0x20)
                er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
            else
                er.ExceptionCode = STATUS_FLOAT_DENORMAL_OPERAND;
            break;
        }
        case 0xFF:  // Stack overflow
            er.ExceptionCode = STATUS_STACK_OVERFLOW;
            er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
            break;
            
        }
    }
    if (id != 1 && id != 3 && !IsNoFaultMsgSet ()) {
        // if we faulted in DllMain doing PROCESS_ATTACH, the process name will
        // be pointing to other process's (the creator) address space. Make sure
        // we don't fault on displaying process name.
        LPWSTR pProcName = pCurProc->lpszProcName? pCurProc->lpszProcName : L"";
        LPCWSTR pszNamePC;
        DWORD dwOfstPC = pctx->Eip;
        pszNamePC = FindModuleNameAndOffset (dwOfstPC, &dwOfstPC);
        if (!((DWORD) pProcName & 0x80000000)
            && (((DWORD) pProcName >> VA_SECTION) != (DWORD) (pCurProc->procnum+1)))
            pProcName = L"";
        NKDbgPrintfW(L"Exception %03x Thread=%8.8lx Proc=%8.8lx '%s'\r\n",
                id, pth, hCurProc, pProcName);
        NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx(%s+0x%8.8lx) ESP=%8.8lx EA=%8.8lx\r\n",
                pCurThread->aky, pctx->Eip, pszNamePC, dwOfstPC, pctx->Esp, info);
        if (IsNoFaultSet ()) {
            NKDbgPrintfW(L"TLSKERN_NOFAULT set... bypassing kernel debugger.\r\n");
        }
    }
    // Invoke the kernel debugger to attempt to debug the exception before
    // letting the program resolve the condition via SEH.
    pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
    if (!(pexi->linkage & 1) && IsValidKPtr (pexi)) {
        // from RaiseException, free the callstack structure
        FreeMem (pexi, HEAP_CALLSTACK);
    }
    if (!UserDbgTrap(&er, pctx, FALSE) && (IsNoFaultSet () || !HDException(&er, pctx, FALSE))) {
        BOOL bHandled = FALSE;
        // don't pass a break point exception to NKDispatchException
        if ((er.ExceptionCode != STATUS_BREAKPOINT) && (er.ExceptionCode != STATUS_SINGLE_STEP)) {
            // to prevent recursive exception due to user messed-up TLS
            KTHRDINFO (pth) &= ~UTLS_INKMODE;
            bHandled = NKDispatchException(pth, &er, pctx);
        }
        if (!bHandled && !UserDbgTrap(&er, pctx, TRUE) && !HDException(&er, pctx, TRUE)) {
            if (er.ExceptionCode == STATUS_BREAKPOINT) {
                if (!pvHDNotifyExdi || pctx->Eip < (DWORD)pvHDNotifyExdi  || pctx->Eip > ((DWORD)pvHDNotifyExdi + HD_NOTIFY_MARGIN))
                    RETAILMSG(1, (TEXT("DEBUG_BREAK @%8.8lx Ignored.\r\n"), pctx->Eip));
                if (*(uchar*)pctx->Eip == 0xCC)
                    ++pctx->Eip;
                else if (*(uchar*)pctx->Eip == 0xCD)
                    pctx->Eip += 2;
            } else {
                // Unhandled exception, terminate the process.
                RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"),
                        er.ExceptionCode));
                if (InSysCall()) {
                    DumpFrame(pth, pctx, id, 0);
                    lpNKHaltSystem ();
                    FakeNKHaltSystem ();
                } else {
                    if (!GET_DEAD(pth)) {
                        PCALLSTACK pcstk = pth->pcstkTop;
                        while (pcstk && !pcstk->akyLast) {
                            pth->pcstkTop = (PCALLSTACK) ((DWORD) pcstk->pcstkNext & ~1);
                            if (IsValidKPtr (pcstk)) {
                                FreeMem (pcstk, HEAP_CALLSTACK);
                            }
                            pcstk = pth->pcstkTop;
                        }
                        DEBUGCHK (!pcstk);   // should this happen, we have a fault in callback that wasn't handled
                                             // by PSL
                        // clean up all the temporary callstack
                        if (er.ExceptionCode == STATUS_STACK_OVERFLOW) {
                            // stack overflow, not much we can do. Make sure we have enough room to run
                            // pExcpExitThread
                            // randomly picked a valid SP
                            pctx->Esp = (DWORD) pth->tlsPtr - SECURESTK_RESERVE - (PAGE_SIZE >> 1);
                        }
                        SET_DEAD(pth);
                        //pth->tlsSecure[TLSSLOT_KERNEL] |= TLSKERN_TRYINGTODIE;

                        pctx->Eip = (ULONG)pExcpExitThread;
//                        pctx->Esp -= 12;                               // room for the faked call
                        ((ulong*)pctx->Esp)[1] = er.ExceptionCode;     // argument, exception code
                        ((PVOID*)pctx->Esp)[2] = er.ExceptionAddress;  // argument, exception address
                        
                        RETAILMSG(1, (TEXT("Terminating thread %8.8lx\r\n"), pth));
                    } else {
                        DumpFrame(pth, pctx, id, 0);
                        RETAILMSG(1, (TEXT("Can't terminate thread %8.8lx, sleeping forever\r\n"), pth));
                        SurrenderCritSecs();
                        Sleep(INFINITE);
                        DEBUGCHK(0);    // should never get here
                    }
                }
            }
        }
    }
    if (id == 14)
        GuardCommit(info);
continueExecution:

    // restore ThrdInfo
    KTHRDINFO (pth) = dwThrdInfo;
    
    // If returning from handling a stack overflow, reset the thread's stack overflow
    // flag. It would be good to free the tail of the stack at this time
    // so that the thread will stack fault again if the stack gets too big. But we
    // are currently using that stack page.
    if (id == 0xFF)
        CLEAR_STACKFAULT(pth);
    if (GET_DYING(pth) && !GET_DEAD(pth) && (pCurProc == pth->pOwnerProc)) {
        SET_DEAD(pth);
        CLEAR_USERBLOCK(pth);
        CLEAR_DEBUGWAIT(pth);
        pctx->Eip = (ULONG)pExcpExitThread;
        ((ulong*)pctx->Esp)[1] = er.ExceptionCode;     // argument, exception code
        ((PVOID*)pctx->Esp)[2] = er.ExceptionAddress;  // argument, exception address
    }   
}



//------------------------------------------------------------------------------
// Capture processor state into a full CONTEXT structure for debugging
// and exception handling.
//
//  (eax) = ptr to EXCINFO structure
//------------------------------------------------------------------------------
Naked 
CaptureContext(void) 
{
    __asm {
        push    ss
        push    esp     // will be repaired by ExceptionDispatch
        pushfd
        push    cs
        push    eax     // Eip filled in by ExceptionDispatch
        push    ebp
        push    eax
        push    ecx
        push    edx
        push    ebx
        push    esi
        push    edi
        push    ds
        push    es
        push    fs
        push    gs
        mov     ecx, KGDT_R3_DATA
        mov     ds, cx
        mov     es, cx
        cld
        sub     esp, size FLOATING_SAVE_AREA
        push    0       // dr7
        push    0       // dr6
        push    0       // dr3
        push    0       // dr2
        push    0       // dr1
        push    0       // dr0
        push    CONTEXT_FULL
        mov     ebx, esp        // (ebx) = ptr to context structure
        push    ebx             // (arg0) = ptr to CONTEXT
        call    ExceptionDispatch

        // Reload processor state from possibly edited 
        lea     esp, [ebx].SegGs
        pop     gs
        pop     fs
        pop     es
        pop     ds
        pop     edi
        pop     esi
        pop     ebx
        pop     edx
        pop     ecx
        mov     ax, cs              // (ax) = current code selector
        xor     eax, [esp+12]       // (ax) = CS ^ target selector
        and     eax, 0000fffcH      // (eax) = selector bits that differ
        jz      short no_ring_switch
        pop     eax
        pop     ebp
        iretd

// Restore frame without a ring switch.  Special care must be taken here because
// we need to restore Esp but an IRETD without a ring switch will not restore
// the SS:ESP.  Since we are returning the same ring, all that needs to be restored
// are Esp and Eip. This is done by copying the new Eip and new Ebp values onto the
// new stack, switching to the new stack and then restoring Ebp and returning.
// The return must be via an IRETD so that single stepping works correctly.
//
// At this point the stack frame is:
//      24  ss
//      20  esp
//      16  flags
//      12  cs
//      08  eip
//      04  ebp
//      00  eax
//      ---------< esp points here

no_ring_switch:
        mov     ebp, [esp+20]       // (ebp) = new stack pointer
        mov     eax, [esp+16]       // (eax) = new EFlags
        mov     [ebp-4], eax        // may overwrite SS value
        mov     eax, [esp+8]        // (eax) = new eip
        mov     [ebp-12], eax       // may overwrite EFlags value
        mov     eax, [esp+4]        // (eax) = new ebp

⌨️ 快捷键说明

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