| OLD | NEW |
| 1 /******************************************************************************* | 1 // mach_override.h semver:1.2.0 |
| 2 » mach_override.h | 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com |
| 3 » » Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzs
ch.com> | 3 // Some rights reserved: http://opensource.org/licenses/mit |
| 4 » » Some rights reserved: <http://opensource.org/licenses/mit-licens
e.php> | 4 // https://github.com/rentzsch/mach_override |
| 5 | 5 |
| 6 ************************************************************************
***/ | |
| 7 | |
| 8 /***************************************************************************//** | |
| 9 @mainpage mach_override | |
| 10 @author Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> | |
| 11 | |
| 12 This package, coded in C to the Mach API, allows you to override ("patch
") | |
| 13 program- and system-supplied functions at runtime. You can fully replace | |
| 14 functions with your implementations, or merely head- or tail-patch the | |
| 15 original implementations. | |
| 16 | |
| 17 Use it by #include'ing mach_override.h from your .c, .m or .mm file(s). | |
| 18 | |
| 19 @todo Discontinue use of Carbon's MakeDataExecutable() and | |
| 20 CompareAndSwap() calls and start using the Mach equivale
nts, if they | |
| 21 exist. If they don't, write them and roll them in. That
way, this | |
| 22 code will be pure Mach, which will make it easier to use
everywhere. | |
| 23 Update: MakeDataExecutable() has been replaced by | |
| 24 msync(MS_INVALIDATE). There is an OSCompareAndSwap in li
bkern, but | |
| 25 I'm currently unsure if I can link against it. May have
to roll in | |
| 26 my own version... | |
| 27 @todo Stop using an entire 4K high-allocated VM page per 28-byte escap
e | |
| 28 branch island. Done right, this will dramatically speed
up escape | |
| 29 island allocations when they number over 250. Then again
, if you're | |
| 30 overriding more than 250 functions, maybe speed isn't yo
ur main | |
| 31 concern... | |
| 32 @todo Add detection of: b, bl, bla, bc, bcl, bcla, bcctrl, bclrl | |
| 33 first-instructions. Initially, we should refuse to overr
ide | |
| 34 functions beginning with these instructions. Eventually,
we should | |
| 35 dynamically rewrite them to make them position-independe
nt. | |
| 36 @todo Write mach_unoverride(), which would remove an override placed o
n a | |
| 37 function. Must be multiple-override aware, which means a
n almost | |
| 38 complete rewrite under the covers, because the target ad
dress can't | |
| 39 be spread across two load instructions like it is now si
nce it will | |
| 40 need to be atomically updatable. | |
| 41 @todo Add non-rentry variants of overrides to test_mach_override. | |
| 42 | |
| 43 ************************************************************************
***/ | |
| 44 | |
| 45 #ifndef _mach_override_ | 6 #ifndef _mach_override_ |
| 46 #define _mach_override_ | 7 #define _mach_override_ |
| 47 | 8 |
| 48 #include <sys/types.h> | 9 #include <sys/types.h> |
| 49 #include <mach/error.h> | 10 #include <mach/error.h> |
| 50 | 11 |
| 51 #ifdef __cplusplus | |
| 52 extern "C" { | |
| 53 #endif | |
| 54 | |
| 55 /** | |
| 56 Returned if the function to be overrided begins with a 'mfctr' instructi
on. | |
| 57 */ | |
| 58 #define err_cannot_override (err_local|1) | 12 #define err_cannot_override (err_local|1) |
| 59 | 13 |
| 60 /*******************************************************************************
*****//** | 14 __BEGIN_DECLS |
| 15 |
| 16 /*******************************************************************************
********* |
| 61 Dynamically overrides the function implementation referenced by | 17 Dynamically overrides the function implementation referenced by |
| 62 originalFunctionAddress with the implentation pointed to by overrideFunc
tionAddress. | 18 originalFunctionAddress with the implentation pointed to by overrideFunc
tionAddress. |
| 63 Optionally returns a pointer to a "reentry island" which, if jumped to,
will resume | 19 Optionally returns a pointer to a "reentry island" which, if jumped to,
will resume |
| 64 the original implementation. | 20 the original implementation. |
| 65 | 21 |
| 66 @param originalFunctionAddress -> Required address
of the function to | 22 @param originalFunctionAddress -> Required address
of the function to |
| 67
override (with overrideFunctionAddress). | 23
override (with overrideFunctionAddress). |
| 68 @param overrideFunctionAddress -> Required address
to the overriding | 24 @param overrideFunctionAddress -> Required address
to the overriding |
| 69
function. | 25
function. |
| 70 @param originalFunctionReentryIsland <- Optional pointer to poin
ter to the | 26 @param originalFunctionReentryIsland <- Optional pointer to poin
ter to the |
| 71
reentry island. Can be NULL. | 27
reentry island. Can be NULL. |
| 72 @result
<- err_cannot_override if the original | 28 @result
<- err_cannot_override if the original |
| 73
function's implementation begins with | 29
function's implementation begins with |
| 74
the 'mfctr' instruction. | 30
the 'mfctr' instruction. |
| 75 | 31 |
| 76 ************************************************************************
************/ | 32 ************************************************************************
************/ |
| 77 | 33 |
| 78 mach_error_t | 34 mach_error_t |
| 79 mach_override_ptr( | 35 mach_override_ptr( |
| 80 void *originalFunctionAddress, | 36 void *originalFunctionAddress, |
| 81 const void *overrideFunctionAddress, | 37 const void *overrideFunctionAddress, |
| 82 void **originalFunctionReentryIsland ); | 38 void **originalFunctionReentryIsland ); |
| 83 | 39 |
| 84 /*******************************************************************************
*****//** | 40 __END_DECLS |
| 85 » | 41 |
| 42 /*******************************************************************************
********* |
| 43 » If you're using C++ this macro will ease the tedium of typedef'ing, nami
ng, keeping |
| 44 » track of reentry islands and defining your override code. See test_mach_
override.cp |
| 45 » for example usage. |
| 86 | 46 |
| 87 ************************************************************************
************/ | 47 ************************************************************************
************/ |
| 88 | 48 |
| 89 #ifdef __cplusplus | 49 #ifdef __cplusplus |
| 50 #define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, OR
IGINAL_FUNCTION_ARGS, ERR ) \ |
| 51 {
\ |
| 52 static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)
ORIGINAL_FUNCTION_ARGS; \ |
| 53 static bool ORIGINAL_FUNCTION_NAME##_overriden = false;
\ |
| 54 class mach_override_class__##ORIGINAL_FUNCTION_NAME {
\ |
| 55 public:
\ |
| 56 static kern_return_t override(void *originalFunctionPtr) {
\ |
| 57 kern_return_t result = err_none;
\ |
| 58 if (!ORIGINAL_FUNCTION_NAME##_overriden) {
\ |
| 59 ORIGINAL_FUNCTION_NAME##_overriden = true;
\ |
| 60 result = mach_override_ptr( (void*)originalFunct
ionPtr,
\ |
| 61
(void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement,
\ |
| 62
(void**)&ORIGINAL_FUNCTION_NAME##_reenter );
\ |
| 63 }
\ |
| 64 return result;
\ |
| 65 }
\ |
| 66 static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTI
ON_ARGS { |
| 90 | 67 |
| 91 #define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, OR
IGINAL_FUNCTION_ARGS, ERR )» » » \ | 68 #define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME )» » » »
» » » » » » » » » »
» » \ |
| 92 » {» » » » » » » » »
» » » » » » » » » »
» » » » » » » » » \ | 69 » » }» » » » » » » »
» » » » » » » » » »
» » » » » » » » \ |
| 93 » » static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_
reenter)ORIGINAL_FUNCTION_ARGS;»» » » \ | 70 » };» » » » » » » » »
» » » » » » » » » »
» » » » » » » » \ |
| 94 » » static bool ORIGINAL_FUNCTION_NAME##_overriden = false;»»
» » » » » » » » » »
» » \ | 71 » » » » » » » » » »
» » » » » » » » » »
» » » » » » » » \ |
| 95 » » class mach_override_class__##ORIGINAL_FUNCTION_NAME {» »
» » » » » » » » » »
» » \ | 72 » err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORI
GINAL_FUNCTION_NAME);» » » » \ |
| 96 » » public:»» » » » » » »
» » » » » » » » » »
» » » » » » » » \ | 73 } |
| 97 » » » static kern_return_t override(void *originalFunctionPtr)
{» » » » » » » » » »
» » \ | |
| 98 » » » » kern_return_t result = err_none;» »
» » » » » » » » » »
» » » » » \ | |
| 99 » » » » if (!ORIGINAL_FUNCTION_NAME##_overriden) {»
» » » » » » » » » »
» » » » \ | |
| 100 » » » » » ORIGINAL_FUNCTION_NAME##_overriden = tru
e;» » » » » » » » » »
» » » » \ | |
| 101 » » » » » result = mach_override_ptr( (void*)origi
nalFunctionPtr,»» » » » » » » »
» » \ | |
| 102 » » » » » » » » » »
» » (void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacemen
t,» \ | |
| 103 » » » » » » » » » »
» » (void**)&ORIGINAL_FUNCTION_NAME##_reenter );» » »
» » » \ | |
| 104 » » » » }» » » » » »
» » » » » » » » » »
» » » » » » » » » \ | |
| 105 » » » » return result;» » » » »
» » » » » » » » » »
» » » » » » » \ | |
| 106 » » » }» » » » » » »
» » » » » » » » » »
» » » » » » » » » \ | |
| 107 » » » static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINA
L_FUNCTION_ARGS { | |
| 108 | |
| 109 #define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME )» » » »
» » » » » » » » » »
» » » \ | |
| 110 » » » }» » » » » » »
» » » » » » » » » »
» » » » » » » » » \ | |
| 111 » » };» » » » » » » »
» » » » » » » » » »
» » » » » » » » » \ | |
| 112 » » » » » » » » » »
» » » » » » » » » »
» » » » » » » » » \ | |
| 113 » » err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((v
oid*)ORIGINAL_FUNCTION_NAME);» » » » \ | |
| 114 » } | |
| 115 | |
| 116 #endif | 74 #endif |
| 117 | 75 |
| 118 #ifdef __cplusplus | |
| 119 } | |
| 120 #endif | |
| 121 #endif // _mach_override_ | 76 #endif // _mach_override_ |
| OLD | NEW |