📄 mdx86.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#include "kernel.h"
#define Naked void __declspec(naked)
extern FXSAVE_AREA g_InitialFPUState;
extern KIDTENTRY g_aIntDescTable[];
extern void (*lpNKHaltSystem)(void);
extern void FakeNKHaltSystem (void);
// Default processor type & revision level information.
DWORD CEProcessorType = PROCESSOR_INTEL_486;
WORD ProcessorLevel = 0;
WORD ProcessorRevision = 0;
DWORD ProcessorFeatures = 0;
DWORD ProcessorFeaturesEx = 0;
DWORD CEInstructionSet = PROCESSOR_X86_32BIT_INSTRUCTION;
DWORD dwFPType;
const wchar_t NKCpuType [] = TEXT("x86");
#define PtrCurThd [KData].pCurThd
#define PtrCurProc [KData].pCurPrc
/* Machine dependent constants */
const DWORD cbMDStkAlign = 4; // stack 4 bytes aligned
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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) {
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 oldMode0;
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));
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void SafeIdentifyCpu(void)
{
__asm {
pushfd
cli
pushfd // Save EFLAGS to stack
pop eax // Store EFLAGS in EAX
mov ecx,eax // Save in ECX for testing later
xor eax,00200000h // Switch bit 21
push eax // Copy changed value to stack
popfd // Save changed EAX to EFLAGS
pushfd // Push EFLAGS to top of stack
pop eax // Store EFLAGS in EAX
cmp eax,ecx // See if bit 21 has changed
jz cpuid_trap // If no change,no CPUID
// CPUID is supported
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
// Let's get extended CPUID data (EAX = 0x80000001)
mov eax, 0x80000001
_emit 0fh // cpuid instruction
_emit 0a2h
mov ProcessorFeaturesEx, edx
cpuid_trap:
popfd
}
}
#pragma warning(disable:4733)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
HandleException(
PTHREAD pth,
int id,
ulong addr
)
{
PEXCINFO pexi;
DWORD stackaddr, *pArgs;
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));
// before we touch pexi, we need to commit stack or we'll fault while
// accessing it.
switch (DemandCommit ((DWORD) pexi, pth)) {
case DCMT_FAILED:
// fatal stack error
NKDbgPrintfW (L"Fatal Stack Error, Terminating thread %8.8lx\r\n", pth);
DumpTctx(pth, id, addr, 10);
pth->ctx.TcxEsp = (DWORD) pth->tlsPtr - SIZE_PRETLS - 512; // arbitrary safe address
pArgs = (LPDWORD) pth->ctx.TcxEsp;
pArgs[0] = 0; // no return address
pArgs[1] = STATUS_STACK_OVERFLOW; // argument, exception code
pArgs[2] = pth->ctx.TcxEip; // argument, exception address
pth->ctx.TcxEip = (DWORD) pExcpExitThread;
KCALLPROFOFF(0);
return TRUE;
case DCMT_NEW:
// commited a new page. check if we hit the last page.
// generate stack overflow exception if yes.
stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
if ((stackaddr >= KSTKBOUND(pth))
|| ((KSTKBOUND(pth) = stackaddr) >= (KSTKBASE(pth) + MIN_STACK_RESERVE))
|| TEST_STACKFAULT(pth)) {
KCALLPROFOFF(0);
return TRUE; // restart instruction
}
SET_STACKFAULT(pth);
id = 0xFF; // stack fault exception code
addr = (DWORD)pexi;
break;
case DCMT_OLD:
// already commited. do nothing
break;
default:
DEBUGCHK (0);
}
// 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;
((PCALLSTACK) pexi)->dwPrcInfo = CST_IN_KERNEL | ((KERNEL_MODE == GetThreadMode(pth))? 0 : CST_MODE_FROM_USER);
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -