📄 mdsh3.c
字号:
// the cause of the exception from the EXCINFO (CALLSTACK) structure.
pctx->R15 += pexi->lowSp + sizeof(CALLSTACK);
exc = pexi->exc;
info = pexi->info;
// Construct an EXCEPTION_RECORD from the EXCINFO structure
er.ExceptionInformation[1] = info;
// TLB Miss on load or store. Attempt to auto-commit the page. If that fails,
// fall through into general exception processing.
if (((exc == 0x3) || (exc == 2)) && AutoCommit(info)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
switch (exc) {
case 8: // Address error (store)
er.ExceptionInformation[0] = 1;
case 7: // Address error (load or instruction fetch)
if (GetContextMode(pctx) != USER_MODE || !(info&0x80000000)) {
er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
break;
}
goto accessError;
case 3: // TLB Miss (store)
case 4: // TLB modification
case 6: // TLB protection violation (store)
er.ExceptionInformation[0] = 1;
case 2: // TLB miss (load or instruction fetch)
case 5: // TLB protection violation (load)
if (ProcessPageFault((exc==3)||(exc==4)||(exc==6), info)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
accessError:
er.ExceptionCode = STATUS_ACCESS_VIOLATION;
er.NumberParameters = 2;
break;
#ifdef SH4
case 0x40:
case 0x41:
KCall((PKFN)SwitchFPUOwner,pctx);
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
case 9: { // floating point exception
DWORD code;
code = GetCauseFloatCode();
#if 0
NKDbgPrintfW(L"ExceptionAddress 0x%x\r\n", er.ExceptionAddress);
NKDbgPrintfW(L"code 0x%x, exc 0x%x\r\n",code,exc);
#endif
if (code & 0x10)
er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
else if (code & 0x8)
er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
else if (code & 0x4)
er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
else if (code & 0x2)
er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
else if (code & 0x1)
er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
else
{
//
// Reach here
// --if code is 0x20 (FPU error)
// --if code is 0x0 (processor thinks an ieee
// exception is possible)
//
// both cases require that fp operation be emulated
// for correct ieee result.
//
// save the fpscr before FPUFlushContext will flush it
// to zero.
//
// FPUFlushContext clears fpscr
//
FPUFlushContext();
//
// Copy current thread fregs and xfreg to user context
//
memcpy(&pctx->FRegs[0],&pCurThread->ctx.FRegs[0],sizeof(DWORD)*16);
memcpy(&pctx->xFRegs[0],&pCurThread->ctx.xFRegs[0],sizeof(DWORD)*16);
pctx->Fpscr = pCurThread->ctx.Fpscr;
pctx->Fpul = pCurThread->ctx.Fpul;
if (HandleHWFloatException(&er,pctx))
{
//
// update current thread context with user context
//
memcpy(&pCurThread->ctx.FRegs[0],&pctx->FRegs[0],sizeof(DWORD)*16);
memcpy(&pCurThread->ctx.xFRegs[0],&pctx->xFRegs[0],sizeof(DWORD)*16);
pCurThread->ctx.Fpul = pctx->Fpul;
pCurThread->ctx.Fpscr = pctx->Fpscr;
pCurThread->ctx.Psr = pctx->Psr;
pctx->Fir+=2; // +2: return control to instruction successor
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
}
//
// Update user context fpscr and fpul
//
pCurThread->ctx.Fpscr = pctx->Fpscr;
pCurThread->ctx.Fpul = pctx->Fpul;
pCurThread->ctx.Psr = pctx->Psr;
break;
}
#endif
case 11: // Breakpoint
pctx->Fir -= 2; // backup to the trapa instruction
er.ExceptionInformation[0] = info;
er.ExceptionCode = STATUS_BREAKPOINT;
break;
case 12: // Reserved instruction
case 13: // Illegal slot instruction
#ifdef SH3
//
// Assume DSP instruction.
// If DSP processor and DSP not enabled, enable the DSP.
//
if ( SH3DSP && ((pctx->Psr & 0x1000) == 0) ){
KCall((PKFN)SwitchDSPOwner,pctx);
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
#endif
er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
break;
case 15: // Hardware breakpoint
er.ExceptionInformation[0] = info;
er.ExceptionCode = STATUS_USER_BREAK;
break;
case 0xFF: // Stack overflow
er.ExceptionCode = STATUS_STACK_OVERFLOW;
er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
break;
}
}
if (exc != 11 && exc != 15) {
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx Proc=%8.8lx '%s'\r\n",
exc<<5, pth, hCurProc,
pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx RA=%8.8lx TEA=%8.8lx\r\n",
pCurThread->aky, pctx->Fir, pctx->PR, 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->Fir));
DumpFrame(pth, pctx, exc<<5, info);
pctx->Fir += 2; // skip over the trapa instruction
} else {
// Terminate the process.
RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"),
er.ExceptionCode));
DumpFrame(pth, pctx, exc<<5, info);
if (InSysCall()) {
OutputDebugStringW(L"Halting system\r\n");
for (;;)
;
} else {
if (!GET_DEAD(pth)) {
SET_DEAD(pth);
pctx->Fir = (ULONG)pExitThread;
pctx->R0 = 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 (exc == 2 || exc == 3)
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 (exc == 0xFF)
CLEAR_STACKFAULT(pth);
if (GET_DYING(pth) && !GET_DEAD(pth) && (pCurProc == pth->pOwnerProc)) {
SET_DEAD(pth);
CLEAR_USERBLOCK(pth);
CLEAR_DEBUGWAIT(pth);
pctx->Fir = (ULONG)pExitThread;
pctx->R0 = 0;
}
return;
}
void DumpFrame(PTHREAD pth, PCONTEXT pctx, DWORD dwExc, DWORD info) {
DWORD oldCCR;
oldCCR = CCR;
CCR = 0; // disable the cache to avoid changing its state
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx AKY=%8.8lx PC=%8.8lx\r\n",
dwExc, pth, pCurThread->aky, pctx->Fir);
NKDbgPrintfW(L" R0=%8.8lx R1=%8.8lx R2=%8.8lx R3=%8.8lx\r\n",
pctx->R0, pctx->R1, pctx->R2, pctx->R3);
NKDbgPrintfW(L" R4=%8.8lx R5=%8.8lx R6=%8.8lx R7=%8.8lx\r\n",
pctx->R4, pctx->R5, pctx->R6, pctx->R7);
NKDbgPrintfW(L" R8=%8.8lx R9=%8.8lx R10=%8.8lx R11=%8.8lx\r\n",
pctx->R8, pctx->R9, pctx->R10, pctx->R11);
NKDbgPrintfW(L"R12=%8.8lx R13=%8.8lx R14=%8.8lx R15=%8.8lx\r\n",
pctx->R12, pctx->R13, pctx->R14, pctx->R15);
NKDbgPrintfW(L" PR=%8.8lx SR=%8.8lx\r\n TEA/TRPA=%8.8x",
pctx->PR, pctx->Psr, info);
NKDbgPrintfW(L"PTEL=%8.8lx PTEH=%8.8lx MMUCR=%8.8lx TTB=%8.8lx\r\n",
MMUPTEL, MMUPTEH, MMUCR, MMUTTB);
NKDbgPrintfW(L"CCR=%8.8lx\r\n", oldCCR);
CCR = oldCCR; // restore original cache state
}
// 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) {
if (!((ulong)lpStack>>VA_SECTION))
lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
pTh->dwStackBase = (DWORD)lpStack;
// Clear all registers: Esp. fpu state for SH-4
memset(&pTh->ctx, 0, sizeof(pTh->ctx));
// Leave room for arguments and TLS on the stack
pTh->ctx.R15 = (ulong)lpStack + cbStack - (TLS_MINIMUM_AVAILABLE*4) - 4*4;
pTh->dwStackBound = pTh->ctx.R15 & ~(PAGE_SIZE-1);
pTh->tlsPtr = (LPDWORD)((ulong)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4));
pTh->ctx.R4 = (ulong)lpStart;
pTh->ctx.R5 = param;
pTh->ctx.PR = 0;
#ifdef SH4
pTh->ctx.Psr = 0x8000; // disable floating point
pTh->ctx.Fpscr = 0x40000; // handle no exceptions
#else
pTh->ctx.Psr = 0;
#endif
pTh->ctx.Fir = (ULONG)lpBase;
pTh->ctx.ContextFlags = CONTEXT_FULL;
SetThreadMode(pTh, ((kmode || bAllKMode) ? KERNEL_MODE : USER_MODE));
}
// main thread stack: from top, TLS 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) {
LPCWSTR pcmdline;
if (!((ulong)lpStack>>VA_SECTION))
lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
pTh->dwStackBase = (DWORD)lpStack;
pcmdline = (LPCWSTR)((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+3)&~3));
memcpy((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+3)&~3),buf,buflen);
pTh->pOwnerProc->lpszProcName = (LPWSTR)((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+3)&~3)-((buflen2+3)&~3));
memcpy(pTh->pOwnerProc->lpszProcName,buf2,buflen2);
KPlpvTls = pTh->tlsPtr = (LPDWORD)((ulong)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4));
return pcmdline;
}
void MDCreateMainThread2(PTHREAD pTh, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, BOOL kmode,
ulong p1, ulong p2, ulong buflen, ulong buflen2, ulong p4) {
// Clear all registers: Esp. fpu state for SH-4
memset(&pTh->ctx, 0, sizeof(pTh->ctx));
// Leave room for arguments on the stack
pTh->ctx.R15 = (pTh->dwStackBase + cbStack - (TLS_MINIMUM_AVAILABLE*4) - 8*4 - ((buflen+3)&~3) - ((buflen2+3)&~3)) & ~7;
pTh->dwStackBound = pTh->ctx.R15 & ~(PAGE_SIZE-1);
pTh->ctx.R4 = (ulong)lpStart;
pTh->ctx.R5 = p1;
pTh->ctx.R6 = p2;
pTh->ctx.R7 = pTh->dwStackBase+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+3)&~3);
((LPDWORD)pTh->ctx.R15)[4] = p4;
pTh->ctx.PR = 0;
#ifdef SH4
pTh->ctx.Psr = 0x8000; // disable floating point
pTh->ctx.Fpscr = 0x40000; // handle no exceptions
#else
pTh->ctx.Psr = 0;
#endif
pTh->ctx.Fir = (ULONG)lpBase;
SetThreadMode(pTh, ((kmode || bAllKMode) ? KERNEL_MODE : USER_MODE));
pTh->ctx.ContextFlags = CONTEXT_FULL;
}
#ifdef XTIME
extern DWORD ExceptionTime;// tick at exception entry
void SyscallTime(int iSyscall) {
DWORD dwTime;
dwTime = ExceptionTime - TMUADDR->tcnt1;
xt.dwTime[iSyscall]+= dwTime;
if ((++xt.dwCount[iSyscall]) == 1)
xt.dwMax[iSyscall]=xt.dwMin[iSyscall]= dwTime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -