-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFunctionAddressProvider.cpp
More file actions
78 lines (66 loc) · 2.58 KB
/
Copy pathFunctionAddressProvider.cpp
File metadata and controls
78 lines (66 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "FunctionAddressProvider.h"
#include "utils/logger.h"
#include <coreinit/dynload.h>
#include <function_patcher/fpatching_defines.h>
uint32_t FunctionAddressProvider::getEffectiveAddressOfFunction(function_replacement_library_type_t library, const char *functionName) {
uint32_t real_addr = 0;
OSDynLoad_Module rpl_handle = nullptr;
OSDynLoad_Error err = OS_DYNLOAD_OK;
for (auto &rplHandle : rpl_handles) {
if (rplHandle.library == library) {
if (rplHandle.handle == nullptr) {
DEBUG_FUNCTION_LINE_VERBOSE("Lets check if rpl is loaded: %s", rplHandle.rplname);
err = OSDynLoad_IsModuleLoaded((char *) rplHandle.rplname, &rplHandle.handle);
}
if (err != OS_DYNLOAD_OK || !rplHandle.handle) {
DEBUG_FUNCTION_LINE_VERBOSE("%s is not loaded yet. Err %d for handle %p", rplHandle.rplname, err, rplHandle.handle);
return 0;
}
rpl_handle = rplHandle.handle;
break;
}
}
if (!rpl_handle) {
DEBUG_FUNCTION_LINE_ERR("Failed to find the RPL handle for %s", functionName);
return 0;
}
OSDynLoad_FindExport(rpl_handle, OS_DYNLOAD_EXPORT_FUNC, functionName, reinterpret_cast<void **>(&real_addr));
if (!real_addr) {
DEBUG_FUNCTION_LINE_VERBOSE("OSDynLoad_FindExport failed for %s", functionName);
return 0;
}
uint32_t realAddrData = *((volatile uint32_t *) real_addr);
if ((realAddrData & 0xFC000003) == 0x48000000) {
auto address_diff = (uint32_t) (realAddrData & 0x01FFFFFC);
if ((realAddrData & 0x02000000) == 0x02000000) {
address_diff = 0xFE000000 + address_diff;
}
real_addr += (int32_t) address_diff;
}
return real_addr;
}
void FunctionAddressProvider::resetHandles() {
for (auto &rplHandle : rpl_handles) {
if (rplHandle.handle != nullptr) {
DEBUG_FUNCTION_LINE_VERBOSE("Resetting handle for rpl: %s", rplHandle.rplname);
}
rplHandle.handle = nullptr;
}
}
function_replacement_library_type_t FunctionAddressProvider::getTypeForHandle(OSDynLoad_Module handle) {
for (auto &rplHandle : rpl_handles) {
if (rplHandle.handle == handle) {
return rplHandle.library;
}
}
return LIBRARY_OTHER;
}
bool FunctionAddressProvider::resetHandle(OSDynLoad_Module handle) {
for (auto &rplHandle : rpl_handles) {
if (rplHandle.handle == handle) {
rplHandle.handle = nullptr;
return true;
}
}
return false;
}