Merge pull request #1344 from comex/mem-tools-testing

MemTools testing
This commit is contained in:
comex 2014-10-19 22:20:30 -04:00
commit 4af98d63bc
4 changed files with 115 additions and 8 deletions

View File

@ -36,7 +36,7 @@
#else #else
#error No context definition for OS #error No context definition for OS
#endif #endif
#elif defined(__APPLE__) #elif defined(__APPLE__) && !defined(USE_SIGACTION_ON_APPLE)
#include <mach/mach.h> #include <mach/mach.h>
#include <mach/message.h> #include <mach/message.h>
#if _M_X86_64 #if _M_X86_64
@ -61,6 +61,26 @@
#else #else
#error No context definition for OS #error No context definition for OS
#endif #endif
#elif defined(__APPLE__)
#include <signal.h>
typedef _STRUCT_MCONTEXT64 SContext;
#define CTX_RAX __ss.__rax
#define CTX_RBX __ss.__rbx
#define CTX_RCX __ss.__rcx
#define CTX_RDX __ss.__rdx
#define CTX_RDI __ss.__rdi
#define CTX_RSI __ss.__rsi
#define CTX_RBP __ss.__rbp
#define CTX_RSP __ss.__rsp
#define CTX_R8 __ss.__r8
#define CTX_R9 __ss.__r9
#define CTX_R10 __ss.__r10
#define CTX_R11 __ss.__r11
#define CTX_R12 __ss.__r12
#define CTX_R13 __ss.__r13
#define CTX_R14 __ss.__r14
#define CTX_R15 __ss.__r15
#define CTX_RIP __ss.__rip
#elif defined(__linux__) #elif defined(__linux__)
#include <signal.h> #include <signal.h>
#if _M_X86_64 #if _M_X86_64

View File

@ -5,12 +5,9 @@
#include <cstdio> #include <cstdio>
#include <vector> #include <vector>
#ifdef __APPLE__
#include "Common/Thread.h"
#endif
#include "Common/CommonFuncs.h" #include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Thread.h"
#include "Common/x64Analyzer.h" #include "Common/x64Analyzer.h"
#include "Core/MemTools.h" #include "Core/MemTools.h"
@ -92,7 +89,7 @@ void InstallExceptionHandler()
void UninstallExceptionHandler() {} void UninstallExceptionHandler() {}
#elif defined(__APPLE__) #elif defined(__APPLE__) && !defined(USE_SIGACTION_ON_APPLE)
void CheckKR(const char* name, kern_return_t kr) void CheckKR(const char* name, kern_return_t kr)
{ {
@ -216,7 +213,7 @@ void UninstallExceptionHandler() {}
static void sigsegv_handler(int sig, siginfo_t *info, void *raw_context) static void sigsegv_handler(int sig, siginfo_t *info, void *raw_context)
{ {
if (sig != SIGSEGV) if (sig != SIGSEGV && sig != SIGBUS)
{ {
// We are not interested in other signals - handle it as usual. // We are not interested in other signals - handle it as usual.
return; return;
@ -233,10 +230,19 @@ static void sigsegv_handler(int sig, siginfo_t *info, void *raw_context)
// Get all the information we can out of the context. // Get all the information we can out of the context.
mcontext_t *ctx = &context->uc_mcontext; mcontext_t *ctx = &context->uc_mcontext;
// assume it's not a write // assume it's not a write
if (!JitInterface::HandleFault(bad_address, ctx)) if (!JitInterface::HandleFault(bad_address,
#ifdef __APPLE__
*ctx
#else
ctx
#endif
))
{ {
// retry and crash // retry and crash
signal(SIGSEGV, SIG_DFL); signal(SIGSEGV, SIG_DFL);
#ifdef __APPLE__
signal(SIGBUS, SIG_DFL);
#endif
} }
} }
@ -254,6 +260,9 @@ void InstallExceptionHandler()
sa.sa_flags = SA_SIGINFO; sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, nullptr); sigaction(SIGSEGV, &sa, nullptr);
#ifdef __APPLE__
sigaction(SIGBUS, &sa, nullptr);
#endif
} }
void UninstallExceptionHandler() void UninstallExceptionHandler()

View File

@ -1 +1,2 @@
add_dolphin_test(MMIOTest MMIOTest.cpp) add_dolphin_test(MMIOTest MMIOTest.cpp)
add_dolphin_test(PageFaultTest PageFaultTest.cpp)

View File

@ -0,0 +1,77 @@
#include <chrono>
#include "Common/CommonTypes.h"
#include "Common/Timer.h"
#include "Core/MemTools.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
// include order is important
#include <gtest/gtest.h>
#if _M_X86_64 || _M_ARM_32
enum
{
#ifdef _WIN32
PAGE_GRAN = 0x10000
#else
PAGE_GRAN = 0x1000
#endif
};
class PageFaultFakeJit : public JitBase
{
public:
// CPUCoreBase methods
void Init() override {}
void Shutdown() override {}
void ClearCache() override {}
void Run() override {}
void SingleStep() override {}
const char *GetName() override { return nullptr; }
// JitBase methods
JitBaseBlockCache *GetBlockCache() override { return nullptr; }
void Jit(u32 em_address) override {}
const CommonAsmRoutinesBase *GetAsmRoutines() override { return nullptr; }
virtual bool HandleFault(uintptr_t access_address, SContext* ctx) override
{
m_pre_unprotect_time = std::chrono::high_resolution_clock::now();
UnWriteProtectMemory(m_data, PAGE_GRAN, /*allowExecute*/ false);
m_post_unprotect_time = std::chrono::high_resolution_clock::now();
return true;
}
void* m_data;
std::chrono::time_point<std::chrono::high_resolution_clock>
m_pre_unprotect_time, m_post_unprotect_time;
};
TEST(PageFault, PageFault)
{
EMM::InstallExceptionHandler();
void* data = AllocateMemoryPages(PAGE_GRAN);
EXPECT_NE(data, nullptr);
WriteProtectMemory(data, PAGE_GRAN, false);
PageFaultFakeJit pfjit;
jit = &pfjit;
pfjit.m_data = data;
auto start = std::chrono::high_resolution_clock::now();
*(volatile int*) data = 5;
auto end = std::chrono::high_resolution_clock::now();
#define AS_NS(diff) ((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count())
EMM::UninstallExceptionHandler();
jit = nullptr;
printf("page fault timing:\n");
printf("start->HandleFault %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start));
printf("UnWriteProtectMemory %llu ns\n", AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time));
printf("HandleFault->end %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time));
printf("total %llu ns\n", AS_NS(end - start));
}
#endif