diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/MemTools.cpp index f810de1b15..d3fadaf39e 100644 --- a/Source/Core/Core/Src/MemTools.cpp +++ b/Source/Core/Core/Src/MemTools.cpp @@ -16,12 +16,19 @@ // http://code.google.com/p/dolphin-emu/ -// TODO: create a working OS-neutral version of this file and put it in Common. - - #ifdef _WIN32 #include + +#else + +#include +#include +#include +#include // Look in here for the context definition. + +#endif + #include #include "Common.h" @@ -35,6 +42,8 @@ namespace EMM { +#ifdef _WIN32 + LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) { switch (pPtrs->ExceptionRecord->ExceptionCode) @@ -69,7 +78,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) #ifdef _M_X64 u64 memspaceTop = memspaceBottom + 0x100000000ULL; #else - u64 memspaceTop = memspaceBottom + 0x40000000; + u64 memspaceTop = memspaceBottom + 0x40000000; #endif if (badAddress < memspaceBottom || badAddress >= memspaceTop) { PanicAlert("Exception handler - access outside memory space. %08x%08x", @@ -136,15 +145,12 @@ void InstallExceptionHandler() #endif } -} -#else +#else // _WIN32) -namespace EMM { - -#if 0 // // backtrace useful function // + void print_trace(const char * msg) { void *array[100]; @@ -160,41 +166,63 @@ void print_trace(const char * msg) free(strings); } -void sigsegv_handler(int signal, int siginfo_t *info, void *raw_context) +void sigsegv_handler(int signal, siginfo_t *info, void *raw_context) { if (signal != SIGSEGV) { // We are not interested in other signals - handle it as usual. return; } - ucontext_t *context = (ucontext_t)raw_context; + ucontext_t *context = (ucontext_t *)raw_context; int si_code = info->si_code; - if (si_code != SEGV_MAPERR) + if (si_code != SEGV_MAPERR && si_code != SEGV_ACCERR) { // Huh? Return. return; } - mcontext_t *ctx = &context->uc_mcontext; void *fault_memory_ptr = (void *)info->si_addr; - void *fault_instruction_ptr = (void *)ctx->mc_rip; - if (!Jit64::IsInJitCode(fault_instruction_ptr)) { + // Get all the information we can out of the context. + mcontext_t *ctx = &context->uc_mcontext; + u8 *fault_instruction_ptr = (u8 *)ctx->gregs[REG_RIP]; + + if (!Jit64::IsInJitCode((const u8 *)fault_instruction_ptr)) { // Let's not prevent debugging. return; } - - u64 memspaceBottom = (u64)Memory::base; - if (badAddress < memspaceBottom) { + + u64 bad_address = (u64)fault_memory_ptr; + u64 memspace_bottom = (u64)Memory::base; + if (bad_address < memspace_bottom) { PanicAlert("Exception handler - access below memory space. %08x%08x", - badAddress >> 32, badAddress); + bad_address >> 32, bad_address); } - u32 emAddress = (u32)(badAddress - memspaceBottom); + u32 em_address = (u32)(bad_address - memspace_bottom); // Backpatch time. - Jit64::BackPatch(fault_instruction_ptr, accessType, emAddress); -} + // Seems we'll need to disassemble to get access_type - that work is probably + // best done and debugged on the Windows side. + int access_type = 0; + CONTEXT fake_ctx; +#ifdef _M_X64 + fake_ctx.Rax = ctx->gregs[REG_RAX]; + fake_ctx.Rip = ctx->gregs[REG_RIP]; +#else + fake_ctx.Eax = ctx->gregs[REG_EAX]; + fake_ctx.Eip = ctx->gregs[REG_EIP]; #endif + u8 *new_rip = Jit64::BackPatch(fault_instruction_ptr, access_type, em_address, &fake_ctx); + if (new_rip) { +#ifdef _M_X64 + ctx->gregs[REG_RAX] = fake_ctx.Rax; + ctx->gregs[REG_RIP] = (u64)new_rip; +#else + ctx->gregs[REG_EAX] = fake_ctx.Rax; + ctx->gregs[REG_EIP] = (u32)new_rip; +#endif + } +} void InstallExceptionHandler() { @@ -203,22 +231,14 @@ void InstallExceptionHandler() return; #endif -#if 0 - sighandler_t old_signal_handler = signal(SIGSEGV , sigsegv_handler); struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = sigsegv_handler; + sa.sa_handler = 0; + sa.sa_sigaction = &sigsegv_handler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, NULL); -#endif - - /* - * signal(xyz); - */ -} - } #endif +} // namespace diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp index ae1efb1a8e..87c7f2ef17 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp @@ -43,11 +43,10 @@ void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) { char disbuf[256]; memset(disbuf, 0, 256); #ifdef _M_IX86 - disasm.disasm32 + disasm.disasm32(0, code_addr, codePtr, disbuf); #else - disasm.disasm64 + disasm.disasm64(0, code_addr, codePtr, disbuf); #endif - (0, code_addr, codePtr, disbuf); PanicAlert("%s\n\n" "Error encountered accessing emulated address %08x.\n" "Culprit instruction: \n%s\nat %08x%08x", @@ -84,7 +83,7 @@ u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx) if (info.operandSize != 4) { BackPatchError(StringFromFormat("BackPatch - no support for operand size %i", info.operandSize), codePtr, emAddress); } - u64 code_addr = (u64)codePtr; + X64Reg addrReg = (X64Reg)info.scaledReg; X64Reg dataReg = (X64Reg)info.regOperandReg; if (info.otherReg != RBX) @@ -185,7 +184,7 @@ u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx) SetCodePtr(oldCodePtr); // We entered here with a BSWAP-ed EAX. We'll have to swap it back. - ctx->Rax = _byteswap_ulong(ctx->Rax); + ctx->Rax = Common::swap32(ctx->Rax); return codePtr - 2; } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h index f30836fc79..f3e923e97e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h @@ -21,7 +21,24 @@ #include "Common.h" #ifdef _WIN32 + #include + +#else + +// A bit of a hack to get things building under linux. We manually fill in this structure as needed +// from the real context. +struct CONTEXT +{ +#ifdef _M_X64 + u64 Rip; + u64 Rax; +#else + u32 Eip; + u32 Eax; +#endif +}; + #endif namespace Jit64 { diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript index 50efeea214..415650e100 100644 --- a/Source/Core/Core/Src/SConscript +++ b/Source/Core/Core/Src/SConscript @@ -80,6 +80,7 @@ files = ["Console.cpp", "PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp", "PowerPC/Interpreter/Interpreter_SystemRegisters.cpp", "PowerPC/Jit64/Jit.cpp", + "PowerPC/Jit64/JitBackpatch.cpp", "PowerPC/Jit64/JitCore.cpp", "PowerPC/Jit64/JitCache.cpp", "PowerPC/Jit64/JitRegCache.cpp",