diff options
Diffstat (limited to 'test_mach_override.cp')
-rw-r--r-- | test_mach_override.cp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/test_mach_override.cp b/test_mach_override.cp new file mode 100644 index 0000000..77ad748 --- /dev/null +++ b/test_mach_override.cp @@ -0,0 +1,108 @@ +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <CoreServices/CoreServices.h> +#include "mach_override.h" + +#define assertStrEqual( EXPECTED, ACTUAL ) if( strcmp( (EXPECTED), (ACTUAL) ) != 0 ) { printf( "EXPECTED: %s\nACTUAL: %s\n", (EXPECTED), (ACTUAL)); assert( strcmp( (EXPECTED), (ACTUAL) ) == 0 ); } +#define assertIntEqual( EXPECTED, ACTUAL ) if( (EXPECTED) != (ACTUAL) ) { printf( "EXPECTED: %d\nACTUAL: %d\n", (EXPECTED), (ACTUAL)); assert( (EXPECTED) == (ACTUAL) ); } + +//------------------------------------------------------------------------------ +#pragma mark Test Local Override by Pointer + +const char* localFunction() { + asm("nop;nop;nop;nop;"); + return __FUNCTION__; +} +const char* (*localOriginalPtr)() = localFunction; + +void testLocalFunctionOverrideByPointer() { + // Test original. + assertStrEqual( "localFunction", localOriginalPtr() ); + + // Override local function by pointer. + kern_return_t err; + + MACH_OVERRIDE( const char*, localFunction, (), err ) { + // Test calling through the reentry island back into the original + // implementation. + assertStrEqual( "localFunction", localFunction_reenter() ); + + return "localFunctionOverride"; + } END_MACH_OVERRIDE(localFunction); + assert( !err ); + + // Test override took effect. + assertStrEqual( "localFunctionOverride", localOriginalPtr() ); +} + +//------------------------------------------------------------------------------ +#pragma mark Test System Override by Pointer + +char* (*strerrorPtr)(int) = strerror; +const char* strerrReturnValue = "Unknown error: 0"; + +void testSystemFunctionOverrideByPointer() { + SInt32 sysv; + if (Gestalt( gestaltSystemVersion, &sysv ) == noErr && sysv >= 0x1070) + strerrReturnValue = "Undefined error: 0"; + + // Test original. + assertStrEqual( strerrReturnValue, strerrorPtr( 0 ) ); + + // Override system function by pointer. + kern_return_t err; + MACH_OVERRIDE( char*, strerror, (int errnum), err ) { + // Test calling through the reentry island back into the original + // implementation. + assertStrEqual( strerrReturnValue, strerror_reenter( 0 ) ); + + return (char *)"strerrorOverride"; + } END_MACH_OVERRIDE(strerror); + assert( !err ); + + // Test override took effect. + assertStrEqual( "strerrorOverride", strerrorPtr( 0 ) ); +} + +//------------------------------------------------------------------------------ +#pragma mark Test System Override by Name + +/* The following is commented out because it does not compile. +int strerror_rOverride( int errnum, char *strerrbuf, size_t buflen ); +int (*strerror_rPtr)( int, char*, size_t ) = strerror_r; +int (*gReentry_strerror_r)( int, char*, size_t ); + +void testSystemFunctionOverrideByName() { + // Test original. + assertIntEqual( ERANGE, strerror_rPtr( 0, NULL, 0 ) ); + + // Override local function by pointer. + kern_return_t err = mach_override( (char*)"_strerror_r", + NULL, + (void*)&strerror_rOverride, + (void**)&gReentry_strerror_r ); + + // Test override took effect. + assertIntEqual( 0, strerror_rPtr( 0, NULL, 0 ) ); +} + +int strerror_rOverride( int errnum, char *strerrbuf, size_t buflen ) { + assertIntEqual( ERANGE, gReentry_strerror_r( 0, NULL, 0 ) ); + + return 0; +} +*/ + +//------------------------------------------------------------------------------ +#pragma mark main + +int main( int argc, const char *argv[] ) { + testLocalFunctionOverrideByPointer(); + testSystemFunctionOverrideByPointer(); + //testSystemFunctionOverrideByName(); + + printf( "success\n" ); + return 0; +} |