From 733b29213097aba25b2398d1dea718622ccd89c2 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 6 Jul 2010 01:09:37 +0000 Subject: [PATCH] - Added backpatching support to systems with mprotect() (e.g. Linux). SVN r2412 (trunk) --- CMakeLists.txt | 7 ++++++- nodebuild.cpp | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c60bfb..61723bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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." ) diff --git a/nodebuild.cpp b/nodebuild.cpp index 14164ee..25b1528 100644 --- a/nodebuild.cpp +++ b/nodebuild.cpp @@ -1054,8 +1054,13 @@ void FNodeBuilder::PrintSet (int l, DWORD set) } #ifdef BACKPATCH +#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#else +#include +#include +#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.