From d3671ab5e009b850c31428e2ec47bc2e3a708df7 Mon Sep 17 00:00:00 2001 From: zilmar Date: Sun, 5 Jun 2016 09:42:49 +1000 Subject: [PATCH] [Project64] Add arm exception handler --- .../Project64-core/MemoryExceptionFilter.cpp | 438 ++++++++++++------ .../N64System/Mips/MemoryVirtualMem.h | 29 ++ 2 files changed, 338 insertions(+), 129 deletions(-) diff --git a/Source/Project64-core/MemoryExceptionFilter.cpp b/Source/Project64-core/MemoryExceptionFilter.cpp index ad62fe69e..2c9cc7ce2 100644 --- a/Source/Project64-core/MemoryExceptionFilter.cpp +++ b/Source/Project64-core/MemoryExceptionFilter.cpp @@ -12,57 +12,52 @@ #include #include #include - -#ifdef _WIN32 -int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer) -{ -#if defined(_M_IX86) && defined(_WIN32) - // to do: Remove the _M_IX86 criteria. This can compile on 64-bit Windows. -#ifndef _WIN64 - DWORD * Reg; - // We need this to fix 32-bit Windows builds, - // because Project64 currently uses uint32_t all the time instead of int32_t. -#else - size_t * Reg; +#ifndef _WIN32 +#include +#endif +#ifdef __arm__ +#include #endif - if (dwExptCode != EXCEPTION_ACCESS_VIOLATION || g_MMU == NULL) +#if defined(__i386__) || defined(_M_IX86) + +bool CMipsMemoryVM::FilterX86Exception(uint32_t MemAddress, X86_CONTEXT & context) +{ + WriteTrace(TraceExceptionHandler, TraceVerbose, "MemAddress: %X", MemAddress); + uint32_t * Reg; + + if (g_MMU == NULL) + { + WriteTrace(TraceExceptionHandler, TraceError, "g_MMU == NULL"); + g_Notify->BreakPoint(__FILE__, __LINE__); + return false; + } + + if ((int32_t)(MemAddress) < 0 || MemAddress > 0x1FFFFFFF) { if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + WriteTrace(TraceExceptionHandler, TraceError, "Invalid memory adderess: %X", MemAddress); + return false; } - //convert the pointer since we are not having win32 structures in headers - LPEXCEPTION_POINTERS lpEP = (LPEXCEPTION_POINTERS)lpExceptionPointer; - - uint32_t MemAddress = (char *)lpEP->ExceptionRecord->ExceptionInformation[1] - (char *)g_MMU->Rdram(); - if ((int32_t)(MemAddress) < 0 || MemAddress > 0x1FFFFFFF) - { - // if (bHaveDebugger()) - // { - // g_Notify->BreakPoint(__FILE__, __LINE__); - // } - return EXCEPTION_EXECUTE_HANDLER; - } - - uint8_t * TypePos = (uint8_t *)lpEP->ContextRecord->Eip; - EXCEPTION_RECORD exRec = *lpEP->ExceptionRecord; + uint8_t * TypePos = (uint8_t *)*(context.Eip); + WriteTrace(TraceExceptionHandler, TraceVerbose, "TypePos[0] = %02X TypePos[1] = %02X", TypePos[0], TypePos[2]); Reg = NULL; if (*TypePos == 0xF3 && (*(TypePos + 1) == 0xA4 || *(TypePos + 1) == 0xA5)) { - uint32_t Start = (lpEP->ContextRecord->Edi - (uint32_t)m_RDRAM); - uint32_t End = Start + lpEP->ContextRecord->Ecx; + uint32_t Start = (*context.Edi - (uint32_t)g_MMU->m_RDRAM); + uint32_t End = Start + *context.Ecx; if ((int32_t)Start < 0) { if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } #ifdef CFB_READ uint32_t count, OldProtect; @@ -79,24 +74,24 @@ int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPoint return EXCEPTION_CONTINUE_EXECUTION; } #endif - if (End < RdramSize()) + if (End < g_MMU->RdramSize() && g_Recompiler) { for (uint32_t count = (Start & ~0xFFF); count < End; count += 0x1000) { g_Recompiler->ClearRecompCode_Phys(count, 0x1000, CRecompiler::Remove_ProtectedMem); } - return EXCEPTION_CONTINUE_EXECUTION; + return true; } - if (Start >= 0x04000000 && End < 0x04002000) + if (Start >= 0x04000000 && End < 0x04002000 && g_Recompiler) { g_Recompiler->ClearRecompCode_Phys(Start & ~0xFFF, 0x1000, CRecompiler::Remove_ProtectedMem); - return EXCEPTION_CONTINUE_EXECUTION; + return true; } if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } uint8_t * ReadPos; @@ -127,14 +122,14 @@ int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPoint switch (*ReadPos & 0x38) { - case 0x00: Reg = &(lpEP->ContextRecord->Eax); break; - case 0x08: Reg = &(lpEP->ContextRecord->Ecx); break; - case 0x10: Reg = &(lpEP->ContextRecord->Edx); break; - case 0x18: Reg = &(lpEP->ContextRecord->Ebx); break; - case 0x20: Reg = &(lpEP->ContextRecord->Esp); break; - case 0x28: Reg = &(lpEP->ContextRecord->Ebp); break; - case 0x30: Reg = &(lpEP->ContextRecord->Esi); break; - case 0x38: Reg = &(lpEP->ContextRecord->Edi); break; + case 0x00: Reg = context.Eax; break; + case 0x08: Reg = context.Ecx; break; + case 0x10: Reg = context.Edx; break; + case 0x18: Reg = context.Ebx; break; + case 0x20: Reg = context.Esp; break; + case 0x28: Reg = context.Ebp; break; + case 0x30: Reg = context.Esi; break; + case 0x38: Reg = context.Edi; break; } switch ((*ReadPos & 0xC7)) @@ -179,7 +174,7 @@ int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPoint { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } if (Reg == NULL) @@ -188,7 +183,7 @@ int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPoint { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } switch (*TypePos) @@ -197,206 +192,391 @@ int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPoint switch (*(TypePos + 1)) { case 0xB6: - if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, false)) + if (!g_MMU->LB_NonMemory(MemAddress, (uint32_t *)Reg, false)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0xB7: - if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, false)) + if (!g_MMU->LH_NonMemory(MemAddress, (uint32_t *)Reg, false)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0xBE: - if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, true)) + if (!g_MMU->LB_NonMemory(MemAddress, (uint32_t *)Reg, true)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0xBF: - if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, true)) + if (!g_MMU->LH_NonMemory(MemAddress, (uint32_t *)Reg, true)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X",MemAddress,(uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; default: if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } break; case 0x66: switch (*(TypePos + 1)) { case 0x8B: - if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, false)) + if (!g_MMU->LH_NonMemory(MemAddress, (uint32_t *)Reg, false)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to half word\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0x89: - if (!SH_NonMemory(MemAddress, *(uint16_t *)Reg)) + if (!g_MMU->SH_NonMemory(MemAddress, *(uint16_t *)Reg)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { g_Notify->DisplayError(stdstr_f("Failed to store half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0xC7: - if (Reg != &lpEP->ContextRecord->Eax) + if (Reg != context.Eax) { if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } - if (!SH_NonMemory(MemAddress, *(uint16_t *)ReadPos)) { + if (!g_MMU->SH_NonMemory(MemAddress, *(uint16_t *)ReadPos)) + { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to store half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to store half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 2); - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)(ReadPos + 2); + return true; default: if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } break; case 0x88: - if (!SB_NonMemory(MemAddress, *(uint8_t *)Reg)) + if (!g_MMU->SB_NonMemory(MemAddress, *(uint8_t *)Reg)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0x8A: - if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, false)) + if (!g_MMU->LB_NonMemory(MemAddress, (uint32_t *)Reg, false)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0x8B: - if (!LW_NonMemory(MemAddress, (uint32_t *)Reg)) + if (!g_MMU->LW_NonMemory(MemAddress, (uint32_t *)Reg)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to load word\n\nMIPS Address: %08X\nX86 Address: %08X", - (char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to load word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0x89: - if (!SW_NonMemory(MemAddress, *(uint32_t *)Reg)) + if (!g_MMU->SW_NonMemory(MemAddress, *(uint32_t *)Reg)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)ReadPos; - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)ReadPos; + return true; case 0xC6: - if (Reg != &lpEP->ContextRecord->Eax) + if (Reg != context.Eax) { if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } - if (!SB_NonMemory(MemAddress, *(uint8_t *)ReadPos)) + if (!g_MMU->SB_NonMemory(MemAddress, *(uint8_t *)ReadPos)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 1); - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)(ReadPos + 1); + return true; case 0xC7: - if (Reg != &lpEP->ContextRecord->Eax) + if (Reg != context.Eax) { if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } - return EXCEPTION_EXECUTE_HANDLER; + return false; } - if (!SW_NonMemory(MemAddress, *(uint32_t *)ReadPos)) + if (!g_MMU->SW_NonMemory(MemAddress, *(uint32_t *)ReadPos)) { if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) { - g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, - (uint8_t *)lpEP->ContextRecord->Eip).c_str()); + g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress, (uint8_t *)*context.Eip).c_str()); } } - lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 4); - return EXCEPTION_CONTINUE_EXECUTION; + *context.Eip = (uint32_t)(ReadPos + 4); + return true; } if (bHaveDebugger()) { g_Notify->BreakPoint(__FILE__, __LINE__); } -#else - g_Notify->BreakPoint(__FILE__, __LINE__); + return false; +} #endif + +#ifdef __arm__ +bool CMipsMemoryVM::FilterArmException(uint32_t MemAddress, mcontext_t & context) +{ + uint32_t * ArmRegisters[16] = + { + (uint32_t*)&context.arm_r0, (uint32_t*)&context.arm_r1, (uint32_t*)&context.arm_r2, (uint32_t*)&context.arm_r3, + (uint32_t*)&context.arm_r4, (uint32_t*)&context.arm_r5, (uint32_t*)&context.arm_r6, (uint32_t*)&context.arm_r7, + (uint32_t*)&context.arm_r8, (uint32_t*)&context.arm_r9, (uint32_t*)&context.arm_r10,(uint32_t*)&context.arm_fp, + (uint32_t*)&context.arm_ip, (uint32_t*)&context.arm_sp, (uint32_t*)&context.arm_lr, (uint32_t*)&context.arm_pc, + }; + + ArmThumbOpcode * OpCode = (ArmThumbOpcode *)context.arm_pc; + if (OpCode->opcode == ArmLDR_Reg) + { + if (!g_MMU->LW_NonMemory(MemAddress, ArmRegisters[OpCode->rt])) + { + if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) + { + g_Notify->DisplayError(stdstr_f("Failed to load word\n\nMIPS Address: %08X\nPC Address: %08X", MemAddress, context.arm_pc).c_str()); + } + } + context.arm_pc = context.arm_pc + 2; + return true; + } + if (OpCode->opcode == ArmSTR_Reg) + { + if (!g_MMU->SW_NonMemory(MemAddress, *ArmRegisters[OpCode->rt])) + { + if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) + { + g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nPC Address: %08X", MemAddress, context.arm_pc).c_str()); + } + } + context.arm_pc = context.arm_pc + 2; + return true; + } + Arm32Opcode * OpCode32 = (Arm32Opcode *)context.arm_pc; + if (OpCode32->uint16.opcode == ArmLDRH_W) + { + //f833 c001 ldrh.w ip, [r3, r1] + if (!g_MMU->LH_NonMemory(MemAddress, ArmRegisters[OpCode32->uint16.rt], false)) + { + if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) + { + g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nPC Address: %08X", MemAddress, context.arm_pc).c_str()); + } + } + context.arm_pc = context.arm_pc + 4; + return true; + } + + if (OpCode32->uint32.opcode == ArmLDRH_Reg && OpCode32->uint32.opcode2 == 0xB) + { + //e19a20b2 ldrh r2, [sl, r2] + if (!g_MMU->LH_NonMemory(MemAddress, ArmRegisters[OpCode32->uint32.rt], false)) + { + if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory)) + { + g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nPC Address: %08X", MemAddress, context.arm_pc).c_str()); + } + } + context.arm_pc = context.arm_pc + 4; + return true; + } + WriteTrace(TraceExceptionHandler, TraceError, "MemAddress = 0x%lx", MemAddress); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r0 = 0x%lx", context.arm_r0); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r1 = 0x%lx", context.arm_r1); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r2 = 0x%lx", context.arm_r2); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r3 = 0x%lx", context.arm_r3); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r4 = 0x%lx", context.arm_r4); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r5 = 0x%lx", context.arm_r5); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r6 = 0x%lx", context.arm_r6); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r7 = 0x%lx", context.arm_r7); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r8 = 0x%lx", context.arm_r8); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r9 = 0x%lx", context.arm_r9); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_r10 = 0x%lx", context.arm_r10); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_fp = 0x%lx", context.arm_fp); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_ip = 0x%lx", context.arm_ip); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_sp = 0x%lx", context.arm_sp); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_lr = 0x%lx", context.arm_lr); + WriteTrace(TraceExceptionHandler, TraceError, "uc->uc_mcontext.arm_pc = 0x%lx", context.arm_pc); + + uint8_t * TypePos = (uint8_t *)context.arm_pc; + WriteTrace(TraceExceptionHandler, TraceError, "TypePos: %02X %02X %02X %02X %02X %02X %02X %02X %02X",TypePos[0],TypePos[1],TypePos[2],TypePos[3],TypePos[4],TypePos[5],TypePos[6],TypePos[7],TypePos[8]); + + WriteTrace(TraceExceptionHandler, TraceError, "OpCode.Hex: %X",OpCode->Hex); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode.opcode: %X",OpCode->opcode); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode.rm: %X",OpCode->rm); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode.rn: %X",OpCode->rn); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode.rt: %X",OpCode->rt); + + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32.Hex: %X",OpCode32->Hex); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint16.opcode: %X",OpCode32->uint16.opcode); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint16.rm: %X",OpCode32->uint16.rm); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint16.rn: %X",OpCode32->uint16.rn); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint16.rt: %X",OpCode32->uint16.rt); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint16.imm2: %X",OpCode32->uint16.imm2); + + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint32.opcode: %X",OpCode32->uint32.opcode); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint32.rn: %X",OpCode32->uint32.rn); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint32.rt: %X",OpCode32->uint32.rt); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint32.opcode2: %X",OpCode32->uint32.opcode2); + WriteTrace(TraceExceptionHandler, TraceError, "OpCode32->uint32.rm: %X",OpCode32->uint32.rm); + return false; +} +#endif + +#ifndef _WIN32 +bool CMipsMemoryVM::SetupSegvHandler (void) +{ + struct sigaction sig_act; + sig_act.sa_flags = SA_SIGINFO | SA_RESTART; + sig_act.sa_sigaction = segv_handler; + return sigaction( SIGSEGV, &sig_act, NULL ) == 0; +} + +void CMipsMemoryVM::segv_handler(int signal, siginfo_t *siginfo, void *sigcontext) +{ + ucontext_t *ucontext = (ucontext_t*)sigcontext; + + WriteTrace(TraceExceptionHandler, TraceNotice, "Segmentation Fault!"); + WriteTrace(TraceExceptionHandler, TraceNotice, "info.si_signo = %d", signal); + WriteTrace(TraceExceptionHandler, TraceNotice, "info.si_errno = %d", siginfo->si_errno); + WriteTrace(TraceExceptionHandler, TraceNotice, "info.si_code = %d", siginfo->si_code); + WriteTrace(TraceExceptionHandler, TraceNotice, "info.si_addr = %p", siginfo->si_addr); + + WriteTrace(TraceExceptionHandler, TraceNotice, "%s: si_addr: %p",__FUNCTION__, siginfo->si_addr); + + uint32_t MemAddress = (char *)siginfo->si_addr - (char *)g_MMU->Rdram(); + WriteTrace(TraceExceptionHandler, TraceNotice, "MemAddress = %X",MemAddress); +#ifdef __i386__ + for(int i = 0; i < NGREG; i++) + { + WriteTrace(TraceExceptionHandler, TraceNotice, "reg[%02d] = 0x%08x", i, ucontext->uc_mcontext.gregs[i]); + } + WriteTrace(TraceExceptionHandler, TraceNotice, "REG_EIP = %X", ucontext->uc_mcontext.gregs[REG_EIP]); + + uint8_t * TypePos = (uint8_t *)ucontext->uc_mcontext.gregs[REG_EIP]; + WriteTrace(TraceExceptionHandler, TraceNotice, "TypePos: %02X %02X %02X %02X %02X %02X %02X %02X %02X",TypePos[0],TypePos[1],TypePos[2],TypePos[3],TypePos[4],TypePos[5],TypePos[6],TypePos[7],TypePos[8]); + + X86_CONTEXT context; + context.Edi = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EDI]; + context.Esi = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_ESI]; + context.Ebx = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EBX]; + context.Edx = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EDX]; + context.Ecx = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_ECX]; + context.Eax = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EAX]; + context.Eip = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EIP]; + context.Esp = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_ESP]; + context.Ebp = (uint32_t*)&ucontext->uc_mcontext.gregs[REG_EBP]; + + if (FilterX86Exception(MemAddress,context)) + { + WriteTrace(TraceExceptionHandler, TraceNotice, "Success!"); + WriteTrace(TraceExceptionHandler, TraceNotice, "REG_EIP = %X", ucontext->uc_mcontext.gregs[REG_EIP]); + return; + } +#elif defined(__arm__) + if (FilterArmException(MemAddress,ucontext->uc_mcontext)) + { + WriteTrace(TraceExceptionHandler, TraceNotice, "Success!"); + return; + } +#endif + WriteTrace(TraceExceptionHandler, TraceError, "Failed quiting now"); + exit(0); //can't return to main, it's where the segfault occured. +} + +#else +int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer) +{ +#if defined(_M_IX86) && defined(_WIN32) + if (dwExptCode != EXCEPTION_ACCESS_VIOLATION || g_MMU == NULL) + { + if (bHaveDebugger()) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + } + + //convert the pointer since we are not having win32 structures in headers + LPEXCEPTION_POINTERS lpEP = (LPEXCEPTION_POINTERS)lpExceptionPointer; + uint32_t MemAddress = (char *)lpEP->ExceptionRecord->ExceptionInformation[1] - (char *)g_MMU->Rdram(); + + X86_CONTEXT context; + context.Edi = (uint32_t*)&lpEP->ContextRecord->Edi; + context.Esi = (uint32_t*)&lpEP->ContextRecord->Esi; + context.Ebx = (uint32_t*)&lpEP->ContextRecord->Ebx; + context.Edx = (uint32_t*)&lpEP->ContextRecord->Edx; + context.Ecx = (uint32_t*)&lpEP->ContextRecord->Ecx; + context.Eax = (uint32_t*)&lpEP->ContextRecord->Eax; + context.Eip = (uint32_t*)&lpEP->ContextRecord->Eip; + context.Esp = (uint32_t*)&lpEP->ContextRecord->Esp; + context.Ebp = (uint32_t*)&lpEP->ContextRecord->Ebp; + + if (FilterX86Exception(MemAddress, context)) + { + WriteTrace(TraceExceptionHandler, TraceNotice, "Success!"); + return EXCEPTION_CONTINUE_EXECUTION; + } return EXCEPTION_EXECUTE_HANDLER; +#else + return EXCEPTION_EXECUTE_HANDLER; +#endif } #endif \ No newline at end of file diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h index a6a8a78cc..2f648770b 100644 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h @@ -18,6 +18,10 @@ #include #include +#ifdef __arm__ +#include +#endif + /* * 64-bit Windows exception recovery facilities will expect to interact with * the 64-bit registers of the Intel architecture (e.g., rax instead of eax). @@ -96,6 +100,10 @@ public: int32_t MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer); void UpdateFieldSerration(uint32_t interlaced); +#ifndef _WIN32 + static bool SetupSegvHandler (void); + static void segv_handler(int signal, siginfo_t *siginfo, void *sigcontext); +#endif //Protect the Memory from being written to void ProtectMemory(uint32_t StartVaddr, uint32_t EndVaddr); @@ -205,6 +213,27 @@ private: static void Write32CartridgeDomain2Address2(void); static void Write32PifRam(void); +#if defined(__i386__) || defined(_M_IX86) + + typedef struct _X86_CONTEXT + { + uint32_t * Edi; + uint32_t * Esi; + uint32_t * Ebx; + uint32_t * Edx; + uint32_t * Ecx; + uint32_t * Eax; + uint32_t * Eip; + uint32_t * Esp; + uint32_t * Ebp; + } X86_CONTEXT; + + static bool FilterX86Exception(uint32_t MemAddress, X86_CONTEXT & context); +#endif +#ifdef __arm__ + static bool FilterArmException(uint32_t MemAddress, mcontext_t & context); +#endif + //Memory Locations static uint8_t * m_Reserve1, *m_Reserve2; uint8_t * m_RDRAM, *m_DMEM, *m_IMEM;