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

📄 mdx86.c

📁 See Hanoi.cpp for the implementation of this cla
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved. */

#include "kernel.h"

#define Naked void __declspec(naked)

extern FXSAVE_AREA g_InitialFPUState;
extern KIDTENTRY g_aIntDescTable[];

// Default processor type & revision level information.
DWORD CEProcessorType = PROCESSOR_INTEL_486;
WORD ProcessorLevel = 0;
WORD ProcessorRevision = 0;
DWORD ProcessorFeatures = 0;

#define FN_BITS_PER_TAGWORD         16
#define FN_TAG_EMPTY                0x3
#define FN_TAG_MASK                 0x3
#define FX_TAG_VALID                0x1
#define NUMBER_OF_FP_REGISTERS      8
#define BYTES_PER_FP_REGISTER       10
#define BYTES_PER_FX_REGISTER       16
#define TS_MASK                     0x00000008
#define FPTYPE_HARDWARE 1
#define FPTYPE_SOFTWARE 2
DWORD dwFPType;

void DumpDwords(PDWORD pdw, int len) {
    int lc;
    lc = 0;
    NKDbgPrintfW(L"Dumping %d dwords", len);
    for (lc = 0 ; len ; ++pdw, ++lc, --len) {
        if (!(lc & 3))
            NKDbgPrintfW(L"\r\n%8.8lx -", pdw);
        NKDbgPrintfW(L" %8.8lx", *pdw);
    }
    NKDbgPrintfW(L"\r\n");
}

void DumpFrame(PTHREAD pth, PCONTEXT pctx, int id, int level) {
    NKDbgPrintfW(L"Exception %02x Thread=%8.8lx AKY=%8.8lx EIP=%8.8lx\r\n",
    		id, pth, pCurThread->aky, pctx->Eip);
    NKDbgPrintfW(L"Eax=%8.8lx Ebx=%8.8lx Ecx=%8.8lx Edx=%8.8lx\r\n",
            pctx->Eax, pctx->Ebx, pctx->Ecx, pctx->Edx);
    NKDbgPrintfW(L"Esi=%8.8lx Edi=%8.8lx Ebp=%8.8lx Esp=%8.8lx\r\n",
            pctx->Esi, pctx->Edi, pctx->Ebp, pctx->Esp);
    NKDbgPrintfW(L"CS=%4.4lx DS=%4.4lx ES=%4.4lx SS=%4.4lx FS=%4.4lx GS=%4.4lx\r\n",
            pctx->SegCs, pctx->SegDs, pctx->SegEs, pctx->SegSs, pctx->SegFs, pctx->SegGs);
    NKDbgPrintfW(L"Flags=%8.8lx\r\n",
            pctx->EFlags);
}

void DumpTctx(PTHREAD pth, int id, ulong addr, int level) {
    ulong espValue, ssValue;
    if ((pth->ctx.TcxCs&0xFFFF) == KGDT_R0_CODE) {
        espValue = pth->ctx.TcxNotEsp+16;
        ssValue = KGDT_R0_DATA;
    } else {
        espValue = pth->ctx.TcxEsp;
        ssValue = pth->ctx.TcxSs;
    }
    NKDbgPrintfW(L"Exception %02x Thread=%8.8lx Proc=%8.8lx '%s'\r\n",
   			id, pth, hCurProc, pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
    NKDbgPrintfW(L"EIP=%8.8lx AKY=%8.8lx Flags=%8.8lx EA=%8.8lx\r\n", 
            pth->ctx.TcxEip, pCurThread->aky, pth->ctx.TcxEFlags, addr);
    NKDbgPrintfW(L"Eax=%8.8lx Ebx=%8.8lx Ecx=%8.8lx Edx=%8.8lx\r\n",
            pth->ctx.TcxEax, pth->ctx.TcxEbx, pth->ctx.TcxEcx, pth->ctx.TcxEdx);
    NKDbgPrintfW(L"Esi=%8.8lx Edi=%8.8lx Ebp=%8.8lx Esp=%8.8lx\r\n",
            pth->ctx.TcxEsi, pth->ctx.TcxEdi, pth->ctx.TcxEbp, espValue);
    NKDbgPrintfW(L"CS=%4.4lx DS=%4.4lx ES=%4.4lx SS=%4.4lx FS=%4.4lx GS=%4.4lx\r\n",
            pth->ctx.TcxCs, pth->ctx.TcxDs, pth->ctx.TcxEs, ssValue,
            pth->ctx.TcxFs, pth->ctx.TcxGs);
   	if (level > 1) {
   	    DWORD addr;
   	    PDWORD pdw;
   	    int count = 16;
   		addr = espValue;
	    if (pth->ctx.TcxEbp >= espValue)
	        count = (pth->ctx.TcxEbp+16 - espValue) / 4;
	    pdw = VerifyAccess((PVOID)addr, VERIFY_KERNEL_OK, CurAKey);
	    if (pdw)
		    DumpDwords((PDWORD)addr, count);
    }
}

typedef struct ExcInfo {
    DWORD   linkage;
	ULONG	oldEip;
	UINT    oldMode;
	UCHAR	id;
	UCHAR   oldTFlag;
	USHORT  error;
	ULONG	info;
	UCHAR	lowSp;
	UCHAR	pad[3];
} EXCINFO;
typedef EXCINFO *PEXCINFO;

ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldEip) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));


