mirror of
https://github.com/wiiu-env/WUMSLoader.git
synced 2025-03-06 16:17:44 +01:00
Add support for 0.3.4 to allow an custom rpl allocator
This commit is contained in:
parent
f05add408e
commit
199e959dcc
@ -1,5 +1,5 @@
|
|||||||
FROM ghcr.io/wiiu-env/devkitppc:20241128
|
FROM ghcr.io/wiiu-env/devkitppc:20241128
|
||||||
|
|
||||||
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20250208 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:0.3.4-dev-20250218-b62548a /artifacts $DEVKITPRO
|
||||||
|
|
||||||
WORKDIR project
|
WORKDIR project
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#define VERSION "v0.2.7"
|
#define VERSION "v0.2.8"
|
||||||
|
|
||||||
void CallInitHooksForModule(const std::shared_ptr<ModuleData> &curModule);
|
void CallInitHooksForModule(const std::shared_ptr<ModuleData> &curModule);
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ void doStart(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Resolve relocations without replacing alloc functions");
|
DEBUG_FUNCTION_LINE_VERBOSE("Resolve relocations without loading additonal rpls");
|
||||||
ResolveRelocations(gLoadedModules, true, gUsedRPLs);
|
ResolveRelocations(gLoadedModules, true, gUsedRPLs);
|
||||||
|
|
||||||
for (auto &curModule : gLoadedModules) {
|
for (auto &curModule : gLoadedModules) {
|
||||||
@ -218,9 +218,14 @@ void doStart(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hacky workaround for modules to allow register a custom rpl allocator function
|
||||||
|
CallHook(gLoadedModules, WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR);
|
||||||
|
|
||||||
|
// Now we can load unloaded rpls.
|
||||||
|
ResolveRelocations(gLoadedModules, false, gUsedRPLs);
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Call Relocations done hook");
|
DEBUG_FUNCTION_LINE_VERBOSE("Call Relocations done hook");
|
||||||
CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
||||||
CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
|
||||||
|
|
||||||
for (auto &curModule : gLoadedModules) {
|
for (auto &curModule : gLoadedModules) {
|
||||||
if (!curModule->isInitBeforeRelocationDoneHook()) {
|
if (!curModule->isInitBeforeRelocationDoneHook()) {
|
||||||
@ -228,7 +233,8 @@ void doStart(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE("Resolve relocations and replace alloc functions");
|
DEBUG_FUNCTION_LINE("Resolve relocations and load unloaded rpls functions");
|
||||||
|
CallHook(gLoadedModules, WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY);
|
||||||
ResolveRelocations(gLoadedModules, false, gUsedRPLs);
|
ResolveRelocations(gLoadedModules, false, gUsedRPLs);
|
||||||
CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,7 @@ std::vector<std::shared_ptr<ModuleData>> gLoadedModules __attribute__((section("
|
|||||||
std::unique_ptr<module_information_single_t[]> gModuleDataInfo __attribute__((section(".data")));
|
std::unique_ptr<module_information_single_t[]> gModuleDataInfo __attribute__((section(".data")));
|
||||||
|
|
||||||
std::map<std::string, OSDynLoad_Module> gUsedRPLs __attribute__((section(".data")));
|
std::map<std::string, OSDynLoad_Module> gUsedRPLs __attribute__((section(".data")));
|
||||||
std::vector<void *> gAllocatedAddresses __attribute__((section(".data")));
|
std::vector<void *> gAllocatedAddresses __attribute__((section(".data")));
|
||||||
|
|
||||||
|
WUMSRPLAllocatorAllocFn gCustomRPLAllocatorAllocFn __attribute__((section(".data"))) = nullptr;
|
||||||
|
WUMSRPLAllocatorFreeFn gCustomRPLAllocatorFreeFn __attribute__((section(".data"))) = nullptr;
|
@ -14,6 +14,9 @@ extern std::unique_ptr<module_information_single_t[]> gModuleDataInfo;
|
|||||||
extern std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
extern std::map<std::string, OSDynLoad_Module> gUsedRPLs;
|
||||||
extern std::vector<void *> gAllocatedAddresses;
|
extern std::vector<void *> gAllocatedAddresses;
|
||||||
|
|
||||||
|
extern WUMSRPLAllocatorAllocFn gCustomRPLAllocatorAllocFn;
|
||||||
|
extern WUMSRPLAllocatorFreeFn gCustomRPLAllocatorFreeFn;
|
||||||
|
|
||||||
#define MEMORY_REGION_START 0x00800000
|
#define MEMORY_REGION_START 0x00800000
|
||||||
#define MEMORY_REGION_SIZE 0x00800000
|
#define MEMORY_REGION_SIZE 0x00800000
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
|
|||||||
}
|
}
|
||||||
} else if (key == "wums" || key == "wum") {
|
} else if (key == "wums" || key == "wum") {
|
||||||
checkedVersion = true;
|
checkedVersion = true;
|
||||||
if (value != "0.3.1" && value != "0.3.2" && value != "0.3.3") {
|
if (value != "0.3.1" && value != "0.3.2" && value != "0.3.3" && value != "0.3.4") {
|
||||||
DEBUG_FUNCTION_LINE_WARN("Ignoring module - Unsupported WUMS version: %s.", value.c_str());
|
DEBUG_FUNCTION_LINE_WARN("Ignoring module - Unsupported WUMS version: %s.", value.c_str());
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -33,33 +33,41 @@ static void CustomDynLoadFree(void *addr) {
|
|||||||
free(addr);
|
free(addr);
|
||||||
|
|
||||||
// Remove from list
|
// Remove from list
|
||||||
auto it = std::find(gAllocatedAddresses.begin(), gAllocatedAddresses.end(), addr);
|
if (const auto it = std::ranges::find(gAllocatedAddresses, addr); it != gAllocatedAddresses.end()) {
|
||||||
if (it != gAllocatedAddresses.end()) {
|
|
||||||
gAllocatedAddresses.erase(it);
|
gAllocatedAddresses.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResolveRelocations(std::vector<std::shared_ptr<ModuleData>> &loadedModules, bool skipMemoryMappingModule, std::map<std::string, OSDynLoad_Module> &usedRPls) {
|
bool ResolveRelocations(const std::vector<std::shared_ptr<ModuleData>> &loadedModules, const bool skipUnloadedRpl, std::map<std::string, OSDynLoad_Module> &usedRPls) {
|
||||||
bool wasSuccessful = true;
|
bool wasSuccessful = true;
|
||||||
|
|
||||||
|
|
||||||
OSDynLoadAllocFn prevDynLoadAlloc = nullptr;
|
OSDynLoadAllocFn prevDynLoadAlloc = nullptr;
|
||||||
OSDynLoadFreeFn prevDynLoadFree = nullptr;
|
OSDynLoadFreeFn prevDynLoadFree = nullptr;
|
||||||
|
|
||||||
OSDynLoad_GetAllocator(&prevDynLoadAlloc, &prevDynLoadFree);
|
if (!skipUnloadedRpl) {
|
||||||
OSDynLoad_SetAllocator(CustomDynLoadAlloc, CustomDynLoadFree);
|
OSDynLoad_GetAllocator(&prevDynLoadAlloc, &prevDynLoadFree);
|
||||||
|
if (gCustomRPLAllocatorAllocFn != nullptr && gCustomRPLAllocatorFreeFn != nullptr) {
|
||||||
|
OSDynLoad_SetAllocator(reinterpret_cast<OSDynLoadAllocFn>(gCustomRPLAllocatorAllocFn), gCustomRPLAllocatorFreeFn);
|
||||||
|
} else {
|
||||||
|
OSDynLoad_SetAllocator(CustomDynLoadAlloc, CustomDynLoadFree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &curModule : loadedModules) {
|
for (auto &curModule : loadedModules) {
|
||||||
DEBUG_FUNCTION_LINE("Let's do the relocations for %s", curModule->getExportName().c_str());
|
DEBUG_FUNCTION_LINE("Let's do the relocations for %s", curModule->getExportName().c_str());
|
||||||
|
|
||||||
auto &relocData = curModule->getRelocationDataList();
|
auto &relocData = curModule->getRelocationDataList();
|
||||||
|
|
||||||
if (!doRelocation(gLoadedModules, relocData, nullptr, 0, usedRPls)) {
|
if (!doRelocation(gLoadedModules, relocData, nullptr, 0, usedRPls, skipUnloadedRpl)) {
|
||||||
wasSuccessful = false;
|
wasSuccessful = false;
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to do Relocations for %s", curModule->getExportName().c_str());
|
DEBUG_FUNCTION_LINE_ERR("Failed to do Relocations for %s", curModule->getExportName().c_str());
|
||||||
OSFatal("Failed to do Relocations");
|
OSFatal("Failed to do Relocations");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSDynLoad_SetAllocator(prevDynLoadAlloc, prevDynLoadFree);
|
if (!skipUnloadedRpl) {
|
||||||
|
OSDynLoad_SetAllocator(prevDynLoadAlloc, prevDynLoadFree);
|
||||||
|
}
|
||||||
|
|
||||||
DCFlushRange((void *) MEMORY_REGION_START, MEMORY_REGION_SIZE);
|
DCFlushRange((void *) MEMORY_REGION_START, MEMORY_REGION_SIZE);
|
||||||
ICInvalidateRange((void *) MEMORY_REGION_START, MEMORY_REGION_SIZE);
|
ICInvalidateRange((void *) MEMORY_REGION_START, MEMORY_REGION_SIZE);
|
||||||
@ -70,8 +78,9 @@ bool ResolveRelocations(std::vector<std::shared_ptr<ModuleData>> &loadedModules,
|
|||||||
bool doRelocation(const std::vector<std::shared_ptr<ModuleData>> &moduleList,
|
bool doRelocation(const std::vector<std::shared_ptr<ModuleData>> &moduleList,
|
||||||
const std::vector<std::unique_ptr<RelocationData>> &relocData,
|
const std::vector<std::unique_ptr<RelocationData>> &relocData,
|
||||||
relocation_trampoline_entry_t *tramp_data,
|
relocation_trampoline_entry_t *tramp_data,
|
||||||
uint32_t tramp_length,
|
const uint32_t tramp_length,
|
||||||
std::map<std::string, OSDynLoad_Module> &usedRPls) {
|
std::map<std::string, OSDynLoad_Module> &usedRPls,
|
||||||
|
const bool skipUnloadedRpl) {
|
||||||
for (auto const &curReloc : relocData) {
|
for (auto const &curReloc : relocData) {
|
||||||
auto &functionName = curReloc->getName();
|
auto &functionName = curReloc->getName();
|
||||||
std::string rplName = curReloc->getImportRPLInformation()->getRPLName();
|
std::string rplName = curReloc->getImportRPLInformation()->getRPLName();
|
||||||
@ -106,7 +115,14 @@ bool doRelocation(const std::vector<std::shared_ptr<ModuleData>> &moduleList,
|
|||||||
OSDynLoad_Module rplHandle = nullptr;
|
OSDynLoad_Module rplHandle = nullptr;
|
||||||
|
|
||||||
if (!usedRPls.contains(rplName)) {
|
if (!usedRPls.contains(rplName)) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Acquire %s", rplName.c_str());
|
OSDynLoad_Module tmp = nullptr;
|
||||||
|
if (OSDynLoad_IsModuleLoaded(rplName.c_str(), &tmp) != OS_DYNLOAD_OK || tmp == nullptr) {
|
||||||
|
if (skipUnloadedRpl) {
|
||||||
|
DEBUG_FUNCTION_LINE_VERBOSE("Skip acquire of %s", rplName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Always acquire to increase refcount and make sure it won't get unloaded while we're using it.
|
// Always acquire to increase refcount and make sure it won't get unloaded while we're using it.
|
||||||
OSDynLoad_Error err = OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
|
OSDynLoad_Error err = OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
|
||||||
if (err != OS_DYNLOAD_OK) {
|
if (err != OS_DYNLOAD_OK) {
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
bool ResolveRelocations(std::vector<std::shared_ptr<ModuleData>> &loadedModules,
|
bool ResolveRelocations(const std::vector<std::shared_ptr<ModuleData>> &loadedModules,
|
||||||
bool skipMemoryMappingModule,
|
bool skipUnloadedRpl,
|
||||||
std::map<std::string, OSDynLoad_Module> &usedRPls);
|
std::map<std::string, OSDynLoad_Module> &usedRPls);
|
||||||
|
|
||||||
bool doRelocation(const std::vector<std::shared_ptr<ModuleData>> &moduleList,
|
bool doRelocation(const std::vector<std::shared_ptr<ModuleData>> &moduleList,
|
||||||
const std::vector<std::unique_ptr<RelocationData>> &relocData,
|
const std::vector<std::unique_ptr<RelocationData>> &relocData,
|
||||||
relocation_trampoline_entry_t *tramp_data,
|
relocation_trampoline_entry_t *tramp_data,
|
||||||
uint32_t tramp_length,
|
uint32_t tramp_length,
|
||||||
std::map<std::string, OSDynLoad_Module> &usedRPls);
|
std::map<std::string, OSDynLoad_Module> &usedRPls,
|
||||||
|
bool skipUnloadedRpl);
|
@ -27,10 +27,15 @@ static const char **hook_names = (const char *[]){
|
|||||||
"WUMS_HOOK_APPLICATION_ENDS",
|
"WUMS_HOOK_APPLICATION_ENDS",
|
||||||
"WUMS_HOOK_RELOCATIONS_DONE",
|
"WUMS_HOOK_RELOCATIONS_DONE",
|
||||||
"WUMS_HOOK_APPLICATION_REQUESTS_EXIT",
|
"WUMS_HOOK_APPLICATION_REQUESTS_EXIT",
|
||||||
|
|
||||||
"WUMS_HOOK_DEINIT",
|
"WUMS_HOOK_DEINIT",
|
||||||
|
|
||||||
"WUMS_HOOK_ALL_APPLICATION_STARTS_DONE",
|
"WUMS_HOOK_ALL_APPLICATION_STARTS_DONE",
|
||||||
"WUMS_HOOK_ALL_APPLICATION_ENDS_DONE",
|
"WUMS_HOOK_ALL_APPLICATION_ENDS_DONE",
|
||||||
"WUMS_HOOK_ALL_APPLICATION_REQUESTS_EXIT_DONE",
|
"WUMS_HOOK_ALL_APPLICATION_REQUESTS_EXIT_DONE",
|
||||||
|
|
||||||
|
"WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR",
|
||||||
|
"WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY",
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -82,6 +87,7 @@ void CallHook(const std::shared_ptr<ModuleData> &module, wums_hook_type_t type)
|
|||||||
type == WUMS_HOOK_DEINIT ||
|
type == WUMS_HOOK_DEINIT ||
|
||||||
type == WUMS_HOOK_ALL_APPLICATION_STARTS_DONE ||
|
type == WUMS_HOOK_ALL_APPLICATION_STARTS_DONE ||
|
||||||
type == WUMS_HOOK_ALL_APPLICATION_ENDS_DONE ||
|
type == WUMS_HOOK_ALL_APPLICATION_ENDS_DONE ||
|
||||||
|
type == WUMS_HOOK_CLEAR_ALLOCATED_RPL_MEMORY ||
|
||||||
type == WUMS_HOOK_ALL_APPLICATION_REQUESTS_EXIT_DONE)) {
|
type == WUMS_HOOK_ALL_APPLICATION_REQUESTS_EXIT_DONE)) {
|
||||||
DEBUG_FUNCTION_LINE("Calling hook of type %s [%d] %d for %s: %08X", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget());
|
DEBUG_FUNCTION_LINE("Calling hook of type %s [%d] %d for %s: %08X", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget());
|
||||||
((void (*)())((uint32_t *) func_ptr))();
|
((void (*)())((uint32_t *) func_ptr))();
|
||||||
@ -92,6 +98,13 @@ void CallHook(const std::shared_ptr<ModuleData> &module, wums_hook_type_t type)
|
|||||||
wums_app_init_args_t args;
|
wums_app_init_args_t args;
|
||||||
args.module_information = &gModuleInformation;
|
args.module_information = &gModuleInformation;
|
||||||
((void (*)(wums_app_init_args_t *))((uint32_t *) func_ptr))(&args);
|
((void (*)(wums_app_init_args_t *))((uint32_t *) func_ptr))(&args);
|
||||||
|
} else if (type == WUMS_HOOK_GET_CUSTOM_RPL_ALLOCATOR) {
|
||||||
|
DEBUG_FUNCTION_LINE("Calling hook of type %s [%d] %d for %s: %08X", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget());
|
||||||
|
|
||||||
|
const auto [allocFn, freeFn] = reinterpret_cast<wums_internal_custom_rpl_allocator_t (*)()>(reinterpret_cast<uint32_t *>(func_ptr))();
|
||||||
|
gCustomRPLAllocatorAllocFn = allocFn;
|
||||||
|
gCustomRPLAllocatorFreeFn = freeFn;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("#########################################");
|
DEBUG_FUNCTION_LINE_ERR("#########################################");
|
||||||
DEBUG_FUNCTION_LINE_ERR("#########HOOK NOT IMPLEMENTED %d#########", type);
|
DEBUG_FUNCTION_LINE_ERR("#########HOOK NOT IMPLEMENTED %d#########", type);
|
||||||
|
@ -49,6 +49,7 @@ extern "C" {
|
|||||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||||
|
|
||||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX(OSReport, "##WARN ## ", "\n", FMT, ##ARGS)
|
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX(OSReport, "##WARN ## ", "\n", FMT, ##ARGS)
|
||||||
|
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX(OSReport, "##INFO ## ", "\n", FMT, ##ARGS)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user