Restore Cxbx's emu exception (SEH) while keep lle exception handler (VEH)

This commit is contained in:
RadWolfie 2018-07-12 10:26:25 -05:00
parent a9d1f60b04
commit 97cf31961b
7 changed files with 73 additions and 38 deletions

View File

@ -188,18 +188,14 @@ void SetupPerTitleKeys()
void CxbxLaunchXbe(void(*Entry)())
{
#ifdef USE_SEH
__try
{
#endif // USE_SEH
Entry();
#ifdef USE_SEH
}
__except (EmuException(GetExceptionInformation()))
{
EmuWarning("Problem with ExceptionFilter");
}
#endif // USE_SEH
}
// Entry point address XOR keys per Xbe type (Retail, Debug or Chihiro) :

View File

@ -196,7 +196,7 @@ bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e)
}
return false;
}
}
void EmuExceptionNonBreakpointUnhandledShow(LPEXCEPTION_POINTERS e)
{
@ -224,12 +224,17 @@ bool IsXboxCodeAddress(xbaddr addr)
// for example by g_VMManager.CheckConflictingVMA(addr, 0).
return (addr >= XBE_IMAGE_BASE) && (addr <= XBE_MAX_VA);
// Note : Not IS_USER_ADDRESS(), that would include host DLL code
}
}
static thread_local bool bOverrideException;
bool IsRdtscInstruction(xbaddr addr);
ULONGLONG CxbxRdTsc(bool xbox);
bool TryHandleException(EXCEPTION_POINTERS *e)
bool lleTryHandleException(EXCEPTION_POINTERS *e)
{
// Initalize local thread variable
bOverrideException = false;
// Only handle exceptions which originate from Xbox code
if (!IsXboxCodeAddress(e->ContextRecord->Eip)) {
return false;
@ -253,8 +258,8 @@ bool TryHandleException(EXCEPTION_POINTERS *e)
}
break;
case STATUS_BREAKPOINT:
// Let user choose between continue or break
return EmuExceptionBreakpointAsk(e);
// Pass breakpoint down to EmuException since VEH doesn't have call stack viewable.
return false;
default:
// Skip past CxbxDebugger-specific exceptions thrown when an unsupported was attached (ie Visual Studio)
if (CxbxDebugger::IsDebuggerException(e->ExceptionRecord->ExceptionCode)) {
@ -267,9 +272,62 @@ bool TryHandleException(EXCEPTION_POINTERS *e)
if (EmuX86_DecodeException(e)) {
// We're allowed to continue :
return true;
}
}
// Try to Report this exception to the debugger, which may allow handling of this exception
// Try to report this exception to the debugger, which may allow handling of this exception
if (CxbxDebugger::CanReport()) {
bool DebuggerHandled = false;
CxbxDebugger::ReportAndHandleException(e->ExceptionRecord, DebuggerHandled);
if (!DebuggerHandled) {
// Kill the process immediately without the Cxbx notifier
EmuExceptionExitProcess();
}
// Bypass exception
}
else {
// notify user
EmuExceptionNonBreakpointUnhandledShow(e);
}
// Unhandled exception :
bOverrideException = true;
return false;
}
// Only for LLE emulation coding (to help performance a little bit better)
LONG NTAPI lleException(EXCEPTION_POINTERS *e)
{
g_bEmuException = true;
LONG result = lleTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
g_bEmuException = false;
return result;
}
// Only for Cxbx emulation coding (to catch all of last resort exception may occur.)
bool EmuTryHandleException(EXCEPTION_POINTERS *e)
{
// Check if lle exception is already called here first before emu exception.
if (bOverrideException) {
return false;
}
// Make sure access-violations reach EmuX86_DecodeException() as soon as possible
if (e->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) {
switch (e->ExceptionRecord->ExceptionCode) {
case STATUS_BREAKPOINT:
// Let user choose between continue or break
return EmuExceptionBreakpointAsk(e);
default:
// Skip past CxbxDebugger-specific exceptions thrown when an unsupported was attached (ie Visual Studio)
if (CxbxDebugger::IsDebuggerException(e->ExceptionRecord->ExceptionCode)) {
return true;
}
}
}
// Try to report this exception to the debugger, which may allow handling of this exception
if (CxbxDebugger::CanReport()) {
bool DebuggerHandled = false;
CxbxDebugger::ReportAndHandleException(e->ExceptionRecord, DebuggerHandled);
@ -290,10 +348,10 @@ bool TryHandleException(EXCEPTION_POINTERS *e)
return false;
}
LONG NTAPI EmuException(EXCEPTION_POINTERS *e)
int EmuException(EXCEPTION_POINTERS *e)
{
g_bEmuException = true;
LONG result = TryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
LONG result = EmuTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
g_bEmuException = false;
return result;
}

View File

@ -48,7 +48,8 @@ inline void NTAPI EmuWarning(const char *szWarningMessage, ...) { }
#endif
// exception handler
extern LONG NTAPI EmuException(EXCEPTION_POINTERS *e);
extern LONG NTAPI lleException(EXCEPTION_POINTERS *e);
int EmuException(EXCEPTION_POINTERS *e);
// print call stack trace
#ifdef _DEBUG

View File

@ -161,21 +161,17 @@ DWORD ExecuteDpcQueue()
// Set DpcRoutineActive to support KeIsExecutingDpc:
KeGetCurrentPrcb()->DpcRoutineActive = TRUE; // Experimental
DbgPrintf("KRNL: Global DpcQueue, calling DPC at 0x%.8X\n", pkdpc->DeferredRoutine);
#ifdef USE_SEH
__try {
#endif // USE_SEH
// Call the Deferred Procedure :
pkdpc->DeferredRoutine(
pkdpc,
pkdpc->DeferredContext,
pkdpc->SystemArgument1,
pkdpc->SystemArgument2);
#ifdef USE_SEH
} __except (EmuException(GetExceptionInformation()))
{
EmuWarning("Problem with ExceptionFilter!");
}
#endif // USE_SEH
KeGetCurrentPrcb()->DpcRoutineActive = FALSE; // Experimental
}
@ -209,20 +205,17 @@ DWORD ExecuteDpcQueue()
break; // while
DbgPrintf("KRNL: Global TimerQueue, calling DPC at 0x%.8X\n", pkdpc->DeferredRoutine);
#ifdef USE_SEH
__try {
#endif // USE_SEH
pkdpc->DeferredRoutine(
pkdpc,
pkdpc->DeferredContext,
pkdpc->SystemArgument1,
pkdpc->SystemArgument2);
#ifdef USE_SEH
} __except (EmuException(GetExceptionInformation()))
{
EmuWarning("Problem with ExceptionFilter!");
}
#endif // USE_SEH
}
}

