📄 mdx86.c
字号:
/* 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 2DWORD 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_storecpu_not_p4: cmp eax, 5 jne short cpu_not_p5 mov eax, PROCESSOR_INTEL_PENTIUM jmp short cpuid_storecpu_not_p5: mov eax, PROCESSOR_INTEL_PENTIUMIIcpuid_store: mov CEProcessorType, eax mov ProcessorLevel, bx mov ProcessorRevision, cx mov ProcessorFeatures, edxcpuid_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 + -