Improve context structure handling on non-Windows.
Instead of copying data into and out of a fake CONTEXT structure with only a few entries, use the platform specific structure directly with a typedef and macros. This is needed because fastmem writes need to be able to access any register from BackPatch. It adds a fair number of repetitive defines, but it's better than the alternative.
This commit is contained in:
parent
4cdce55615
commit
29dc253fde
|
@ -81,11 +81,9 @@ void sigsegv_handler(int signal, siginfo_t *info, void *raw_context)
|
|||
|
||||
u32 em_address = (u32)(bad_address - memspace_bottom);
|
||||
|
||||
CONTEXT fake_ctx;
|
||||
fake_ctx.reg_pc = ctx->arm_pc;
|
||||
const u8 *new_rip = jit->BackPatch(fault_instruction_ptr, em_address, &fake_ctx);
|
||||
const u8 *new_rip = jit->BackPatch(fault_instruction_ptr, em_address, ctx);
|
||||
if (new_rip) {
|
||||
ctx->arm_pc = fake_ctx.reg_pc;
|
||||
ctx->arm_pc = (u32) new_rip;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ bool DisamLoadStore(const u32 inst, ARMReg &rD, u8 &accessSize, bool &Store)
|
|||
const u8 *JitArm::BackPatch(u8 *codePtr, u32, void *ctx_void)
|
||||
{
|
||||
// TODO: This ctx needs to be filled with our information
|
||||
CONTEXT *ctx = (CONTEXT *)ctx_void;
|
||||
SContext *ctx = (SContext *)ctx_void;
|
||||
|
||||
// We need to get the destination register before we start
|
||||
u32 Value = *(u32*)codePtr;
|
||||
|
@ -90,7 +90,7 @@ const u8 *JitArm::BackPatch(u8 *codePtr, u32, void *ctx_void)
|
|||
|
||||
if (!DisamLoadStore(Value, rD, accessSize, Store))
|
||||
{
|
||||
printf("Invalid backpatch at location 0x%08x(0x%08x)\n", ctx->reg_pc, Value);
|
||||
printf("Invalid backpatch at location 0x%08x(0x%08x)\n", ctx->CTX_PC, Value);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ const u8 *JitArm::BackPatch(u8 *codePtr, u32, void *ctx_void)
|
|||
emitter.MOV(R1, R10); // Addr- 5
|
||||
emitter.BL(R14); // 6
|
||||
emitter.POP(4, R0, R1, R2, R3); // 7
|
||||
u32 newPC = ctx->reg_pc - (ARMREGOFFSET + 4 * 4);
|
||||
ctx->reg_pc = newPC;
|
||||
u32 newPC = ctx->CTX_PC - (ARMREGOFFSET + 4 * 4);
|
||||
ctx->CTX_PC = newPC;
|
||||
emitter.FlushIcache();
|
||||
return codePtr;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ const u8 *JitArm::BackPatch(u8 *codePtr, u32, void *ctx_void)
|
|||
emitter.MOV(R14, R0); // 6
|
||||
emitter.POP(4, R0, R1, R2, R3); // 7
|
||||
emitter.MOV(rD, R14); // 8
|
||||
ctx->reg_pc -= ARMREGOFFSET + (4 * 4);
|
||||
ctx->CTX_PC -= ARMREGOFFSET + (4 * 4);
|
||||
emitter.FlushIcache();
|
||||
return codePtr;
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info)
|
|||
const u8 *Jitx86Base::BackPatch(u8 *codePtr, u32 emAddress, void *ctx_void)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
CONTEXT *ctx = (CONTEXT *)ctx_void;
|
||||
SContext *ctx = (SContext *)ctx_void;
|
||||
|
||||
if (!jit->IsInCodeSpace(codePtr))
|
||||
return 0; // this will become a regular crash real soon after this
|
||||
|
@ -206,7 +206,7 @@ const u8 *Jitx86Base::BackPatch(u8 *codePtr, u32 emAddress, void *ctx_void)
|
|||
if (info.instructionSize < 3)
|
||||
PanicAlert("Instruction too small");
|
||||
// We entered here with a BSWAP-ed EAX. We'll have to swap it back.
|
||||
ctx->Rax = Common::swap32((u32)ctx->Rax);
|
||||
ctx->CTX_RAX = Common::swap32((u32)ctx->CTX_RAX);
|
||||
return codePtr - 2;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -10,38 +10,220 @@
|
|||
#include "x64Analyzer.h"
|
||||
#include "Thunk.h"
|
||||
|
||||
// Declarations and definitions
|
||||
// ----------
|
||||
// meh.
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
typedef CONTEXT SContext;
|
||||
#if defined(_M_X64)
|
||||
#define CTX_RAX Rax
|
||||
#define CTX_RBX Rbx
|
||||
#define CTX_RCX Rcx
|
||||
#define CTX_RDX Rdx
|
||||
#define CTX_RDI Rdi
|
||||
#define CTX_RSI Rsi
|
||||
#define CTX_RBP Rbp
|
||||
#define CTX_RSP Rsp
|
||||
#define CTX_R8 R8
|
||||
#define CTX_R9 R9
|
||||
#define CTX_R10 R10
|
||||
#define CTX_R11 R11
|
||||
#define CTX_R12 R12
|
||||
#define CTX_R13 R13
|
||||
#define CTX_R14 R14
|
||||
#define CTX_R15 R15
|
||||
#define CTX_RIP Rip
|
||||
#elif defined(_M_IX86)
|
||||
#define CTX_EAX Eax
|
||||
#define CTX_EBX Ebx
|
||||
#define CTX_ECX Ecx
|
||||
#define CTX_EDX Edx
|
||||
#define CTX_EDI Edi
|
||||
#define CTX_ESI Esi
|
||||
#define CTX_EBP Ebp
|
||||
#define CTX_ESP Esp
|
||||
#define CTX_EIP Eip
|
||||
#else
|
||||
#error No context definition for OS
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#if defined(_M_X64)
|
||||
typedef x86_thread_state64_t SContext;
|
||||
#define CTX_RAX __rax
|
||||
#define CTX_RBX __rbx
|
||||
#define CTX_RCX __rcx
|
||||
#define CTX_RDX __rdx
|
||||
#define CTX_RDI __rdi
|
||||
#define CTX_RSI __rsi
|
||||
#define CTX_RBP __rbp
|
||||
#define CTX_RSP __rsp
|
||||
#define CTX_R8 __r8
|
||||
#define CTX_R9 __r9
|
||||
#define CTX_R10 __r10
|
||||
#define CTX_R11 __r11
|
||||
#define CTX_R12 __r12
|
||||
#define CTX_R13 __r13
|
||||
#define CTX_R14 __r14
|
||||
#define CTX_R15 __r15
|
||||
#define CTX_RIP __rip
|
||||
#elif defined(_M_IX86)
|
||||
typedef x86_thread_state_t SContext;
|
||||
#define CTX_EAX __eax
|
||||
#define CTX_EBX __ebx
|
||||
#define CTX_ECX __ecx
|
||||
#define CTX_EDX __edx
|
||||
#define CTX_EDI __edi
|
||||
#define CTX_ESI __esi
|
||||
#define CTX_EBP __ebp
|
||||
#define CTX_ESP __esp
|
||||
#define CTX_EIP __eip
|
||||
#elif defined(_M_ARM)
|
||||
typedef arm_thread_state_t SContext;
|
||||
// Add others if required.
|
||||
#define CTX_PC __pc
|
||||
#else
|
||||
#error No context definition for OS
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#include <signal.h>
|
||||
#if defined(_M_X64)
|
||||
#include <ucontext.h>
|
||||
typedef mcontext_t SContext;
|
||||
#define CTX_RAX gregs[REG_RAX]
|
||||
#define CTX_RBX gregs[REG_RBX]
|
||||
#define CTX_RCX gregs[REG_RCX]
|
||||
#define CTX_RDX gregs[REG_RDX]
|
||||
#define CTX_RDI gregs[REG_RDI]
|
||||
#define CTX_RSI gregs[REG_RSI]
|
||||
#define CTX_RBP gregs[REG_RBP]
|
||||
#define CTX_RSP gregs[REG_RSP]
|
||||
#define CTX_R8 gregs[REG_R8]
|
||||
#define CTX_R9 gregs[REG_R9]
|
||||
#define CTX_R10 gregs[REG_R10]
|
||||
#define CTX_R11 gregs[REG_R11]
|
||||
#define CTX_R12 gregs[REG_R12]
|
||||
#define CTX_R13 gregs[REG_R13]
|
||||
#define CTX_R14 gregs[REG_R14]
|
||||
#define CTX_R15 gregs[REG_R15]
|
||||
#define CTX_RIP gregs[REG_RIP]
|
||||
#elif defined(_M_IX86)
|
||||
#include <ucontext.h>
|
||||
typedef mcontext_t SContext;
|
||||
#define CTX_EAX gregs[REG_EAX]
|
||||
#define CTX_EBX gregs[REG_EBX]
|
||||
#define CTX_ECX gregs[REG_ECX]
|
||||
#define CTX_EDX gregs[REG_EDX]
|
||||
#define CTX_EDI gregs[REG_EDI]
|
||||
#define CTX_ESI gregs[REG_ESI]
|
||||
#define CTX_EBP gregs[REG_EBP]
|
||||
#define CTX_ESP gregs[REG_ESP]
|
||||
#define CTX_EIP gregs[REG_EIP]
|
||||
#elif defined(ANDROID)
|
||||
// Add others if required.
|
||||
typedef struct sigcontext SContext;
|
||||
#define CTX_PC arm_pc
|
||||
#else
|
||||
#error No context definition for OS
|
||||
#endif
|
||||
#elif defined(__NetBSD__)
|
||||
#include <ucontext.h>
|
||||
typedef mcontext_t SContext;
|
||||
#if defined(_M_X64)
|
||||
#define CTX_RAX __gregs[_REG_RAX]
|
||||
#define CTX_RBX __gregs[_REG_RBX]
|
||||
#define CTX_RCX __gregs[_REG_RCX]
|
||||
#define CTX_RDX __gregs[_REG_RDX]
|
||||
#define CTX_RDI __gregs[_REG_RDI]
|
||||
#define CTX_RSI __gregs[_REG_RSI]
|
||||
#define CTX_RBP __gregs[_REG_RBP]
|
||||
#define CTX_RSP __gregs[_REG_RSP]
|
||||
#define CTX_R8 __gregs[_REG_R8]
|
||||
#define CTX_R9 __gregs[_REG_R9]
|
||||
#define CTX_R10 __gregs[_REG_R10]
|
||||
#define CTX_R11 __gregs[_REG_R11]
|
||||
#define CTX_R12 __gregs[_REG_R12]
|
||||
#define CTX_R13 __gregs[_REG_R13]
|
||||
#define CTX_R14 __gregs[_REG_R14]
|
||||
#define CTX_R15 __gregs[_REG_R15]
|
||||
#define CTX_RIP __gregs[_REG_RIP]
|
||||
#elif defined(_M_IX86)
|
||||
#define CTX_EAX __gregs[__REG_EAX]
|
||||
#define CTX_EBX __gregs[__REG_EBX]
|
||||
#define CTX_ECX __gregs[__REG_ECX]
|
||||
#define CTX_EDX __gregs[__REG_EDX]
|
||||
#define CTX_EDI __gregs[__REG_EDI]
|
||||
#define CTX_ESI __gregs[__REG_ESI]
|
||||
#define CTX_EBP __gregs[__REG_EBP]
|
||||
#define CTX_ESP __gregs[__REG_ESP]
|
||||
#define CTX_EIP __gregs[__REG_EIP]
|
||||
#else
|
||||
#error No context definition for OS
|
||||
#endif
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <ucontext.h>
|
||||
typedef mcontext_t SContext;
|
||||
#if defined(_M_X64)
|
||||
#define CTX_RAX mc_rax
|
||||
#define CTX_RBX mc_rbx
|
||||
#define CTX_RCX mc_rcx
|
||||
#define CTX_RDX mc_rdx
|
||||
#define CTX_RDI mc_rdi
|
||||
#define CTX_RSI mc_rsi
|
||||
#define CTX_RBP mc_rbp
|
||||
#define CTX_RSP mc_rsp
|
||||
#define CTX_R8 mc_r8
|
||||
#define CTX_R9 mc_r9
|
||||
#define CTX_R10 mc_r10
|
||||
#define CTX_R11 mc_r11
|
||||
#define CTX_R12 mc_r12
|
||||
#define CTX_R13 mc_r13
|
||||
#define CTX_R14 mc_r14
|
||||
#define CTX_R15 mc_r15
|
||||
#define CTX_RIP mc_rip
|
||||
#elif defined(_M_IX86)
|
||||
#define CTX_EAX mc_eax
|
||||
#define CTX_EBX mc_ebx
|
||||
#define CTX_ECX mc_ecx
|
||||
#define CTX_EDX mc_edx
|
||||
#define CTX_EDI mc_edi
|
||||
#define CTX_ESI mc_esi
|
||||
#define CTX_EBP mc_ebp
|
||||
#define CTX_ESP mc_esp
|
||||
#define CTX_EIP mc_eip
|
||||
#else
|
||||
#error No context definition for OS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// void Jit(u32 em_address);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
// 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
|
||||
#if defined(_M_X64)
|
||||
#define CTX_PC CTX_RIP
|
||||
#include <stddef.h>
|
||||
static inline u64 *ContextRN(SContext* ctx, int n)
|
||||
{
|
||||
#ifdef _M_ARM
|
||||
u32 reg_pc;
|
||||
#else
|
||||
#ifdef _M_X64
|
||||
u64 Rip;
|
||||
u64 Rax;
|
||||
#else
|
||||
u32 Eip;
|
||||
u32 Eax;
|
||||
#endif
|
||||
#endif
|
||||
static const u8 offsets[] =
|
||||
{
|
||||
offsetof(SContext, CTX_RAX),
|
||||
offsetof(SContext, CTX_RCX),
|
||||
offsetof(SContext, CTX_RDX),
|
||||
offsetof(SContext, CTX_RBX),
|
||||
offsetof(SContext, CTX_RSP),
|
||||
offsetof(SContext, CTX_RBP),
|
||||
offsetof(SContext, CTX_RSI),
|
||||
offsetof(SContext, CTX_RDI),
|
||||
offsetof(SContext, CTX_R8),
|
||||
offsetof(SContext, CTX_R9),
|
||||
offsetof(SContext, CTX_R10),
|
||||
offsetof(SContext, CTX_R11),
|
||||
offsetof(SContext, CTX_R12),
|
||||
offsetof(SContext, CTX_R13),
|
||||
offsetof(SContext, CTX_R14),
|
||||
offsetof(SContext, CTX_R15)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_M_ARM)
|
||||
#define CONTEXT_PC(ctx) ((ctx)->reg_pc)
|
||||
#elif defined(_M_X64)
|
||||
#define CONTEXT_PC(ctx) ((ctx)->Rip)
|
||||
#else
|
||||
#define CONTEXT_PC(ctx) ((ctx)->Eip)
|
||||
return (u64 *) ((char *) ctx + offsets[n]);
|
||||
}
|
||||
#elif defined(_M_IX86)
|
||||
#define CTX_PC CTX_EIP
|
||||
#endif
|
||||
|
||||
class TrampolineCache : public Gen::XCodeBlock
|
||||
|
|
|
@ -2,44 +2,11 @@
|
|||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#ifndef ANDROID
|
||||
#include <sys/ucontext.h> // Look in here for the context definition.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#include <mach/message.h>
|
||||
#include "Thread.h"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define CREG_RAX(ctx) (*(ctx))->__ss.__rax
|
||||
#define CREG_RIP(ctx) (*(ctx))->__ss.__rip
|
||||
#define CREG_EAX(ctx) (*(ctx))->__ss.__eax
|
||||
#define CREG_EIP(ctx) (*(ctx))->__ss.__eip
|
||||
#elif defined __FreeBSD__
|
||||
#define CREG_RAX(ctx) (ctx)->mc_rax
|
||||
#define CREG_RIP(ctx) (ctx)->mc_rip
|
||||
#define CREG_EAX(ctx) (ctx)->mc_eax
|
||||
#define CREG_EIP(ctx) (ctx)->mc_eip
|
||||
#elif defined __linux__
|
||||
#define CREG_RAX(ctx) (ctx)->gregs[REG_RAX]
|
||||
#define CREG_RIP(ctx) (ctx)->gregs[REG_RIP]
|
||||
#define CREG_EAX(ctx) (ctx)->gregs[REG_EAX]
|
||||
#define CREG_EIP(ctx) (ctx)->gregs[REG_EIP]
|
||||
#elif defined __NetBSD__
|
||||
#define CREG_RAX(ctx) (ctx)->__gregs[_REG_RAX]
|
||||
#define CREG_RIP(ctx) (ctx)->__gregs[_REG_RIP]
|
||||
#define CREG_EAX(ctx) (ctx)->__gregs[_REG_EAX]
|
||||
#define CREG_EIP(ctx) (ctx)->__gregs[_REG_EIP]
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -73,9 +40,9 @@ void print_trace(const char * msg)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool DoFault(u64 bad_address, CONTEXT *ctx)
|
||||
bool DoFault(u64 bad_address, SContext *ctx)
|
||||
{
|
||||
if (!JitInterface::IsInCodeSpace((u8*) CONTEXT_PC(ctx)))
|
||||
if (!JitInterface::IsInCodeSpace((u8*) ctx->CTX_PC))
|
||||
{
|
||||
// Let's not prevent debugging.
|
||||
return false;
|
||||
|
@ -93,10 +60,10 @@ bool DoFault(u64 bad_address, CONTEXT *ctx)
|
|||
return false;
|
||||
}
|
||||
u32 em_address = (u32)(bad_address - memspace_bottom);
|
||||
const u8 *new_pc = jit->BackPatch((u8*) CONTEXT_PC(ctx), em_address, ctx);
|
||||
const u8 *new_pc = jit->BackPatch((u8*) ctx->CTX_PC, em_address, ctx);
|
||||
if (new_pc)
|
||||
{
|
||||
CONTEXT_PC(ctx) = (u64) new_pc;
|
||||
ctx->CTX_PC = (u64) new_pc;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -244,14 +211,8 @@ void ExceptionThread(mach_port_t port)
|
|||
}
|
||||
|
||||
x86_thread_state64_t *state = (x86_thread_state64_t *) msg_in.old_state;
|
||||
CONTEXT fake_ctx;
|
||||
fake_ctx.Rax = state->__rax;
|
||||
fake_ctx.Rip = state->__rip;
|
||||
|
||||
bool ok = DoFault(msg_in.code[1], &fake_ctx);
|
||||
|
||||
state->__rax = fake_ctx.Rax;
|
||||
state->__rip = fake_ctx.Rip;
|
||||
bool ok = DoFault(msg_in.code[1], state);
|
||||
|
||||
// Set up the reply.
|
||||
msg_out.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(msg_in.Head.msgh_bits), 0);
|
||||
|
@ -324,26 +285,8 @@ void sigsegv_handler(int sig, siginfo_t *info, void *raw_context)
|
|||
|
||||
// Get all the information we can out of the context.
|
||||
mcontext_t *ctx = &context->uc_mcontext;
|
||||
CONTEXT fake_ctx;
|
||||
#ifdef _M_X64
|
||||
fake_ctx.Rax = CREG_RAX(ctx);
|
||||
fake_ctx.Rip = CREG_RIP(ctx);
|
||||
#else
|
||||
fake_ctx.Eax = CREG_EAX(ctx);
|
||||
fake_ctx.Eip = CREG_EIP(ctx);
|
||||
#endif
|
||||
// assume it's not a write
|
||||
if (DoFault(bad_address, &fake_ctx))
|
||||
{
|
||||
#ifdef _M_X64
|
||||
CREG_RAX(ctx) = fake_ctx.Rax;
|
||||
CREG_RIP(ctx) = fake_ctx.Rip;
|
||||
#else
|
||||
CREG_EAX(ctx) = fake_ctx.Eax;
|
||||
CREG_EIP(ctx) = fake_ctx.Eip;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
if (!DoFault(bad_address, ctx))
|
||||
{
|
||||
// retry and crash
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
|
|
Loading…
Reference in New Issue