update Windows' SEH, fix overflow exception, and non-Windows platform support

This commit is contained in:
RadWolfie 2020-05-29 20:56:38 -05:00
parent 64f69f78ae
commit b5358508d6
9 changed files with 147 additions and 184 deletions

View File

@ -986,15 +986,8 @@ typedef struct {
void WINAPI EmuFiberStartup(fiber_context_t* context) void WINAPI EmuFiberStartup(fiber_context_t* context)
{ {
__try LPFIBER_START_ROUTINE pfStartRoutine = (LPFIBER_START_ROUTINE)context->lpStartRoutine;
{ pfStartRoutine(context->lpParameter);
LPFIBER_START_ROUTINE pfStartRoutine = (LPFIBER_START_ROUTINE)context->lpStartRoutine;
pfStartRoutine(context->lpParameter);
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter");
}
} }
// ****************************************************************** // ******************************************************************

View File

@ -88,14 +88,8 @@ public:
m_Pending = false; m_Pending = false;
} }
__try { BOOLEAN(__stdcall *ServiceRoutine)(xboxkrnl::PKINTERRUPT, void*) = (BOOLEAN(__stdcall *)(xboxkrnl::PKINTERRUPT, void*))Interrupt->ServiceRoutine;
BOOLEAN(__stdcall *ServiceRoutine)(xboxkrnl::PKINTERRUPT, void*) = (BOOLEAN(__stdcall *)(xboxkrnl::PKINTERRUPT, void*))Interrupt->ServiceRoutine; BOOLEAN result = ServiceRoutine(Interrupt, Interrupt->ServiceContext);
BOOLEAN result = ServiceRoutine(Interrupt, Interrupt->ServiceContext);
}
__except (EmuException(GetExceptionInformation()))
{
EmuLogEx(CXBXR_MODULE::KRNL, LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
} }
private: private:
bool m_Asserted = false; bool m_Asserted = false;

View File

@ -301,17 +301,13 @@ void ExecuteDpcQueue()
// Set DpcRoutineActive to support KeIsExecutingDpc: // Set DpcRoutineActive to support KeIsExecutingDpc:
KeGetCurrentPrcb()->DpcRoutineActive = TRUE; // Experimental KeGetCurrentPrcb()->DpcRoutineActive = TRUE; // Experimental
EmuLog(LOG_LEVEL::DEBUG, "Global DpcQueue, calling DPC at 0x%.8X", pkdpc->DeferredRoutine); EmuLog(LOG_LEVEL::DEBUG, "Global DpcQueue, calling DPC at 0x%.8X", pkdpc->DeferredRoutine);
__try {
// Call the Deferred Procedure : // Call the Deferred Procedure :
pkdpc->DeferredRoutine( pkdpc->DeferredRoutine(
pkdpc, pkdpc,
pkdpc->DeferredContext, pkdpc->DeferredContext,
pkdpc->SystemArgument1, pkdpc->SystemArgument1,
pkdpc->SystemArgument2); pkdpc->SystemArgument2);
} __except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
KeGetCurrentPrcb()->DpcRoutineActive = FALSE; // Experimental KeGetCurrentPrcb()->DpcRoutineActive = FALSE; // Experimental
} }

View File

