Merge pull request #28 from RadWolfie/fix-pr-1341
Restore Cxbx's emu exception (SEH) while keep LLE exception handler (VEH)
This commit is contained in:
commit
866f986136
|
@ -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) :
|
||||
|
|
|
@ -196,7 +196,7 @@ bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e)
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuExceptionNonBreakpointUnhandledShow(LPEXCEPTION_POINTERS e)
|
||||
{
|
||||
|
@ -226,10 +226,33 @@ bool IsXboxCodeAddress(xbaddr addr)
|
|||
// Note : Not IS_USER_ADDRESS(), that would include host DLL code
|
||||
}
|
||||
|
||||
void genericException(EXCEPTION_POINTERS *e) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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 +276,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,33 +290,58 @@ 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
|
||||
if (CxbxDebugger::CanReport()) {
|
||||
bool DebuggerHandled = false;
|
||||
CxbxDebugger::ReportAndHandleException(e->ExceptionRecord, DebuggerHandled);
|
||||
if (DebuggerHandled) {
|
||||
// Bypass exception
|
||||
return false;
|
||||
}
|
||||
|
||||
// Kill the process immediately without the Cxbx notifier
|
||||
EmuExceptionExitProcess();
|
||||
}
|
||||
else {
|
||||
// notify user
|
||||
EmuExceptionNonBreakpointUnhandledShow(e);
|
||||
}
|
||||
genericException(e);
|
||||
|
||||
// We do not need EmuException to handle it again.
|
||||
bOverrideException = true;
|
||||
|
||||
// Unhandled exception :
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG NTAPI EmuException(EXCEPTION_POINTERS *e)
|
||||
// Only for LLE emulation coding (to help performance a little bit better)
|
||||
LONG NTAPI lleException(EXCEPTION_POINTERS *e)
|
||||
{
|
||||
g_bEmuException = true;
|
||||
LONG result = TryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
|
||||
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 first before emu exception.
|
||||
if (bOverrideException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genericException(e);
|
||||
|
||||
// Unhandled exception :
|
||||
return false;
|
||||
}
|
||||
|
||||
int EmuException(EXCEPTION_POINTERS *e)
|
||||
{
|
||||
g_bEmuException = true;
|
||||
LONG result = EmuTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
|
||||
g_bEmuException = false;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
|
Loading…
Reference in New Issue