📄 mdsh3.c
字号:
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 && !IsNoFaultMsgSet ()) {
// if we faulted in DllMain doing PROCESS_ATTACH, the process name will
// be pointing to other process's (the creator) address space. Make sure
// we don't fault on displaying process name.
LPWSTR pProcName = pCurProc->lpszProcName? pCurProc->lpszProcName : L"";
LPCWSTR pszNamePC, pszNameRA;
DWORD dwOfstPC = pctx->Fir, dwOfstRA = pctx->PR;
pszNamePC = FindModuleNameAndOffset (dwOfstPC, &dwOfstPC);
pszNameRA = FindModuleNameAndOffset (dwOfstRA, &dwOfstRA);
if (!((DWORD) pProcName & 0x80000000)
&& (((DWORD) pProcName >> VA_SECTION) != (DWORD) (pCurProc->procnum+1)))
pProcName = L"";
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx Proc=%8.8lx '%s'\r\n",
exc<<5, pth, hCurProc, pProcName);
NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx(%s+0x%8.8lx) RA=%8.8lx(%s+0x%8.8lx) TEA=%8.8lx\r\n",
pCurThread->aky, pctx->Fir, pszNamePC, dwOfstPC, pctx->PR, pszNameRA, dwOfstRA, info);
if (IsNoFaultSet ()) {
NKDbgPrintfW(L"TLSKERN_NOFAULT set... bypassing kernel debugger.\r\n");
}
}
DEBUGMSG (ZONE_SEH, (L"ExceptionDispatch: PSR = %8.8lx\r\n", pctx->Psr));
// 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 (!(pexi->linkage & 1) && IsValidKPtr (pexi)) {
// from RaiseException, free the callstack structure
FreeMem (pexi, HEAP_CALLSTACK);
}
if (!UserDbgTrap(&er,pctx,FALSE) && (IsNoFaultSet () || !HDException(&er, pctx, FALSE))) {
BOOL bHandled = FALSE;
// don't pass a break point exception to NKDispatchException
if (er.ExceptionCode != STATUS_BREAKPOINT) {
// to prevent recursive exception due to user messed-up TLS
KTHRDINFO (pth) &= ~UTLS_INKMODE;
bHandled = NKDispatchException(pth, &er, pctx);
}
if (!bHandled && !UserDbgTrap(&er, pctx, TRUE) && !HDException(&er, pctx, TRUE)) {
if (er.ExceptionCode == STATUS_BREAKPOINT) {
if (!pvHDNotifyExdi || pctx->Fir < (DWORD)pvHDNotifyExdi || pctx->Fir > ((DWORD)pvHDNotifyExdi + HD_NOTIFY_MARGIN))
RETAILMSG(1, (TEXT("DEBUG_BREAK @%8.8lx Ignored.\r\n"), pctx->Fir));
pctx->Fir += 2; // skip over the trapa instruction
} else {
// Terminate the process.
RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"),
er.ExceptionCode));
if (InSysCall()) {
DumpFrame(pth, pctx, exc<<5, info);
lpNKHaltSystem ();
FakeNKHaltSystem ();
} else {
if (!GET_DEAD(pth)) {
PCALLSTACK pcstk = pth->pcstkTop;
while (pcstk && !pcstk->akyLast) {
pth->pcstkTop = (PCALLSTACK) ((DWORD) pcstk->pcstkNext & ~1);
if (IsValidKPtr (pcstk)) {
FreeMem (pcstk, HEAP_CALLSTACK);
}
pcstk = pth->pcstkTop;
}
DEBUGCHK (!pcstk); // should this happen, we have a fault in callback that wasn't handled
// by PSL
// clean up all the temporary callstack
if (er.ExceptionCode == STATUS_STACK_OVERFLOW) {
// stack overflow, not much we can do. Make sure we have enough room to run
// pExcpExitThread
// randomly picked a valid SP
pctx->R15 = (DWORD) pth->tlsPtr - SECURESTK_RESERVE - (PAGE_SIZE >> 1);
}
SET_DEAD(pth);
//pth->tlsSecure[TLSSLOT_KERNEL] |= TLSKERN_TRYINGTODIE;
pctx->Fir = (ULONG)pExcpExitThread;
pctx->R4 = er.ExceptionCode; // argument: exception code
pctx->R5 = (ULONG)er.ExceptionAddress; // argument: exception address
RETAILMSG(1, (TEXT("Terminating thread %8.8lx, PSR = %8.8lx\r\n"), pth, pctx->Psr));
} else {
DumpFrame(pth, pctx, exc<<5, info);
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:
// restore ThrdInfo
KTHRDINFO (pth) = dwThrdInfo;
// 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)pExcpExitThread;
pctx->R4 = er.ExceptionCode; // argument: exception code
pctx->R5 = (ULONG)er.ExceptionAddress; // argument: exception address
}
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
}
/* Machine dependent constants */
const DWORD cbMDStkAlign = 4; // stack 4 bytes aligned
//------------------------------------------------------------------------------
// normal thread stack: from top, TLS, PRETLS, then args then free
//------------------------------------------------------------------------------
void
MDCreateThread(
PTHREAD pTh,
LPVOID lpStack,
DWORD cbStack,
LPVOID lpBase,
LPVOID lpStart,
BOOL kmode,
ulong param
)
{
DEBUGCHK ((ulong)lpStack>>VA_SECTION);
pTh->tlsPtr = TLSPTR (lpStack, cbStack);
KSTKBASE(pTh) = (DWORD)lpStack;
// Clear all registers: Esp. fpu state for SH-4
memset(&pTh->ctx, 0, sizeof(pTh->ctx));
// Leave room for arguments and TLS and PRETLS on the stack
pTh->ctx.R15 = (ulong) pTh->tlsPtr - SIZE_PRETLS - 4*4;
KSTKBOUND(pTh) = pTh->ctx.R15 & ~(PAGE_SIZE-1);
pTh->ctx.R4 = (ulong)lpStart;
pTh->ctx.R5 = param;
pTh->ctx.PR = 0;
#ifdef SH4
pTh->ctx.Psr = SR_FPU_DISABLED; // disable floating point
pTh->ctx.Fpscr = 0x40000; // handle no exceptions
#else
pTh->ctx.Psr = 0; // disable DSP
#endif
pTh->ctx.Fir = (ULONG)lpBase;
pTh->ctx.ContextFlags = CONTEXT_FULL;
if (kmode || bAllKMode) {
SetThreadMode (pTh, KERNEL_MODE);
KTHRDINFO (pTh) |= UTLS_INKMODE;
} else {
SetThreadMode (pTh, USER_MODE);
KTHRDINFO (pTh) &= ~UTLS_INKMODE;
}
}
//------------------------------------------------------------------------------
// main thread stack: from top, TLS then buf then buf2 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
)
{
LPDWORD pArgs;
PPROCESS pprc = pTh->pOwnerProc;
// Clear all registers: Esp. fpu state for SH-4
memset(&pTh->ctx, 0, sizeof(pTh->ctx));
// Leave room for arguments on stack
pTh->ctx.R15 = ((ulong) pCurSP - 8*4) & ~7;
KSTKBOUND(pTh) = pTh->ctx.R15 & ~(PAGE_SIZE-1);
pArgs = (LPDWORD)pTh->ctx.R15;
pTh->ctx.R4 = (ulong)lpStart;
pTh->ctx.R5 = (ulong)pprc->hProc;
pTh->ctx.R6 = dwModCnt;
pTh->ctx.R7 = (ulong) pprc->pcmdline;
pArgs[4] = (DWORD) hCoreDll;
pArgs[5] = pprc->e32.e32_sect14rva;
pArgs[6] = pprc->e32.e32_sect14size;
pArgs[7] = (DWORD) pprc->BasePtr;
pTh->ctx.PR = 0;
#ifdef SH4
pTh->ctx.Psr = SR_FPU_DISABLED; // disable floating point
pTh->ctx.Fpscr = 0x40000; // handle no exceptions
#else
pTh->ctx.Psr = 0; // disable DSP
#endif
pTh->ctx.Fir = (ULONG)lpBase;
if (kmode || bAllKMode) {
SetThreadMode (pTh, KERNEL_MODE);
KTHRDINFO (pTh) |= UTLS_INKMODE;
} else {
SetThreadMode (pTh, USER_MODE);
KTHRDINFO (pTh) &= ~UTLS_INKMODE;
}
pTh->ctx.ContextFlags = CONTEXT_FULL;
}
// For the SH3 the compiler generated exception functions expect the following input arguments:
// Exception Filter: r4 = frame, r5 = exception pointers
// Termination Handler: r4 = frame, r5 = abnormal term flag
#define __C_ExecuteExceptionFilter(eptr, fn, efrm) ((fn)((efrm), (eptr)))
#define __C_ExecuteTerminationHandler(bAb, fn, efrm) ((fn)((efrm), (bAb)))
//------------------------------------------------------------------------------
// Routine Description:
// This function scans the scope tables associated with the specified
// procedure and calls exception and termination handlers as necessary.
//
// Arguments:
// ExceptionRecord - Supplies a pointer to an exception record.
//
// EstablisherFrame - Supplies a pointer to frame of the establisher function.
//
// ContextRecord - Supplies a pointer to a context record.
//
// DispatcherContext - Supplies a pointer to the exception dispatcher or
// unwind dispatcher context.
//
// Return Value:
// If the exception is handled by one of the exception filter routines, then
// there is no return from this routine and RtlUnwind is called. Otherwise,
// an exception disposition value of continue execution or continue search is
// returned.
//------------------------------------------------------------------------------
EXCEPTION_DISPOSITION __C_specific_handler(
PEXCEPTION_RECORD ExceptionRecord,
PVOID EstablisherFrame,
PCONTEXT ContextRecord,
PDISPATCHER_CONTEXT DispatcherContext
)
{
ULONG ControlPc;
EXCEPTION_FILTER ExceptionFilter;
EXCEPTION_POINTERS ExceptionPointers;
PRUNTIME_FUNCTION FunctionEntry;
ULONG Index;
PSCOPE_TABLE ScopeTable;
ULONG TargetPc;
TERMINATION_HANDLER TerminationHandler;
LONG Value;
// Get address of where control left the establisher, the address of the
// function table entry that describes the function, and the address of
// the scope table.
ControlPc = DispatcherContext->ControlPc;
FunctionEntry = DispatcherContext->FunctionEntry;
ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
// If an unwind is not in progress, then scan the scope table and call
// the appropriate exception filter routines. Otherwise, scan the scope
// table and call the appropriate termination handlers using the target
// PC obtained from the context record.
// are called.
if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
// Scan the scope table and call the appropriate exception filter
// routines.
ExceptionPointers.ExceptionRecord = ExceptionRecord;
ExceptionPointers.ContextRecord = ContextRecord;
for (Index = 0; Index < ScopeTable->Count; Index += 1) {
if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
(ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
ScopeTable->ScopeRecord[Index].JumpTarget) {
// Call the exception filter routine.
ExceptionFilter = (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
Value = __C_ExecuteExceptionFilter(&ExceptionPointers,ExceptionFilter,(ULONG)EstablisherFrame);
// If the return value is less than zero, then dismiss the
// exception. Otherwise, if the value is greater than zero,
// then unwind to the target exception handler. Otherwise,
// continue the search for an exception filter.
if (Value < 0)
return ExceptionContinueExecution;
else if (Value > 0) {
DispatcherContext->ControlPc = ScopeTable->ScopeRecord[Index].JumpTarget;
return ExceptionExecuteHandler;
}
}
}
} else {
// Scan the scope table and call the appropriate termination handler
// routines.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -