Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
3.1 KiB

  1. // mach_override.h semver:1.2.0
  2. // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
  3. // Some rights reserved: http://opensource.org/licenses/mit
  4. // https://github.com/rentzsch/mach_override
  5. #ifndef _mach_override_
  6. #define _mach_override_
  7. #include <sys/types.h>
  8. #include <mach/error.h>
  9. #define err_cannot_override (err_local|1)
  10. __BEGIN_DECLS
  11. /****************************************************************************************
  12. Dynamically overrides the function implementation referenced by
  13. originalFunctionAddress with the implentation pointed to by overrideFunctionAddress.
  14. Optionally returns a pointer to a "reentry island" which, if jumped to, will resume
  15. the original implementation.
  16. @param originalFunctionAddress -> Required address of the function to
  17. override (with overrideFunctionAddress).
  18. @param overrideFunctionAddress -> Required address to the overriding
  19. function.
  20. @param originalFunctionReentryIsland <- Optional pointer to pointer to the
  21. reentry island. Can be NULL.
  22. @result <- err_cannot_override if the original
  23. function's implementation begins with
  24. the 'mfctr' instruction.
  25. ************************************************************************************/
  26. mach_error_t
  27. mach_override_ptr(
  28. void *originalFunctionAddress,
  29. const void *overrideFunctionAddress,
  30. void **originalFunctionReentryIsland );
  31. __END_DECLS
  32. /****************************************************************************************
  33. If you're using C++ this macro will ease the tedium of typedef'ing, naming, keeping
  34. track of reentry islands and defining your override code. See test_mach_override.cp
  35. for example usage.
  36. ************************************************************************************/
  37. #ifdef __cplusplus
  38. #define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR ) \
  39. { \
  40. static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS; \
  41. static bool ORIGINAL_FUNCTION_NAME##_overriden = false; \
  42. class mach_override_class__##ORIGINAL_FUNCTION_NAME { \
  43. public: \
  44. static kern_return_t override(void *originalFunctionPtr) { \
  45. kern_return_t result = err_none; \
  46. if (!ORIGINAL_FUNCTION_NAME##_overriden) { \
  47. ORIGINAL_FUNCTION_NAME##_overriden = true; \
  48. result = mach_override_ptr( (void*)originalFunctionPtr, \
  49. (void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement, \
  50. (void**)&ORIGINAL_FUNCTION_NAME##_reenter ); \
  51. } \
  52. return result; \
  53. } \
  54. static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS {
  55. #define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME ) \
  56. } \
  57. }; \
  58. \
  59. err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME); \
  60. }
  61. #endif
  62. #endif // _mach_override_