📄 mdsched.c
字号:
LPVOID lpStack,
DWORD cbStack,
LPVOID lpBase,
LPVOID lpStart,
BOOL kmode,
ulong param
)
{
DEBUGCHK ((ulong)lpStack>>VA_SECTION);
#ifdef DEBUG
// Clear out the register context for debugging.
memset(&pTh->ctx, 0xBD, sizeof(pTh->ctx));
#endif
pTh->tlsPtr = TLSPTR (lpStack, cbStack);
// Leave room for arguments and PRETLS on the stack
pTh->ctx.IntSp = (ulong) pTh->tlsPtr - SIZE_PRETLS - 4*REG_SIZE;
KSTKBASE(pTh) = (DWORD) lpStack;
KSTKBOUND(pTh) = (DWORD) pTh->ctx.IntSp & ~(PAGE_SIZE-1);
pTh->ctx.IntA0 = (ulong)lpStart;
pTh->ctx.IntA1 = param;
pTh->ctx.IntK0 = 0;
pTh->ctx.IntK1 = 0;
pTh->ctx.IntRa = 0;
pTh->ctx.Fir = (ULONG)lpBase;
if (kmode || bAllKMode) {
pTh->ctx.Psr = PSR_XX_C | PSR_FR_C | PSR_UX_C | KERNEL_MODE;
KTHRDINFO (pTh) |= UTLS_INKMODE;
} else {
pTh->ctx.Psr = PSR_XX_C | PSR_FR_C | PSR_UX_C | USER_MODE;
KTHRDINFO (pTh) &= ~UTLS_INKMODE;
}
#ifdef MIPS_HAS_FPU
pTh->ctx.Fsr = 0x01000000; // handle no exceptions
#endif
pTh->ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
}
// main thread stack: from top, TLS then PRETLS then buf then buf2 (ascii) then args then free
void MDInitSecureStack(LPBYTE lpStack)
{
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
MDSetupMainThread (
PTHREAD pTh,
LPBYTE pCurSP,
LPVOID lpBase,
LPVOID lpStart,
BOOL kmode,
ulong dwModCnt
)
{
REG_TYPE *pArgs;
PPROCESS pprc = pTh->pOwnerProc;
#ifdef DEBUG
// Clear out the register context for debugging.
memset(&pTh->ctx, 0xBD, sizeof(pTh->ctx));
#endif
// Leave room for arguments, PRETLS, command line, and program name on the stack
pTh->ctx.IntSp = (DWORD) pCurSP - 8*REG_SIZE; // 8 arguments
KSTKBOUND(pTh) = (DWORD) pTh->ctx.IntSp & ~(PAGE_SIZE-1);
pArgs = (REG_TYPE*)pTh->ctx.IntSp;
pTh->ctx.IntA0 = (ulong)lpStart;
pTh->ctx.IntA2 = dwModCnt;
pTh->ctx.IntA3 = (DWORD) pprc->pcmdline;
#if defined(MIPSIV)
// Make sure we sign extend pointer arguments (i.e. hInstance and hPrevInstance)
pTh->ctx.IntA1 = (long) pprc->hProc;
pArgs[4] = (long) hCoreDll;
pArgs[7] = (long) pprc->BasePtr;
#else
pTh->ctx.IntA1 = (DWORD) pprc->hProc;
pArgs[4] = (DWORD) hCoreDll;
pArgs[7] = (DWORD) pprc->BasePtr;
#endif
pArgs[5] = pprc->e32.e32_sect14rva;
pArgs[6] = pprc->e32.e32_sect14size;
pTh->ctx.IntK0 = 0;
pTh->ctx.IntK1 = 0;
pTh->ctx.IntRa = 0;
pTh->ctx.Fir = (ULONG)lpBase;
if (kmode || bAllKMode) {
pTh->ctx.Psr = PSR_XX_C | PSR_FR_C | PSR_UX_C | KERNEL_MODE;
KTHRDINFO (pTh) |= UTLS_INKMODE;
} else {
pTh->ctx.Psr = PSR_XX_C | PSR_FR_C | PSR_UX_C | USER_MODE;
KTHRDINFO (pTh) &= ~UTLS_INKMODE;
}
#ifdef MIPS_HAS_FPU
pTh->ctx.Fsr = 0x01000000; // handle no exceptions
#endif
pTh->ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
}
typedef struct ExcInfo {
DWORD linkage;
ULONG oldFir;
UINT oldMode0;
CAUSE causeAndMode;
ULONG badVAddr;
UCHAR lowSp;
UCHAR pad[3];
} EXCINFO;
typedef EXCINFO *PEXCINFO;
ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldFir) == offsetof(CALLSTACK,retAddr));
//ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
HandleException(
PTHREAD pth,
CAUSE cause,
ULONG badVAddr
)
{
PEXCINFO pexi;
DWORD stackaddr;
KCALLPROFON(0);
#if 0
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx(%8.8lx) Proc=%8.8lx '%s'\r\n",
cause.XCODE, pCurThread,pth, hCurProc, pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx RA=%8.8lx BVA=%8.8lx\r\n",
pCurThread->aky, pth->ctx.Fir, pth->ctx.IntRa, badVAddr);
#endif
pexi = (struct ExcInfo *)((pth->ctx.IntSp & ~63) - ALIGNSTK (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);
DumpFrame(pth, &pth->ctx, cause, badVAddr, 10);
pth->ctx.IntA0 = STATUS_STACK_OVERFLOW;
pth->ctx.IntA1 = pth->ctx.Fir;
pth->ctx.IntSp = (DWORD) pth->tlsPtr - SIZE_PRETLS - 512; // arbitrary safe address
pth->ctx.Fir = (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);
cause.XCODE = 30; // stack fault exception code
badVAddr = (DWORD)pexi;
break;
case DCMT_OLD:
// already commited. do nothing
break;
default:
DEBUGCHK (0);
}
if (pth->ctx.Fir != (ulong)CaptureContext+4) {
pexi->causeAndMode = cause;
pexi->lowSp = (UCHAR)(pth->ctx.IntSp & 63);
pexi->oldFir = pth->ctx.Fir;
((PCALLSTACK) pexi)->dwPrcInfo = CST_IN_KERNEL | (((KERNEL_MODE == GetThreadMode(pth)) || InDebugger)? 0 : CST_MODE_FROM_USER);
//pexi->oldMode = GetThreadMode(pth);
pexi->badVAddr = badVAddr;
pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
pCurThread->pcstkTop = (PCALLSTACK)pexi;
pth->ctx.IntSp = (DWORD)pexi;
pth->ctx.Psr = PSR_XX_C | PSR_FR_C | PSR_UX_C | KERNEL_MODE;
pth->ctx.Fir = (ulong)CaptureContext;
KCALLPROFOFF(0);
return TRUE; // continue execution
}
DumpFrame(pth, &pth->ctx, cause, badVAddr, 10);
RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pth));
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;
extern BOOL SetCPUHardwareWatch(LPVOID, DWORD);
#ifdef MIPS_HAS_FPU
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SwitchFPUOwner(
PCONTEXT pctx
)
{
KCALLPROFON(61);
if (g_CurFPUOwner != pCurThread) {
if (g_CurFPUOwner)
SaveFloatContext(g_CurFPUOwner);
g_CurFPUOwner = pCurThread;
RestoreFloatContext(pCurThread);
}
KCALLPROFOFF(61);
}
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ExceptionDispatch(
PCONTEXT pctx
)
{
PTHREAD pth;
PEXCINFO pexi;
EXCEPTION_RECORD er;
ULONG badVAddr;
int xcode;
CAUSE cause;
PEXCARGS pea;
DWORD dwThrdInfo = KTHRDINFO (pCurThread); // need to save it since it might get changed during exception handling
pth = pCurThread;
// Get the EXCINFO off the thread's callstack.
pexi = (PEXCINFO)pth->pcstkTop;
DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Fir=%8.8lx\r\n"),pexi, pexi->oldFir));
// Update CONTEXT with infomation saved in the EXCINFO structure
pctx->Fir = pexi->oldFir;
SetContextMode(pctx, (((PCALLSTACK)pexi)->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE);
#if (_M_MRX000 >= 5000)
// Mips4
pctx->Psr |= PSR_XX_C | PSR_FR_C | PSR_UX_C;
#endif
pctx->IntSp = (ULONG)pctx + sizeof(CONTEXT);
memset(&er, 0, sizeof(er));
er.ExceptionAddress = (PVOID)pctx->Fir;
// 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)) {
xcode = -1;
pctx->Fir -= 4; // to avoid boundary problems at the end of a try block.
DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
pctx->IntA0, pctx->IntA1, pctx->IntA2, pexi));
er.ExceptionCode = (DWORD)pctx->IntA0;
er.ExceptionFlags = (DWORD)pctx->IntA1;
if (pctx->IntA3 && pctx->IntA2) {
if (pctx->IntA2 > EXCEPTION_MAXIMUM_PARAMETERS) {
er.ExceptionCode = STATUS_INVALID_PARAMETER;
er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
} else {
memcpy(er.ExceptionInformation, (void*)pctx->IntA3, (DWORD)pctx->IntA2*sizeof(DWORD));
er.NumberParameters = (DWORD)pctx->IntA2;
}
}
} else {
// CPU detected exception. Extract some additional information about
// the cause of the exception from the EXCINFO (CALLSTACK) structure.
badVAddr = pexi->badVAddr;
cause = pexi->causeAndMode;
xcode = pexi->causeAndMode.XCODE;
pctx->Fir = pexi->oldFir;
pctx->IntSp += pexi->lowSp + ALIGNSTK (sizeof(CALLSTACK));
if (((xcode == 2) || (xcode == 3)) && AutoCommit(badVAddr)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
switch (xcode) {
case 0: // RaiseException or invalid system call
er.ExceptionCode = STATUS_INVALID_SYSTEM_SERVICE;
if ((pea = (PEXCARGS)badVAddr) != 0) {
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;
}
}
}
break;
case 5: // Address error (store)
case 4: // Address error (load or instruction fetch)
if (GetContextMode(pctx) != USER_MODE || !(badVAddr&0x80000000)) {
er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
break;
}
goto accessError;
case 2: // TLB miss (load or instruction fetch)
case 3: // TLB Miss (store)
case 1: // TLB modification
if (!InSysCall ()
&& ((GetContextMode(pctx) != USER_MODE) || !(badVAddr&0x80000000))
&& ProcessPageFault((xcode==3) || (xcode == 1), badVAddr)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
accessError:
er.ExceptionInformation[0] = xcode & 1;
er.ExceptionCode = STATUS_ACCESS_VIOLATION;
er.ExceptionInformation[1] = badVAddr;
er.NumberParameters = 2;
break;
case 6: // Bus error (instruction fetch)
case 7: // Bus error (data reference)
er.ExceptionInformation[0] = xcode & 1;
er.ExceptionCode = STATUS_ACCESS_VIOLATION;
er.ExceptionInformation[1] = badVAddr;
er.NumberParameters = 2;
break;
case 9: // Breakpoint
if (IsMIPS16Supported && (pctx->Fir & 1)) { // MIPS16 mode
er.ExceptionInformation[0] = *(USHORT *)(pctx->Fir & ~1);
er.ExceptionCode = STATUS_BREAKPOINT;
if (er.ExceptionInformation[0] == MIPS16_BREAK (DIVIDE_BY_ZERO_BREAKPOINT)) {
er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
} else if (er.ExceptionInformation[0] == MIPS16_BREAK (MULTIPLY_OVERFLOW_BREAKPOINT) ||
er.ExceptionInformation[0] == MIPS16_BREAK (DIVIDE_OVERFLOW_BREAKPOINT)) {
er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
} else if (er.ExceptionInformation[0] == MIPS16_BREAK (BREAKIN_BREAKPOINT)) {
pctx->Fir += 2;
}
} else { // MIPS32 mode
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -