- Added backpatching support to systems with mprotect() (e.g. Linux).

SVN r2412 (trunk)
This commit is contained in:
Randy Heit 2010-07-06 01:09:37 +00:00
parent 08216817e5
commit 733b292130
2 changed files with 25 additions and 2 deletions

View file

@ -34,7 +34,12 @@ if( SSE_MATTERS )
if( WIN32 ) if( WIN32 )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." ) set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( WIN32 ) else( WIN32 )
CHECK_FUNCTION_EXISTS(mprotect HAVE_MPROTECT)
if( HAVE_MPROTECT )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( HAVE_MPROTECT )
set( BACKPATCH 0 ) set( BACKPATCH 0 )
endif( HAVE_MPROTECT )
endif( WIN32 ) endif( WIN32 )
set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." ) set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." )
set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." ) set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." )

View file

@ -1054,8 +1054,13 @@ void FNodeBuilder::PrintSet (int l, DWORD set)
} }
#ifdef BACKPATCH #ifdef BACKPATCH
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#else
#include <sys/mman.h>
#include <limits.h>
#endif
#ifdef __GNUC__ #ifdef __GNUC__
extern "C" int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) extern "C" int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
@ -1076,7 +1081,7 @@ int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVe
#else #else
calleroffset = CallerOffset; calleroffset = CallerOffset;
#endif #endif
// printf ("Patching for SSE %d\n", SSELevel); // printf ("Patching for SSE %d @ %p %d\n", SSELevel, calleroffset, *calleroffset);
if (SSELevel == 2) if (SSELevel == 2)
{ {
@ -1095,10 +1100,23 @@ int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVe
} }
// Patch the caller. // Patch the caller.
#ifdef _WIN32
if (VirtualProtect (calleroffset, 4, PAGE_EXECUTE_READWRITE, &oldprotect)) if (VirtualProtect (calleroffset, 4, PAGE_EXECUTE_READWRITE, &oldprotect))
#else
// must make this page-aligned for mprotect
long pagesize = sysconf(_SC_PAGESIZE);
char *callerpage = (char *)((intptr_t)calleroffset & ~(pagesize - 1));
size_t protectlen = (intptr_t)calleroffset + 4 - (intptr_t)callerpage;
int ptect;
if (!(ptect = mprotect(callerpage, protectlen, PROT_READ|PROT_WRITE|PROT_EXEC)))
#endif
{ {
*calleroffset += diff; *calleroffset += diff;
#ifdef _WIN32
VirtualProtect (calleroffset, 4, oldprotect, &oldprotect); VirtualProtect (calleroffset, 4, oldprotect, &oldprotect);
#else
mprotect(callerpage, protectlen, PROT_READ|PROT_EXEC);
#endif
} }
// And return by calling the real function. // And return by calling the real function.