@ -643,19 +643,14 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration
{ {
/* Call the DPC */ /* Call the DPC */
EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine); EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine);
__try {
// Call the Deferred Procedure : // Call the Deferred Procedure :
DpcEntry[i].Routine( DpcEntry[i].Routine(
DpcEntry[i].Dpc, DpcEntry[i].Dpc,
DpcEntry[i].Context, DpcEntry[i].Context,
UlongToPtr(SystemTime.u.LowPart), UlongToPtr(SystemTime.u.LowPart),
UlongToPtr(SystemTime.u.HighPart) UlongToPtr(SystemTime.u.HighPart)
); );
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
} }
/* Reset accounting */ /* Reset accounting */
@ -691,19 +686,14 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration
{ {
/* Call the DPC */ /* Call the DPC */
EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine); EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine);
__try {
// Call the Deferred Procedure : // Call the Deferred Procedure :
DpcEntry[i].Routine( DpcEntry[i].Routine(
DpcEntry[i].Dpc, DpcEntry[i].Dpc,
DpcEntry[i].Context, DpcEntry[i].Context,
UlongToPtr(SystemTime.u.LowPart), UlongToPtr(SystemTime.u.LowPart),
UlongToPtr(SystemTime.u.HighPart) UlongToPtr(SystemTime.u.HighPart)
); );
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
} }
/* Reset accounting */ /* Reset accounting */
@ -736,19 +726,14 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration
{ {
/* Call the DPC */ /* Call the DPC */
EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine); EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine);
__try {
// Call the Deferred Procedure : // Call the Deferred Procedure :
DpcEntry[i].Routine( DpcEntry[i].Routine(
DpcEntry[i].Dpc, DpcEntry[i].Dpc,
DpcEntry[i].Context, DpcEntry[i].Context,
UlongToPtr(SystemTime.u.LowPart), UlongToPtr(SystemTime.u.LowPart),
UlongToPtr(SystemTime.u.HighPart) UlongToPtr(SystemTime.u.HighPart)
); );
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
} }
/* Lower IRQL if we need to */ /* Lower IRQL if we need to */
@ -851,19 +836,14 @@ xboxkrnl::VOID FASTCALL xboxkrnl::KiTimerListExpire
{ {
/* Call the DPC */ /* Call the DPC */
EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine); EmuLog(LOG_LEVEL::DEBUG, "%s, calling DPC at 0x%.8X", __func__, DpcEntry[i].Routine);
__try {
// Call the Deferred Procedure : // Call the Deferred Procedure :
DpcEntry[i].Routine( DpcEntry[i].Routine(
DpcEntry[i].Dpc, DpcEntry[i].Dpc,
DpcEntry[i].Context, DpcEntry[i].Context,
UlongToPtr(SystemTime.u.LowPart), UlongToPtr(SystemTime.u.LowPart),
UlongToPtr(SystemTime.u.HighPart) UlongToPtr(SystemTime.u.HighPart)
); );
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
} }
/* Lower IRQL */ /* Lower IRQL */

View File

@ -137,19 +137,12 @@ static unsigned int WINAPI PCSTProxy
SuspendThread(GetCurrentThread()); SuspendThread(GetCurrentThread());
} }
__try auto routine = (xboxkrnl::PKSYSTEM_ROUTINE)SystemRoutine;
{ // Debugging notice : When the below line shows up with an Exception dialog and a
auto routine = (xboxkrnl::PKSYSTEM_ROUTINE)SystemRoutine; // message like: "Exception thrown at 0x00026190 in cxbx.exe: 0xC0000005: Access
// Debugging notice : When the below line shows up with an Exception dialog and a // violation reading location 0xFD001804.", then this is AS-DESIGNED behaviour!
// message like: "Exception thrown at 0x00026190 in cxbx.exe: 0xC0000005: Access // (To avoid repetitions, uncheck "Break when this exception type is thrown").
// violation reading location 0xFD001804.", then this is AS-DESIGNED behaviour! routine(xboxkrnl::PKSTART_ROUTINE(StartRoutine), StartContext);
// (To avoid repetitions, uncheck "Break when this exception type is thrown").
routine(xboxkrnl::PKSTART_ROUTINE(StartRoutine), StartContext);
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!");
}
// This will also handle thread notification : // This will also handle thread notification :
LOG_TEST_CASE("Thread returned from SystemRoutine"); LOG_TEST_CASE("Thread returned from SystemRoutine");
@ -165,15 +158,8 @@ void PspSystemThreadStartup
IN PVOID StartContext IN PVOID StartContext
) )
{ {
__try
{
(StartRoutine)(StartContext);
}
__except (EmuException(GetExceptionInformation()))
// TODO : Call PspUnhandledExceptionInSystemThread(GetExceptionInformation()) // TODO : Call PspUnhandledExceptionInSystemThread(GetExceptionInformation())
{ (StartRoutine)(StartContext);
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter!"); // TODO : Disable?
}
xboxkrnl::PsTerminateSystemThread(STATUS_SUCCESS); xboxkrnl::PsTerminateSystemThread(STATUS_SUCCESS);
} }

