win64/jit: Generate unwind table for the jit code cache

This required moving the SH4_TCB outside the exe, as new tables that belong on the executable are ignored.
This isn't perfect, but there's a large area to scan for available address space so it shouldn't be a problem
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2015-08-07 15:54:51 +02:00 committed by TwistedUmbrella
parent e6a9d3e661
commit e3845465f0
3 changed files with 142 additions and 13 deletions

View File

@ -28,7 +28,8 @@
#if FEAT_SHREC != DYNAREC_NONE
//uh uh
u8 SH4_TCB[2*CODE_SIZE+4096]
#if !defined(_WIN64)
u8 SH4_TCB[CODE_SIZE+4096]
#if HOST_OS == OS_WINDOWS || FEAT_SHREC != DYNAREC_JIT
;
#elif HOST_OS == OS_LINUX
@ -38,6 +39,7 @@ u8 SH4_TCB[2*CODE_SIZE+4096]
#else
#error SH4_TCB ALLOC
#endif
#endif
u8* CodeCache;
@ -421,30 +423,43 @@ void recSh4_Init()
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x0C000000));
#endif
//align to next page ..
CodeCache = (u8*)(((unat)SH4_TCB+4095)& ~4095);
#if defined(_WIN64)
for (int i = 10; i < 1300; i++) {
//align to next page ..
u8* ptr = (u8*)recSh4_Init - i * 1024 * 1024;
CodeCache = (u8*)VirtualAlloc(ptr, CODE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);//; (u8*)(((unat)SH4_TCB+4095)& ~4095);
if (CodeCache)
break;
}
#else
CodeCache = (u8*)(((unat)SH4_TCB+4095)& ~4095);
#endif
#if HOST_OS == OS_DARWIN
munmap(CodeCache, CODE_SIZE*2);
CodeCache = (u8*)mmap(CodeCache, 2*CODE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
munmap(CodeCache, CODE_SIZE);
CodeCache = (u8*)mmap(CodeCache, CODE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
#endif
#if HOST_OS == OS_WINDOWS
DWORD old;
VirtualProtect(CodeCache,CODE_SIZE*2,PAGE_EXECUTE_READWRITE,&old);
VirtualProtect(CodeCache,CODE_SIZE,PAGE_EXECUTE_READWRITE,&old);
#elif HOST_OS == OS_LINUX || HOST_OS == OS_DARWIN
printf("\n\t CodeCache addr: %p | from: %p | addr here: %p\n", CodeCache, CodeCache, recSh4_Init);
#if FEAT_SHREC == DYNAREC_JIT
if (mprotect(CodeCache, CODE_SIZE*2, PROT_READ|PROT_WRITE|PROT_EXEC))
if (mprotect(CodeCache, CODE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC))
{
perror("\n\tError,Couldnt mprotect CodeCache!");
die("Couldnt mprotect CodeCache");
}
#endif
memset(CodeCache,0xFF,CODE_SIZE*2);
memset(CodeCache,0xFF,CODE_SIZE);
#endif
ngen_init();

View File

@ -46,7 +46,7 @@
#include "blockmanager.h"
#define CODE_SIZE (4*1024*1024)
#define CODE_SIZE (6*1024*1024)
//alternative emit ptr, set to 0 to use the main buffer

View File

@ -106,9 +106,12 @@ bool VramLockedWrite(u8* address);
bool ngen_Rewrite(unat& addr,unat retadr,unat acc);
bool BM_LockedWrite(u8* address);
int ExeptionHandler(u32 dwCode, void* pExceptionPointers)
LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
{
EXCEPTION_POINTERS* ep=(EXCEPTION_POINTERS*)pExceptionPointers;
EXCEPTION_POINTERS* ep = ExceptionInfo;
u32 dwCode = ep->ExceptionRecord->ExceptionCode;
EXCEPTION_RECORD* pExceptionRecord=ep->ExceptionRecord;
@ -117,6 +120,8 @@ int ExeptionHandler(u32 dwCode, void* pExceptionPointers)
u8* address=(u8*)pExceptionRecord->ExceptionInformation[1];
//printf("[EXC] During access to : 0x%X\n", address);
if (VramLockedWrite(address))
{
return EXCEPTION_CONTINUE_EXECUTION;
@ -489,6 +494,108 @@ void ReserveBottomMemory()
#endif
}
#ifdef _WIN64
#include "hw/sh4/dyna/ngen.h"
typedef union _UNWIND_CODE {
struct {
u8 CodeOffset;
u8 UnwindOp : 4;
u8 OpInfo : 4;
};
USHORT FrameOffset;
} UNWIND_CODE, *PUNWIND_CODE;
typedef struct _UNWIND_INFO {
u8 Version : 3;
u8 Flags : 5;
u8 SizeOfProlog;
u8 CountOfCodes;
u8 FrameRegister : 4;
u8 FrameOffset : 4;
//ULONG ExceptionHandler;
UNWIND_CODE UnwindCode[1];
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
* union {
* OPTIONAL ULONG ExceptionHandler;
* OPTIONAL ULONG FunctionEntry;
* };
* OPTIONAL ULONG ExceptionData[]; */
} UNWIND_INFO, *PUNWIND_INFO;
static RUNTIME_FUNCTION Table[1];
static _UNWIND_INFO unwind_info[1];
EXCEPTION_DISPOSITION
__gnat_SEH_error_handler(struct _EXCEPTION_RECORD* ExceptionRecord,
void *EstablisherFrame,
struct _CONTEXT* ContextRecord,
void *DispatcherContext)
{
EXCEPTION_POINTERS ep;
ep.ContextRecord = ContextRecord;
ep.ExceptionRecord = ExceptionRecord;
return (EXCEPTION_DISPOSITION)ExeptionHandler(&ep);
}
PRUNTIME_FUNCTION
seh_callback(
_In_ DWORD64 ControlPc,
_In_opt_ PVOID Context
) {
unwind_info[0].Version = 1;
unwind_info[0].Flags = UNW_FLAG_UHANDLER;
/* We don't use the unwinding info so fill the structure with 0 values. */
unwind_info[0].SizeOfProlog = 0;
unwind_info[0].CountOfCodes = 0;
unwind_info[0].FrameOffset = 0;
unwind_info[0].FrameRegister = 0;
/* Add the exception handler. */
// unwind_info[0].ExceptionHandler =
// (DWORD)((u8 *)__gnat_SEH_error_handler - CodeCache);
/* Set its scope to the entire program. */
Table[0].BeginAddress = 0;// (CodeCache - (u8*)__ImageBase);
Table[0].EndAddress = /*(CodeCache - (u8*)__ImageBase) +*/ CODE_SIZE;
Table[0].UnwindData = (DWORD)((u8 *)unwind_info - CodeCache);
printf("TABLE CALLBACK\n");
//for (;;);
return Table;
}
void setup_seh() {
#if 1
/* Get the base of the module. */
//u8* __ImageBase = (u8*)GetModuleHandle(NULL);
/* Current version is always 1 and we are registering an
exception handler. */
unwind_info[0].Version = 1;
unwind_info[0].Flags = UNW_FLAG_NHANDLER;
/* We don't use the unwinding info so fill the structure with 0 values. */
unwind_info[0].SizeOfProlog = 0;
unwind_info[0].CountOfCodes = 1;
unwind_info[0].FrameOffset = 0;
unwind_info[0].FrameRegister = 0;
/* Add the exception handler. */
unwind_info[0].UnwindCode[0].CodeOffset = 0;
unwind_info[0].UnwindCode[0].UnwindOp = 2;// UWOP_ALLOC_SMALL;
unwind_info[0].UnwindCode[0].OpInfo = 0x20 / 8;
//unwind_info[0].ExceptionHandler =
//(DWORD)((u8 *)__gnat_SEH_error_handler - CodeCache);
/* Set its scope to the entire program. */
Table[0].BeginAddress = 0;// (CodeCache - (u8*)__ImageBase);
Table[0].EndAddress = /*(CodeCache - (u8*)__ImageBase) +*/ CODE_SIZE;
Table[0].UnwindData = (DWORD)((u8 *)unwind_info - CodeCache);
/* Register the unwind information. */
RtlAddFunctionTable(Table, 1, (DWORD64)CodeCache);
#endif
//verify(RtlInstallFunctionTableCallback((unat)CodeCache | 0x3, (DWORD64)CodeCache, CODE_SIZE, seh_callback, 0, 0));
}
#endif
int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShowCmd)
{
ReserveBottomMemory();
@ -511,19 +618,26 @@ int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine
SetupPath();
//SetUnhandledExceptionFilter(&ExeptionHandler);
__try
{
{
int dc_init(int argc,wchar* argv[]);
void dc_run();
void dc_term();
dc_init(argc,argv);
#ifdef _WIN64
setup_seh();
#endif
dc_run();
dc_term();
}
__except( (EXCEPTION_CONTINUE_EXECUTION==ExeptionHandler( GetExceptionCode(), (GetExceptionInformation()))) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH )
__except( ExeptionHandler(GetExceptionInformation()) )
{
printf("Unhandled exception - Emulation thread halted...\n");
}
SetUnhandledExceptionFilter(0);
return 0;
}