Increase the maximum number of relocations from 500 to 1000. Refactor some code to a "PluginManagement" class.

This commit is contained in:
Maschell 2020-05-03 10:21:05 +02:00
parent 89445b77c2
commit 6d8fd08f25
7 changed files with 157 additions and 110 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@
*.rpx *.rpx
build/ build/
*.save-failed *.save-failed
.idea/
cmake-build-debug/
CMakeLists.txt

View File

@ -0,0 +1,90 @@
#include <plugin/PluginContainer.h>
#include <utils/ElfUtils.h>
#include <coreinit/cache.h>
#include "patcher/hooks_patcher_static.h"
#include "patcher/hooks_patcher.h"
#include "PluginManagement.h"
#include "hooks.h"
bool PluginManagement::doRelocation(const std::vector<RelocationData> &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length, uint32_t trampolinID) {
std::map<std::string,OSDynLoad_Module> 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<PluginContainer> 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<PluginContainer> 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_index<gPluginInformation->number_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);
}
}

20
source/PluginManagement.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <common/plugin_defines.h>
#include <vector>
class PluginManagement {
public:
static void Init(std::vector<PluginContainer> pInformation);
static void doRelocations(std::vector<PluginContainer> plugins, relocation_trampolin_entry_t *trampData, uint32_t tramp_size);
static void memsetBSS(std::vector<PluginContainer> plugins);
static void callInitHooks(plugin_information_t *pluginInformation);
static void PatchFunctionsAndCallHooks(plugin_information_t* gPluginInformation);
static bool doRelocation(const std::vector<RelocationData> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolinID);
};

View File

@ -35,7 +35,7 @@ extern "C" {
#define MAXIMUM_PLUGIN_DESCRIPTION_LENGTH 255 #define MAXIMUM_PLUGIN_DESCRIPTION_LENGTH 255
#define MAXIMUM_PLUGIN_META_FIELD_LENGTH 51 #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_HOOKS_PER_PLUGIN 25
#define MAXIMUM_FUNCTION_PER_PLUGIN 100 #define MAXIMUM_FUNCTION_PER_PLUGIN 100
@ -57,7 +57,7 @@ struct plugin_meta_info_t {
}; };
struct plugin_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]; plugin_section_info_t sectionInfos[MAXIMUM_PLUGIN_SECTION_LENGTH];
uint32_t number_used_functions; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_PLUGIN 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. replacement_data_function_t functions[MAXIMUM_FUNCTION_PER_PLUGIN]; // Replacement information for each function.

View File

