Get the "MemTools" and backpatching code to build on linux. Not yet activated.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1532 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-12-14 17:29:13 +00:00
parent f3eda7d85a
commit 7eefb7743b
4 changed files with 75 additions and 38 deletions

View File

@ -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 <windows.h>
#else
#include <execinfo.h>
#include <stdio.h>
#include <signal.h>
#include <sys/ucontext.h> // Look in here for the context definition.
#endif
#include <vector>
#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

View File

@ -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;
}

View File

@ -21,7 +21,24 @@
#include "Common.h"
#ifdef _WIN32
#include <windows.h>
#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 {

View File

@ -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",