Naked CpuIdTrap6Handler(void)
{
    __asm {
        // Illegal opcode handler when executing cpuid instruction
        add     dword ptr [esp], 2  // skip the cpuid instr by incrementing eip
        xor     eax, eax        // simulate an unsupported cpuid instruction
        xor     ebx, ebx        // by returning 0 for return values
        xor     ecx, ecx
        xor     edx, edx
        iretd
    }
}

void IdentifyCpu(void)
{
    __asm {
        pushfd
        cli
        mov     ecx, offset g_aIntDescTable
        push    dword ptr [ecx+30h]     // Save Trap06 handler in case
        push    dword ptr [ecx+34h]     // the CPUID instruction faults
        mov     eax, offset CpuIdTrap6Handler
        mov     word ptr [ecx+30h], ax  // Set LowWord
        shr     eax, 16
        mov     word ptr [ecx+36h], ax  // Set HighWord
        xor     eax, eax                // argument to CPUID
        _emit   0fh                     // cpuid instruction
        _emit   0a2h                    // sets eax, ebx, ecx, edx
        cmp     ebx, 756e6547h          // check for "Genu" string
        jne     short cpuid_trap        // not an Intel processor
        cmp     edx, 49656e69h          // check for "ineI" string
        jne     short cpuid_trap        // not an Intel processor
        cmp     ecx, 6c65746eh          // check for "ntel" string
        jne     short cpuid_trap        // not an Intel processor
        cmp     eax, 1                  // make sure level 1 is supported
        jc      short cpuid_trap        // no, then keep defaults
        mov     eax, 1                  // get the family and stepping
        _emit   0fh                     // cpuid instruction
        _emit   0a2h
        mov     ebx, eax
        mov     ecx, eax
        shr     ebx, 4
        and     ebx, 0Fh                // (ebx) = model
        and     ecx, 0Fh                // (ecx) = stepping
        shr     eax, 8
        and     eax, 0Fh                // (eax) = family
        cmp     eax, 4
        jne     cpu_not_p4
        mov     eax, PROCESSOR_INTEL_486
        jmp     short cpuid_store
cpu_not_p4:
        cmp     eax, 5
        jne     short cpu_not_p5
        mov     eax, PROCESSOR_INTEL_PENTIUM
        jmp     short cpuid_store
cpu_not_p5:
        mov     eax, PROCESSOR_INTEL_PENTIUMII
cpuid_store:
        mov     CEProcessorType, eax
        mov     ProcessorLevel, bx
        mov     ProcessorRevision, cx
        mov     ProcessorFeatures, edx
cpuid_trap:
        mov     ecx, offset g_aIntDescTable
        pop     dword ptr [ecx+34h]     // restore trap6 handler
        pop     dword ptr [ecx+30h]
        popfd
    }
}