View File

@ -167,10 +167,8 @@ static unsigned int WINAPI PCSTProxy
}
// use the special calling convention
#ifdef USE_SEH
__try
{
#endif // USE_SEH
// Given the non-standard calling convention (requiring
// the first argument in ebp+4) we need the below __asm.
//
@ -187,14 +185,11 @@ static unsigned int WINAPI PCSTProxy
lea ebp, [esp - 4]
jmp near esi
}
#ifdef USE_SEH
}
__except (EmuException(GetExceptionInformation()))
{
EmuWarning("Problem with ExceptionFilter!");
}
#endif // USE_SEH
callComplete:
@ -212,19 +207,15 @@ void PspSystemThreadStartup
IN PVOID StartContext
)
{
#ifdef USE_SEH
__try
{
#endif // USE_SEH
(StartRoutine)(StartContext);
#ifdef USE_SEH
}
__except (EmuException(GetExceptionInformation()))
// TODO : Call PspUnhandledExceptionInSystemThread(GetExceptionInformation())
{
EmuWarning("Problem with ExceptionFilter!"); // TODO : Disable?
}
#endif // USE_SEH
xboxkrnl::PsTerminateSystemThread(STATUS_SUCCESS);
}

View File

@ -1131,8 +1131,8 @@ opcode_error:
void EmuX86_Init()
{
DbgPrintf("X86 : Initializing distorm version %d\n", distorm_version());
#ifndef USE_SEH // implies VEH
AddVectoredExceptionHandler(/*FirstHandler=*/ULONG(true), EmuException);
#endif // !USE_SEG
AddVectoredExceptionHandler(/*FirstHandler=*/ULONG(true), lleException);
EmuX86_InitContextRecordOffsetByRegisterType();
}

View File

@ -1390,19 +1390,15 @@ typedef struct {
void WINAPI EmuFiberStartup(fiber_context_t* context)
{
#ifdef USE_SEH
__try
{
#endif //USE_SEH
LPFIBER_START_ROUTINE pfStartRoutine = (LPFIBER_START_ROUTINE)context->lpStartRoutine;
pfStartRoutine(context->lpParameter);
#ifdef USE_SEH
}
__except (EmuException(GetExceptionInformation()))
{
EmuWarning("Problem with ExceptionFilter");
}
#endif //USE_SEH
}
// ******************************************************************