xpcom/build/mach_override.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/build/mach_override.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,121 @@
     1.4 +/*******************************************************************************
     1.5 +	mach_override.h
     1.6 +		Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
     1.7 +		Some rights reserved: <http://opensource.org/licenses/mit-license.php>
     1.8 +
     1.9 +	***************************************************************************/
    1.10 +
    1.11 +/***************************************************************************//**
    1.12 +	@mainpage	mach_override
    1.13 +	@author		Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
    1.14 +	
    1.15 +	This package, coded in C to the Mach API, allows you to override ("patch")
    1.16 +	program- and system-supplied functions at runtime. You can fully replace
    1.17 +	functions with your implementations, or merely head- or tail-patch the
    1.18 +	original implementations.
    1.19 +	
    1.20 +	Use it by #include'ing mach_override.h from your .c, .m or .mm file(s).
    1.21 +	
    1.22 +	@todo	Discontinue use of Carbon's MakeDataExecutable() and
    1.23 +			CompareAndSwap() calls and start using the Mach equivalents, if they
    1.24 +			exist. If they don't, write them and roll them in. That way, this
    1.25 +			code will be pure Mach, which will make it easier to use everywhere.
    1.26 +			Update: MakeDataExecutable() has been replaced by
    1.27 +			msync(MS_INVALIDATE). There is an OSCompareAndSwap in libkern, but
    1.28 +			I'm currently unsure if I can link against it. May have to roll in
    1.29 +			my own version...
    1.30 +	@todo	Stop using an entire 4K high-allocated VM page per 28-byte escape
    1.31 +			branch island. Done right, this will dramatically speed up escape
    1.32 +			island allocations when they number over 250. Then again, if you're
    1.33 +			overriding more than 250 functions, maybe speed isn't your main
    1.34 +			concern...
    1.35 +	@todo	Add detection of: b, bl, bla, bc, bcl, bcla, bcctrl, bclrl
    1.36 +			first-instructions. Initially, we should refuse to override
    1.37 +			functions beginning with these instructions. Eventually, we should
    1.38 +			dynamically rewrite them to make them position-independent.
    1.39 +	@todo	Write mach_unoverride(), which would remove an override placed on a
    1.40 +			function. Must be multiple-override aware, which means an almost
    1.41 +			complete rewrite under the covers, because the target address can't
    1.42 +			be spread across two load instructions like it is now since it will
    1.43 +			need to be atomically updatable.
    1.44 +	@todo	Add non-rentry variants of overrides to test_mach_override.
    1.45 +
    1.46 +	***************************************************************************/
    1.47 +
    1.48 +#ifndef		_mach_override_
    1.49 +#define		_mach_override_
    1.50 +
    1.51 +#include <sys/types.h>
    1.52 +#include <mach/error.h>
    1.53 +
    1.54 +#ifdef	__cplusplus
    1.55 +	extern	"C"	{
    1.56 +#endif
    1.57 +
    1.58 +/**
    1.59 +	Returned if the function to be overrided begins with a 'mfctr' instruction.
    1.60 +*/
    1.61 +#define	err_cannot_override	(err_local|1)
    1.62 +
    1.63 +/************************************************************************************//**
    1.64 +	Dynamically overrides the function implementation referenced by
    1.65 +	originalFunctionAddress with the implentation pointed to by overrideFunctionAddress.
    1.66 +	Optionally returns a pointer to a "reentry island" which, if jumped to, will resume
    1.67 +	the original implementation.
    1.68 +	
    1.69 +	@param	originalFunctionAddress			->	Required address of the function to
    1.70 +												override (with overrideFunctionAddress).
    1.71 +	@param	overrideFunctionAddress			->	Required address to the overriding
    1.72 +												function.
    1.73 +	@param	originalFunctionReentryIsland	<-	Optional pointer to pointer to the
    1.74 +												reentry island. Can be nullptr.
    1.75 +	@result									<-	err_cannot_override if the original
    1.76 +												function's implementation begins with
    1.77 +												the 'mfctr' instruction.
    1.78 +
    1.79 +	************************************************************************************/
    1.80 +
    1.81 +    mach_error_t
    1.82 +mach_override_ptr(
    1.83 +	void *originalFunctionAddress,
    1.84 +    const void *overrideFunctionAddress,
    1.85 +    void **originalFunctionReentryIsland );
    1.86 +
    1.87 +/************************************************************************************//**
    1.88 +	
    1.89 +
    1.90 +	************************************************************************************/
    1.91 + 
    1.92 +#ifdef	__cplusplus
    1.93 +
    1.94 +#define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR )			\
    1.95 +	{																												\
    1.96 +		static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS;				\
    1.97 +		static bool ORIGINAL_FUNCTION_NAME##_overriden = false;														\
    1.98 +		class mach_override_class__##ORIGINAL_FUNCTION_NAME {														\
    1.99 +		public:																										\
   1.100 +			static kern_return_t override(void *originalFunctionPtr) {												\
   1.101 +				kern_return_t result = err_none;																	\
   1.102 +				if (!ORIGINAL_FUNCTION_NAME##_overriden) {															\
   1.103 +					ORIGINAL_FUNCTION_NAME##_overriden = true;														\
   1.104 +					result = mach_override_ptr( (void*)originalFunctionPtr,											\
   1.105 +												(void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement,	\
   1.106 +												(void**)&ORIGINAL_FUNCTION_NAME##_reenter );						\
   1.107 +				}																									\
   1.108 +				return result;																						\
   1.109 +			}																										\
   1.110 +			static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS {
   1.111 +
   1.112 +#define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME )																	\
   1.113 +			}																										\
   1.114 +		};																											\
   1.115 +																													\
   1.116 +		err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME);				\
   1.117 +	}
   1.118 + 
   1.119 +#endif
   1.120 +
   1.121 +#ifdef	__cplusplus
   1.122 +	}
   1.123 +#endif
   1.124 +#endif	//	_mach_override_

mercurial