View File

@ -171,14 +171,7 @@ void SetupPerTitleKeys()
void CxbxLaunchXbe(void(*Entry)()) void CxbxLaunchXbe(void(*Entry)())
{ {
__try Entry();
{
Entry();
}
__except (EmuException(GetExceptionInformation()))
{
EmuLog(LOG_LEVEL::WARNING, "Problem with ExceptionFilter");
}
} }
// Entry point address XOR keys per Xbe type (Retail, Debug or Chihiro) : // Entry point address XOR keys per Xbe type (Retail, Debug or Chihiro) :
@ -1205,6 +1198,8 @@ void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_res
ImportLibraries((XbeImportEntry*)CxbxKrnl_Xbe->m_Header.dwNonKernelImportDirAddr); ImportLibraries((XbeImportEntry*)CxbxKrnl_Xbe->m_Header.dwNonKernelImportDirAddr);
} }
g_ExceptionManager = new ExceptionManager(); // If in need to add VEHs, move this line earlier. (just in case)
// Launch the XBE : // Launch the XBE :
{ {
// Load TLS // Load TLS
@ -1822,6 +1817,12 @@ void CxbxKrnlShutDown()
} }
EmuShared::Cleanup(); EmuShared::Cleanup();
if (g_ExceptionManager) {
delete g_ExceptionManager;
g_ExceptionManager = nullptr;
}
TerminateProcess(g_CurrentProcessHandle, 0); TerminateProcess(g_CurrentProcessHandle, 0);
} }

View File

