From 6d8fd08f251eee2e1a9a3da021d6826d966c763b Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 3 May 2020 10:21:05 +0200 Subject: [PATCH] Increase the maximum number of relocations from 500 to 1000. Refactor some code to a "PluginManagement" class. --- .gitignore | 3 + source/PluginManagement.cpp | 90 ++++++++++++ source/PluginManagement.h | 20 +++ source/common/plugin_defines.h | 4 +- source/main.cpp | 143 +++++-------------- source/plugin/DynamicLinkingHelper.cpp | 2 +- source/plugin/PluginContainerPersistence.cpp | 5 +- 7 files changed, 157 insertions(+), 110 deletions(-) create mode 100644 source/PluginManagement.cpp create mode 100644 source/PluginManagement.h diff --git a/.gitignore b/.gitignore index 1bc8861..06980ab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ *.rpx build/ *.save-failed +.idea/ +cmake-build-debug/ +CMakeLists.txt diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp new file mode 100644 index 0000000..a75a564 --- /dev/null +++ b/source/PluginManagement.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include "patcher/hooks_patcher_static.h" +#include "patcher/hooks_patcher.h" +#include "PluginManagement.h" +#include "hooks.h" + + +bool PluginManagement::doRelocation(const std::vector &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length, uint32_t trampolinID) { + std::map moduleHandleCache; + for (auto const& cur : relocData) { + std::string functionName = cur.getName(); + std::string rplName = cur.getImportRPLInformation().getName(); + int32_t isData = cur.getImportRPLInformation().isData(); + OSDynLoad_Module rplHandle = 0; + if(moduleHandleCache.count(rplName) > 0) { + rplHandle = moduleHandleCache[rplName]; + } else { + OSDynLoad_Acquire(rplName.c_str(), &rplHandle); + moduleHandleCache[rplName] = rplHandle; + } + + uint32_t functionAddress = 0; + OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void**) &functionAddress); + if(functionAddress == 0) { + DEBUG_FUNCTION_LINE("Failed to find export for %s", functionName.c_str()); + return false; + } else { + //DEBUG_FUNCTION_LINE("Found export for %s %s", rplName.c_str(), functionName.c_str()); + } + if(!ElfUtils::elfLinkOne(cur.getType(), cur.getOffset(), cur.getAddend(), (uint32_t) cur.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT,trampolinID)) { + DEBUG_FUNCTION_LINE("Relocation failed\n"); + return false; + } + } + + DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); + ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); + return true; +} + + +void PluginManagement::doRelocations(std::vector plugins, relocation_trampolin_entry_t * trampData, uint32_t tramp_size) { + for(auto & pluginContainer : plugins) { + DEBUG_FUNCTION_LINE("Doing relocations for plugin: %s", pluginContainer.getMetaInformation().getName().c_str()); + + if(!PluginManagement::doRelocation(pluginContainer.getPluginInformation().getRelocationDataList(), trampData, tramp_size, pluginContainer.getPluginInformation().getTrampolinId())) { + DEBUG_FUNCTION_LINE("Relocation failed"); + } + } +} + +void PluginManagement::memsetBSS(std::vector plugins) { + for(auto & pluginContainer : plugins) { + auto sbssSection = pluginContainer.getPluginInformation().getSectionInfo(".sbss"); + if(sbssSection){ + DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)", sbssSection->getAddress(), sbssSection->getSize()); + memset((void*)sbssSection->getAddress(), 0, sbssSection->getSize()); + } + auto bssSection = pluginContainer.getPluginInformation().getSectionInfo(".bss"); + if(bssSection) { + DEBUG_FUNCTION_LINE("memset .bss %08X (%d)", bssSection->getAddress(), bssSection->getSize()); + memset((void*)bssSection->getAddress(), 0, bssSection->getSize()); + } + } +} + +void PluginManagement::callInitHooks(plugin_information_t *pluginInformation) { + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_WUT_MALLOC); + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB); + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_WUT_STDCPP); + + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_VID_MEM); + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_KERNEL); + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_OVERLAY); + CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_PLUGIN); +} + +void PluginManagement::PatchFunctionsAndCallHooks(plugin_information_t* gPluginInformation) { + PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static); + PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks); + + for(int32_t plugin_index=0; plugin_indexnumber_used_plugins; plugin_index++) { + CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB,plugin_index); + CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_START,plugin_index); + //new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]); + CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index); + } +} diff --git a/source/PluginManagement.h b/source/PluginManagement.h new file mode 100644 index 0000000..4c3aad3 --- /dev/null +++ b/source/PluginManagement.h @@ -0,0 +1,20 @@ +#pragma once + + +#include +#include + +class PluginManagement { +public: + + static void Init(std::vector pInformation); + + static void doRelocations(std::vector plugins, relocation_trampolin_entry_t *trampData, uint32_t tramp_size); + static void memsetBSS(std::vector plugins); + + static void callInitHooks(plugin_information_t *pluginInformation); + + static void PatchFunctionsAndCallHooks(plugin_information_t* gPluginInformation); + + static bool doRelocation(const std::vector &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolinID); +}; \ No newline at end of file diff --git a/source/common/plugin_defines.h b/source/common/plugin_defines.h index b373e64..eedd5ca 100644 --- a/source/common/plugin_defines.h +++ b/source/common/plugin_defines.h @@ -35,7 +35,7 @@ extern "C" { #define MAXIMUM_PLUGIN_DESCRIPTION_LENGTH 255 #define MAXIMUM_PLUGIN_META_FIELD_LENGTH 51 -#define DYN_LINK_RELOCATION_LIST_LENGTH 500 +#define PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH 1000 #define MAXIMUM_HOOKS_PER_PLUGIN 25 #define MAXIMUM_FUNCTION_PER_PLUGIN 100 @@ -57,7 +57,7 @@ struct plugin_meta_info_t { }; struct plugin_info_t { - dyn_linking_relocation_entry_t linking_entries[DYN_LINK_RELOCATION_LIST_LENGTH]; + dyn_linking_relocation_entry_t linking_entries[PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH]; plugin_section_info_t sectionInfos[MAXIMUM_PLUGIN_SECTION_LENGTH]; uint32_t number_used_functions; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_PLUGIN replacement_data_function_t functions[MAXIMUM_FUNCTION_PER_PLUGIN]; // Replacement information for each function. diff --git a/source/main.cpp b/source/main.cpp index c235649..4ae8b54 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -15,18 +15,18 @@ #include "utils/logger.h" #include "utils/utils.h" #include "kernel/kernel_utils.h" -#include "patcher/hooks_patcher_static.h" -#include "patcher/hooks_patcher.h" + #include "utils/ElfUtils.h" #include "common/relocation_defines.h" #include "common/plugin_defines.h" #include "common/plugin_defines.h" #include "common/module_defines.h" #include "hooks.h" +#include "PluginManagement.h" #include MEMHeapHandle pluginDataHeap __attribute__((section(".data"))) = 0; -plugin_information_t * gPluginInformation __attribute__((section(".data"))) = NULL; +plugin_information_t *gPluginInformation __attribute__((section(".data"))) = NULL; int test(); @@ -36,157 +36,90 @@ int main(int argc, char **argv) { test(); } -bool doRelocation(const std::vector &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length, uint32_t trampolinID) { - std::map moduleHandleCache; - for (auto const& cur : relocData) { - std::string functionName = cur.getName(); - std::string rplName = cur.getImportRPLInformation().getName(); - int32_t isData = cur.getImportRPLInformation().isData(); - OSDynLoad_Module rplHandle = 0; - if(moduleHandleCache.count(rplName) > 0) { - rplHandle = moduleHandleCache[rplName]; - } else { - OSDynLoad_Acquire(rplName.c_str(), &rplHandle); - moduleHandleCache[rplName] = rplHandle; - } - - uint32_t functionAddress = 0; - OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void**) &functionAddress); - if(functionAddress == 0) { - DEBUG_FUNCTION_LINE("Failed to find export for %s", functionName.c_str()); - return false; - } else { - //DEBUG_FUNCTION_LINE("Found export for %s %s", rplName.c_str(), functionName.c_str()); - } - if(!ElfUtils::elfLinkOne(cur.getType(), cur.getOffset(), cur.getAddend(), (uint32_t) cur.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT,trampolinID)) { - DEBUG_FUNCTION_LINE("Relocation failed\n"); - return false; - } - } - - DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); - ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); - return true; -} - int test() { WHBLogUdpInit(); log_init(); - bool pluginFreshLoaded = false; - if(pluginDataHeap == NULL) { + bool initNeeded = false; + if (pluginDataHeap == NULL) { kernelInitialize(); DEBUG_FUNCTION_LINE("Kernel init done"); - DCFlushRange((void*)0x00880000, sizeof(module_information_t)); + DCFlushRange((void *) 0x00880000, sizeof(module_information_t)); uint32_t endAddress = 0; - DEBUG_FUNCTION_LINE("Using %d modules",gModuleData->number_used_modules); - for(int i = 0; i < gModuleData->number_used_modules; i++) { - DEBUG_FUNCTION_LINE("%08x",gModuleData->module_data[i].endAddress); + DEBUG_FUNCTION_LINE("Using %d modules", gModuleData->number_used_modules); + for (int i = 0; i < gModuleData->number_used_modules; i++) { + DEBUG_FUNCTION_LINE("%08x", gModuleData->module_data[i].endAddress); uint32_t curEndAddr = gModuleData->module_data[i].endAddress; - if(curEndAddr > endAddress) { + if (curEndAddr > endAddress) { endAddress = curEndAddr; } } // If this address is 0, make sure the header common match the one - // in the SetupPayload repo. (I know thats a bad idea) + // in the SetupPayload repo. (I know that's a bad idea) endAddress = (endAddress + 0x100) & 0xFFFFFF00; DEBUG_FUNCTION_LINE("endAddress: %08X", endAddress); DEBUG_FUNCTION_LINE("Create heap"); - pluginDataHeap = MEMCreateExpHeapEx((void*) (endAddress), 0x00FFF000 - endAddress, 0); + pluginDataHeap = MEMCreateExpHeapEx((void *) (endAddress), 0x00FFF000 - endAddress, 0); - if(pluginDataHeap != NULL) { - if(gPluginInformation == NULL) { - gPluginInformation = (plugin_information_t*) MEMAllocFromExpHeapEx(pluginDataHeap, sizeof(plugin_information_t), 4); - if(gPluginInformation == NULL) { + if (pluginDataHeap != NULL) { + if (gPluginInformation == NULL) { + gPluginInformation = (plugin_information_t *) MEMAllocFromExpHeapEx(pluginDataHeap, sizeof(plugin_information_t), 4); + if (gPluginInformation == NULL) { DEBUG_FUNCTION_LINE("Failed to allocate global plugin information"); return 0; } + memset((void *) gPluginInformation, 0, sizeof(plugin_information_t)); } - DEBUG_FUNCTION_LINE("MEMGetAllocatableSizeForExpHeapEx %d kb", MEMGetAllocatableSizeForExpHeapEx(pluginDataHeap, 4)/1024); + DEBUG_FUNCTION_LINE("MEMGetAllocatableSizeForExpHeapEx %d kb", MEMGetAllocatableSizeForExpHeapEx(pluginDataHeap, 4) / 1024); std::vector pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", pluginDataHeap); std::vector plugins; DEBUG_FUNCTION_LINE("Loaded %d plugin data", pluginList.size()); - for(auto & pluginData : pluginList) { + for (auto &pluginData : pluginList) { DEBUG_FUNCTION_LINE("Load meta information"); auto metaInfo = PluginMetaInformationFactory::loadPlugin(pluginData); - if(metaInfo) { + if (metaInfo) { PluginContainer container; container.setMetaInformation(metaInfo.value()); container.setPluginData(pluginData); plugins.push_back(container); } } - uint8_t trampolinID = 0; - for(auto & pluginContainer : plugins) { - std::optional data = PluginInformationFactory::load(pluginContainer.getPluginData(), pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, trampolinID); + for (auto &pluginContainer : plugins) { + uint32_t trampolineId = pluginContainer.getPluginInformation().getTrampolinId(); + std::optional data = PluginInformationFactory::load(pluginContainer.getPluginData(), pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, trampolineId); - if(!data) { + if (!data) { DEBUG_FUNCTION_LINE("Failed to load Plugin %s", pluginContainer.getMetaInformation().getName().c_str()); break; } pluginContainer.setPluginInformation(data.value()); - for (const auto& kv : data->getSectionInfoList()) { + for (const auto &kv : data->getSectionInfoList()) { DEBUG_FUNCTION_LINE("%s = %s %08X %d", kv.first.c_str(), kv.second.getName().c_str(), kv.second.getAddress(), kv.second.getSize()); } - - trampolinID++; - - PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer); + if (!PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer)) { + DEBUG_FUNCTION_LINE("Failed to save plugin"); + } } - pluginFreshLoaded = true; + initNeeded = true; } } - if(pluginDataHeap != NULL) { + if (pluginDataHeap != NULL) { std::vector plugins = PluginContainerPersistence::loadPlugins(gPluginInformation); - for(auto & pluginContainer : plugins) { - DEBUG_FUNCTION_LINE("Doing relocations for plugin: %s", pluginContainer.getMetaInformation().getName().c_str()); + PluginManagement::doRelocations(plugins, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH); + PluginManagement::memsetBSS(plugins); - if(!doRelocation(pluginContainer.getPluginInformation().getRelocationDataList(), gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, pluginContainer.getPluginInformation().getTrampolinId())) { - DEBUG_FUNCTION_LINE("Relocation failed"); - } - - auto sbssSection = pluginContainer.getPluginInformation().getSectionInfo(".sbss"); - if(sbssSection){ - DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)", sbssSection->getAddress(), sbssSection->getSize()); - memset((void*)sbssSection->getAddress(), 0, sbssSection->getSize()); - } - auto bssSection = pluginContainer.getPluginInformation().getSectionInfo(".bss"); - if(bssSection) { - DEBUG_FUNCTION_LINE("memset .bss %08X (%d)", bssSection->getAddress(), bssSection->getSize()); - memset((void*)bssSection->getAddress(), 0, bssSection->getSize()); - } + DCFlushRange((void *) 0x00800000, 0x00800000); + ICInvalidateRange((void *) 0x00800000, 0x00800000); + if (initNeeded) { + PluginManagement::callInitHooks(gPluginInformation); + initNeeded = false; } - DCFlushRange((void*)0x00800000, 0x00800000); - ICInvalidateRange((void*)0x00800000, 0x00800000); - - if(pluginFreshLoaded) { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_MALLOC); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_STDCPP); - - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_VID_MEM); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_KERNEL); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_OVERLAY); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_PLUGIN); - pluginFreshLoaded = false; - } - - PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static); - PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks); - - for(int32_t plugin_index=0; plugin_indexnumber_used_plugins; plugin_index++) { - CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB,plugin_index); - CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_START,plugin_index); - //new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]); - CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index); - } + PluginManagement::PatchFunctionsAndCallHooks(gPluginInformation); } return 0; } - - diff --git a/source/plugin/DynamicLinkingHelper.cpp b/source/plugin/DynamicLinkingHelper.cpp index 0f34873..d252dae 100644 --- a/source/plugin/DynamicLinkingHelper.cpp +++ b/source/plugin/DynamicLinkingHelper.cpp @@ -97,8 +97,8 @@ bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_entry_t * li curEntry->destination = (void*) destination; curEntry->functionEntry = functionName; curEntry->importEntry = importInfo; - return true; } + DEBUG_FUNCTION_LINE("Failed to find empty slot for saving relocations entry. We ned more than %d slots.", linking_entry_length); return false; } diff --git a/source/plugin/PluginContainerPersistence.cpp b/source/plugin/PluginContainerPersistence.cpp index cd034f0..494917f 100644 --- a/source/plugin/PluginContainerPersistence.cpp +++ b/source/plugin/PluginContainerPersistence.cpp @@ -70,7 +70,8 @@ bool PluginContainerPersistence::savePlugin(plugin_information_t * pluginInforma // Relocation std::vector relocationData = pluginInfo.getRelocationDataList(); for (auto & reloc : relocationData) { - if(!DynamicLinkingHelper::addReloationEntry(&(pluginInformation->linking_data), plugin_data->info.linking_entries, DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) { + if(!DynamicLinkingHelper::addReloationEntry(&(pluginInformation->linking_data), plugin_data->info.linking_entries, PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) { + DEBUG_FUNCTION_LINE("Failed to add a relocation entry"); return false; } } @@ -257,7 +258,7 @@ std::vector PluginContainerPersistence::loadPlugins(plugin_info } /* load relocation data */ - for(uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) { + for(uint32_t j = 0; j < PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH; j++) { dyn_linking_relocation_entry_t * linking_entry = &(plugin_data->info.linking_entries[j]); if(linking_entry->destination == NULL) { break;