BOOL HandleException(PTHREAD pth, int id, ulong addr) {
	PEXCINFO pexi;
	DWORD stackaddr;
	KCALLPROFON(0);
#if 0
    NKDbgPrintfW(L"Exception %02x Thread=%8.8lx(%8.8lx) IP=%8.8lx EA=%8.8lx Err=%4.4x\r\n",
   			id, pCurThread,pth, pth->ctx.TcxEip, addr, pth->ctx.TcxError & 0xFFFF);
#endif
    pexi = (struct ExcInfo *)((pth->ctx.TcxEsp & ~63) - sizeof(CALLSTACK));
    if (!((DWORD)pexi & 0x80000000) && DemandCommit((DWORD)pexi)) {
		stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
		if ((stackaddr >= pth->dwStackBound) || (stackaddr < pth->dwStackBase) ||
			((pth->dwStackBound = stackaddr) >= (pth->dwStackBase + MIN_STACK_RESERVE)) ||
			TEST_STACKFAULT(pth)) {
			KCALLPROFOFF(0);
			return 1; // restart instruction
		}
		SET_STACKFAULT(pth);
		id = 0xFF;		// stack fault exception code
		addr = (DWORD)pexi;
	}
	// Setup to capture the exception context in kernel mode but
	// running in thread context to allow preemption and stack growth.
	if (pth->ctx.TcxEip != (ulong)CaptureContext) {
		pexi->id = id;
		pexi->lowSp = (CHAR)(pth->ctx.TcxEsp & 63);
		pexi->oldEip = pth->ctx.TcxEip;
		pexi->oldMode = GetThreadMode(pth);
		pexi->info = addr;
		if (id != 16)
			pexi->error = (USHORT)pth->ctx.TcxError;
		else {
			WORD status;
		    _asm fnstsw status;
		    pexi->error = status;
			_asm fnclex;			
		}
		pexi->oldTFlag = (UCHAR)(pth->ctx.TcxEFlags >> 8) & 1;
        pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
        pCurThread->pcstkTop = (PCALLSTACK)pexi;
        pth->ctx.TcxEsp = (DWORD)pexi;
		pth->ctx.TcxEFlags &= ~0x0100; // Unset TF while in the debugger
		pth->ctx.TcxEip = (ulong)CaptureContext;
		if (pexi->oldMode != KERNEL_MODE)
    		SetThreadMode(pth, KERNEL_MODE);
    	KCALLPROFOFF(0);
		return TRUE;			// continue execution
	}
	DumpTctx(pth, id, addr, 10);
	RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pCurThread));
	SurrenderCritSecs();
	SET_RUNSTATE(pth,RUNSTATE_BLOCKED);
	RunList.pth = 0;
	SetReschedule();
	KCALLPROFOFF(0);
	return 0;
}

typedef struct _EXCARGS {
	DWORD dwExceptionCode;		/* exception code	*/
	DWORD dwExceptionFlags;		/* continuable exception flag	*/
	DWORD cArguments;			/* number of arguments in array	*/
	DWORD *lpArguments;			/* address of array of arguments	*/
} EXCARGS;
typedef EXCARGS *PEXCARGS;

BOOL SetCPUHardwareWatch(LPVOID lpv, DWORD dwFlags) {
    static PPROCESS pOwnerProc;
    
    if (!InSysCall()) 
        return KCall((PKFN)SetCPUHardwareWatch, lpv, dwFlags);
        
    KCALLPROFON(73);

    if (lpv == 0) {
        // dwFlags=0 means check to see if we want to take this breakpoint
        if (dwFlags == (DWORD)-1) {
            // check to see which breakpoint went off and
            // clear the debug register
            DWORD dwReason;
            DWORD dwMask=~0xf;
            _asm {
                mov eax, dr6
                mov dwReason, eax
                and eax, dwMask
                mov dr6, eax
            }
            // was the zeroptr breakpoint hit?
            if (dwReason&0x2 && pOwnerProc != pCurProc) {
                OutputDebugString(L"zero mapped breakpoint hit in wrong process!\r\n");
                KCALLPROFOFF(73);
                return 0;
            }
            KCALLPROFOFF(73);
            return 1;
        } else {
            // dwFlags=1 means disable the data watchpoint
            dwFlags = ~0xf;
            _asm {
                mov eax, dr7
                and eax, dwFlags
                mov dr7, eax
            }
            KCALLPROFOFF(73);
            return 1;
        }
    } else {
        DWORD dwMask=~0xff000f;
        LPVOID lpvZero=(LPVOID)UnMapPtr(lpv);
        if (dwFlags == HARDWARE_WATCH_READ) {
            dwFlags = 0xff000a;
        } else {
            dwFlags = 0xdd000a;
        }
        _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;
	BOOL bHandled;
	PEXCARGS pea;
	EXCEPTION_RECORD er;
	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, pexi->oldMode);
	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:
    		if (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)) {

⌨️ 快捷键说明

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