- 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 )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( WIN32 )
set( BACKPATCH 0 )
CHECK_FUNCTION_EXISTS(mprotect HAVE_MPROTECT)
if( HAVE_MPROTECT )
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
else( HAVE_MPROTECT )
set( BACKPATCH 0 )
endif( HAVE_MPROTECT )
endif( WIN32 )
set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." )
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 _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/mman.h>
#include <limits.h>
#endif
#ifdef __GNUC__
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
calleroffset = CallerOffset;
#endif
// printf ("Patching for SSE %d\n", SSELevel);
// printf ("Patching for SSE %d @ %p %d\n", SSELevel, calleroffset, *calleroffset);
if (SSELevel == 2)
{
@ -1095,10 +1100,23 @@ int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVe
}
// Patch the caller.
#ifdef _WIN32
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;
#ifdef _WIN32
VirtualProtect (calleroffset, 4, oldprotect, &oldprotect);
#else
mprotect(callerpage, protectlen, PROT_READ|PROT_EXEC);
#endif
}
// And return by calling the real function.