@ -217,7 +217,14 @@ bool IsXboxCodeAddress(xbaddr addr)
// Note : Not IS_USER_ADDRESS(), that would include host DLL code // Note : Not IS_USER_ADDRESS(), that would include host DLL code
} }
#include "distorm.h"
bool EmuX86_DecodeOpcode(const uint8_t* Eip, _DInst& info);
void EmuX86_DistormLogInstruction(const uint8_t* Eip, _DInst& info, LOG_LEVEL log_level);
void genericException(EXCEPTION_POINTERS *e) { void genericException(EXCEPTION_POINTERS *e) {
_DInst info;
if (EmuX86_DecodeOpcode((uint8_t*)e->ContextRecord->Eip, info)) {
EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info, LOG_LEVEL::FATAL);
}
// 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()) { if (CxbxDebugger::CanReport()) {
bool DebuggerHandled = false; bool DebuggerHandled = false;
@ -278,8 +285,6 @@ bool lleTryHandleException(EXCEPTION_POINTERS *e)
return true; return true;
} }
genericException(e);
// We do not need EmuException to handle it again. // We do not need EmuException to handle it again.
bOverrideException = true; bOverrideException = true;
@ -288,7 +293,7 @@ bool lleTryHandleException(EXCEPTION_POINTERS *e)
} }
// Only for LLE emulation coding (to help performance a little bit better) // Only for LLE emulation coding (to help performance a little bit better)
LONG NTAPI lleException(EXCEPTION_POINTERS *e) LONG WINAPI lleException(EXCEPTION_POINTERS *e)
{ {
g_bEmuException = true; g_bEmuException = true;
LONG result = lleTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; LONG result = lleTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
@ -302,6 +307,7 @@ bool EmuTryHandleException(EXCEPTION_POINTERS *e)
// Check if lle exception is already called first before emu exception. // Check if lle exception is already called first before emu exception.
if (bOverrideException) { if (bOverrideException) {
genericException(e);
return false; return false;
} }
@ -345,16 +351,17 @@ bool EmuTryHandleException(EXCEPTION_POINTERS *e)
// Unhandled exception : // Unhandled exception :
return false; return false;
} }
int EmuException(EXCEPTION_POINTERS *e) long WINAPI EmuException(struct _EXCEPTION_POINTERS* e)
{ {
g_bEmuException = true; g_bEmuException = true;
LONG result = EmuTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; LONG result = EmuTryHandleException(e) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
g_bEmuException = false; g_bEmuException = false;
return result; return result;
} }
// exception handle for that tough final exit :) // exception handle for that tough final exit :)
// TODO: We might just well as delete this, duplicate of EmuExceptionNonBreakpointUnhandledShow
int ExitException(LPEXCEPTION_POINTERS e) int ExitException(LPEXCEPTION_POINTERS e)
{ {
static int count = 0; static int count = 0;
@ -395,15 +402,25 @@ ExceptionManager::ExceptionManager()
ExceptionManager::~ExceptionManager() ExceptionManager::~ExceptionManager()
{ {
for (auto i_handle : veh_handles) { for (auto i_handle : veh_handles) {
RemoveVectoredExceptionHandler(i_handle); (void)RemoveVectoredExceptionHandler(i_handle);
} }
veh_handles.clear(); veh_handles.clear();
#ifdef _MSC_VER // Windows' C++ exception is using SEH, we cannot use VEH for error reporter system.
(void)SetUnhandledExceptionFilter(nullptr);
#endif
} }
// Require to be set right before we call xbe's entry point. // Require to be set right before we call xbe's entry point.
void ExceptionManager::EmuX86_Init() void ExceptionManager::EmuX86_Init()
{ {
accept_request = false; // Do not allow add VEH during emulation. accept_request = false; // Do not allow add VEH during emulation.
AddVEH(1, lleException, true); // Front line call
// Last call plus show exception error than terminate early.
#ifdef _MSC_VER // Windows' C++ exception is using SEH, we cannot use VEH for error reporter system.
(void)SetUnhandledExceptionFilter(EmuException);
#else // Untested for other platforms, may will behave as expected.
AddVEH(0, EmuException, true);
#endif
} }
bool ExceptionManager::AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler) bool ExceptionManager::AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler)

View File

