📄 mdx86.c
字号:
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) {
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx Proc=%8.8lx '%s'\r\n",
id, pth, hCurProc,
pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx ESP=%8.8lx EA=%8.8lx\r\n",
pCurThread->aky, pctx->Eip, pctx->Esp, info);
if (UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) {
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 (!UserDbgTrap(&er,pctx,FALSE) && ((UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) || !KDTrap(&er, pctx, FALSE))) {
bHandled = NKDispatchException(pth, &er, pctx);
if (!bHandled) {
if (!UserDbgTrap(&er, pctx, TRUE) && !KDTrap(&er, pctx, TRUE)) {
if (er.ExceptionCode == STATUS_BREAKPOINT) {
RETAILMSG(1, (TEXT("DEBUG_BREAK @%8.8lx Ignored.\r\n"), pctx->Eip));
DumpFrame(pth, pctx, id, 0);
if (*(uchar*)pctx->Eip == 0xCC)
++pctx->Eip;
else if (*(uchar*)pctx->Eip == 0xCD)
pctx->Eip += 2;
} else {
// Terminate the process.
RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"),
er.ExceptionCode));
DumpFrame(pth, pctx, id, 2);
if (InSysCall()) {
OutputDebugStringW(L"Halting system\r\n");
for (;;)
;
} else {
if (!GET_DEAD(pth)) {
SET_DEAD(pth);
pctx->Eip = (ULONG)pExitThread;
((ulong*)pctx->Esp)[1] = 0;
RETAILMSG(1, (TEXT("Terminating thread %8.8lx\r\n"), pth));
} else {
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:
// 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)pExitThread;
((ulong*)pctx->Esp)[1] = 0;
}
}
// 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
mov [ebp-16], eax // may overwrite CS value
mov [ebp-8], cs
pop eax // restore Eax
lea esp, [ebp-16] // (esp) = new stack (with Ebp & IRET frame pushed on)
pop ebp // (ebp) = original Ebp
iretd // continue at the desired address
}
}
// normal thread stack: from top, TLS then args then free
void MDCreateThread(PTHREAD pTh, LPVOID lpStack, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, DWORD dwVMBase, BOOL kmode, ulong param) {
ulong *args;
NK_PCR *pcr;
if (!((ulong)lpStack>>VA_SECTION))
lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
pTh->dwStackBase = (DWORD)lpStack;
// Allocate space for TLS & PCR info.
pcr = (NK_PCR *)((ulong)lpStack+cbStack - sizeof(NK_PCR));
// Allocate space for arguments to the start function.
pTh->ctx.TcxEsp = (ulong)pcr - 3*4;
pTh->dwStackBound = pTh->ctx.TcxEsp & ~(PAGE_SIZE-1);
args = (ulong*)pTh->ctx.TcxEsp;
pcr->ExceptionList = 0;
pcr->InitialStack = pTh->ctx.TcxEsp;
pcr->StackLimit = (DWORD)lpStack;
pTh->tlsPtr = pcr->tls;
args[1] = (ulong)lpStart;
args[2] = param;
args[0] = 0; // set return address to fault
pTh->ctx.TcxEip = (ULONG)lpBase;
pTh->ctx.TcxDs = KGDT_R3_DATA;
pTh->ctx.TcxEs = KGDT_R3_DATA;
pTh->ctx.TcxFs = KGDT_PCR;
pTh->ctx.TcxGs = 0;
pTh->ctx.TcxEFlags = 0x3200; // IOPL=3, IF=1
if (dwFPType == FPTYPE_HARDWARE) {
if (ProcessorFeatures & CPUID_FXSR) {
memcpy(&pcr->tcxExtended, &g_InitialFPUState,
sizeof(pcr->tcxExtended));
} else {
memcpy(&pcr->tcxFPU, &g_InitialFPUState, (sizeof(pcr->tcxFPU)+16));
}
} else if (dwFPType == FPTYPE_SOFTWARE)
memset(pcr->Emx87Data, 0, sizeof(pcr->Emx87Data));
SetThreadMode(pTh, ((kmode || bAllKMode) ? KERNEL_MODE : USER_MODE));
}
// main thread stack: from top, PCR then buf then buf2 then buf2 (ascii) then args then free
LPCWSTR MDCreateMainThread1(PTHREAD pTh, LPVOID lpStack, DWORD cbStack, DWORD dwVMBase,
LPBYTE buf, ulong buflen, LPBYTE buf2, ulong buflen2) {
LPBYTE buffer;
LPCWSTR pcmdline;
if (!((ulong)lpStack>>VA_SECTION))
lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
pTh->dwStackBase = (DWORD)lpStack;
// Allocate space for extra parameters on the stack and copy the bytes there.
buffer = (LPBYTE)((ulong)lpStack+cbStack-sizeof(NK_PCR) - (buflen+3&~3));
pcmdline = (LPCWSTR)buffer;
memcpy(buffer, buf, buflen);
buffer -= (buflen2+3&~3);
memcpy(buffer, buf2, buflen2);
KPlpvTls = pTh->tlsPtr = ((NK_PCR *)(pTh->dwStackBase+cbStack - sizeof(NK_PCR)))->tls;
pTh->pOwnerProc->lpszProcName = (LPWSTR)buffer;
return pcmdline;
}
void MDCreateMainThread2(PTHREAD pTh, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, BOOL kmode,
ulong p1, ulong p2, ulong buflen, ulong buflen2, ulong p4) {
LPBYTE buffer;
ulong *args;
NK_PCR *pcr;
// Allocate space for TLS & PCR info.
pcr = (NK_PCR *)(pTh->dwStackBase+cbStack - sizeof(NK_PCR));
pcr->ExceptionList = 0;
pcr->InitialStack = pTh->ctx.TcxEsp;
pcr->StackLimit = pTh->dwStackBase;
KPlpvTls = pTh->tlsPtr = pcr->tls;
// Allocate space for arguments to the start function.
buffer = (LPBYTE)(pTh->dwStackBase+cbStack-sizeof(NK_PCR) - (buflen+3&~3));
buffer -= (buflen2+3&~3);
pTh->ctx.TcxEsp = (ulong)buffer - 6*4;
pTh->dwStackBound = pTh->ctx.TcxEsp & ~(PAGE_SIZE-1);
args = (ulong*)pTh->ctx.TcxEsp;
args[1] = (ulong)lpStart;
args[2] = p1;
args[3] = p2;
args[4] = pTh->dwStackBase+cbStack-sizeof(NK_PCR) - (buflen+3&~3);
args[5] = p4;
args[0] = 0; // set return address to fault
pTh->ctx.TcxEip = (ULONG)lpBase;
pTh->ctx.TcxDs = KGDT_R3_DATA;
pTh->ctx.TcxEs = KGDT_R3_DATA;
pTh->ctx.TcxFs = KGDT_PCR;
pTh->ctx.TcxGs = 0;
pTh->ctx.TcxEFlags = 0x3200; // IOPL=3, IF=1
if (dwFPType == FPTYPE_HARDWARE) {
if (ProcessorFeatures & CPUID_FXSR) {
memcpy(&pcr->tcxExtended, &g_InitialFPUState,
sizeof(pcr->tcxExtended));
} else {
memcpy(&pcr->tcxFPU, &g_InitialFPUState, (sizeof(pcr->tcxFPU)+16));
}
} else if (dwFPType == FPTYPE_SOFTWARE)
memset(pcr->Emx87Data, 0, sizeof(pcr->Emx87Data));
SetThreadMode(pTh, ((kmode || bAllKMode) ? KERNEL_MODE : USER_MODE));
}
void ZeroPage(void *pvPage) {
_asm {
mov edi, pvPage
mov ecx, PAGE_SIZE/4
xor eax, eax
rep stosd
}
}
extern void FPUFlushContext(void);
BOOL DoThreadGetContext(HANDLE hTh, LPCONTEXT lpContext) {
PTHREAD pth;
PFXSAVE_AREA FxArea;
PFLOATING_SAVE_AREA FnArea;
ACCESSKEY ulOldKey;
if (!(pth = HandleToThread(hTh))) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (lpContext->ContextFlags & ~(CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SWITCHKEY(ulOldKey,0xffffffff);
if (pth->pThrdDbg && pth->pThrdDbg->psavedctx) {
if ((lpContext->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
lpContext->Ebp = pth->pThrdDbg->psavedctx->Ebp;
lpContext->Eip = pth->pThrdDbg->psavedctx->Eip;
lpContext->SegCs = pth->pThrdDbg->psavedctx->SegCs;
lpContext->EFlags = pth->pThrdDbg->psavedctx->EFlags;
lpContext->Esp = pth->pThrdDbg->psavedctx->Esp;
lpContext->SegSs = pth->pThrdDbg->psavedctx->SegSs;
}
if ((lpContext->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
lpContext->Edi = pth->pThrdDbg->psavedctx->Edi;
lpContext->Esi = pth->pThrdDbg->psavedctx->Esi;
lpContext->Ebx = pth->pThrdDbg->psavedctx->Ebx;
lpContext->Edx = pth->pThrdDbg->psavedctx->Edx;
lpContext->Ecx = pth->pThrdDbg->psavedctx->Ecx;
lpContext->Eax = pth->pThrdDbg->psavedctx->Eax;
}
if ((lpContext->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
lpContext->SegGs = pth->pThrdDbg->psavedctx->SegGs;
lpContext->SegFs = pth->pThrdDbg->psavedctx->SegFs;
lpContext->SegEs = pth->pThrdDbg->psavedctx->SegEs;
lpContext->SegDs = pth->pThrdDbg->psavedctx->SegDs;
}
if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT) {
FPUFlushContext();
lpContext->FloatSave = pth->pThrdDbg->psavedctx->FloatSave;
}
if ((lpContext->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS) {
}
} else {
if ((lpContext->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
lpContext->Ebp = pth->ctx.TcxEbp;
lpContext->Eip = pth->ctx.TcxEip;
lpContext->SegCs = pth->ctx.TcxCs;
lpContext->EFlags = pth->ctx.TcxEFlags;
lpContext->Esp = pth->ctx.TcxEsp;
lpContext->SegSs = pth->ctx.TcxSs;
}
if ((lpContext->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
lpContext->Edi = pth->ctx.TcxEdi;
lpContext->Esi = pth->ctx.TcxEsi;
lpContext->Ebx = pth->ctx.TcxEbx;
lpContext->Edx = pth->ctx.TcxEdx;
lpContext->Ecx = pth->ctx.TcxEcx;
lpContext->Eax = pth->ctx.TcxEax;
}
if ((lpContext->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS) {
lpContext->SegGs = pth->ctx.TcxGs;
lpContext->SegFs = pth->ctx.TcxFs;
lpContext->SegEs = pth->ctx.TcxEs;
lpContext->SegDs = pth->ctx.TcxDs;
}
if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT) {
if (ProcessorFeatures & CPUID_FXSR) {
FxArea = (PFXSAVE_AREA) PTH_TO_FLTSAVEAREAPTR(pth);
FnArea = &lpContext->FloatSave;
__asm {
// We won't get here if emulating FP, so CR0.EM will be 0
call FPUFlushContext // FPUFlushContext sets CR0.TS
clts
mov eax, FxArea
FXRESTOR_EAX // convert from fxsave format
mov eax, FnArea // in NK_PCR to fnsave format
fnsave [eax] // in CONTEXT structure
fwait
mov eax, cr0
or eax, TS_MASK
mov cr0, eax
}
} else {
FPUFlushContext();
lpContext->FloatSave = *(PTH_TO_FLTSAVEAREAPTR(pth));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -