update Windows' SEH, fix overflow exception, and non-Windows platform support
This commit is contained in:
parent
64f69f78ae
commit
b5358508d6
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue