xpcom/build/mach_override.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial