mirror of
https://github.com/wiiu-env/libfunctionpatcher.git
synced 2024-10-31 23:25:09 +01:00
Update the lib to dynamically use the FunctionPatcherModule
This commit is contained in:
parent
abaf6cbc0d
commit
7eeadb500b
25
Makefile
25
Makefile
@ -70,7 +70,6 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
DEFFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.def)))
|
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@ -88,7 +87,7 @@ endif
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
export OFILES_SRC := $(DEFFILES:.def=.o) $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
|
export OFILES_SRC := $(SFILES:.s=.o) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
@ -99,10 +98,10 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|||||||
.PHONY: all dist-bin dist-src dist install clean
|
.PHONY: all dist-bin dist-src dist install clean
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: lib/libfunctionpatcher.a share/libfunctionpatcher.ld
|
all: lib/libfunctionpatcher.a
|
||||||
|
|
||||||
dist-bin: all
|
dist-bin: all
|
||||||
@tar --exclude=*~ -cjf libfunctionpatcher-$(VERSION).tar.bz2 include lib share
|
@tar --exclude=*~ -cjf libfunctionpatcher-$(VERSION).tar.bz2 include lib
|
||||||
|
|
||||||
dist-src:
|
dist-src:
|
||||||
@tar --exclude=*~ -cjf libfunctionpatcher-src-$(VERSION).tar.bz2 include source Makefile
|
@tar --exclude=*~ -cjf libfunctionpatcher-src-$(VERSION).tar.bz2 include source Makefile
|
||||||
@ -114,18 +113,14 @@ install: dist-bin
|
|||||||
bzip2 -cd libfunctionpatcher-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wums
|
bzip2 -cd libfunctionpatcher-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/wums
|
||||||
|
|
||||||
lib:
|
lib:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||||
|
|
||||||
share:
|
|
||||||
@[ -d $@ ] || mkdir -p $@
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||||
|
|
||||||
share/libfunctionpatcher.ld :$(SOURCES) $(INCLUDES) | share release
|
|
||||||
mv $(CURDIR)/release/*.ld $(CURDIR)/$@
|
|
||||||
|
|
||||||
lib/libfunctionpatcher.a :$(SOURCES) $(INCLUDES) | lib release
|
lib/libfunctionpatcher.a :$(SOURCES) $(INCLUDES) | lib release
|
||||||
|
@$(shell [ ! -d lib ] && mkdir -p lib)
|
||||||
|
@$(shell [ ! -d release ] && mkdir -p release)
|
||||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||||
BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \
|
BUILD_CFLAGS="-DNDEBUG=1 -O2 -s" \
|
||||||
DEPSDIR=$(CURDIR)/release \
|
DEPSDIR=$(CURDIR)/release \
|
||||||
@ -149,12 +144,6 @@ $(OUTPUT) : $(OFILES)
|
|||||||
|
|
||||||
$(OFILES_SRC) : $(HFILES)
|
$(OFILES_SRC) : $(HFILES)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.o: %.def
|
|
||||||
$(SILENTMSG) $(notdir $<)
|
|
||||||
$(SILENTCMD)rplimportgen $< $*.s $*.ld $(ERROR_FILTER)
|
|
||||||
$(SILENTCMD)$(CC) -x assembler-with-cpp $(ASFLAGS) -c $*.s -o $@ $(ERROR_FILTER)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%_bin.h %.bin.o : %.bin
|
%_bin.h %.bin.o : %.bin
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
10
README.md
10
README.md
@ -6,20 +6,13 @@ Requires [wut](https://github.com/devkitPro/wut) for building.
|
|||||||
Install via `make install`.
|
Install via `make install`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
When linking, make sure to add the `libfunctionpatcher.ld` file to the LDFLAGS.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```
|
|
||||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libfunctionpatcher.ld
|
|
||||||
```
|
|
||||||
|
|
||||||
Make also sure to define
|
Make also sure to define
|
||||||
```
|
```
|
||||||
WUMS_ROOT := $(DEVKITPRO)/wums
|
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||||
```
|
```
|
||||||
and add `-lfunctionpatcher` to `LIBS` and `$(WUMS_ROOT)` to `LIBDIRS`.
|
and add `-lfunctionpatcher` to `LIBS` and `$(WUMS_ROOT)` to `LIBDIRS`.
|
||||||
|
|
||||||
After that you can simply include `<function_patcher/function_patching.h>` to get access to the function patcher functions.
|
After that you can simply include `<function_patcher/function_patching.h>` to get access to the function patcher functions after calling `FunctionPatcher_InitLibrary()`.
|
||||||
|
|
||||||
## Use this lib in Dockerfiles.
|
## Use this lib in Dockerfiles.
|
||||||
A prebuilt version of this lib can found on dockerhub. To use it for your projects, add this to your Dockerfile.
|
A prebuilt version of this lib can found on dockerhub. To use it for your projects, add this to your Dockerfile.
|
||||||
@ -32,5 +25,4 @@ Replace [tag] with a tag you want to use, a list of tags can be found [here](htt
|
|||||||
It's highly recommended to pin the version to the **latest date** instead of using `latest`.
|
It's highly recommended to pin the version to the **latest date** instead of using `latest`.
|
||||||
|
|
||||||
## Format the code via docker
|
## Format the code via docker
|
||||||
|
|
||||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./include -i`
|
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source ./include -i`
|
||||||
|
@ -1,6 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <wut.h>
|
||||||
|
|
||||||
|
typedef enum FunctionPatcherStatus {
|
||||||
|
FUNCTION_PATCHER_RESULT_SUCCESS = 0,
|
||||||
|
FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND = -0x1,
|
||||||
|
FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT = -0x2,
|
||||||
|
FUNCTION_PATCHER_RESULT_UNSUPPORTED_VERSION = -0x3,
|
||||||
|
FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT = -0x10,
|
||||||
|
FUNCTION_PATCHER_RESULT_PATCH_NOT_FOUND = -0x11,
|
||||||
|
FUNCTION_PATCHER_RESULT_UNSUPPORTED_STRUCT_VERSION = -0x12,
|
||||||
|
FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED = -0x20,
|
||||||
|
FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND = -0x21,
|
||||||
|
FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR = -0x1000,
|
||||||
|
} FunctionPatcherStatus;
|
||||||
|
|
||||||
|
typedef uint32_t FunctionPatcherAPIVersion;
|
||||||
|
|
||||||
|
#define FUNCTION_PATCHER_MODULE_API_VERSION_ERROR 0xFFFFFFFF
|
||||||
|
|
||||||
typedef enum function_replacement_library_type_t {
|
typedef enum function_replacement_library_type_t {
|
||||||
LIBRARY_AVM,
|
LIBRARY_AVM,
|
||||||
|
@ -1,15 +1,110 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fpatching_defines.h"
|
#include "fpatching_defines.h"
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool FunctionPatcherPatchFunction(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle);
|
/**
|
||||||
|
* Returns a FunctionPatcherStatus as a string
|
||||||
|
* @param status
|
||||||
|
* @return String representation of a given status
|
||||||
|
**/
|
||||||
|
const char *FunctionPatcher_GetStatusStr(FunctionPatcherStatus status);
|
||||||
|
|
||||||
extern bool FunctionPatcherRestoreFunction(PatchedFunctionHandle outHandle);
|
/**
|
||||||
|
* This function has to be called before any other function of this lib (except FunctionPatcher_GetVersion) can be used.
|
||||||
|
*
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS: The library has been initialized successfully. Other functions can now be used.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND: The module could not be found. Make sure the module is loaded.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT: The module is missing an expected export.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNSUPPORTED_API_VERSION: The version of the loaded module is not compatible with this version of the lib.
|
||||||
|
**/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_InitLibrary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deinitializes the RPXLoader lib
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS or FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR
|
||||||
|
*/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_DeInitLibrary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the API Version of the loaded FunctionPatcherModule.<br>
|
||||||
|
* <br>
|
||||||
|
* Requires FunctionPatcher API version 2 or higher
|
||||||
|
* @param outVersion pointer to the variable where the version will be stored.
|
||||||
|
*
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS: The API version has been store in the version ptr.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND: The module could not be found. Make sure the module is loaded.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT: The module is missing an expected export.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT: Invalid version pointer.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR: Retrieving the module version failed.
|
||||||
|
**/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_GetVersion(FunctionPatcherAPIVersion *outVersion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a patch of a function. You can use the `REPLACE_FUNCTION_XXX` macro for filling the function_replacement_data_t struct. <br>
|
||||||
|
* When adding this function it'll be attempted to apply this patch, see `outHasBeenPatched` this initial patch was successful. <br>
|
||||||
|
* If the target could not be patched when adding it (e.g. because the target library is not loaded), <br>
|
||||||
|
* the function will be patched as soon as the RPL of the library is loaded (via OSDynLoad_XXX or due to a application switch) and unloaded <br>
|
||||||
|
* if a the RPL unloads <br>
|
||||||
|
* The function patches will survive an application switches, the only way to deregister it is to call FunctionPatcher_RemoveFunctionPatch <br>
|
||||||
|
* with the PatchedFunctionHandle. <br>
|
||||||
|
* <br>
|
||||||
|
* It is possible to patch the same function multiple times, the function patches will stack. <br>
|
||||||
|
* The most recent patch to a function will be called first. real_xxx inside this patch refers then to the "previous patch"<br>
|
||||||
|
* <br>
|
||||||
|
* Requires FunctionPatcher API version 2 or higher
|
||||||
|
* @param function_data Provides information about which function should be patched in which manner. See `REPLACE_FUNCTION_XXX` macros.
|
||||||
|
* @param outHandle (optional) stores a handle of the function patch on success
|
||||||
|
* @param outHasBeenPatched (optional) stores is the initial function **patch** was successful
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS: The function function patch has been **added**. This does **NOT** mean the function <br>
|
||||||
|
* has already been patched. See `outHasBeenPatched` if the function actually is already patched. <br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call FunctionPatcher_InitLibrary() before using this function.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded FunctionPatcherModule version.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT: The given function_data was NULL.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNSUPPORTED_STRUCT_VERSION: Given function_data was in a unsupported version.<br>
|
||||||
|
**/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_AddFunctionPatch(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle, bool *outHasBeenPatched);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a given function patch by handle. If the function is currently patched, the function will be restored. <br>
|
||||||
|
* It is possible to to restore a function that has been patched multiple times. Other function patches of the function will <br>
|
||||||
|
* stay intact. To achieve this the target function might the restored/patched multiple times and should not be called <br>
|
||||||
|
* until this function returns. <br>
|
||||||
|
* <br>
|
||||||
|
* Requires FunctionPatcher API version 2 or higher
|
||||||
|
* @param handle The function patch that should be removed.
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS: The function function patch has been **removed**.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call FunctionPatcher_InitLibrary() before using this function.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded FunctionPatcherModule version.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_PATCH_NOT_FOUND: The given handle does not refer to a valid patch.<br>
|
||||||
|
**/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_RemoveFunctionPatch(PatchedFunctionHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a function patch is actually applied. Functions only will be applied if the target <br>
|
||||||
|
* library is loaded.
|
||||||
|
* <br>
|
||||||
|
* Requires FunctionPatcher API version 2 or higher
|
||||||
|
* @param handle Handle of the function patch to check.
|
||||||
|
* @param outIsFunctionPatched Stores the result on success.
|
||||||
|
* @return FUNCTION_PATCHER_RESULT_SUCCESS: The result has been stored in `outIsFunctionPatched`.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED: Library was not initialized. Call FunctionPatcher_InitLibrary() before using this function.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND: Command not supported by the currently loaded FunctionPatcherModule version.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT: The given handle was NULL.<br>
|
||||||
|
* FUNCTION_PATCHER_RESULT_PATCH_NOT_FOUND: The given handle does not refer to a valid patch.<br>
|
||||||
|
**/
|
||||||
|
FunctionPatcherStatus FunctionPatcher_IsFunctionPatched(PatchedFunctionHandle handle, bool *outIsFunctionPatched);
|
||||||
|
|
||||||
|
WUT_DEPRECATED("Please use FunctionPatcher_AddFunctionPatch instead")
|
||||||
|
bool FunctionPatcherPatchFunction(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle);
|
||||||
|
|
||||||
|
WUT_DEPRECATED("Please use FunctionPatcher_RemoveFunctionPatch instead")
|
||||||
|
bool FunctionPatcherRestoreFunction(PatchedFunctionHandle handle);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
23
source/logger.h
Normal file
23
source/logger.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <coreinit/debug.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#define __FILENAME__ ({ \
|
||||||
|
const char *__filename = __FILE__; \
|
||||||
|
const char *__pos = strrchr(__filename, '/'); \
|
||||||
|
if (!__pos) __pos = strrchr(__filename, '\\'); \
|
||||||
|
__pos ? __pos + 1 : __filename; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define LOG_APP_TYPE "L"
|
||||||
|
#define LOG_APP_NAME "libfunctionpatcher"
|
||||||
|
|
||||||
|
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||||
|
do { \
|
||||||
|
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||||
|
|
||||||
|
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARNING## ", "\n", FMT, ##ARGS)
|
@ -1,5 +0,0 @@
|
|||||||
:NAME homebrew_functionpatcher
|
|
||||||
|
|
||||||
:TEXT
|
|
||||||
FunctionPatcherPatchFunction
|
|
||||||
FunctionPatcherRestoreFunction
|
|
180
source/utils.cpp
Normal file
180
source/utils.cpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
#include <coreinit/debug.h>
|
||||||
|
#include <coreinit/dynload.h>
|
||||||
|
#include <function_patcher/function_patching.h>
|
||||||
|
|
||||||
|
static OSDynLoad_Module sModuleHandle = nullptr;
|
||||||
|
|
||||||
|
// Introduced in API version 2.
|
||||||
|
static FunctionPatcherStatus (*sFPGetVersion)(FunctionPatcherAPIVersion *) = nullptr;
|
||||||
|
static FunctionPatcherStatus (*sFPAddFunctionPatch)(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle, bool *outHasBeenPatched) = nullptr;
|
||||||
|
static FunctionPatcherStatus (*sFPRemoveFunctionPatch)(PatchedFunctionHandle handle) = nullptr;
|
||||||
|
static FunctionPatcherStatus (*sFPIsFunctionPatched)(PatchedFunctionHandle handle, bool *outIsPatched) = nullptr;
|
||||||
|
|
||||||
|
// Deprecated functions
|
||||||
|
static bool (*sFunctionPatcherPatchFunction)(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle) = nullptr;
|
||||||
|
static bool (*sFunctionPatcherRestoreFunction)(PatchedFunctionHandle handle) = nullptr;
|
||||||
|
|
||||||
|
static FunctionPatcherAPIVersion sFunctionPatcherVersion = FUNCTION_PATCHER_MODULE_API_VERSION_ERROR;
|
||||||
|
|
||||||
|
const char *FunctionPatcher_GetStatusStr(FunctionPatcherStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case FUNCTION_PATCHER_RESULT_SUCCESS:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_SUCCESS";
|
||||||
|
case FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND";
|
||||||
|
case FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT";
|
||||||
|
case FUNCTION_PATCHER_RESULT_UNSUPPORTED_VERSION:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_UNSUPPORTED_VERSION";
|
||||||
|
case FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT";
|
||||||
|
case FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED";
|
||||||
|
case FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND";
|
||||||
|
case FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR";
|
||||||
|
case FUNCTION_PATCHER_RESULT_PATCH_NOT_FOUND:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_PATCH_NOT_FOUND";
|
||||||
|
case FUNCTION_PATCHER_RESULT_UNSUPPORTED_STRUCT_VERSION:
|
||||||
|
return "FUNCTION_PATCHER_RESULT_UNSUPPORTED_STRUCT_VERSION";
|
||||||
|
}
|
||||||
|
return "FUNCTION_PATCHER_RESULT_UNKNOWN_ERROR";
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_InitLibrary() {
|
||||||
|
if (OSDynLoad_Acquire("homebrew_functionpatcher", &sModuleHandle) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("OSDynLoad_Acquire failed.");
|
||||||
|
return FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FPGetVersion", (void **) &sFPGetVersion) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("FindExport FPGetVersion failed.");
|
||||||
|
return FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = FunctionPatcher_GetVersion(&sFunctionPatcherVersion);
|
||||||
|
if (res != FUNCTION_PATCHER_RESULT_SUCCESS) {
|
||||||
|
sFunctionPatcherVersion = FUNCTION_PATCHER_MODULE_API_VERSION_ERROR;
|
||||||
|
return FUNCTION_PATCHER_RESULT_UNSUPPORTED_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FPAddFunctionPatch", (void **) &sFPAddFunctionPatch) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("FindExport FPAddFunctionPatch failed.");
|
||||||
|
sFPAddFunctionPatch = nullptr;
|
||||||
|
}
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FPRemoveFunctionPatch", (void **) &sFPRemoveFunctionPatch) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("FindExport FPRemoveFunctionPatch failed.");
|
||||||
|
sFPRemoveFunctionPatch = nullptr;
|
||||||
|
}
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FPIsFunctionPatched", (void **) &sFPIsFunctionPatched) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("FindExport FPIsFunctionPatched failed.");
|
||||||
|
sFPIsFunctionPatched = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FUNCTION_PATCHER_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_DeInitLibrary() {
|
||||||
|
sFPAddFunctionPatch = nullptr;
|
||||||
|
sFPRemoveFunctionPatch = nullptr;
|
||||||
|
sFPIsFunctionPatched = nullptr;
|
||||||
|
sFunctionPatcherVersion = FUNCTION_PATCHER_MODULE_API_VERSION_ERROR;
|
||||||
|
OSDynLoad_Release(sModuleHandle);
|
||||||
|
sModuleHandle = nullptr;
|
||||||
|
return FUNCTION_PATCHER_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionPatcherPatchFunctionDecl(function_replacement_data_t *, PatchedFunctionHandle *);
|
||||||
|
bool FunctionPatcherPatchFunction(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle) {
|
||||||
|
if (sFunctionPatcherPatchFunction == nullptr) {
|
||||||
|
if (OSDynLoad_Acquire("homebrew_functionpatcher", &sModuleHandle) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("OSDynLoad_Acquire failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FunctionPatcherPatchFunction", (void **) &sFunctionPatcherPatchFunction) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("FindExport FunctionPatcherPatchFunction failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcherPatchFunctionDecl)>(sFunctionPatcherPatchFunction)(function_data, outHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionPatcherRestoreFunctionDecl(PatchedFunctionHandle);
|
||||||
|
bool FunctionPatcherRestoreFunction(PatchedFunctionHandle handle) {
|
||||||
|
if (sFunctionPatcherRestoreFunction == nullptr) {
|
||||||
|
if (OSDynLoad_Acquire("homebrew_functionpatcher", &sModuleHandle) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("OSDynLoad_Acquire failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FunctionPatcherRestoreFunction", (void **) &sFunctionPatcherRestoreFunction) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("FindExport FunctionPatcherRestoreFunction failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcherRestoreFunctionDecl)>(sFunctionPatcherRestoreFunction)(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_GetVersion(FunctionPatcherAPIVersion *outVersion) {
|
||||||
|
if (sFPGetVersion == nullptr) {
|
||||||
|
if (OSDynLoad_Acquire("homebrew_functionpatcher", &sModuleHandle) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("OSDynLoad_Acquire failed.");
|
||||||
|
return FUNCTION_PATCHER_RESULT_MODULE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSDynLoad_FindExport(sModuleHandle, FALSE, "FPGetVersion", (void **) &sFPGetVersion) != OS_DYNLOAD_OK) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("FindExport FPGetVersion failed.");
|
||||||
|
return FUNCTION_PATCHER_RESULT_MODULE_MISSING_EXPORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcher_GetVersion)>(sFPGetVersion)(outVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_AddFunctionPatch(function_replacement_data_t *function_data, PatchedFunctionHandle *outHandle, bool *outHasBeenPatched) {
|
||||||
|
if (sFunctionPatcherVersion == FUNCTION_PATCHER_MODULE_API_VERSION_ERROR) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED;
|
||||||
|
}
|
||||||
|
if (sFPAddFunctionPatch == nullptr || sFunctionPatcherVersion < 2) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_data == nullptr) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcher_AddFunctionPatch)>(sFPAddFunctionPatch)(function_data, outHandle, outHasBeenPatched);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_RemoveFunctionPatch(PatchedFunctionHandle handle) {
|
||||||
|
if (sFunctionPatcherVersion == FUNCTION_PATCHER_MODULE_API_VERSION_ERROR) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED;
|
||||||
|
}
|
||||||
|
if (sFPRemoveFunctionPatch == nullptr || sFunctionPatcherVersion < 2) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == 0) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcher_RemoveFunctionPatch)>(sFPRemoveFunctionPatch)(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionPatcherStatus FunctionPatcher_IsFunctionPatched(PatchedFunctionHandle handle, bool *outIsFunctionPatched) {
|
||||||
|
if (sFunctionPatcherVersion == FUNCTION_PATCHER_MODULE_API_VERSION_ERROR) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_LIB_UNINITIALIZED;
|
||||||
|
}
|
||||||
|
if (sFPIsFunctionPatched == nullptr || sFunctionPatcherVersion < 2) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_UNSUPPORTED_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == 0 || outIsFunctionPatched == nullptr) {
|
||||||
|
return FUNCTION_PATCHER_RESULT_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<decltype(&FunctionPatcher_IsFunctionPatched)>(sFPIsFunctionPatched)(handle, outIsFunctionPatched);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user