@ -35,8 +35,6 @@
std::string FormatTitleId(uint32_t title_id); std::string FormatTitleId(uint32_t title_id);
// exception handler // exception handler
extern LONG NTAPI lleException(EXCEPTION_POINTERS *e);
int EmuException(EXCEPTION_POINTERS *e);
class ExceptionManager { class ExceptionManager {
public: public:
ExceptionManager(); ExceptionManager();

View File

@ -57,6 +57,8 @@ extern std::atomic_bool g_bEnableAllInterrupts;
static int field_pin = 0; static int field_pin = 0;
static thread_local bool g_tls_isEmuX86Managed;
uint32_t EmuX86_IORead(xbaddr addr, int size) uint32_t EmuX86_IORead(xbaddr addr, int size)
{ {
switch (addr) { switch (addr) {
@ -110,48 +112,36 @@ void EmuX86_IOWrite(xbaddr addr, uint32_t value, int size)
uint32_t EmuX86_Mem_Read(xbaddr addr, int size) uint32_t EmuX86_Mem_Read(xbaddr addr, int size)
{ {
__try { switch (size) {
case sizeof(uint32_t) :
switch (size) { return *(uint32_t*)addr;
case sizeof(uint32_t) : case sizeof(uint16_t) :
return *(uint32_t*)addr; return *(uint16_t*)addr;
case sizeof(uint16_t) : case sizeof(uint8_t) :
return *(uint16_t*)addr; return *(uint8_t*)addr;
case sizeof(uint8_t) : default:
return *(uint8_t*)addr; // UNREACHABLE(size);
default: assert(false);
// UNREACHABLE(size);
assert(false);
return 0;
}
}
__except (true) { // TODO : EXCEPTION_EXECUTE_HANDLER instead of true?
EmuLog(LOG_LEVEL::WARNING, "EmuX86_Mem_Read Failed (0x%08X, %d)", addr, size);
return 0; return 0;
} }
} }
void EmuX86_Mem_Write(xbaddr addr, uint32_t value, int size) void EmuX86_Mem_Write(xbaddr addr, uint32_t value, int size)
{ {
__try { switch (size) {
switch (size) { case sizeof(uint32_t) :
case sizeof(uint32_t) : *(uint32_t*)addr = (uint32_t)value;
*(uint32_t*)addr = (uint32_t)value; break;
break; case sizeof(uint16_t) :
case sizeof(uint16_t) : *(uint16_t*)addr = (uint16_t)value;
*(uint16_t*)addr = (uint16_t)value; break;
break; case sizeof(uint8_t) :
case sizeof(uint8_t) : *(uint8_t*)addr = (uint8_t)value;
*(uint8_t*)addr = (uint8_t)value; break;
break; default:
default: // UNREACHABLE(size);
// UNREACHABLE(size); assert(false);
assert(false); return;
return;
}
}
__except (true) { // TODO : EXCEPTION_EXECUTE_HANDLER instead of true?
EmuLog(LOG_LEVEL::WARNING, "EmuX86_Mem_Write Failed (0x%08X, 0x%08X, %d)", addr, value, size);
} }
} }
@ -187,23 +177,25 @@ uint32_t EmuX86_Read(xbaddr addr, int size)
uint32_t value; uint32_t value;
if (addr >= XBOX_FLASH_ROM_BASE) { // 0xFFF00000 - 0xFFFFFFF if (addr >= XBOX_FLASH_ROM_BASE) { // 0xFFF00000 - 0xFFFFFFF
value = EmuFlash_Read32(addr - XBOX_FLASH_ROM_BASE); // TODO : Make flash access size-aware return EmuFlash_Read32(addr - XBOX_FLASH_ROM_BASE); // TODO : Make flash access size-aware
} else if(addr == 0xFE80200C) {
// TODO: Remove this once we have an LLE APU Device
return GetAPUTime();
} else {
// Pass the Read to the PCI Bus, this will handle devices with BARs set to MMIO addresses
if (g_PCIBus->MMIORead(addr, &value, size)) {
return value;
}
//pass the memory-access through to normal memory :
value = EmuX86_Mem_Read(addr, size);
EmuLog(LOG_LEVEL::DEBUG, "Read(0x%08X, %d) = 0x%08X", addr, size, value);
} }
return value; // TODO: Remove this once we have an LLE APU Device
if(addr == 0xFE80200C) {
return GetAPUTime();
}
// Pass the Read to the PCI Bus, this will handle devices with BARs set to MMIO addresses
if (g_PCIBus->MMIORead(addr, &value, size)) {
return value;
}
// EmuX86 is not suppose to do direct read to host memory and should be handle from
// redirect from above statements. If it doesn't meet any requirement, then should be
// handle as possible fatal crash instead of return corrupt value.
g_tls_isEmuX86Managed = false;
return 0;
} }
void EmuX86_Write(xbaddr addr, uint32_t value, int size) void EmuX86_Write(xbaddr addr, uint32_t value, int size)
@ -224,9 +216,10 @@ void EmuX86_Write(xbaddr addr, uint32_t value, int size)
return; return;
} }
// Pass the memory-access through to normal memory : // EmuX86 is not suppose to do direct write to host memory and should be handle from
EmuLog(LOG_LEVEL::DEBUG, "Write(0x%.8X, 0x%.8X, %d)", addr, value, size); // redirect from above statements. If it doesn't meet any requirement, then should be
EmuX86_Mem_Write(addr, value, size); // handle as possible fatal crash instead of set corrupt value.
g_tls_isEmuX86Managed = false;
} }
int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 }; int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 };
@ -2786,7 +2779,7 @@ void output_segment(std::stringstream &output, _DInst &info)
output << Distorm_RegStrings[SEGMENT_GET(info.segment)] << ":"; output << Distorm_RegStrings[SEGMENT_GET(info.segment)] << ":";
} }
void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info) void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info, LOG_LEVEL log_level)
{ {
std::stringstream output; std::stringstream output;
@ -2907,7 +2900,7 @@ void EmuX86_DistormLogInstruction(const uint8_t *Eip, _DInst &info)
#define FLAG_GET_PREFIX(flags) ((flags) & 7) // To get the LOCK/REPNZ/REP prefixes. #define FLAG_GET_PREFIX(flags) ((flags) & 7) // To get the LOCK/REPNZ/REP prefixes.
*/ */
EmuLog(LOG_LEVEL::DEBUG, output.str().c_str()); EmuLog(log_level, output.str().c_str());
} }
int EmuX86_OpcodeSize(uint8_t *Eip) int EmuX86_OpcodeSize(uint8_t *Eip)
@ -2928,10 +2921,9 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
// However, if for any reason, an opcode operand cannot be read from or written to, // However, if for any reason, an opcode operand cannot be read from or written to,
// that case may be logged, but it shouldn't fail the opcode handler. // that case may be logged, but it shouldn't fail the opcode handler.
_DInst info; _DInst info;
g_tls_isEmuX86Managed = true;
DWORD StartingEip = e->ContextRecord->Eip; DWORD StartingEip = e->ContextRecord->Eip;
LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { EmuLog(LOG_LEVEL::DEBUG, "Starting instruction emulation from 0x%08X", e->ContextRecord->Eip);
EmuLog(LOG_LEVEL::DEBUG, "Starting instruction emulation from 0x%08X", e->ContextRecord->Eip);
}
// Execute op-codes until we hit an unhandled instruction, or an error occurs // Execute op-codes until we hit an unhandled instruction, or an error occurs
//while (true) //while (true)
@ -2947,7 +2939,7 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
} }
LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) { LOG_CHECK_ENABLED(LOG_LEVEL::DEBUG) {
EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info); EmuX86_DistormLogInstruction((uint8_t*)e->ContextRecord->Eip, info, LOG_LEVEL::DEBUG);
} }
switch (info.opcode) { // Keep these cases alphabetically ordered and condensed switch (info.opcode) { // Keep these cases alphabetically ordered and condensed
@ -3295,10 +3287,15 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
return true; return true;
} // switch info.opcode } // switch info.opcode
e->ContextRecord->Eip += info.size; if (g_tls_isEmuX86Managed) {
e->ContextRecord->Eip += info.size;
}
else {
break;
}
} // while true } // while true
return true; return g_tls_isEmuX86Managed;
opcode_error: opcode_error:
EmuLog(LOG_LEVEL::WARNING, "0x%08X: Error while handling instruction %s (%u)", e->ContextRecord->Eip, Distorm_OpcodeString(info.opcode), info.opcode); EmuLog(LOG_LEVEL::WARNING, "0x%08X: Error while handling instruction %s (%u)", e->ContextRecord->Eip, Distorm_OpcodeString(info.opcode), info.opcode);
@ -3310,7 +3307,8 @@ void EmuX86_Init()
{ {
EmuLog(LOG_LEVEL::DEBUG, "Initializing distorm version %d", distorm_version()); EmuLog(LOG_LEVEL::DEBUG, "Initializing distorm version %d", distorm_version());
AddVectoredExceptionHandler(/*FirstHandler=*/ULONG(true), lleException); // Initialize emulation exception to ensure they are front and last line of exception.
g_ExceptionManager->EmuX86_Init();
EmuX86_InitContextRecordOffsetByRegisterType(); EmuX86_InitContextRecordOffsetByRegisterType();
EmuX86_InitMemoryBackedRegisters(); EmuX86_InitMemoryBackedRegisters();