@ -15,14 +15,14 @@
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "kernel/kernel_utils.h" #include "kernel/kernel_utils.h"
#include "patcher/hooks_patcher_static.h"
#include "patcher/hooks_patcher.h"
#include "utils/ElfUtils.h" #include "utils/ElfUtils.h"
#include "common/relocation_defines.h" #include "common/relocation_defines.h"
#include "common/plugin_defines.h" #include "common/plugin_defines.h"
#include "common/plugin_defines.h" #include "common/plugin_defines.h"
#include "common/module_defines.h" #include "common/module_defines.h"
#include "hooks.h" #include "hooks.h"
#include "PluginManagement.h"
#include <whb/sdcard.h> #include <whb/sdcard.h>
MEMHeapHandle pluginDataHeap __attribute__((section(".data"))) = 0; MEMHeapHandle pluginDataHeap __attribute__((section(".data"))) = 0;
@ -36,43 +36,10 @@ int main(int argc, char **argv) {
test(); test();
} }
bool doRelocation(const std::vector<RelocationData> &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length, uint32_t trampolinID) {
std::map<std::string,OSDynLoad_Module> 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() { int test() {
WHBLogUdpInit(); WHBLogUdpInit();
log_init(); log_init();
bool pluginFreshLoaded = false; bool initNeeded = false;
if (pluginDataHeap == NULL) { if (pluginDataHeap == NULL) {
kernelInitialize(); kernelInitialize();
DEBUG_FUNCTION_LINE("Kernel init done"); DEBUG_FUNCTION_LINE("Kernel init done");
@ -87,7 +54,7 @@ int test() {
} }
} }
// If this address is 0, make sure the header common match the one // 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; endAddress = (endAddress + 0x100) & 0xFFFFFF00;
DEBUG_FUNCTION_LINE("endAddress: %08X", endAddress); DEBUG_FUNCTION_LINE("endAddress: %08X", endAddress);
@ -101,6 +68,7 @@ int test() {
DEBUG_FUNCTION_LINE("Failed to allocate global plugin information"); DEBUG_FUNCTION_LINE("Failed to allocate global plugin information");
return 0; 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<PluginData> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", pluginDataHeap); std::vector<PluginData> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", pluginDataHeap);
@ -116,9 +84,9 @@ int test() {
plugins.push_back(container); plugins.push_back(container);
} }
} }
uint8_t trampolinID = 0;
for (auto &pluginContainer : plugins) { for (auto &pluginContainer : plugins) {
std::optional<PluginInformation> data = PluginInformationFactory::load(pluginContainer.getPluginData(), pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, trampolinID); uint32_t trampolineId = pluginContainer.getPluginInformation().getTrampolinId();
std::optional<PluginInformation> 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()); DEBUG_FUNCTION_LINE("Failed to load Plugin %s", pluginContainer.getMetaInformation().getName().c_str());
@ -129,64 +97,29 @@ int test() {
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()); DEBUG_FUNCTION_LINE("%s = %s %08X %d", kv.first.c_str(), kv.second.getName().c_str(), kv.second.getAddress(), kv.second.getSize());
} }
if (!PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer)) {
trampolinID++; DEBUG_FUNCTION_LINE("Failed to save plugin");
PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer);
} }
pluginFreshLoaded = true; }
initNeeded = true;
} }
} }
if (pluginDataHeap != NULL) { if (pluginDataHeap != NULL) {
std::vector<PluginContainer> plugins = PluginContainerPersistence::loadPlugins(gPluginInformation); std::vector<PluginContainer> plugins = PluginContainerPersistence::loadPlugins(gPluginInformation);
for(auto & pluginContainer : plugins) { PluginManagement::doRelocations(plugins, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
DEBUG_FUNCTION_LINE("Doing relocations for plugin: %s", pluginContainer.getMetaInformation().getName().c_str()); 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); DCFlushRange((void *) 0x00800000, 0x00800000);
ICInvalidateRange((void *) 0x00800000, 0x00800000); ICInvalidateRange((void *) 0x00800000, 0x00800000);
if(pluginFreshLoaded) { if (initNeeded) {
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_MALLOC); PluginManagement::callInitHooks(gPluginInformation);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB); initNeeded = false;
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); PluginManagement::PatchFunctionsAndCallHooks(gPluginInformation);
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
for(int32_t plugin_index=0; plugin_index<gPluginInformation->number_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);
}
} }
return 0; return 0;
} }

View File

@ -97,8 +97,8 @@ bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_entry_t * li
curEntry->destination = (void*) destination; curEntry->destination = (void*) destination;
curEntry->functionEntry = functionName; curEntry->functionEntry = functionName;
curEntry->importEntry = importInfo; curEntry->importEntry = importInfo;
return true; 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; return false;
} }

View File

@ -70,7 +70,8 @@ bool PluginContainerPersistence::savePlugin(plugin_information_t * pluginInforma
// Relocation // Relocation
std::vector<RelocationData> relocationData = pluginInfo.getRelocationDataList(); std::vector<RelocationData> relocationData = pluginInfo.getRelocationDataList();
for (auto & reloc : relocationData) { 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; return false;
} }
} }
@ -257,7 +258,7 @@ std::vector<PluginContainer> PluginContainerPersistence::loadPlugins(plugin_info
} }
/* load relocation data */ /* 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]); dyn_linking_relocation_entry_t * linking_entry = &(plugin_data->info.linking_entries[j]);
if(linking_entry->destination == NULL) { if(linking_entry->destination == NULL) {
break; break;