From cda9c3e055e6ba366fe91193267f6f5063adb83b Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 14 May 2022 14:00:20 +0200 Subject: [PATCH] Rewrite the plugin backend, use smart pointers is possible, don't persist in structs and simplify code --- Dockerfile | 12 +- source/PluginManagement.cpp | 195 ++++------ source/PluginManagement.h | 20 +- source/common/plugin_defines.h | 119 ------ source/config/WUPSConfig.h | 4 +- source/config/WUPSConfigItem.h | 4 +- source/globals.cpp | 18 +- source/globals.h | 31 +- source/hooks.cpp | 126 +++---- source/hooks.h | 10 +- source/main.cpp | 239 +++--------- source/patcher/hooks_patcher_static.cpp | 130 +++---- source/patcher/hooks_patcher_static.h | 4 +- source/plugin/DynamicLinkingHelper.cpp | 107 ------ source/plugin/DynamicLinkingHelper.h | 66 ---- source/plugin/FunctionData.h | 44 ++- source/plugin/ImportRPLInformation.h | 14 +- source/plugin/PluginContainer.h | 63 ++-- source/plugin/PluginContainerPersistence.cpp | 348 ------------------ source/plugin/PluginContainerPersistence.h | 11 - source/plugin/PluginData.cpp | 70 +--- source/plugin/PluginData.h | 35 +- source/plugin/PluginDataFactory.cpp | 48 ++- source/plugin/PluginDataFactory.h | 7 +- source/plugin/PluginDataPersistence.cpp | 35 -- source/plugin/PluginDataPersistence.h | 15 - source/plugin/PluginInformation.cpp | 20 - source/plugin/PluginInformation.h | 67 ++-- source/plugin/PluginInformationFactory.cpp | 201 +++++----- source/plugin/PluginInformationFactory.h | 10 +- source/plugin/PluginMetaInformation.h | 30 +- .../plugin/PluginMetaInformationFactory.cpp | 34 +- source/plugin/PluginMetaInformationFactory.h | 9 +- source/plugin/RelocationData.h | 12 +- source/plugin/SectionInfo.h | 17 +- source/utils/ConfigUtils.cpp | 66 ++-- source/utils/StringTools.cpp | 211 ++--------- source/utils/StringTools.h | 45 ++- source/utils/exports.cpp | 145 ++++---- source/utils/utils.cpp | 2 +- source/utils/utils.h | 34 +- 41 files changed, 790 insertions(+), 1888 deletions(-) delete mode 100644 source/common/plugin_defines.h delete mode 100644 source/plugin/DynamicLinkingHelper.cpp delete mode 100644 source/plugin/DynamicLinkingHelper.h delete mode 100644 source/plugin/PluginContainerPersistence.cpp delete mode 100644 source/plugin/PluginContainerPersistence.h delete mode 100644 source/plugin/PluginDataPersistence.cpp delete mode 100644 source/plugin/PluginDataPersistence.h delete mode 100644 source/plugin/PluginInformation.cpp diff --git a/Dockerfile b/Dockerfile index 6a9d904..d8b1156 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -FROM wiiuenv/devkitppc:20220213 +FROM wiiuenv/devkitppc:20220507 -COPY --from=wiiuenv/wiiumodulesystem:20220127 /artifacts $DEVKITPRO -COPY --from=wiiuenv/wiiupluginsystem:20220123 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libfunctionpatcher:20210924 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libmappedmemory:20210924 /artifacts $DEVKITPRO -COPY --from=wiiuenv/libwupsbackend:20220213 /artifacts $DEVKITPRO +COPY --from=wiiuenv/wiiumodulesystem:20220512 /artifacts $DEVKITPRO +COPY --from=wiiuenv/wiiupluginsystem:20220513 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libfunctionpatcher:20220507 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libmappedmemory:20220211 /artifacts $DEVKITPRO +COPY --from=wiiuenv/libwupsbackend:20220514 /artifacts $DEVKITPRO WORKDIR project \ No newline at end of file diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index 9f72b3c..1904303 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -1,20 +1,19 @@ -#include -#include -#include -#include -#include - +#include "PluginManagement.h" +#include "hooks.h" #include "patcher/hooks_patcher_static.h" #include "plugin/PluginContainer.h" #include "plugin/PluginInformationFactory.h" #include "plugin/PluginMetaInformationFactory.h" - -#include "PluginManagement.h" -#include "globals.h" -#include "hooks.h" #include "utils/ElfUtils.h" +#include "utils/utils.h" +#include +#include +#include +#include +#include +#include -bool PluginManagement::doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID) { +bool PluginManagement::doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID) { std::map moduleHandleCache; for (auto const &cur : relocData) { uint32_t functionAddress = 0; @@ -35,7 +34,7 @@ bool PluginManagement::doRelocation(const std::vectorgetImportRPLInformation()->getName(); + auto rplName = cur->getImportRPLInformation()->getRPLName(); int32_t isData = cur->getImportRPLInformation()->isData(); OSDynLoad_Module rplHandle = nullptr; if (moduleHandleCache.count(rplName) > 0) { @@ -54,153 +53,93 @@ bool PluginManagement::doRelocation(const std::vectorgetType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT, trampolineID)) { - DEBUG_FUNCTION_LINE_ERR("Relocation failed"); + DEBUG_FUNCTION_LINE_ERR("elfLinkOne failed"); return false; } } + // Unloading RPLs which you want to use is stupid. + // Never uncomment this again. + /* for (auto &cur : moduleHandleCache) { + // Release handle if they are not from DynLoadPatchModule + if (((uint32_t) cur.second & 0xFFFF0000) != 0x13370000) { + OSDynLoad_Release(cur.second); + } + } */ + DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampoline_entry_t)); ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampoline_entry_t)); + OSMemoryBarrier(); return true; } -void PluginManagement::doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size) { +bool PluginManagement::doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size) { for (auto &pluginContainer : plugins) { DEBUG_FUNCTION_LINE_VERBOSE("Doing relocations for plugin: %s", pluginContainer->getMetaInformation()->getName().c_str()); - if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), trampData, tramp_size, pluginContainer->getPluginInformation()->getTrampolineId())) { - DEBUG_FUNCTION_LINE_ERR("Relocation failed"); + return false; } } + return true; } -void PluginManagement::memsetBSS(const std::vector> &plugins) { - for (auto &pluginContainer : plugins) { - auto sbssSection = pluginContainer->getPluginInformation()->getSectionInfo(".sbss"); - if (sbssSection) { - DEBUG_FUNCTION_LINE_VERBOSE("memset .sbss %08X (%d)", sbssSection.value()->getAddress(), sbssSection.value()->getSize()); - memset((void *) sbssSection.value()->getAddress(), 0, sbssSection.value()->getSize()); - } - auto bssSection = pluginContainer->getPluginInformation()->getSectionInfo(".bss"); - if (bssSection) { - DEBUG_FUNCTION_LINE_VERBOSE("memset .bss %08X (%d)", bssSection.value()->getAddress(), bssSection.value()->getSize()); - memset((void *) bssSection.value()->getAddress(), 0, bssSection.value()->getSize()); - } - } -} - -void PluginManagement::RestorePatches(plugin_information_t *pluginInformation, BOOL pluginOnly) { - for (int32_t plugin_index = pluginInformation->number_used_plugins - 1; plugin_index >= 0; plugin_index--) { - FunctionPatcherRestoreFunctions(pluginInformation->plugin_data[plugin_index].info.functions, pluginInformation->plugin_data[plugin_index].info.number_used_functions); - } - if (!pluginOnly) { - FunctionPatcherRestoreFunctions(method_hooks_hooks_static, method_hooks_size_hooks_static); - } -} - -void PluginManagement::unloadPlugins(plugin_information_t *pluginInformation, MEMHeapHandle pluginHeap, BOOL freePluginData) { - - RestorePatches(pluginInformation, true); - for (int32_t plugin_index = 0; plugin_index < pluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin = &(pluginInformation->plugin_data[plugin_index]); - if (freePluginData) { - if (plugin->data.buffer != nullptr) { - if (plugin->data.memoryType == eMemTypeMEM2) { - DEBUG_FUNCTION_LINE_VERBOSE("Free plugin data buffer for %s [%08X]", plugin->meta.name, plugin->data.buffer); - free(plugin->data.buffer); - } else if (plugin->data.memoryType == eMemTypeExpHeap) { - DEBUG_FUNCTION_LINE_VERBOSE("Free plugin data buffer for %s [%08X on heap %08X]", plugin->meta.name, plugin->data.buffer, plugin->data.heapHandle); - MEMFreeToExpHeap((MEMHeapHandle) plugin->data.heapHandle, plugin->data.buffer); - } else { - DEBUG_FUNCTION_LINE_ERR("########################"); - DEBUG_FUNCTION_LINE_ERR("Failed to free memory from plugin"); - DEBUG_FUNCTION_LINE_ERR("########################"); - } - plugin->data.buffer = nullptr; - plugin->data.bufferLength = 0; - } else { - DEBUG_FUNCTION_LINE_ERR("Plugin has no copy of elf saved in memory, can't free it"); - } - } - if (plugin->info.allocatedTextMemoryAddress != nullptr) { - MEMFreeToExpHeap((MEMHeapHandle) pluginHeap, plugin->info.allocatedTextMemoryAddress); - DEBUG_FUNCTION_LINE_VERBOSE("Deleted allocated .text section for plugin %s [%08X]", plugin->meta.name, plugin->info.allocatedTextMemoryAddress); - } - if (plugin->info.allocatedDataMemoryAddress != nullptr) { - MEMFreeToExpHeap((MEMHeapHandle) pluginHeap, plugin->info.allocatedDataMemoryAddress); - DEBUG_FUNCTION_LINE_VERBOSE("Deleted allocated .data section for plugin %s [%08X]", plugin->meta.name, plugin->info.allocatedDataMemoryAddress); - } - - for (uint32_t i = 0; i < gTrampolineDataSize; i++) { - auto trampoline = &(gTrampolineData[i]); - if (trampoline->id == plugin->info.trampolineId) { - trampoline->id = 0; - trampoline->status = RELOC_TRAMP_FREE; +bool PluginManagement::RestoreFunctionPatches(const std::vector> &plugins) { + for (const auto &cur : std::ranges::reverse_view(plugins)) { + for (const auto &curFunction : std::ranges::reverse_view(cur->getPluginInformation()->getFunctionDataList())) { + if (!curFunction->restore()) { + return false; } } } - - memset((void *) pluginInformation, 0, sizeof(plugin_information_t)); + return true; } -void PluginManagement::callInitHooks(plugin_information_t *pluginInformation) { - CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_STORAGE); - CallHook(pluginInformation, WUPS_LOADER_HOOK_INIT_PLUGIN); +bool PluginManagement::DoFunctionPatches(const std::vector> &plugins) { + for (const auto &cur : plugins) { + for (const auto &curFunction : cur->getPluginInformation()->getFunctionDataList()) { + if (!curFunction->patch()) { + return false; + } + } + } + return true; +} + +void PluginManagement::callInitHooks(const std::vector> &plugins) { + CallHook(plugins, WUPS_LOADER_HOOK_INIT_STORAGE); + CallHook(plugins, WUPS_LOADER_HOOK_INIT_PLUGIN); DEBUG_FUNCTION_LINE_VERBOSE("Done calling init hooks"); } -void module_callback(OSDynLoad_Module module, - void *userContext, - OSDynLoad_NotifyReason reason, - OSDynLoad_NotifyData *infos) { - if (reason == OS_DYNLOAD_NOTIFY_LOADED) { - auto *pluginInformation = (plugin_information_t *) userContext; - for (int32_t plugin_index = 0; plugin_index < pluginInformation->number_used_plugins; plugin_index++) { - FunctionPatcherPatchFunction(pluginInformation->plugin_data[plugin_index].info.functions, pluginInformation->plugin_data[plugin_index].info.number_used_functions); - } - } -} - -void PluginManagement::PatchFunctionsAndCallHooks(plugin_information_t *pluginInformation) { - DEBUG_FUNCTION_LINE_VERBOSE("Patching functions"); - FunctionPatcherPatchFunction(method_hooks_hooks_static, method_hooks_size_hooks_static); - - DCFlushRange((void *) 0x00800000, 0x00800000); - ICInvalidateRange((void *) 0x00800000, 0x00800000); - - for (int32_t plugin_index = 0; plugin_index < pluginInformation->number_used_plugins; plugin_index++) { - CallHookEx(pluginInformation, WUPS_LOADER_HOOK_APPLICATION_STARTS, plugin_index); - FunctionPatcherPatchFunction(pluginInformation->plugin_data[plugin_index].info.functions, pluginInformation->plugin_data[plugin_index].info.number_used_functions); - CallHookEx(pluginInformation, WUPS_LOADER_HOOK_FUNCTIONS_PATCHED, plugin_index); - } - OSDynLoad_AddNotifyCallback(module_callback, pluginInformation); -} - -std::vector> -PluginManagement::loadPlugins(const std::vector> &pluginList, MEMHeapHandle heapHandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length) { - std::vector> plugins; +std::vector> +PluginManagement::loadPlugins(const std::forward_list> &pluginList, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length) { + std::vector> plugins; + uint32_t trampolineID = 0; for (auto &pluginData : pluginList) { - DEBUG_FUNCTION_LINE_VERBOSE("Load meta information"); auto metaInfo = PluginMetaInformationFactory::loadPlugin(pluginData); if (metaInfo) { - auto container = std::make_shared(); - container->setMetaInformation(metaInfo.value()); - container->setPluginData(pluginData); - plugins.push_back(container); + auto info = PluginInformationFactory::load(pluginData, trampoline_data, trampoline_data_length, trampolineID++); + if (!info) { + DEBUG_FUNCTION_LINE_ERR("Failed to load Plugin %s", metaInfo.value()->getName().c_str()); + continue; + } + auto container = make_unique_nothrow(std::move(metaInfo.value()), std::move(info.value()), pluginData); + if (!container) { + DEBUG_FUNCTION_LINE_ERR("Failed to create PluginContainer, skipping %s", metaInfo.value()->getName().c_str()); + continue; + } + plugins.push_back(std::move(container)); } else { - DEBUG_FUNCTION_LINE("Failed to get meta information"); + DEBUG_FUNCTION_LINE_ERR("Failed to get meta information"); } } - uint32_t trampolineID = 0; - for (auto &pluginContainer : plugins) { - auto info = PluginInformationFactory::load(pluginContainer->getPluginData(), heapHandle, trampoline_data, trampoline_data_length, trampolineID++); - if (!info) { - DEBUG_FUNCTION_LINE("Failed to load Plugin %s", pluginContainer->getMetaInformation()->getName().c_str()); - continue; - } - pluginContainer->setPluginInformation(info.value()); + + if (!PluginManagement::DoFunctionPatches(plugins)) { + DEBUG_FUNCTION_LINE_ERR("Failed to patch functions"); + OSFatal("Failed to patch functions"); } + return plugins; -} +} \ No newline at end of file diff --git a/source/PluginManagement.h b/source/PluginManagement.h index bce621f..d9eb339 100644 --- a/source/PluginManagement.h +++ b/source/PluginManagement.h @@ -1,26 +1,22 @@ #pragma once #include "plugin/PluginContainer.h" -#include +#include #include #include +#include class PluginManagement { public: - static void doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size); + static std::vector> loadPlugins(const std::forward_list> &pluginList, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length); - static void memsetBSS(const std::vector> &plugins); + static void callInitHooks(const std::vector> &plugins); - static void callInitHooks(plugin_information_t *pluginInformation); + static bool doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size); - static void PatchFunctionsAndCallHooks(plugin_information_t *gPluginInformation); + static bool doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID); - static bool doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID); + static bool DoFunctionPatches(const std::vector> &plugins); - static void unloadPlugins(plugin_information_t *pluginInformation, MEMHeapHandle pluginHeap, BOOL freePluginData); - - static std::vector> - loadPlugins(const std::vector> &pluginList, MEMHeapHandle pHeader, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length); - - static void RestorePatches(plugin_information_t *pluginInformation, BOOL pluginOnly); + static bool RestoreFunctionPatches(const std::vector> &plugins); }; \ No newline at end of file diff --git a/source/common/plugin_defines.h b/source/common/plugin_defines.h deleted file mode 100644 index 5ab5722..0000000 --- a/source/common/plugin_defines.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2018-2019 Maschell - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAXIMUM_PLUGIN_SECTION_LENGTH 10 -#define MAXIMUM_PLUGIN_SECTION_NAME_LENGTH 20 - -#define MAXIMUM_PLUGIN_PATH_NAME_LENGTH 256 -#define MAXIMUM_PLUGIN_NAME_LENGTH 51 -#define MAXIMUM_PLUGIN_DESCRIPTION_LENGTH 100 -#define MAXIMUM_PLUGIN_META_FIELD_LENGTH 51 - -#define PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH 1000 - -#define MAXIMUM_HOOKS_PER_PLUGIN 25 -#define MAXIMUM_FUNCTION_PER_PLUGIN 100 - -struct plugin_section_info_t { - char name[MAXIMUM_PLUGIN_SECTION_NAME_LENGTH] = ""; - uint32_t addr{}; - uint32_t size{}; -}; - -struct plugin_meta_info_t { - char name[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - char author[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - char version[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - char license[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - char buildTimestamp[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - char descripion[MAXIMUM_PLUGIN_DESCRIPTION_LENGTH] = ""; - char storageId[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = ""; - uint32_t size{}; -}; - -struct replacement_data_hook_t { - void *func_pointer = nullptr; /* [will be filled] */ - wups_loader_hook_type_t type{}; /* [will be filled] */ -}; - -struct plugin_function_symbol_data_t { - char *name; - void *address; - uint32_t size; -}; - -struct plugin_info_t { - 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 - function_replacement_data_t functions[MAXIMUM_FUNCTION_PER_PLUGIN]{}; // Replacement information for each function. - uint32_t number_used_hooks{}; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_PLUGIN - replacement_data_hook_t hooks[MAXIMUM_HOOKS_PER_PLUGIN]; // Replacement information for each function. - uint8_t trampolineId{}; - plugin_function_symbol_data_t *function_symbol_data = nullptr; - uint32_t number_function_symbol_data = 0; - void *allocatedTextMemoryAddress = nullptr; - void *allocatedDataMemoryAddress = nullptr; - void *allocatedFuncSymStringTableAddress = nullptr; -}; - -struct plugin_data_t { - char *buffer = nullptr; - size_t bufferLength = 0; - int memoryType = 0; - int heapHandle = 0; -}; - -struct plugin_information_single_t { - plugin_meta_info_t meta; - plugin_info_t info; - plugin_data_t data; - int32_t priority{}; // Priority of this plugin -}; - -#define MAXIMUM_PLUGINS 32 - -struct plugin_information_t { - int32_t number_used_plugins = 0; // Number of used plugins. Maximum is MAXIMUM_PLUGINS - plugin_information_single_t plugin_data[MAXIMUM_PLUGINS]; - dyn_linking_relocation_data_t linking_data{}; // RPL and function name list -}; - -struct plugin_information_on_reload_t { - int32_t number_used_plugins = 0; // Number of used plugins. Maximum is MAXIMUM_PLUGINS - plugin_data_t plugin_data[MAXIMUM_PLUGINS]; - bool loadOnReload = false; -}; - -#ifdef __cplusplus -} -#endif diff --git a/source/config/WUPSConfig.h b/source/config/WUPSConfig.h index b767f4b..05329a4 100644 --- a/source/config/WUPSConfig.h +++ b/source/config/WUPSConfig.h @@ -39,7 +39,7 @@ public: /** \return Returns the name of this WUPSConfig **/ - std::string getName() { + [[nodiscard]] const std::string &getName() const { return this->name; } @@ -53,7 +53,7 @@ public: \return On success, the created and inserted category will be returned. **/ std::optional addCategory(const std::string &categoryName) { - auto curCat = new WUPSConfigCategory(categoryName); + auto curCat = new (std::nothrow) WUPSConfigCategory(categoryName); if (curCat == nullptr) { return {}; } diff --git a/source/config/WUPSConfigItem.h b/source/config/WUPSConfigItem.h index a1352b5..fe651b4 100644 --- a/source/config/WUPSConfigItem.h +++ b/source/config/WUPSConfigItem.h @@ -69,7 +69,7 @@ public: if (res == 0) { return buf; } else { - return StringTools::strfmt("[ERROR %d]", res); + return string_format("[ERROR %d]", res); } } DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED"); @@ -87,7 +87,7 @@ public: if (res == 0) { return buf; } else { - return StringTools::strfmt("[ERROR %d]", res); + return string_format("[ERROR %d]", res); } } DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED"); diff --git a/source/globals.cpp b/source/globals.cpp index 2e85b20..94769a3 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -1,15 +1,11 @@ #include "globals.h" -MEMHeapHandle gPluginDataHeap __attribute__((section(".data"))) = nullptr; -MEMHeapHandle gPluginInformationHeap __attribute__((section(".data"))) = nullptr; -plugin_information_t *gPluginInformation __attribute__((section(".data"))) = nullptr; -plugin_information_on_reload_t gLinkOnReload __attribute__((section(".data"))); -module_information_t *gModuleData __attribute__((section(".data"))) = nullptr; -relocation_trampoline_entry_t *gTrampolineData __attribute__((section(".data"))) = nullptr; +StoredBuffer gStoredTVBuffer __attribute__((section(".data"))) = {}; +StoredBuffer gStoredDRCBuffer __attribute__((section(".data"))) = {}; -uint32_t gPluginDataHeapSize __attribute__((section(".data"))) = 0; -uint32_t gPluginInformationHeapSize __attribute__((section(".data"))) = 0; -uint32_t gTrampolineDataSize __attribute__((section(".data"))) = 0; +std::vector> gLoadedPlugins __attribute__((section(".data"))); +relocation_trampoline_entry_t *gTrampData __attribute__((section(".data"))) = nullptr; -StoredBuffer storedTVBuffer __attribute__((section(".data"))) = {}; -StoredBuffer storedDRCBuffer __attribute__((section(".data"))) = {}; +std::forward_list> gLoadedData __attribute__((section(".data"))); +std::forward_list> gLoadOnNextLaunch __attribute__((section(".data"))); +std::mutex gLoadedDataMutex __attribute__((section(".data"))); diff --git a/source/globals.h b/source/globals.h index 1e93226..165070d 100644 --- a/source/globals.h +++ b/source/globals.h @@ -1,22 +1,19 @@ #pragma once - -#include - -#include "common/plugin_defines.h" #include "plugin/PluginContainer.h" #include "utils/ConfigUtils.h" +#include +#include +#include +#include +#include -extern plugin_information_t *gPluginInformation; -extern MEMHeapHandle gPluginDataHeap; -extern MEMHeapHandle gPluginInformationHeap; -extern uint32_t gPluginDataHeapSize; -extern uint32_t gPluginInformationHeapSize; -extern plugin_information_on_reload_t gLinkOnReload; -extern module_information_t *gModuleData; -extern relocation_trampoline_entry_t *gTrampolineData; -extern uint32_t gTrampolineDataSize; -extern StoredBuffer storedTVBuffer; -extern StoredBuffer storedDRCBuffer; +extern StoredBuffer gStoredTVBuffer; +extern StoredBuffer gStoredDRCBuffer; -#define PLUGIN_DATA_HEAP_SIZE (8 * 1024 * 1024) -#define NUMBER_OF_TRAMPS 1024 \ No newline at end of file +#define TRAMP_DATA_SIZE 1024 +extern relocation_trampoline_entry_t *gTrampData; +extern std::vector> gLoadedPlugins; + +extern std::forward_list> gLoadedData; +extern std::forward_list> gLoadOnNextLaunch; +extern std::mutex gLoadedDataMutex; \ No newline at end of file diff --git a/source/hooks.cpp b/source/hooks.cpp index 562fd22..a74abbf 100644 --- a/source/hooks.cpp +++ b/source/hooks.cpp @@ -1,24 +1,9 @@ #include "hooks.h" +#include "plugin/PluginContainer.h" #include "utils/StorageUtils.h" #include "utils/logger.h" - -void CallHook(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type) { - CallHookEx(pluginInformation, hook_type, -1); -} - -bool HasHookCallHook(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type) { - for (int32_t plugin_index = 0; plugin_index < pluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin_data = &pluginInformation->plugin_data[plugin_index]; - - for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) { - replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j]; - if (hook_data->type == hook_type) { - return true; - } - } - } - return false; -} +#include +#include static const char **hook_names = (const char *[]){ "WUPS_LOADER_HOOK_INIT_WUT_MALLOC", @@ -43,71 +28,64 @@ static const char **hook_names = (const char *[]){ "WUPS_LOADER_HOOK_INIT_PLUGIN", "WUPS_LOADER_HOOK_DEINIT_PLUGIN", "WUPS_LOADER_HOOK_APPLICATION_STARTS", - "WUPS_LOADER_HOOK_FUNCTIONS_PATCHED", "WUPS_LOADER_HOOK_RELEASE_FOREGROUND", "WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND", "WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT", "WUPS_LOADER_HOOK_APPLICATION_ENDS"}; -void CallHookEx(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) { +void CallHook(const std::vector> &plugins, wups_loader_hook_type_t hook_type) { DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d]", hook_names[hook_type], hook_type); - for (int32_t plugin_index = 0; plugin_index < pluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin_data = &pluginInformation->plugin_data[plugin_index]; - if (plugin_index_needed != -1 && plugin_index_needed != plugin_index) { - continue; - } + for (auto &plugin : plugins) { + CallHook(plugin, hook_type); + } +} - //DEBUG_FUNCTION_LINE("Checking hook functions for %s.",plugin_data->plugin_name); - //DEBUG_FUNCTION_LINE("Found hooks: %d",plugin_data->number_used_hooks); - for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) { - replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j]; - if (hook_data->type == hook_type) { - DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s for plugin %s [%d]", hook_names[hook_data->type], plugin_data->meta.name, hook_type); - void *func_ptr = hook_data->func_pointer; - if (func_ptr != nullptr) { - //DEBUG_FUNCTION_LINE("function pointer is %08x",func_ptr); - if (hook_type == WUPS_LOADER_HOOK_INIT_PLUGIN || - hook_type == WUPS_LOADER_HOOK_DEINIT_PLUGIN || - hook_type == WUPS_LOADER_HOOK_APPLICATION_STARTS || - hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED || - hook_type == WUPS_LOADER_HOOK_APPLICATION_ENDS || - hook_type == WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT || - hook_type == WUPS_LOADER_HOOK_INIT_WUT_MALLOC || - hook_type == WUPS_LOADER_HOOK_FINI_WUT_MALLOC || - hook_type == WUPS_LOADER_HOOK_INIT_WUT_NEWLIB || - hook_type == WUPS_LOADER_HOOK_FINI_WUT_NEWLIB || - hook_type == WUPS_LOADER_HOOK_INIT_WUT_STDCPP || - hook_type == WUPS_LOADER_HOOK_FINI_WUT_STDCPP || - hook_type == WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB || - hook_type == WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB || - hook_type == WUPS_LOADER_HOOK_INIT_WUT_SOCKETS || - hook_type == WUPS_LOADER_HOOK_FINI_WUT_SOCKETS || - hook_type == WUPS_LOADER_HOOK_INIT_WRAPPER || - hook_type == WUPS_LOADER_HOOK_FINI_WRAPPER || - hook_type == WUPS_LOADER_HOOK_GET_CONFIG || - hook_type == WUPS_LOADER_HOOK_CONFIG_CLOSED || - hook_type == WUPS_LOADER_HOOK_RELEASE_FOREGROUND || - hook_type == WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND) { - // clang-format off - ((void(*)())((uint32_t *) func_ptr))(); - // clang-format on - } else if (hook_type == WUPS_LOADER_HOOK_INIT_STORAGE) { - wups_loader_init_storage_args_t args; - args.open_storage_ptr = &StorageUtils::OpenStorage; - args.close_storage_ptr = &StorageUtils::CloseStorage; - args.plugin_id = plugin_data->meta.storageId; - // clang-format off - ((void(*)(wups_loader_init_storage_args_t))((uint32_t *) func_ptr))(args); - // clang-format on - } else { - DEBUG_FUNCTION_LINE_ERR("######################################"); - DEBUG_FUNCTION_LINE_ERR("Hook is not implemented %s [%d]", hook_names[hook_type], hook_type); - DEBUG_FUNCTION_LINE_ERR("######################################"); - } +void CallHook(const std::unique_ptr &plugin, wups_loader_hook_type_t hook_type) { + for (const auto &hook : plugin->getPluginInformation()->getHookDataList()) { + if (hook->getType() == hook_type) { + DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s for plugin %s [%d]", hook_names[hook->getType()], plugin->metaInformation->getName().c_str(), hook_type); + void *func_ptr = hook->getFunctionPointer(); + if (func_ptr != nullptr) { + if (hook_type == WUPS_LOADER_HOOK_INIT_PLUGIN || + hook_type == WUPS_LOADER_HOOK_DEINIT_PLUGIN || + hook_type == WUPS_LOADER_HOOK_APPLICATION_STARTS || + hook_type == WUPS_LOADER_HOOK_APPLICATION_ENDS || + hook_type == WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT || + hook_type == WUPS_LOADER_HOOK_INIT_WUT_MALLOC || + hook_type == WUPS_LOADER_HOOK_FINI_WUT_MALLOC || + hook_type == WUPS_LOADER_HOOK_INIT_WUT_NEWLIB || + hook_type == WUPS_LOADER_HOOK_FINI_WUT_NEWLIB || + hook_type == WUPS_LOADER_HOOK_INIT_WUT_STDCPP || + hook_type == WUPS_LOADER_HOOK_FINI_WUT_STDCPP || + hook_type == WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB || + hook_type == WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB || + hook_type == WUPS_LOADER_HOOK_INIT_WUT_SOCKETS || + hook_type == WUPS_LOADER_HOOK_FINI_WUT_SOCKETS || + hook_type == WUPS_LOADER_HOOK_INIT_WRAPPER || + hook_type == WUPS_LOADER_HOOK_FINI_WRAPPER || + hook_type == WUPS_LOADER_HOOK_GET_CONFIG || + hook_type == WUPS_LOADER_HOOK_CONFIG_CLOSED || + hook_type == WUPS_LOADER_HOOK_RELEASE_FOREGROUND || + hook_type == WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND) { + // clang-format off + ((void(*)())((uint32_t *) func_ptr))(); + // clang-format on + } else if (hook_type == WUPS_LOADER_HOOK_INIT_STORAGE) { + wups_loader_init_storage_args_t args; + args.open_storage_ptr = &StorageUtils::OpenStorage; + args.close_storage_ptr = &StorageUtils::CloseStorage; + args.plugin_id = plugin->getMetaInformation()->getStorageId().c_str(); + // clang-format off + ((void(*)(wups_loader_init_storage_args_t))((uint32_t *) func_ptr))(args); + // clang-format on } else { - DEBUG_FUNCTION_LINE_ERR("Failed to call hook. It was not defined"); + DEBUG_FUNCTION_LINE_ERR("######################################"); + DEBUG_FUNCTION_LINE_ERR("Hook is not implemented %s [%d]", hook_names[hook_type], hook_type); + DEBUG_FUNCTION_LINE_ERR("######################################"); } + } else { + DEBUG_FUNCTION_LINE_ERR("Failed to call hook. It was not defined"); } } } -} +} \ No newline at end of file diff --git a/source/hooks.h b/source/hooks.h index 3272fd1..6d0a05c 100644 --- a/source/hooks.h +++ b/source/hooks.h @@ -1,10 +1,10 @@ #pragma once -#include "common/plugin_defines.h" +#include "plugin/PluginContainer.h" +#include +#include #include -void CallHook(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type); +void CallHook(const std::vector> &plugins, wups_loader_hook_type_t hook_type); -void CallHookEx(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type, int32_t plugin_index_needed); - -bool HasHookCallHook(plugin_information_t *pluginInformation, wups_loader_hook_type_t hook_type); +void CallHook(const std::unique_ptr &plugin, wups_loader_hook_type_t hook_type); \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index a04083e..5995739 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,55 +2,46 @@ #include "globals.h" #include "hooks.h" #include "patcher/hooks_patcher_static.h" -#include "plugin/PluginContainerPersistence.h" #include "plugin/PluginDataFactory.h" -#include "plugin/PluginDataPersistence.h" #include "utils/utils.h" -#include #include -#include -#include #include WUMS_MODULE_EXPORT_NAME("homebrew_wupsbackend"); WUMS_USE_WUT_DEVOPTAB(); -WUMS_INITIALIZE(args) { +WUMS_INITIALIZE() { initLogging(); - - gModuleData = args.module_information; - if (gModuleData == nullptr) { - OSFatal("WUPS-Backend: Failed to get gModuleData pointer."); + DEBUG_FUNCTION_LINE("Patching functions"); + for (uint32_t i = 0; i < method_hooks_static_size; i++) { + if (!FunctionPatcherPatchFunction(&method_hooks_static[i], nullptr)) { + OSFatal("homebrew_wupsbackend: Failed to patch function"); + } } - if (gModuleData->version != MODULE_INFORMATION_VERSION) { - OSFatal("WUPS-Backend: The module information struct version does not match."); - } - DEBUG_FUNCTION_LINE("Init successful"); deinitLogging(); } WUMS_APPLICATION_REQUESTS_EXIT() { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT); + uint32_t upid = OSGetUPID(); + if (upid != 2 && upid != 15) { + return; + } + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_APPLICATION_REQUESTS_EXIT); } WUMS_APPLICATION_ENDS() { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_ENDS); - if (gLinkOnReload.loadOnReload) { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_FINI_WRAPPER); + uint32_t upid = OSGetUPID(); + if (upid != 2 && upid != 15) { + return; } - CallHook(gPluginInformation, WUPS_LOADER_HOOK_FINI_WUT_SOCKETS); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_APPLICATION_ENDS); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_SOCKETS); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB); - auto pluginInformation = gPluginInformation; - for (int32_t plugin_index = pluginInformation->number_used_plugins - 1; plugin_index >= 0; plugin_index--) { - FunctionPatcherRestoreDynamicFunctions(pluginInformation->plugin_data[plugin_index].info.functions, pluginInformation->plugin_data[plugin_index].info.number_used_functions); - } - FunctionPatcherRestoreDynamicFunctions(method_hooks_hooks_static, method_hooks_size_hooks_static); deinitLogging(); } -void *allocOnCustomHeap(int alignment, int size); WUMS_APPLICATION_STARTS() { uint32_t upid = OSGetUPID(); @@ -59,179 +50,67 @@ WUMS_APPLICATION_STARTS() { } initLogging(); bool initNeeded = false; - if (gPluginDataHeap == nullptr) { - DCFlushRange((void *) gModuleData, sizeof(module_information_t)); - uint32_t endAddress = 0; - for (int i = 0; i < gModuleData->number_used_modules; i++) { - uint32_t curEndAddr = gModuleData->module_data[i].endAddress; - if (curEndAddr > endAddress) { - endAddress = curEndAddr; - } - } - memset((void *) &gLinkOnReload, 0, sizeof(gLinkOnReload)); - // If this address is 0, make sure the header common match the one - // in the SetupPayload repo. (I know that's a bad idea) - endAddress = (endAddress + 0x100) & 0xFFFFFF00; + std::lock_guard lock(gLoadedDataMutex); - gPluginInformationHeapSize = 0x00FFF000 - endAddress; - - DEBUG_FUNCTION_LINE("Create heap for plugins information"); - gPluginInformationHeap = MEMCreateExpHeapEx((void *) (endAddress), gPluginInformationHeapSize, 0); - - if (gPluginInformationHeap == nullptr) { - OSFatal("PluginBackend: Failed to allocate memory for plugin information"); - } - - void *pluginHeapMemory = allocOnCustomHeap(0x1000, PLUGIN_DATA_HEAP_SIZE); - if (pluginHeapMemory == nullptr) { - DEBUG_FUNCTION_LINE("Use plugins information heap as fallback"); - gPluginDataHeap = gPluginInformationHeap; - gPluginDataHeapSize = gPluginInformationHeapSize; - } else { - gPluginDataHeap = MEMCreateExpHeapEx(pluginHeapMemory, PLUGIN_DATA_HEAP_SIZE, 0); - gPluginDataHeapSize = PLUGIN_DATA_HEAP_SIZE; - } - - if (gPluginDataHeap != nullptr) { - if (gPluginInformation == nullptr) { - DEBUG_FUNCTION_LINE_VERBOSE("Allocate gPluginInformation on heap %08X (size: %d bytes)", gPluginInformationHeap, sizeof(plugin_information_t)); - gPluginInformation = (plugin_information_t *) MEMAllocFromExpHeapEx(gPluginInformationHeap, sizeof(plugin_information_t), 4); - if (gPluginInformation == nullptr) { - OSFatal("PluginBackend: Failed to allocate global plugin information"); - return; - } - memset((void *) gPluginInformation, 0, sizeof(plugin_information_t)); - } - if (gTrampolineData == nullptr) { - DEBUG_FUNCTION_LINE_VERBOSE("Allocate gTrampolineData on heap %08X (size: %d bytes)", gPluginDataHeap, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS); - gTrampolineData = (relocation_trampoline_entry_t *) MEMAllocFromExpHeapEx(gPluginDataHeap, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS, 4); - if (gTrampolineData == nullptr) { - OSFatal("PluginBackend: Failed to allocate gTrampolineData"); - return; - } - gTrampolineDataSize = NUMBER_OF_TRAMPS; - memset((void *) gTrampolineData, 0, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS); - } - DEBUG_FUNCTION_LINE("Available memory for storing plugins: %d kb", MEMGetAllocatableSizeForExpHeapEx(gPluginDataHeap, 4) / 1024); - - auto pluginPath = getPluginPath(); - - DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str()); - - std::vector> pluginList = PluginDataFactory::loadDir(pluginPath, gPluginDataHeap); - DEBUG_FUNCTION_LINE("Loaded data for %d plugins.", pluginList.size()); - - auto plugins = PluginManagement::loadPlugins(pluginList, gPluginDataHeap, gTrampolineData, gTrampolineDataSize); - for (auto &pluginContainer : plugins) { -#ifdef DEBUG - for (const auto &kv : pluginContainer->getPluginInformation()->getSectionInfoList()) { - DEBUG_FUNCTION_LINE_VERBOSE("%s = %s %08X %d", kv.first.c_str(), kv.second->getName().c_str(), kv.second->getAddress(), kv.second->getSize()); - } -#endif - if (!PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer, gPluginDataHeap)) { - DEBUG_FUNCTION_LINE_ERR("Failed to save plugin"); - } - } - - initNeeded = true; + if (gTrampData == nullptr) { + gTrampData = (relocation_trampoline_entry_t *) memalign(0x4, sizeof(relocation_trampoline_entry_t) * TRAMP_DATA_SIZE); + if (gTrampData == nullptr) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocated the memory for the trampoline data"); + OSFatal("Failed to allocated the memory for the trampoline data"); } } - if (gLinkOnReload.loadOnReload) { - DEBUG_FUNCTION_LINE("Reload with new plugin list."); - std::vector> pluginDataList; - for (int32_t i = 0; i < gLinkOnReload.number_used_plugins; i++) { - auto pluginData = PluginDataPersistence::load(&gLinkOnReload.plugin_data[i]); - pluginDataList.push_back(pluginData); - } - for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin = &(gPluginInformation->plugin_data[plugin_index]); - BOOL doDelete = true; - for (auto &pluginData : pluginDataList) { - if (pluginData->buffer == plugin->data.buffer) { - doDelete = false; - break; - } - } - if (doDelete) { - DEBUG_FUNCTION_LINE("We need to delete the plugin data for plugin %s", plugin->meta.name); - if (plugin->data.buffer != nullptr) { - if (plugin->data.memoryType == eMemTypeMEM2) { - DEBUG_FUNCTION_LINE_VERBOSE("Free plugin data buffer for %s [%08X]", plugin->meta.name, plugin->data.buffer); - free(plugin->data.buffer); - } else if (plugin->data.memoryType == eMemTypeExpHeap) { - DEBUG_FUNCTION_LINE_VERBOSE("Free plugin data buffer for %s [%08X on heap %08X]", plugin->meta.name, plugin->data.buffer, plugin->data.heapHandle); - MEMFreeToExpHeap((MEMHeapHandle) plugin->data.heapHandle, plugin->data.buffer); - } else { - DEBUG_FUNCTION_LINE_ERR("########################"); - DEBUG_FUNCTION_LINE_ERR("Failed to free memory from plugin"); - DEBUG_FUNCTION_LINE_ERR("########################"); - } - plugin->data.buffer = nullptr; - plugin->data.bufferLength = 0; - } else { - DEBUG_FUNCTION_LINE_ERR("Plugin %s has no copy of elf saved in memory, can't free it", plugin->meta.name); - } - } - } + if (gLoadedPlugins.empty()) { + auto pluginPath = getPluginPath(); - PluginManagement::unloadPlugins(gPluginInformation, gPluginDataHeap, false); + DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str()); - auto plugins = PluginManagement::loadPlugins(pluginDataList, gPluginDataHeap, gTrampolineData, gTrampolineDataSize); + auto pluginData = PluginDataFactory::loadDir(pluginPath); - for (auto &pluginContainer : plugins) { - DEBUG_FUNCTION_LINE("Stored information for plugin %s ; %s", pluginContainer->getMetaInformation()->getName().c_str(), pluginContainer->getMetaInformation()->getAuthor().c_str()); - if (!PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer, gPluginDataHeap)) { - DEBUG_FUNCTION_LINE_ERR("Failed to save plugin"); - } - } - gLinkOnReload.loadOnReload = false; - initNeeded = true; + gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData, TRAMP_DATA_SIZE); + + initNeeded = true; } - if (gPluginDataHeap != nullptr) { - auto plugins = PluginContainerPersistence::loadPlugins(gPluginInformation); - PluginManagement::doRelocations(plugins, gTrampolineData, DYN_LINK_TRAMPOLINE_LIST_LENGTH); + if (!gLoadOnNextLaunch.empty()) { + DEBUG_FUNCTION_LINE("Restore function patches of currently loaded plugins."); + PluginManagement::RestoreFunctionPatches(gLoadedPlugins); + DEBUG_FUNCTION_LINE("Unload existing plugins."); + gLoadedPlugins.clear(); + DEBUG_FUNCTION_LINE("Load new plugins"); + + gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData, TRAMP_DATA_SIZE); + initNeeded = true; + } + + DEBUG_FUNCTION_LINE("Clear plugin data lists."); + gLoadOnNextLaunch.clear(); + gLoadedData.clear(); + + if (!gLoadedPlugins.empty()) { + if (!PluginManagement::doRelocations(gLoadedPlugins, gTrampData, TRAMP_DATA_SIZE)) { + DEBUG_FUNCTION_LINE_ERR("Relocations failed"); + OSFatal("Relocations failed"); + } // PluginManagement::memsetBSS(plugins); - DCFlushRange((void *) gPluginDataHeap, gPluginDataHeapSize); - ICInvalidateRange((void *) gPluginDataHeap, gPluginDataHeapSize); - DCFlushRange((void *) gPluginInformation, sizeof(plugin_information_t)); - ICInvalidateRange((void *) gPluginInformation, sizeof(plugin_information_t)); - if (initNeeded) { - 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(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_MALLOC); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_STDCPP); } - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB); - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_SOCKETS); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_SOCKETS); if (initNeeded) { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WRAPPER); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WRAPPER); } if (initNeeded) { - PluginManagement::callInitHooks(gPluginInformation); + PluginManagement::callInitHooks(gLoadedPlugins); } - PluginManagement::PatchFunctionsAndCallHooks(gPluginInformation); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_APPLICATION_STARTS); } -} - -void *allocOnCustomHeap(int alignment, int size) { - OSDynLoad_Module module; - OSDynLoad_Error dyn_res = OSDynLoad_Acquire("homebrew_memorymapping", &module); - if (dyn_res != OS_DYNLOAD_OK) { - return nullptr; - } - uint32_t *custom_memalign; - dyn_res = OSDynLoad_FindExport(module, true, "MEMAllocFromMappedMemoryEx", reinterpret_cast(&custom_memalign)); - auto *customMEMAllocFromDefaultHeapEx = (void *(*) (uint32_t, int) ) * custom_memalign; - - if (dyn_res != OS_DYNLOAD_OK) { - return nullptr; - } - return customMEMAllocFromDefaultHeapEx(size, alignment); -} +} \ No newline at end of file diff --git a/source/patcher/hooks_patcher_static.cpp b/source/patcher/hooks_patcher_static.cpp index 88f0ee0..2402908 100644 --- a/source/patcher/hooks_patcher_static.cpp +++ b/source/patcher/hooks_patcher_static.cpp @@ -6,7 +6,6 @@ #include "../globals.h" #include "../hooks.h" -#include "../utils/ConfigUtils.h" uint8_t vpadPressCooldown = 0xFF; bool configMenuOpened = false; @@ -24,21 +23,21 @@ DECL_FUNCTION(void, GX2SwapScanBuffers, void) { } DECL_FUNCTION(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, GX2SurfaceFormat format, GX2BufferingMode buffering_mode) { - storedTVBuffer.buffer = buffer; - storedTVBuffer.buffer_size = buffer_size; - storedTVBuffer.mode = tv_render_mode; - storedTVBuffer.surface_format = format; - storedTVBuffer.buffering_mode = buffering_mode; + gStoredTVBuffer.buffer = buffer; + gStoredTVBuffer.buffer_size = buffer_size; + gStoredTVBuffer.mode = tv_render_mode; + gStoredTVBuffer.surface_format = format; + gStoredTVBuffer.buffering_mode = buffering_mode; return real_GX2SetTVBuffer(buffer, buffer_size, tv_render_mode, format, buffering_mode); } DECL_FUNCTION(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, uint32_t drc_mode, GX2SurfaceFormat surface_format, GX2BufferingMode buffering_mode) { - storedDRCBuffer.buffer = buffer; - storedDRCBuffer.buffer_size = buffer_size; - storedDRCBuffer.mode = drc_mode; - storedDRCBuffer.surface_format = surface_format; - storedDRCBuffer.buffering_mode = buffering_mode; + gStoredDRCBuffer.buffer = buffer; + gStoredDRCBuffer.buffer_size = buffer_size; + gStoredDRCBuffer.mode = drc_mode; + gStoredDRCBuffer.surface_format = surface_format; + gStoredDRCBuffer.buffering_mode = buffering_mode; return real_GX2SetDRCBuffer(buffer, buffer_size, drc_mode, surface_format, buffering_mode); } @@ -51,7 +50,7 @@ DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *mess if (message != nullptr && res) { if (lastData0 != message->args[0]) { if (message->args[0] == 0xFACEF000) { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND); } else if (message->args[0] == 0xD1E0D1E0) { // Implemented via WUMS Hook } @@ -64,7 +63,7 @@ DECL_FUNCTION(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *mess DECL_FUNCTION(void, OSReleaseForeground) { if (OSGetCoreId() == 1) { - CallHook(gPluginInformation, WUPS_LOADER_HOOK_RELEASE_FOREGROUND); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_RELEASE_FOREGROUND); } real_OSReleaseForeground(); } @@ -115,45 +114,34 @@ DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol, uint32_t symbolNameBufferLength, char *moduleNameBuffer, uint32_t moduleNameBufferLength) { - for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin = &(gPluginInformation->plugin_data[plugin_index]); - plugin_section_info_t *section = nullptr; - - for (auto §ionInfo : plugin->info.sectionInfos) { - if (sectionInfo.addr == 0 && sectionInfo.size == 0) { - break; - } - if (strncmp(sectionInfo.name, ".text", sizeof(sectionInfo.name)) == 0) { - section = §ionInfo; - break; - } - } - if (section == nullptr) { - continue; - } - if (addr < section->addr || addr >= (section->addr + section->size)) { + for (auto &plugin : gLoadedPlugins) { + auto sectionInfoOpt = plugin->getPluginInformation()->getSectionInfo(".text"); + if (!sectionInfoOpt) { continue; } - strncpy(moduleNameBuffer, plugin->meta.name, moduleNameBufferLength); - if (plugin->info.function_symbol_data != nullptr && plugin->info.number_function_symbol_data > 1) { - for (uint32_t i = 0; i < plugin->info.number_function_symbol_data - 1; i++) { - auto symbolData = &plugin->info.function_symbol_data[i]; - auto symbolDataNext = &plugin->info.function_symbol_data[i + 1]; - if (i == plugin->info.number_function_symbol_data - 2 || (addr >= (uint32_t) symbolData->address && addr < (uint32_t) symbolDataNext->address)) { - strncpy(symbolNameBuffer, symbolData->name, moduleNameBufferLength); - if (outDistance) { - *outDistance = addr - (uint32_t) symbolData->address; - } - return 0; - } + auto §ionInfo = sectionInfoOpt.value(); + + if (!sectionInfo->isInSection(addr)) { + continue; + } + + strncpy(moduleNameBuffer, plugin->getMetaInformation()->getName().c_str(), moduleNameBufferLength - 1); + auto functionSymbolDataOpt = plugin->getPluginInformation()->getNearestFunctionSymbolData(addr); + if (functionSymbolDataOpt) { + auto &functionSymbolData = functionSymbolDataOpt.value(); + + strncpy(symbolNameBuffer, functionSymbolData->getName().c_str(), moduleNameBufferLength); + if (outDistance) { + *outDistance = addr - (uint32_t) functionSymbolData->getAddress(); } + return 0; } strncpy(symbolNameBuffer, ".text", symbolNameBufferLength); if (outDistance) { - *outDistance = addr - (uint32_t) section->addr; + *outDistance = addr - (uint32_t) sectionInfo->getAddress(); } return 0; @@ -163,48 +151,34 @@ DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol, } DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t bufSize) { - for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin = &(gPluginInformation->plugin_data[plugin_index]); - plugin_section_info_t *section = nullptr; - - for (auto §ionInfo : plugin->info.sectionInfos) { - if (sectionInfo.addr == 0 && sectionInfo.size == 0) { - break; - } - if (strncmp(sectionInfo.name, ".text", sizeof(sectionInfo.name)) == 0) { - section = §ionInfo; - break; - } - } - if (section == nullptr) { - continue; - } - if (addr < section->addr || addr >= (section->addr + section->size)) { + for (auto &plugin : gLoadedPlugins) { + auto sectionInfoOpt = plugin->getPluginInformation()->getSectionInfo(".text"); + if (!sectionInfoOpt) { continue; } - auto pluginNameLen = strlen(plugin->meta.name); + auto §ionInfo = sectionInfoOpt.value(); + + if (!sectionInfo->isInSection(addr)) { + continue; + } + + auto pluginNameLen = strlen(plugin->getMetaInformation()->getName().c_str()); int32_t spaceLeftInBuffer = (int32_t) bufSize - (int32_t) pluginNameLen - 1; if (spaceLeftInBuffer < 0) { spaceLeftInBuffer = 0; } - strncpy(buffer, plugin->meta.name, bufSize); + strncpy(buffer, plugin->getMetaInformation()->getName().c_str(), bufSize - 1); - if (plugin->info.function_symbol_data != nullptr && plugin->info.number_function_symbol_data > 1) { - for (uint32_t i = 0; i < plugin->info.number_function_symbol_data - 1; i++) { - auto symbolData = &plugin->info.function_symbol_data[i]; - auto symbolDataNext = &plugin->info.function_symbol_data[i + 1]; - if (i == plugin->info.number_function_symbol_data - 2 || (addr >= (uint32_t) symbolData->address && addr < (uint32_t) symbolDataNext->address)) { - if (spaceLeftInBuffer > 2) { - buffer[pluginNameLen] = '|'; - buffer[pluginNameLen + 1] = '\0'; - strncpy(buffer + pluginNameLen + 1, symbolData->name, spaceLeftInBuffer - 1); - } - return (uint32_t) symbolData->address; - } - } + auto functionSymbolDataOpt = plugin->getPluginInformation()->getNearestFunctionSymbolData(addr); + if (functionSymbolDataOpt) { + auto &functionSymbolData = functionSymbolDataOpt.value(); + buffer[pluginNameLen] = '|'; + buffer[pluginNameLen + 1] = '\0'; + strncpy(buffer + pluginNameLen + 1, functionSymbolData->getName().c_str(), spaceLeftInBuffer - 1); } - return addr; + + return 0; } return real_KiGetAppSymbolName(addr, buffer, bufSize); @@ -212,7 +186,7 @@ DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t #pragma GCC pop_options -function_replacement_data_t method_hooks_hooks_static[] __attribute__((section(".data"))) = { +function_replacement_data_t method_hooks_static[] __attribute__((section(".data"))) = { REPLACE_FUNCTION(GX2SwapScanBuffers, LIBRARY_GX2, GX2SwapScanBuffers), REPLACE_FUNCTION(GX2SetTVBuffer, LIBRARY_GX2, GX2SetTVBuffer), REPLACE_FUNCTION(GX2SetDRCBuffer, LIBRARY_GX2, GX2SetDRCBuffer), @@ -225,4 +199,4 @@ function_replacement_data_t method_hooks_hooks_static[] __attribute__((section(" }; -uint32_t method_hooks_size_hooks_static __attribute__((section(".data"))) = sizeof(method_hooks_hooks_static) / sizeof(function_replacement_data_t); \ No newline at end of file +uint32_t method_hooks_static_size __attribute__((section(".data"))) = sizeof(method_hooks_static) / sizeof(function_replacement_data_t); \ No newline at end of file diff --git a/source/patcher/hooks_patcher_static.h b/source/patcher/hooks_patcher_static.h index c761d1f..9ca5579 100644 --- a/source/patcher/hooks_patcher_static.h +++ b/source/patcher/hooks_patcher_static.h @@ -6,8 +6,8 @@ extern "C" { #endif -extern function_replacement_data_t method_hooks_hooks_static[]; -extern uint32_t method_hooks_size_hooks_static; +extern function_replacement_data_t method_hooks_static[]; +extern uint32_t method_hooks_static_size; #ifdef __cplusplus } diff --git a/source/plugin/DynamicLinkingHelper.cpp b/source/plugin/DynamicLinkingHelper.cpp deleted file mode 100644 index 621ef85..0000000 --- a/source/plugin/DynamicLinkingHelper.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "DynamicLinkingHelper.h" -#include -#include - -dyn_linking_function_t *DynamicLinkingHelper::getOrAddFunctionEntryByName(dyn_linking_relocation_data_t *data, const char *functionName) { - if (data == nullptr) { - DEBUG_FUNCTION_LINE_ERR("data was NULL"); - return nullptr; - } - if (functionName == nullptr) { - DEBUG_FUNCTION_LINE_ERR("functionName was NULL"); - return nullptr; - } - dyn_linking_function_t *result = nullptr; - for (auto &curEntry : data->functions) { - if (strlen(curEntry.functionName) == 0) { - if (strlen(functionName) > DYN_LINK_FUNCTION_NAME_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Failed to add function name, it's too long."); - return nullptr; - } - strncpy(curEntry.functionName, functionName, DYN_LINK_FUNCTION_NAME_LENGTH); - result = &curEntry; - break; - } - if (strncmp(curEntry.functionName, functionName, DYN_LINK_FUNCTION_NAME_LENGTH) == 0) { - result = &curEntry; - break; - } - } - return result; -} - -dyn_linking_import_t *DynamicLinkingHelper::getOrAddFunctionImportByName(dyn_linking_relocation_data_t *data, const char *importName) { - return getOrAddImport(data, importName, false); -} - -dyn_linking_import_t *DynamicLinkingHelper::getOrAddDataImportByName(dyn_linking_relocation_data_t *data, const char *importName) { - return getOrAddImport(data, importName, true); -} - -dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData) { - if (importName == nullptr || data == nullptr) { - return nullptr; - } - dyn_linking_import_t *result = nullptr; - for (auto &curEntry : data->imports) { - if (strlen(curEntry.importName) == 0) { - if (strlen(importName) > DYN_LINK_IMPORT_NAME_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Failed to add Import, it's too long."); - return nullptr; - } - strncpy(curEntry.importName, importName, DYN_LINK_IMPORT_NAME_LENGTH); - curEntry.isData = isData; - result = &curEntry; - break; - } - if (strncmp(curEntry.importName, importName, DYN_LINK_IMPORT_NAME_LENGTH) == 0 && (curEntry.isData == isData)) { - return &curEntry; - } - } - return result; -} - -bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, - const std::shared_ptr &relocationData) { - return addReloationEntry(linking_data, linking_entries, linking_entry_length, relocationData->getType(), relocationData->getOffset(), relocationData->getAddend(), relocationData->getDestination(), - relocationData->getName(), - relocationData->getImportRPLInformation()); -} - -bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, - int32_t addend, const void *destination, - const std::string &name, const std::shared_ptr &rplInfo) { - dyn_linking_import_t *importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo->getName().c_str(), rplInfo->isData()); - if (importInfoGbl == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Getting import info failed. Probably maximum of %d rpl files to import reached.", DYN_LINK_IMPORT_LIST_LENGTH); - return false; - } - - dyn_linking_function_t *functionInfo = DynamicLinkingHelper::getOrAddFunctionEntryByName(linking_data, name.c_str()); - if (functionInfo == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Getting import info failed. Probably maximum of %d function to be relocated reached.", DYN_LINK_FUNCTION_LIST_LENGTH); - return false; - } - - return addReloationEntry(linking_entries, linking_entry_length, type, offset, addend, destination, functionInfo, importInfoGbl); -} - -bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, - dyn_linking_function_t *functionName, - dyn_linking_import_t *importInfo) { - for (uint32_t i = 0; i < linking_entry_length; i++) { - dyn_linking_relocation_entry_t *curEntry = &(linking_entries[i]); - if (curEntry->functionEntry != nullptr) { - continue; - } - curEntry->type = type; - curEntry->offset = offset; - curEntry->addend = addend; - curEntry->destination = (void *) destination; - curEntry->functionEntry = functionName; - curEntry->importEntry = importInfo; - return true; - } - DEBUG_FUNCTION_LINE_ERR("Failed to find empty slot for saving relocations entry. We need more than %d slots.", linking_entry_length); - return false; -} diff --git a/source/plugin/DynamicLinkingHelper.h b/source/plugin/DynamicLinkingHelper.h deleted file mode 100644 index 20c9c8f..0000000 --- a/source/plugin/DynamicLinkingHelper.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "RelocationData.h" -#include -#include -#include -#include - -class DynamicLinkingHelper { -public: - /** - Gets the function entry for a given function name. If the function name is not present in the list, it will be added. - - \param functionName Name of the function - \return Returns a pointer to the entry which contains the functionName. Null on error or if the list full. - **/ - static dyn_linking_function_t *getOrAddFunctionEntryByName(dyn_linking_relocation_data_t *data, const char *functionName); - - /** - Gets the function import entry for a given function name. If the import is not present in the list, it will be added. - This will return entries for _function_ imports. - - \param importName Name of the function - \return Returns a pointer to the function import entry which contains the importName. Null on error or if the list full. - **/ - static dyn_linking_import_t *getOrAddFunctionImportByName(dyn_linking_relocation_data_t *data, const char *importName); - - - /** - Gets the data import entry for a given data name. If the import is not present in the list, it will be added. - This will return entries for _data_ imports. - - \param importName Name of the data - \return Returns a pointer to the data import entry which contains the importName. Null on error or if the list full. - **/ - static dyn_linking_import_t *getOrAddDataImportByName(dyn_linking_relocation_data_t *data, const char *importName); - - - /** - Gets the import entry for a given data name and type. If the import is not present in the list, it will be added. - This will return entries for _data_ and _function_ imports, depending on the isData parameter. - - \param importName Name of the data - \param isData Set this to true to return a data import - - \return Returns a pointer to the data import entry which contains the importName. Null on error or if the list full. - **/ - static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData); - - static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, - const std::shared_ptr &relocationData); - - static bool - addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, - const void *destination, const std::string &name, - const std::shared_ptr &rplInfo); - - static bool addReloationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, - dyn_linking_function_t *functionName, - dyn_linking_import_t *importInfo); - -private: - DynamicLinkingHelper() = default; - - ~DynamicLinkingHelper() = default; -}; diff --git a/source/plugin/FunctionData.h b/source/plugin/FunctionData.h index 31b0adb..d0ce979 100644 --- a/source/plugin/FunctionData.h +++ b/source/plugin/FunctionData.h @@ -16,17 +16,19 @@ ****************************************************************************/ #pragma once +#include "utils/logger.h" #include +#include #include class FunctionData { public: - FunctionData(void *paddress, void *vaddress, const std::string &name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall, + FunctionData(void *paddress, void *vaddress, std::string name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall, FunctionPatcherTargetProcess targetProcess) { this->paddress = paddress; this->vaddress = vaddress; - this->name = name; + this->name = std::move(name); this->library = library; this->targetProcess = targetProcess; this->replaceAddr = replaceAddr; @@ -63,6 +65,42 @@ public: return targetProcess; } + bool patch() { + if (handle == 0) { + function_replacement_data_t functionData = { + .VERSION = FUNCTION_REPLACEMENT_DATA_STRUCT_VERSION, + .physicalAddr = reinterpret_cast(this->paddress), + .virtualAddr = reinterpret_cast(this->vaddress), + .replaceAddr = reinterpret_cast(this->replaceAddr), + .replaceCall = static_cast(this->replaceCall), + .library = this->library, + .function_name = this->name.c_str(), + .targetProcess = this->targetProcess}; + + if (!FunctionPatcherPatchFunction(&functionData, &handle)) { + DEBUG_FUNCTION_LINE_ERR("Failed to patch function"); + return false; + } + } else { + DEBUG_FUNCTION_LINE("Function is already patched"); + } + return true; + } + + bool restore() { + if (handle != 0) { + if (!FunctionPatcherRestoreFunction(handle)) { + DEBUG_FUNCTION_LINE_ERR("Failed to restore function patch"); + return false; + } + handle = 0; + } else { + DEBUG_FUNCTION_LINE("Was not patched."); + } + + return true; + } + private: void *paddress = nullptr; void *vaddress = nullptr; @@ -71,4 +109,6 @@ private: FunctionPatcherTargetProcess targetProcess; void *replaceAddr = nullptr; void *replaceCall = nullptr; + + PatchedFunctionHandle handle = 0; }; diff --git a/source/plugin/ImportRPLInformation.h b/source/plugin/ImportRPLInformation.h index 09d6896..ab6e408 100644 --- a/source/plugin/ImportRPLInformation.h +++ b/source/plugin/ImportRPLInformation.h @@ -24,22 +24,24 @@ class ImportRPLInformation { public: - explicit ImportRPLInformation(std::string name, bool isData = false) { - this->name = std::move(name); - this->_isData = isData; + explicit ImportRPLInformation(std::string name) { + this->name = std::move(name); } ~ImportRPLInformation() = default; - [[nodiscard]] std::string getName() const { + [[nodiscard]] const std::string &getName() const { return name; } + [[nodiscard]] std::string getRPLName() const { + return name.substr(strlen(".dimport_")); + } + [[nodiscard]] bool isData() const { - return _isData; + return name.starts_with(".dimport_"); } private: std::string name; - bool _isData = false; }; diff --git a/source/plugin/PluginContainer.h b/source/plugin/PluginContainer.h index 9381d86..84a18e8 100644 --- a/source/plugin/PluginContainer.h +++ b/source/plugin/PluginContainer.h @@ -1,19 +1,19 @@ /**************************************************************************** - * Copyright (C) 2020 Maschell - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ +* Copyright (C) 2020 Maschell +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +****************************************************************************/ #pragma once @@ -21,42 +21,33 @@ #include "PluginInformation.h" #include "PluginMetaInformation.h" #include +#include class PluginContainer { public: - PluginContainer(const PluginContainer &other) { - this->pluginData = other.pluginData; - this->pluginInformation = other.pluginInformation; - this->metaInformation = other.metaInformation; + PluginContainer(std::unique_ptr metaInformation, std::unique_ptr pluginInformation, std::shared_ptr pluginData) + : metaInformation(std::move(metaInformation)), + pluginInformation(std::move(pluginInformation)), + pluginData(std::move(pluginData)) { } - PluginContainer() = default; - - [[nodiscard]] const std::shared_ptr &getMetaInformation() const { + [[nodiscard]] const std::unique_ptr &getMetaInformation() const { return this->metaInformation; } - void setMetaInformation(const std::shared_ptr &metaInfo) { - this->metaInformation = metaInfo; - } - - [[nodiscard]] const std::shared_ptr &getPluginInformation() const { + [[nodiscard]] const std::unique_ptr &getPluginInformation() const { return pluginInformation; } - void setPluginInformation(const std::shared_ptr &_pluginInformation) { - this->pluginInformation = _pluginInformation; - } - [[nodiscard]] const std::shared_ptr &getPluginData() const { return pluginData; } - void setPluginData(const std::shared_ptr &_pluginData) { - this->pluginData = _pluginData; + uint32_t getHandle() { + return (uint32_t) this; } - std::shared_ptr pluginData; - std::shared_ptr metaInformation; - std::shared_ptr pluginInformation; + const std::unique_ptr metaInformation; + const std::unique_ptr pluginInformation; + const std::shared_ptr pluginData; }; diff --git a/source/plugin/PluginContainerPersistence.cpp b/source/plugin/PluginContainerPersistence.cpp deleted file mode 100644 index 830d28a..0000000 --- a/source/plugin/PluginContainerPersistence.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include - -#include - -#include "DynamicLinkingHelper.h" -#include "PluginContainer.h" -#include "PluginContainerPersistence.h" -#include "PluginDataPersistence.h" -#include "PluginInformationFactory.h" -#include "PluginMetaInformationFactory.h" - -bool PluginContainerPersistence::savePlugin(plugin_information_t *pluginInformation, const std::shared_ptr &plugin, MEMHeapHandle heapHandle) { - int32_t plugin_count = pluginInformation->number_used_plugins; - - auto pluginName = plugin->getMetaInformation()->getName(); - - if (plugin_count >= MAXIMUM_PLUGINS - 1) { - DEBUG_FUNCTION_LINE_ERR("Maximum of %d plugins reached. %s won't be loaded!", MAXIMUM_PLUGINS, pluginName.c_str()); - return false; - } - // Copy data to global struct. - plugin_information_single_t *plugin_data = &(pluginInformation->plugin_data[plugin_count]); - - // Make sure everything is reset. - memset((void *) plugin_data, 0, sizeof(plugin_information_single_t)); - - const auto &pluginMetaInfo = plugin->getMetaInformation(); - auto plugin_meta_data = &plugin_data->meta; - - if (pluginMetaInfo->getName().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: name will be truncated."); - } - strncpy(plugin_meta_data->name, pluginMetaInfo->getName().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - if (pluginMetaInfo->getAuthor().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: author will be truncated."); - } - strncpy(plugin_meta_data->author, pluginMetaInfo->getAuthor().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - - if (pluginMetaInfo->getVersion().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: version will be truncated."); - } - strncpy(plugin_meta_data->version, pluginMetaInfo->getVersion().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - - if (pluginMetaInfo->getLicense().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: license will be truncated."); - } - strncpy(plugin_meta_data->license, pluginMetaInfo->getLicense().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - - if (pluginMetaInfo->getBuildTimestamp().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: build timestamp will be truncated."); - } - strncpy(plugin_meta_data->buildTimestamp, pluginMetaInfo->getBuildTimestamp().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - - if (pluginMetaInfo->getDescription().size() >= MAXIMUM_PLUGIN_DESCRIPTION_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: description will be truncated."); - DEBUG_FUNCTION_LINE_ERR("%s", pluginMetaInfo->getDescription().c_str()); - } - strncpy(plugin_meta_data->descripion, pluginMetaInfo->getDescription().c_str(), MAXIMUM_PLUGIN_DESCRIPTION_LENGTH - 1); - - if (pluginMetaInfo->getStorageId().length() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) { - DEBUG_FUNCTION_LINE_ERR("Warning: plugin storage id will be truncated."); - } - strncpy(plugin_meta_data->storageId, pluginMetaInfo->getStorageId().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1); - - plugin_meta_data->size = pluginMetaInfo->getSize(); - - auto pluginInfo = plugin->getPluginInformation(); - - // Relocation - auto relocationData = pluginInfo->getRelocationDataList(); - for (auto &reloc : relocationData) { - if (!DynamicLinkingHelper::addReloationEntry(&(pluginInformation->linking_data), plugin_data->info.linking_entries, PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) { - DEBUG_FUNCTION_LINE_ERR("Failed to add a relocation entry"); - return false; - } - } - - auto function_data_list = pluginInfo->getFunctionDataList(); - auto hook_data_list = pluginInfo->getHookDataList(); - - if (function_data_list.size() > MAXIMUM_FUNCTION_PER_PLUGIN) { - DEBUG_FUNCTION_LINE_ERR("Plugin %s would replace to many function (%d, maximum is %d). It won't be loaded.", pluginName.c_str(), function_data_list.size(), MAXIMUM_FUNCTION_PER_PLUGIN); - return false; - } - if (hook_data_list.size() > MAXIMUM_HOOKS_PER_PLUGIN) { - DEBUG_FUNCTION_LINE_ERR("Plugin %s would set too many hooks (%d, maximum is %d). It won't be loaded.", pluginName.c_str(), hook_data_list.size(), MAXIMUM_HOOKS_PER_PLUGIN); - return false; - } - - if (pluginName.length() > MAXIMUM_PLUGIN_NAME_LENGTH - 1) { - DEBUG_FUNCTION_LINE_ERR("Name for plugin %s was too long to be stored.", pluginName.c_str()); - return false; - } - - /* Store function replacement information */ - uint32_t i = 0; - for (auto &curFunction : pluginInfo->getFunctionDataList()) { - function_replacement_data_t *function_data = &plugin_data->info.functions[i]; - if (strlen(curFunction->getName().c_str()) > MAXIMUM_FUNCTION_NAME_LENGTH - 1) { - DEBUG_FUNCTION_LINE_ERR("Could not add function \"%s\" for plugin \"%s\" function name is too long.", curFunction->getName().c_str(), pluginName.c_str()); - continue; - } - - DEBUG_FUNCTION_LINE_VERBOSE("Adding function \"%s\" for plugin \"%s\"", curFunction->getName().c_str(), pluginName.c_str()); - - strncpy(function_data->function_name, curFunction->getName().c_str(), MAXIMUM_FUNCTION_NAME_LENGTH - 1); - - function_data->VERSION = FUNCTION_REPLACEMENT_DATA_STRUCT_VERSION; - function_data->library = (function_replacement_library_type_t) curFunction->getLibrary(); - function_data->replaceAddr = (uint32_t) curFunction->getReplaceAddress(); - function_data->replaceCall = (uint32_t) curFunction->getReplaceCall(); - function_data->physicalAddr = (uint32_t) curFunction->getPhysicalAddress(); - function_data->virtualAddr = (uint32_t) curFunction->getVirtualAddress(); - function_data->targetProcess = curFunction->getTargetProcess(); - - plugin_data->info.number_used_functions++; - i++; - } - - i = 0; - for (auto &curHook : pluginInfo->getHookDataList()) { - replacement_data_hook_t *hook_data = &plugin_data->info.hooks[i]; - - DEBUG_FUNCTION_LINE_VERBOSE("Set hook for plugin \"%s\" of type %08X to target %08X", plugin_data->meta.name, curHook->getType(), (void *) curHook->getFunctionPointer()); - - hook_data->func_pointer = (void *) curHook->getFunctionPointer(); - hook_data->type = curHook->getType(); - - plugin_data->info.number_used_hooks++; - i++; - } - - /* Saving SectionInfos */ - for (auto &curSection : pluginInfo->getSectionInfoList()) { - bool foundFreeSlot = false; - uint32_t slot = 0; - for (uint32_t j = 0; j < MAXIMUM_PLUGIN_SECTION_LENGTH; j++) { - auto *sectionInfo = &(plugin_data->info.sectionInfos[j]); - if (sectionInfo->addr == 0 && sectionInfo->size == 0) { - foundFreeSlot = true; - slot = j; - break; - } - } - if (foundFreeSlot) { - auto *sectionInfo = &(plugin_data->info.sectionInfos[slot]); - if (curSection.first.length() > MAXIMUM_PLUGIN_SECTION_NAME_LENGTH - 1) { - DEBUG_FUNCTION_LINE_ERR("Could not add section info \"%s\" for plugin \"%s\" section name is too long.", curSection.first.c_str(), pluginName.c_str()); - break; - } - strncpy(sectionInfo->name, curSection.first.c_str(), MAXIMUM_PLUGIN_SECTION_NAME_LENGTH - 1); - sectionInfo->addr = curSection.second->getAddress(); - sectionInfo->size = curSection.second->getSize(); - - } else { - DEBUG_FUNCTION_LINE_ERR("Failed to store SectionInfos"); - return false; - } - } - plugin_data->info.trampolineId = pluginInfo->getTrampolineId(); - plugin_data->info.allocatedTextMemoryAddress = pluginInfo->allocatedTextMemoryAddress; - plugin_data->info.allocatedDataMemoryAddress = pluginInfo->allocatedDataMemoryAddress; - - uint32_t entryCount = pluginInfo->getFunctionSymbolDataList().size(); - if (entryCount > 0) { - // Saving SectionInfos - uint32_t funcSymStringLen = 1; - for (auto &curFuncSym : pluginInfo->getFunctionSymbolDataList()) { - funcSymStringLen += curFuncSym->getName().length() + 1; - } - - char *stringTable = (char *) MEMAllocFromExpHeapEx(heapHandle, funcSymStringLen, 0x4); - if (stringTable == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Failed alloc memory to store string table for function symbol data"); - return false; - } - memset(stringTable, 0, funcSymStringLen); - DEBUG_FUNCTION_LINE("Allocated %d for the function symbol string table", funcSymStringLen); - auto *entryTable = (plugin_function_symbol_data_t *) MEMAllocFromExpHeapEx(heapHandle, entryCount * sizeof(plugin_function_symbol_data_t), 0x4); - if (entryTable == nullptr) { - MEMFreeToExpHeap((MEMHeapHandle) heapHandle, stringTable); - free(stringTable); - DEBUG_FUNCTION_LINE_ERR("Failed alloc memory to store function symbol data"); - return false; - } - DEBUG_FUNCTION_LINE("Allocated %d for the function symbol data", entryCount * sizeof(plugin_function_symbol_data_t)); - - uint32_t curStringOffset = 0; - uint32_t curEntryIndex = 0; - for (auto &curFuncSym : pluginInfo->getFunctionSymbolDataList()) { - entryTable[curEntryIndex].address = curFuncSym->getAddress(); - entryTable[curEntryIndex].name = &stringTable[curStringOffset]; - entryTable[curEntryIndex].size = curFuncSym->getSize(); - auto len = curFuncSym->getName().length() + 1; - memcpy(stringTable + curStringOffset, curFuncSym->getName().c_str(), len); - curStringOffset += len; - curEntryIndex++; - } - - plugin_data->info.allocatedFuncSymStringTableAddress = stringTable; - plugin_data->info.function_symbol_data = entryTable; - } - - plugin_data->info.number_function_symbol_data = entryCount; - - /* Copy plugin data */ - auto pluginData = plugin->getPluginData(); - auto plugin_data_data = &plugin_data->data; - - PluginDataPersistence::save(plugin_data_data, pluginData); - - pluginInformation->number_used_plugins++; - - DCFlushRange((void *) pluginInformation, sizeof(plugin_information_t)); - ICInvalidateRange((void *) pluginInformation, sizeof(plugin_information_t)); - - return true; -} - -std::vector> PluginContainerPersistence::loadPlugins(plugin_information_t *pluginInformation) { - std::vector> result; - if (pluginInformation == nullptr) { - DEBUG_FUNCTION_LINE_ERR("pluginInformation == nullptr"); - return result; - } - DCFlushRange((void *) pluginInformation, sizeof(plugin_information_t)); - ICInvalidateRange((void *) pluginInformation, sizeof(plugin_information_t)); - - int32_t plugin_count = pluginInformation->number_used_plugins; - if (plugin_count > MAXIMUM_PLUGINS) { - DEBUG_FUNCTION_LINE_ERR("pluginInformation->plugin_count was bigger then allowed. %d > %d. Limiting to %d", plugin_count, MAXIMUM_PLUGINS, MAXIMUM_PLUGINS); - plugin_count = MAXIMUM_PLUGINS; - } - for (int32_t i = 0; i < plugin_count; i++) { - // Copy data from struct. - plugin_information_single_t *plugin_data = &(pluginInformation->plugin_data[i]); - - auto metaInformation = std::shared_ptr(new PluginMetaInformation); - - plugin_meta_info_t *meta = &(plugin_data->meta); - metaInformation->setAuthor(meta->author); - metaInformation->setVersion(meta->version); - metaInformation->setBuildTimestamp(meta->buildTimestamp); - metaInformation->setLicense(meta->license); - metaInformation->setDescription(meta->descripion); - metaInformation->setSize(meta->size); - metaInformation->setName(meta->name); - metaInformation->setStorageId(meta->storageId); - - plugin_data_t *data = &(plugin_data->data); - - auto pluginData = PluginDataPersistence::load(data); - - auto curPluginInformation = std::make_shared(); - - curPluginInformation->setTrampolineId(plugin_data->info.trampolineId); - curPluginInformation->allocatedTextMemoryAddress = plugin_data->info.allocatedTextMemoryAddress; - curPluginInformation->allocatedDataMemoryAddress = plugin_data->info.allocatedDataMemoryAddress; - - for (auto &curItem : plugin_data->info.sectionInfos) { - plugin_section_info_t *sectionInfo = &curItem; - if (sectionInfo->addr == 0 && sectionInfo->size == 0) { - continue; - } - DEBUG_FUNCTION_LINE_VERBOSE("Add SectionInfo %s", sectionInfo->name); - std::string name(sectionInfo->name); - curPluginInformation->addSectionInfo(std::make_shared(name, sectionInfo->addr, sectionInfo->size)); - } - - /* load hook data */ - uint32_t hookCount = plugin_data->info.number_used_hooks; - - if (hookCount > MAXIMUM_HOOKS_PER_PLUGIN) { - DEBUG_FUNCTION_LINE_ERR("number_used_hooks was bigger then allowed. %d > %d. Limiting to %d", hookCount, MAXIMUM_HOOKS_PER_PLUGIN, MAXIMUM_HOOKS_PER_PLUGIN); - hookCount = MAXIMUM_HOOKS_PER_PLUGIN; - } - - for (uint32_t j = 0; j < hookCount; j++) { - replacement_data_hook_t *hook_entry = &(plugin_data->info.hooks[j]); - curPluginInformation->addHookData(std::make_shared(hook_entry->func_pointer, hook_entry->type)); - } - - bool storageHasId = true; - for (auto const &value : curPluginInformation->getHookDataList()) { - if (value->getType() == WUPS_LOADER_HOOK_INIT_STORAGE && - metaInformation->getStorageId().empty()) { - storageHasId = false; - } - } - if (!storageHasId) { - DEBUG_FUNCTION_LINE_ERR("Plugin is using the storage API but has not set an ID"); - continue; - } - - /* load function replacement data */ - uint32_t functionReplaceCount = plugin_data->info.number_used_functions; - - if (functionReplaceCount > MAXIMUM_FUNCTION_PER_PLUGIN) { - DEBUG_FUNCTION_LINE_ERR("number_used_functions was bigger then allowed. %d > %d. Limiting to %d", functionReplaceCount, MAXIMUM_FUNCTION_PER_PLUGIN, MAXIMUM_FUNCTION_PER_PLUGIN); - functionReplaceCount = MAXIMUM_FUNCTION_PER_PLUGIN; - } - - for (uint32_t j = 0; j < functionReplaceCount; j++) { - function_replacement_data_t *entry = &(plugin_data->info.functions[j]); - auto func = std::make_shared((void *) entry->physicalAddr, (void *) entry->virtualAddr, entry->function_name, (function_replacement_library_type_t) entry->library, - (void *) entry->replaceAddr, - (void *) entry->replaceCall, entry->targetProcess); - curPluginInformation->addFunctionData(func); - } - - /* load relocation data */ - for (auto &linking_entry : plugin_data->info.linking_entries) { - if (linking_entry.destination == nullptr) { - break; - } - dyn_linking_import_t *importEntry = linking_entry.importEntry; - if (importEntry == nullptr) { - DEBUG_FUNCTION_LINE_ERR("importEntry was nullptr, skipping relocation entry"); - continue; - } - dyn_linking_function_t *functionEntry = linking_entry.functionEntry; - - if (functionEntry == nullptr) { - DEBUG_FUNCTION_LINE_ERR("functionEntry was nullptr, skipping relocation entry"); - continue; - } - auto rplInfo = std::make_shared(importEntry->importName, importEntry->isData); - std::string functionName(functionEntry->functionName); - auto reloc = std::make_shared(linking_entry.type, linking_entry.offset, linking_entry.addend, linking_entry.destination, functionName, rplInfo); - curPluginInformation->addRelocationData(reloc); - } - - /* load function symbol data */ - for (uint32_t j = 0; j < plugin_data->info.number_function_symbol_data; j++) { - auto symbol_data = &plugin_data->info.function_symbol_data[j]; - std::string symbol_name = symbol_data->name; - auto funSymbolData = std::make_shared(symbol_name, (void *) symbol_data->address, symbol_data->size); - curPluginInformation->addFunctionSymbolData(funSymbolData); - } - - auto container = std::make_shared(); - container->setMetaInformation(metaInformation); - container->setPluginData(pluginData); - container->setPluginInformation(curPluginInformation); - result.push_back(container); - } - return result; -} diff --git a/source/plugin/PluginContainerPersistence.h b/source/plugin/PluginContainerPersistence.h deleted file mode 100644 index 87bf3dd..0000000 --- a/source/plugin/PluginContainerPersistence.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "../common/plugin_defines.h" -#include "PluginContainer.h" - -class PluginContainerPersistence { -public: - static bool savePlugin(plugin_information_t *pluginInformation, const std::shared_ptr &plugin, MEMHeapHandle heapHandle); - - static std::vector> loadPlugins(plugin_information_t *pluginInformation); -}; diff --git a/source/plugin/PluginData.cpp b/source/plugin/PluginData.cpp index fc0f8ee..41c985f 100644 --- a/source/plugin/PluginData.cpp +++ b/source/plugin/PluginData.cpp @@ -1,63 +1,15 @@ #include "PluginData.h" +#include "utils/logger.h" +#include "utils/utils.h" -#include "../utils/logger.h" -#include - -PluginData::PluginData(const PluginData &obj) { - this->buffer = obj.buffer; - this->heapHandle = obj.heapHandle; - this->memoryType = obj.memoryType; - this->length = obj.length; -} - -void PluginData::freeMemory() { - if (buffer == nullptr) { - return; - } - - switch (memoryType) { - default: - case eMemTypeExpHeap: - DEBUG_FUNCTION_LINE_VERBOSE("Free PluginData buffer %08X on heap %08X", buffer, this->heapHandle); - MEMFreeToExpHeap(this->heapHandle, buffer); - this->buffer = nullptr; - break; - case eMemTypeMEM2: - DEBUG_FUNCTION_LINE_VERBOSE("Free PluginData buffer %08X on default heap", buffer); - free(this->buffer); - this->buffer = nullptr; - break; +PluginData::PluginData(const std::vector &input) : length(input.size()) { + auto data_copy = make_unique_nothrow(length); + if (!data_copy) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate space on default heap"); + this->length = 0; + } else { + DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb on default heap", length / 1024); + memcpy(data_copy.get(), &input[0], length); + this->buffer = std::move(data_copy); } } - -PluginData::PluginData(const std::vector &buffer) : PluginData(buffer, nullptr, eMemTypeMEM2) { -} - -PluginData::PluginData(const std::vector &input, MEMHeapHandle heapHandle, eMemoryTypes memoryType) : heapHandle(heapHandle), - memoryType(memoryType), - length(input.size()) { - void *data_copy = nullptr; - switch (memoryType) { - default: - case eMemTypeExpHeap: - data_copy = MEMAllocFromExpHeapEx(heapHandle, length, 4); - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb on ExpHeap", length / 1024); - if (data_copy == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Failed to allocate space on exp heap"); - } else { - memcpy(data_copy, &input[0], length); - } - this->buffer = data_copy; - break; - case eMemTypeMEM2: - data_copy = memalign(4, length); - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb on default heap", length / 1024); - if (data_copy == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Failed to allocate space on default heap"); - } else { - memcpy(data_copy, &input[0], length); - } - this->buffer = data_copy; - break; - } -} \ No newline at end of file diff --git a/source/plugin/PluginData.h b/source/plugin/PluginData.h index 052db31..f0f144d 100644 --- a/source/plugin/PluginData.h +++ b/source/plugin/PluginData.h @@ -19,41 +19,18 @@ #include #include +#include #include #include -#include "../elfio/elfio.hpp" - -using namespace ELFIO; - -enum eMemoryTypes { - eMemTypeMEM2, - eMemTypeExpHeap -}; - class PluginData { public: - ~PluginData() = default; - - void freeMemory(); - - PluginData(const PluginData &obj); - - PluginData() = default; - - void *buffer = nullptr; - MEMHeapHandle heapHandle{}; - eMemoryTypes memoryType{}; - size_t length = 0; - -private: explicit PluginData(const std::vector &buffer); - PluginData(const std::vector &input, MEMHeapHandle heapHandle, eMemoryTypes memoryType); + uint32_t getHandle() { + return (uint32_t) this; + } - friend class PluginDataFactory; - - friend class PluginContainer; - - friend class PluginDataPersistence; + size_t length = 0; + std::unique_ptr buffer; }; diff --git a/source/plugin/PluginDataFactory.cpp b/source/plugin/PluginDataFactory.cpp index c6324de..6987f6b 100644 --- a/source/plugin/PluginDataFactory.cpp +++ b/source/plugin/PluginDataFactory.cpp @@ -15,33 +15,35 @@ * along with this program. If not, see . ****************************************************************************/ #include "PluginDataFactory.h" -#include "../fs/FSUtils.h" -#include "../utils/StringTools.h" +#include "fs/FSUtils.h" +#include "utils/StringTools.h" +#include "utils/logger.h" +#include "utils/utils.h" #include +#include #include #include -std::vector> PluginDataFactory::loadDir(const std::string &path, MEMHeapHandle heapHandle) { - std::vector> result; +std::forward_list> PluginDataFactory::loadDir(const std::string &path) { + std::forward_list> result; struct dirent *dp; DIR *dfd; if (path.empty()) { - DEBUG_FUNCTION_LINE_VERBOSE("Path was empty"); + DEBUG_FUNCTION_LINE_ERR("Failed to load Plugins from dir: Path was empty"); return result; } if ((dfd = opendir(path.c_str())) == nullptr) { - DEBUG_FUNCTION_LINE_VERBOSE("Couldn't open dir %s", path.c_str()); + DEBUG_FUNCTION_LINE_ERR("Couldn't open dir %s", path.c_str()); return result; } while ((dp = readdir(dfd)) != nullptr) { struct stat stbuf {}; - std::string full_file_path = StringTools::strfmt("%s/%s", path.c_str(), dp->d_name); - StringTools::RemoveDoubleSlashs(full_file_path); + auto full_file_path = string_format("%s/%s", path.c_str(), dp->d_name); if (stat(full_file_path.c_str(), &stbuf) == -1) { - DEBUG_FUNCTION_LINE_VERBOSE("Unable to stat file: %s", full_file_path.c_str()); + DEBUG_FUNCTION_LINE_ERR("Unable to stat file: %s", full_file_path.c_str()); continue; } @@ -49,24 +51,25 @@ std::vector> PluginDataFactory::loadDir(const std::s continue; } else { DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str()); - auto pluginData = load(full_file_path, heapHandle); + auto pluginData = load(full_file_path); if (pluginData) { - result.push_back(pluginData.value()); + result.push_front(std::move(pluginData.value())); + } else { + DEBUG_FUNCTION_LINE_ERR("Failed to load plugin: %s", full_file_path.c_str()); } } } - if (dfd != nullptr) { - closedir(dfd); - } + + closedir(dfd); return result; } -std::optional> PluginDataFactory::load(const std::string &filename, MEMHeapHandle heapHandle) { +std::optional> PluginDataFactory::load(const std::string &filename) { uint8_t *buffer = nullptr; uint32_t fsize = 0; if (FSUtils::LoadFileToMem(filename.c_str(), &buffer, &fsize) < 0) { - DEBUG_FUNCTION_LINE_VERBOSE("Failed to load file"); + DEBUG_FUNCTION_LINE_ERR("Failed to load %s into memory", filename.c_str()); return {}; } @@ -77,13 +80,18 @@ std::optional> PluginDataFactory::load(const std::st DEBUG_FUNCTION_LINE_VERBOSE("Loaded file!"); - return load(result, heapHandle); + return load(result); } -std::optional> PluginDataFactory::load(std::vector &buffer, MEMHeapHandle heapHandle) { +std::optional> PluginDataFactory::load(const std::vector &buffer) { if (buffer.empty()) { - return std::nullopt; + return {}; } - return std::shared_ptr(new PluginData(buffer, heapHandle, eMemoryTypes::eMemTypeMEM2)); + auto res = make_unique_nothrow(buffer); + if (!res) { + return {}; + } + + return res; } diff --git a/source/plugin/PluginDataFactory.h b/source/plugin/PluginDataFactory.h index 25b137e..c67fec5 100644 --- a/source/plugin/PluginDataFactory.h +++ b/source/plugin/PluginDataFactory.h @@ -19,6 +19,7 @@ #include "PluginData.h" #include +#include #include #include #include @@ -26,9 +27,9 @@ class PluginDataFactory { public: - static std::vector> loadDir(const std::string &path, MEMHeapHandle heapHandle); + static std::forward_list> loadDir(const std::string &path); - static std::optional> load(const std::string &path, MEMHeapHandle heapHandle); + static std::optional> load(const std::string &path); - static std::optional> load(std::vector &buffer, MEMHeapHandle heapHandle); + static std::optional> load(const std::vector &buffer); }; diff --git a/source/plugin/PluginDataPersistence.cpp b/source/plugin/PluginDataPersistence.cpp deleted file mode 100644 index ab20d61..0000000 --- a/source/plugin/PluginDataPersistence.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "PluginDataPersistence.h" -#include "../common/plugin_defines.h" -#include - -bool PluginDataPersistence::save(plugin_data_t *pluginDataStruct, const std::shared_ptr &plugin) { - if (pluginDataStruct == nullptr) { - return false; - } - pluginDataStruct->buffer = (char *) plugin->buffer; - pluginDataStruct->bufferLength = plugin->length; - pluginDataStruct->memoryType = plugin->memoryType; - pluginDataStruct->heapHandle = (int) plugin->heapHandle; - return true; -} - -bool PluginDataPersistence::save(plugin_data_t *pluginDataStruct, PluginData *plugin) { - if (pluginDataStruct == nullptr) { - return false; - } - pluginDataStruct->buffer = (char *) plugin->buffer; - pluginDataStruct->bufferLength = plugin->length; - pluginDataStruct->memoryType = plugin->memoryType; - pluginDataStruct->heapHandle = (int) plugin->heapHandle; - return true; -} - -std::shared_ptr PluginDataPersistence::load(plugin_data_t *pluginDataStruct) { - auto pluginData = std::make_shared(); - - pluginData->buffer = pluginDataStruct->buffer; - pluginData->length = pluginDataStruct->bufferLength; - pluginData->memoryType = (eMemoryTypes) pluginDataStruct->memoryType; - pluginData->heapHandle = (MEMHeapHandle) pluginDataStruct->heapHandle; - return pluginData; -} \ No newline at end of file diff --git a/source/plugin/PluginDataPersistence.h b/source/plugin/PluginDataPersistence.h deleted file mode 100644 index deac7f0..0000000 --- a/source/plugin/PluginDataPersistence.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "../common/plugin_defines.h" -#include "PluginData.h" -#include - -class PluginDataPersistence { - -public: - static bool save(plugin_data_t *pluginDataStruct, const std::shared_ptr &plugin); - - static bool save(plugin_data_t *pluginDataStruct, PluginData *plugin); - - static std::shared_ptr load(plugin_data_t *pluginDataStruct); -}; diff --git a/source/plugin/PluginInformation.cpp b/source/plugin/PluginInformation.cpp deleted file mode 100644 index 7365f16..0000000 --- a/source/plugin/PluginInformation.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "PluginInformation.h" - -PluginInformation::PluginInformation(const PluginInformation &other) { - for (const auto &i : other.hook_data_list) { - hook_data_list.push_back(i); - } - for (const auto &i : other.function_data_list) { - function_data_list.push_back(i); - } - for (const auto &i : other.relocation_data_list) { - relocation_data_list.push_back(i); - } - for (const auto &i : other.symbol_data_list) { - symbol_data_list.insert(i); - } - section_info_list = other.section_info_list; - trampolineId = other.trampolineId; - allocatedTextMemoryAddress = other.allocatedTextMemoryAddress; - allocatedDataMemoryAddress = other.allocatedDataMemoryAddress; -} \ No newline at end of file diff --git a/source/plugin/PluginInformation.h b/source/plugin/PluginInformation.h index f4f9495..0fcc97e 100644 --- a/source/plugin/PluginInformation.h +++ b/source/plugin/PluginInformation.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,47 +40,41 @@ struct FunctionSymbolDataComparator { class PluginInformation { public: - PluginInformation(const PluginInformation &other); - - PluginInformation() = default; - - virtual ~PluginInformation() = default; - - void addHookData(const std::shared_ptr &hook_data) { - hook_data_list.push_back(hook_data); + void addHookData(std::unique_ptr hook_data) { + hook_data_list.push_back(std::move(hook_data)); } - [[nodiscard]] const std::vector> &getHookDataList() const { + [[nodiscard]] const std::vector> &getHookDataList() const { return hook_data_list; } - void addFunctionData(const std::shared_ptr &function_data) { - function_data_list.push_back(function_data); + void addFunctionData(std::unique_ptr function_data) { + function_data_list.push_back(std::move(function_data)); } - [[nodiscard]] const std::vector> &getFunctionDataList() const { + [[nodiscard]] const std::vector> &getFunctionDataList() const { return function_data_list; } - void addRelocationData(const std::shared_ptr &relocation_data) { - relocation_data_list.push_back(relocation_data); + void addRelocationData(std::unique_ptr relocation_data) { + relocation_data_list.push_back(std::move(relocation_data)); } - [[nodiscard]] const std::vector> &getRelocationDataList() const { + [[nodiscard]] const std::vector> &getRelocationDataList() const { return relocation_data_list; } - void addFunctionSymbolData(const std::shared_ptr &symbol_data) { - symbol_data_list.insert(symbol_data); + void addFunctionSymbolData(std::shared_ptr symbol_data) { + symbol_data_list.insert(std::move(symbol_data)); } [[nodiscard]] const std::set, FunctionSymbolDataComparator> &getFunctionSymbolDataList() const { return symbol_data_list; } - void addSectionInfo(const std::shared_ptr §ionInfo) { - section_info_list[sectionInfo->getName()] = sectionInfo; + void addSectionInfo(std::shared_ptr sectionInfo) { + section_info_list[sectionInfo->getName()] = std::move(sectionInfo); } [[nodiscard]] const std::map> &getSectionInfoList() const { @@ -87,7 +82,7 @@ public: } [[nodiscard]] std::optional> getSectionInfo(const std::string §ionName) const { - if (getSectionInfoList().count(sectionName) > 0) { + if (getSectionInfoList().contains(sectionName)) { return section_info_list.at(sectionName); } return std::nullopt; @@ -101,19 +96,37 @@ public: return trampolineId; } + [[nodiscard]] std::optional> getNearestFunctionSymbolData(uint32_t address) const { + std::shared_ptr result; + + bool foundHit = false; + for (auto &cur : symbol_data_list) { + if (foundHit && address < (uint32_t) cur->getAddress()) { + break; + } + if (address >= (uint32_t) cur->getAddress()) { + result = cur; + foundHit = true; + } + } + if (result) { + return result; + } + + return {}; + } + private: - std::vector> hook_data_list; - std::vector> function_data_list; - std::vector> relocation_data_list; + std::vector> hook_data_list; + std::vector> function_data_list; + std::vector> relocation_data_list; std::set, FunctionSymbolDataComparator> symbol_data_list; std::map> section_info_list; uint8_t trampolineId = 0; - void *allocatedTextMemoryAddress = nullptr; - void *allocatedDataMemoryAddress = nullptr; + std::unique_ptr allocatedTextMemoryAddress; + std::unique_ptr allocatedDataMemoryAddress; friend class PluginInformationFactory; - - friend class PluginContainerPersistence; }; diff --git a/source/plugin/PluginInformationFactory.cpp b/source/plugin/PluginInformationFactory.cpp index 926027f..9e9ef50 100644 --- a/source/plugin/PluginInformationFactory.cpp +++ b/source/plugin/PluginInformationFactory.cpp @@ -22,28 +22,36 @@ #include #include #include -#include #include using namespace ELFIO; -std::optional> -PluginInformationFactory::load(const std::shared_ptr &pluginData, MEMHeapHandle heapHandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, +std::optional> +PluginInformationFactory::load(const std::shared_ptr &pluginData, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, uint8_t trampolineId) { - if (pluginData->buffer == nullptr) { + if (!pluginData->buffer) { DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr"); - return std::nullopt; + return {}; } elfio reader; - if (!reader.load((char *) pluginData->buffer, pluginData->length)) { + if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); - return std::nullopt; + return {}; } - auto pluginInfo = std::make_shared(); + auto pluginInfo = make_unique_nothrow(); + if (!pluginInfo) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate PluginInformation"); + return {}; + } - uint32_t sec_num = reader.sections.size(); - auto **destinations = (uint8_t **) malloc(sizeof(uint8_t *) * sec_num); + uint32_t sec_num = reader.sections.size(); + + auto destinations = make_unique_nothrow(sec_num); + if (!destinations) { + DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array"); + return {}; + } uint32_t totalSize = 0; @@ -69,21 +77,22 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME } } } - void *text_data = MEMAllocFromExpHeapEx(heapHandle, text_size, 0x1000); - if (text_data == nullptr) { + + auto text_data = make_unique_nothrow(text_size); + if (!text_data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .text section (%d bytes)", text_size); - - return std::nullopt; + return {}; } - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb from ExpHeap", text_size / 1024); - void *data_data = MEMAllocFromExpHeapEx(heapHandle, data_size, 0x1000); - if (data_data == nullptr) { + + DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", text_size / 1024); + + auto data_data = make_unique_nothrow(data_size); + if (!data_data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .data section (%d bytes)", data_size); - - MEMFreeToExpHeap(heapHandle, text_data); - return std::nullopt; + return {}; } - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb from ExpHeap", data_size / 1024); + + DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", data_size / 1024); for (uint32_t i = 0; i < sec_num; ++i) { section *psec = reader.sections[i]; @@ -97,23 +106,20 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME uint32_t destination = address; if ((address >= 0x02000000) && address < 0x10000000) { - destination += (uint32_t) text_data; + destination += (uint32_t) text_data.get(); destination -= 0x02000000; - destinations[psec->get_index()] = (uint8_t *) text_data; + destinations[psec->get_index()] = (uint8_t *) text_data.get(); } else if ((address >= 0x10000000) && address < 0xC0000000) { - destination += (uint32_t) data_data; + destination += (uint32_t) data_data.get(); destination -= 0x10000000; - destinations[psec->get_index()] = (uint8_t *) data_data; + destinations[psec->get_index()] = (uint8_t *) data_data.get(); } else if (address >= 0xC0000000) { - destination += (uint32_t) data_data; + destination += (uint32_t) data_data.get(); destination -= 0xC0000000; //destinations[psec->get_index()] = (uint8_t *) data_data; //destinations[psec->get_index()] -= 0xC0000000; } else { DEBUG_FUNCTION_LINE_ERR("Unhandled case"); - free(destinations); - MEMFreeToExpHeap(heapHandle, text_data); - MEMFreeToExpHeap(heapHandle, data_data); return std::nullopt; } @@ -127,8 +133,13 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME memcpy((void *) destination, p, sectionSize); } - std::string sectionName(psec->get_name()); - pluginInfo->addSectionInfo(std::make_shared(sectionName, destination, sectionSize)); + auto sectionInfo = make_unique_nothrow(psec->get_name(), destination, sectionSize); + if (!sectionInfo) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocat SectionInfo"); + return {}; + } + + pluginInfo->addSectionInfo(std::move(sectionInfo)); DEBUG_FUNCTION_LINE_VERBOSE("Saved %s section info. Location: %08X size: %08X", psec->get_name().c_str(), destination, sectionSize); totalSize += sectionSize; @@ -142,29 +153,23 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME section *psec = reader.sections[i]; if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) { DEBUG_FUNCTION_LINE_VERBOSE("Linking (%d)... %s at %08X", i, psec->get_name().c_str(), destinations[psec->get_index()]); - - if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data, (uint32_t) data_data, trampoline_data, trampoline_data_length, + if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data.get(), (uint32_t) data_data.get(), trampoline_data, trampoline_data_length, trampolineId)) { - DEBUG_FUNCTION_LINE_ERR("elfLink failed"); - free(destinations); - MEMFreeToExpHeap(heapHandle, text_data); - MEMFreeToExpHeap(heapHandle, data_data); - return std::nullopt; + DEBUG_FUNCTION_LINE_ERR("linkSection failed"); + return {}; } } } - auto relocationData = getImportRelocationData(reader, destinations); - for (auto const &reloc : relocationData) { - pluginInfo->addRelocationData(reloc); + if (!PluginInformationFactory::addImportRelocationData(pluginInfo, reader, destinations)) { + DEBUG_FUNCTION_LINE_ERR("addImportRelocationData failed"); + return {}; } - DCFlushRange((void *) text_data, text_size); - ICInvalidateRange((void *) text_data, text_size); - DCFlushRange((void *) data_data, data_size); - ICInvalidateRange((void *) data_data, data_size); - - free(destinations); + DCFlushRange((void *) text_data.get(), text_size); + ICInvalidateRange((void *) text_data.get(), text_size); + DCFlushRange((void *) data_data.get(), data_size); + ICInvalidateRange((void *) data_data.get(), data_size); pluginInfo->setTrampolineId(trampolineId); @@ -175,9 +180,13 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME if (entries != nullptr) { for (size_t j = 0; j < entries_count; j++) { wups_loader_hook_t *hook = &entries[j]; - DEBUG_FUNCTION_LINE_VERBOSE("Saving hook of plugin Type: %08X, target: %08X" /*,pluginData->getPluginInformation()->getName().c_str()*/, hook->type, (void *) hook->target); - auto hook_data = std::make_shared((void *) hook->target, hook->type); - pluginInfo->addHookData(hook_data); + DEBUG_FUNCTION_LINE_VERBOSE("Saving hook of plugin Type: %08X, target: %08X", hook->type, (void *) hook->target); + auto hookData = make_unique_nothrow((void *) hook->target, hook->type); + if (!hookData) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate HookData"); + return {}; + } + pluginInfo->addHookData(std::move(hookData)); } } } @@ -193,11 +202,19 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME cur_function->_function.name /*,pluginData->getPluginInformation()->getName().c_str()*/, cur_function->_function.physical_address, cur_function->_function.virtual_address, cur_function->_function.library, cur_function->_function.target, (void *) cur_function->_function.call_addr); - auto function_data = std::make_shared((void *) cur_function->_function.physical_address, (void *) cur_function->_function.virtual_address, cur_function->_function.name, - (function_replacement_library_type_t) cur_function->_function.library, - (void *) cur_function->_function.target, (void *) cur_function->_function.call_addr, - (FunctionPatcherTargetProcess) cur_function->_function.targetProcess); - pluginInfo->addFunctionData(function_data); + + auto functionData = make_unique_nothrow((void *) cur_function->_function.physical_address, + (void *) cur_function->_function.virtual_address, + cur_function->_function.name, + (function_replacement_library_type_t) cur_function->_function.library, + (void *) cur_function->_function.target, + (void *) cur_function->_function.call_addr, + (FunctionPatcherTargetProcess) cur_function->_function.targetProcess); + if (!functionData) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionData"); + return {}; + } + pluginInfo->addFunctionData(std::move(functionData)); } } } @@ -228,8 +245,13 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME continue; } - auto finalAddress = offsetVal + sectionOpt.value()->getAddress(); - pluginInfo->addFunctionSymbolData(std::make_shared(name, (void *) finalAddress, (uint32_t) size)); + auto finalAddress = offsetVal + sectionOpt.value()->getAddress(); + auto functionSymbolData = make_unique_nothrow(name, (void *) finalAddress, (uint32_t) size); + if (!functionSymbolData) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionSymbolData"); + return {}; + } + pluginInfo->addFunctionSymbolData(std::move(functionSymbolData)); } } } @@ -238,24 +260,31 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME } } + if (totalSize > text_size + data_size) { + DEBUG_FUNCTION_LINE_ERR("We didn't allocate enough memory!!"); + return std::nullopt; + } + // Save the addresses for the allocated memory. This way we can free it again :) - pluginInfo->allocatedDataMemoryAddress = data_data; - pluginInfo->allocatedTextMemoryAddress = text_data; + pluginInfo->allocatedDataMemoryAddress = std::move(data_data); + pluginInfo->allocatedTextMemoryAddress = std::move(text_data); return pluginInfo; } -std::vector> PluginInformationFactory::getImportRelocationData(const elfio &reader, uint8_t **destinations) { - std::vector> result; - - std::map infoMap; +bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr &pluginInfo, const elfio &reader, const std::unique_ptr &destinations) { + std::map> infoMap; uint32_t sec_num = reader.sections.size(); for (uint32_t i = 0; i < sec_num; ++i) { - section *psec = reader.sections[i]; + auto *psec = reader.sections[i]; if (psec->get_type() == 0x80000002) { - infoMap[i] = psec->get_name(); + auto info = make_shared_nothrow(psec->get_name()); + if (!info) { + return false; + } + infoMap[i] = std::move(info); } } @@ -274,7 +303,7 @@ std::vector> PluginInformationFactory::getImport if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); - break; + return false; } auto adjusted_sym_value = (uint32_t) sym_value; @@ -282,35 +311,28 @@ std::vector> PluginInformationFactory::getImport continue; } - std::string fimport = ".fimport_"; - std::string dimport = ".dimport_"; - - bool isData = false; - - std::string rplName; - std::string rawSectionName = infoMap[sym_section_index]; - - if (rawSectionName.size() < fimport.size()) { - DEBUG_FUNCTION_LINE_ERR("Section name was shorter than expected, skipping this relocation"); - continue; - } else if (std::equal(fimport.begin(), fimport.end(), rawSectionName.begin())) { - rplName = rawSectionName.substr(fimport.size()); - } else if (std::equal(dimport.begin(), dimport.end(), rawSectionName.begin())) { - rplName = rawSectionName.substr(dimport.size()); - isData = true; - } else { - DEBUG_FUNCTION_LINE_ERR("invalid section name"); - continue; + uint32_t section_index = psec->get_info(); + if (!infoMap.contains(sym_section_index)) { + DEBUG_FUNCTION_LINE_ERR("Relocation is referencing a unknown section. %d destination: %08X sym_name %s", section_index, destinations[section_index], sym_name.c_str()); + return false; } - auto rplInfo = std::make_shared(rplName, isData); + auto relocationData = make_unique_nothrow(type, + offset - 0x02000000, + addend, + (void *) (destinations[section_index]), + sym_name, + infoMap[sym_section_index]); + if (!relocationData) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate RelocationData"); + return false; + } - uint32_t section_index = psec->get_info(); - result.push_back(std::make_shared(type, offset - 0x02000000, addend, (void *) (destinations[section_index]), sym_name, rplInfo)); + pluginInfo->addRelocationData(std::move(relocationData)); } } } - return result; + return true; } bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, @@ -380,6 +402,5 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section return true; } } - DEBUG_FUNCTION_LINE_ERR("Failed to find relocation section"); return true; } diff --git a/source/plugin/PluginInformationFactory.h b/source/plugin/PluginInformationFactory.h index 5693244..2560e2e 100644 --- a/source/plugin/PluginInformationFactory.h +++ b/source/plugin/PluginInformationFactory.h @@ -27,15 +27,17 @@ #include #include + class PluginInformationFactory { public: - static std::optional> - load(const std::shared_ptr &pluginData, MEMHeapHandle heaphandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, uint8_t trampolineId); + static std::optional> + load(const std::shared_ptr &pluginData, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, + uint8_t trampolineId); static bool - linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, + linkSection(const ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, uint8_t trampolineId); - static std::vector> getImportRelocationData(const elfio &reader, uint8_t **destinations); + static bool addImportRelocationData(const std::unique_ptr &pluginInfo, const ELFIO::elfio &reader, const std::unique_ptr &destinations); }; diff --git a/source/plugin/PluginMetaInformation.h b/source/plugin/PluginMetaInformation.h index 30e8a13..454b7cc 100644 --- a/source/plugin/PluginMetaInformation.h +++ b/source/plugin/PluginMetaInformation.h @@ -59,36 +59,36 @@ public: private: PluginMetaInformation() = default; - void setName(const std::string &_name) { - this->name = _name; + void setName(std::string _name) { + this->name = std::move(_name); } - void setAuthor(const std::string &_author) { - this->author = _author; + void setAuthor(std::string _author) { + this->author = std::move(_author); } - void setVersion(const std::string &_version) { - this->version = _version; + void setVersion(std::string _version) { + this->version = std::move(_version); } - void setLicense(const std::string &_license) { - this->license = _license; + void setLicense(std::string _license) { + this->license = std::move(_license); } - void setBuildTimestamp(const std::string &_buildtimestamp) { - this->buildtimestamp = _buildtimestamp; + void setBuildTimestamp(std::string _buildtimestamp) { + this->buildtimestamp = std::move(_buildtimestamp); } - void setDescription(const std::string &_description) { - this->description = _description; + void setDescription(std::string _description) { + this->description = std::move(_description); } void setSize(size_t _size) { this->size = _size; } - void setStorageId(const std::string &_storageId) { - this->storageId = _storageId; + void setStorageId(std::string _storageId) { + this->storageId = std::move(_storageId); } std::string name; @@ -102,7 +102,5 @@ private: friend class PluginMetaInformationFactory; - friend class PluginContainerPersistence; - friend class PluginContainer; }; diff --git a/source/plugin/PluginMetaInformationFactory.cpp b/source/plugin/PluginMetaInformationFactory.cpp index acba5f9..054431e 100644 --- a/source/plugin/PluginMetaInformationFactory.cpp +++ b/source/plugin/PluginMetaInformationFactory.cpp @@ -16,27 +16,25 @@ ****************************************************************************/ #include "PluginMetaInformationFactory.h" -#include "../fs/FSUtils.h" -#include "../utils/StringTools.h" +#include "elfio/elfio.hpp" +#include "fs/FSUtils.h" #include -using namespace ELFIO; - -std::optional> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr &pluginData) { - if (pluginData->buffer == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr"); - return std::nullopt; +std::optional> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr &pluginData) { + if (!pluginData->buffer) { + DEBUG_FUNCTION_LINE_ERR("Buffer is empty"); + return {}; } - elfio reader; - if (!reader.load((char *) pluginData->buffer, pluginData->length)) { + ELFIO::elfio reader; + if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); return {}; } return loadPlugin(reader); } -std::optional> PluginMetaInformationFactory::loadPlugin(std::string &filePath) { - elfio reader; +std::optional> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) { + ELFIO::elfio reader; uint8_t *buffer = nullptr; uint32_t length = 0; @@ -54,8 +52,8 @@ std::optional> PluginMetaInformationFacto return res; } -std::optional> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) { - elfio reader; +std::optional> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) { + ELFIO::elfio reader; if (!reader.load(buffer, size)) { DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file"); return std::nullopt; @@ -64,15 +62,15 @@ std::optional> PluginMetaInformationFacto return loadPlugin(reader); } -std::optional> PluginMetaInformationFactory::loadPlugin(const elfio &reader) { +std::optional> PluginMetaInformationFactory::loadPlugin(const ELFIO::elfio &reader) { size_t pluginSize = 0; - auto pluginInfo = std::shared_ptr(new PluginMetaInformation); + auto pluginInfo = std::unique_ptr(new PluginMetaInformation); uint32_t sec_num = reader.sections.size(); for (uint32_t i = 0; i < sec_num; ++i) { - section *psec = reader.sections[i]; + ELFIO::section *psec = reader.sections[i]; // Calculate total size: if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) { @@ -118,7 +116,7 @@ std::optional> PluginMetaInformationFacto } else if (key == "storage_id") { pluginInfo->setStorageId(value); } else if (key == "wups") { - if (value != "0.7.0") { + if (value != "0.7.1") { DEBUG_FUNCTION_LINE_ERR("Warning: Ignoring plugin - Unsupported WUPS version: %s.", value.c_str()); return std::nullopt; } diff --git a/source/plugin/PluginMetaInformationFactory.h b/source/plugin/PluginMetaInformationFactory.h index 22d3adf..f0e6ae7 100644 --- a/source/plugin/PluginMetaInformationFactory.h +++ b/source/plugin/PluginMetaInformationFactory.h @@ -19,6 +19,7 @@ #include "PluginData.h" #include "PluginMetaInformation.h" +#include "elfio/elfio.hpp" #include #include #include @@ -26,11 +27,11 @@ class PluginMetaInformationFactory { public: - static std::optional> loadPlugin(const std::shared_ptr &pluginData); + static std::optional> loadPlugin(const std::shared_ptr &pluginData); - static std::optional> loadPlugin(std::string &filePath); + static std::optional> loadPlugin(const std::string &filePath); - static std::optional> loadPlugin(char *buffer, size_t size); + static std::optional> loadPlugin(char *buffer, size_t size); - static std::optional> loadPlugin(const elfio &reader); + static std::optional> loadPlugin(const ELFIO::elfio &reader); }; diff --git a/source/plugin/RelocationData.h b/source/plugin/RelocationData.h index c283658..89963f0 100644 --- a/source/plugin/RelocationData.h +++ b/source/plugin/RelocationData.h @@ -25,12 +25,12 @@ class RelocationData { public: - RelocationData(const char type, size_t offset, int32_t addend, void *destination, std::string &name, std::shared_ptr rplInfo) : type(type), - offset(offset), - addend(addend), - destination(destination), - name(name), - rplInfo(std::move(rplInfo)) { + RelocationData(const char type, size_t offset, int32_t addend, void *destination, std::string name, std::shared_ptr rplInfo) : type(type), + offset(offset), + addend(addend), + destination(destination), + name(std::move(name)), + rplInfo(std::move(rplInfo)) { } RelocationData(const RelocationData &o2) = default; diff --git a/source/plugin/SectionInfo.h b/source/plugin/SectionInfo.h index e837f94..87d1007 100644 --- a/source/plugin/SectionInfo.h +++ b/source/plugin/SectionInfo.h @@ -22,18 +22,11 @@ class SectionInfo { public: - SectionInfo(std::string &name, uint32_t address, uint32_t sectionSize) : name(name), - address(address), - sectionSize(sectionSize) { + SectionInfo(std::string name, uint32_t address, uint32_t sectionSize) : name(std::move(name)), + address(address), + sectionSize(sectionSize) { } - SectionInfo() = default; - - SectionInfo(const SectionInfo &o2) = default; - - - virtual ~SectionInfo() = default; - [[nodiscard]] const std::string &getName() const { return name; } @@ -46,6 +39,10 @@ public: return sectionSize; } + [[nodiscard]] uint32_t isInSection(uint32_t addr) const { + return addr >= address && addr < address + sectionSize; + } + private: std::string name; uint32_t address{}; diff --git a/source/utils/ConfigUtils.cpp b/source/utils/ConfigUtils.cpp index ec0af04..f3a7c4c 100644 --- a/source/utils/ConfigUtils.cpp +++ b/source/utils/ConfigUtils.cpp @@ -3,6 +3,7 @@ #include "../config/WUPSConfig.h" #include "../globals.h" #include "DrawUtils.h" +#include "hooks.h" #include "logger.h" #include @@ -118,24 +119,20 @@ static uint32_t remapClassicButtons(uint32_t buttons) { void ConfigUtils::displayMenu() { std::vector configs; - for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin_data = &gPluginInformation->plugin_data[plugin_index]; - if (plugin_data == nullptr) { - continue; - } + for (auto &plugin : gLoadedPlugins) { ConfigDisplayItem cfg; - cfg.name = std::string(plugin_data->meta.name); - cfg.author = std::string(plugin_data->meta.author); - cfg.version = std::string(plugin_data->meta.version); + cfg.name = plugin->metaInformation->getName(); + cfg.author = plugin->metaInformation->getAuthor(); + cfg.version = plugin->metaInformation->getVersion(); cfg.enabled = true; - for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) { - replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j]; - if (hook_data->type == WUPS_LOADER_HOOK_GET_CONFIG /*WUPS_LOADER_HOOK_GET_CONFIG*/) { - if (hook_data->func_pointer == nullptr) { + for (auto &hook : plugin->getPluginInformation()->getHookDataList()) { + + if (hook->getType() == WUPS_LOADER_HOOK_GET_CONFIG /*WUPS_LOADER_HOOK_GET_CONFIG*/) { + if (hook->getFunctionPointer() == nullptr) { break; } - auto *cur_config = reinterpret_cast(((WUPSConfigHandle(*)())((uint32_t *) hook_data->func_pointer))()); + auto *cur_config = reinterpret_cast(((WUPSConfigHandle(*)())((uint32_t *) hook->getFunctionPointer()))()); if (cur_config == nullptr) { break; } @@ -509,8 +506,7 @@ void ConfigUtils::displayMenu() { DrawUtils::setFontColor(COLOR_TEXT); - std::string headline; - StringTools::strprintf(headline, "%s - %s", currentConfig->config->getName().c_str(), currentCategory->getName().c_str()); + auto headline = string_format("%s - %s", currentConfig->config->getName().c_str(), currentCategory->getName().c_str()); // draw top bar DrawUtils::setFontSize(24); DrawUtils::print(16, 6 + 24, headline.c_str()); @@ -553,25 +549,7 @@ void ConfigUtils::displayMenu() { } } - for (int32_t plugin_index = 0; plugin_index < gPluginInformation->number_used_plugins; plugin_index++) { - plugin_information_single_t *plugin_data = &gPluginInformation->plugin_data[plugin_index]; - if (plugin_data == nullptr) { - continue; - } - - for (uint32_t j = 0; j < plugin_data->info.number_used_hooks; j++) { - replacement_data_hook_t *hook_data = &plugin_data->info.hooks[j]; - if (hook_data->type == WUPS_LOADER_HOOK_CONFIG_CLOSED) { - if (hook_data->func_pointer == nullptr) { - break; - } - // clang-format off - ((void(*)())((uint32_t *) hook_data->func_pointer))(); - // clang-format on - break; - } - } - } + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_CONFIG_CLOSED); for (const auto &element : configs) { DEBUG_FUNCTION_LINE("Delete %08X", element.config); @@ -594,15 +572,15 @@ void ConfigUtils::openConfigMenu() { if (!screenbuffer0 || !screenbuffer1) { if (screenbuffer0 == nullptr) { - if (storedTVBuffer.buffer_size >= screen_buf0_size) { - screenbuffer0 = storedTVBuffer.buffer; + if (gStoredTVBuffer.buffer_size >= screen_buf0_size) { + screenbuffer0 = gStoredTVBuffer.buffer; skipScreen0Free = true; DEBUG_FUNCTION_LINE_VERBOSE("Use storedTVBuffer"); } } if (screenbuffer1 == nullptr) { - if (storedDRCBuffer.buffer_size >= screen_buf1_size) { - screenbuffer1 = storedDRCBuffer.buffer; + if (gStoredDRCBuffer.buffer_size >= screen_buf1_size) { + screenbuffer1 = gStoredDRCBuffer.buffer; skipScreen1Free = true; DEBUG_FUNCTION_LINE_VERBOSE("Use storedDRCBuffer"); } @@ -641,14 +619,14 @@ void ConfigUtils::openConfigMenu() { error_exit: - if (storedTVBuffer.buffer != nullptr) { - GX2SetTVBuffer(storedTVBuffer.buffer, storedTVBuffer.buffer_size, static_cast(storedTVBuffer.mode), - storedTVBuffer.surface_format, storedTVBuffer.buffering_mode); + if (gStoredTVBuffer.buffer != nullptr) { + GX2SetTVBuffer(gStoredTVBuffer.buffer, gStoredTVBuffer.buffer_size, static_cast(gStoredTVBuffer.mode), + gStoredTVBuffer.surface_format, gStoredTVBuffer.buffering_mode); } - if (storedDRCBuffer.buffer != nullptr) { - GX2SetDRCBuffer(storedDRCBuffer.buffer, storedDRCBuffer.buffer_size, static_cast(storedDRCBuffer.mode), - storedDRCBuffer.surface_format, storedDRCBuffer.buffering_mode); + if (gStoredDRCBuffer.buffer != nullptr) { + GX2SetDRCBuffer(gStoredDRCBuffer.buffer, gStoredDRCBuffer.buffer_size, static_cast(gStoredDRCBuffer.mode), + gStoredDRCBuffer.surface_format, gStoredDRCBuffer.buffering_mode); } if (!skipScreen0Free && screenbuffer0) { MEMFreeToMappedMemory(screenbuffer0); diff --git a/source/utils/StringTools.cpp b/source/utils/StringTools.cpp index b8a3dec..3fa643a 100644 --- a/source/utils/StringTools.cpp +++ b/source/utils/StringTools.cpp @@ -1,157 +1,35 @@ /*************************************************************************** - * Copyright (C) 2010 - * by Dimok - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any - * damages arising from the use of this software. - * - * Permission is granted to anyone to use this software for any - * purpose, including commercial applications, and to alter it and - * redistribute it freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you - * must not claim that you wrote the original software. If you use - * this software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and - * must not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - * for WiiXplorer 2010 - ***************************************************************************/ -#include -#include -#include -#include +* Copyright (C) 2010 +* by Dimok +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any +* damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any +* purpose, including commercial applications, and to alter it and +* redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you +* must not claim that you wrote the original software. If you use +* this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and +* must not be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +* +* for WiiXplorer 2010 +***************************************************************************/ + +#include #include +#include #include -#include #include - -BOOL StringTools::EndsWith(const std::string &a, const std::string &b) { - if (b.size() > a.size()) - return false; - return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin()); -} - -const char *StringTools::byte_to_binary(int32_t x) { - static char b[9]; - b[0] = '\0'; - - int32_t z; - for (z = 128; z > 0; z >>= 1) { - strcat(b, ((x & z) == z) ? "1" : "0"); - } - - return b; -} - -std::string StringTools::removeCharFromString(std::string &input, char toBeRemoved) { - std::string output = input; - size_t position; - while (1) { - position = output.find(toBeRemoved); - if (position == std::string::npos) - break; - output.erase(position, 1); - } - return output; -} - -const char *StringTools::fmt(const char *format, ...) { - static char strChar[512]; - strChar[0] = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(strChar, format, va) >= 0)) { - va_end(va); - return (const char *) strChar; - } - va_end(va); - - return nullptr; -} - -const wchar_t *StringTools::wfmt(const char *format, ...) { - static char tmp[512]; - static wchar_t strWChar[512]; - strWChar[0] = 0; - tmp[0] = 0; - - if (!format) - return (const wchar_t *) strWChar; - - if (strcmp(format, "") == 0) - return (const wchar_t *) strWChar; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - int bt; - int32_t strlength = strlen(tmp); - bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512); - - if (bt > 0) { - strWChar[bt] = 0; - return (const wchar_t *) strWChar; - } - } - va_end(va); - - return nullptr; -} - -int32_t StringTools::strprintf(std::string &str, const char *format, ...) { - static char tmp[512]; - tmp[0] = 0; - int32_t result = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - str = tmp; - result = str.size(); - } - va_end(va); - - return result; -} - -std::string StringTools::strfmt(const char *format, ...) { - std::string str; - static char tmp[512]; - tmp[0] = 0; - - va_list va; - va_start(va, format); - if ((vsprintf(tmp, format, va) >= 0)) { - str = tmp; - } - va_end(va); - - return str; -} - -BOOL StringTools::char2wchar_t(const char *strChar, wchar_t *dest) { - if (!strChar || !dest) - return false; - - int bt; - bt = mbstowcs(dest, strChar, strlen(strChar)); - if (bt > 0) { - dest[bt] = 0; - return true; - } - - return false; -} - int32_t StringTools::strtokcmp(const char *string, const char *compare, const char *separator) { if (!string || !compare) return -1; @@ -171,38 +49,3 @@ int32_t StringTools::strtokcmp(const char *string, const char *compare, const ch return -1; } - -int32_t StringTools::strextcmp(const char *string, const char *extension, char seperator) { - if (!string || !extension) - return -1; - - char *ptr = strrchr(string, seperator); - if (!ptr) - return -1; - - return strcasecmp(ptr + 1, extension); -} - - -std::vector StringTools::stringSplit(const std::string &inValue, const std::string &splitter) { - std::string value = inValue; - std::vector result; - while (true) { - uint32_t index = value.find(splitter); - if (index == std::string::npos) { - result.push_back(value); - break; - } - std::string first = value.substr(0, index); - result.push_back(first); - if (index + splitter.size() == value.length()) { - result.push_back(""); - break; - } - if (index + splitter.size() > value.length()) { - break; - } - value = value.substr(index + splitter.size(), value.length()); - } - return result; -} diff --git a/source/utils/StringTools.h b/source/utils/StringTools.h index 1a30df9..c64de2c 100644 --- a/source/utils/StringTools.h +++ b/source/utils/StringTools.h @@ -23,34 +23,35 @@ * * for WiiXplorer 2010 ***************************************************************************/ -#ifndef __STRING_TOOLS_H -#define __STRING_TOOLS_H +#pragma once +#include "logger.h" +#include "utils.h" +#include +#include #include #include #include +template +std::string string_format(const std::string &format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' + auto size = static_cast(size_s); + auto buf = make_unique_nothrow(size); + if (!buf) { + DEBUG_FUNCTION_LINE_ERR("string_format failed, not enough memory"); + OSFatal("string_format failed, not enough memory"); + return std::string(""); + } + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside +} + + class StringTools { public: - static BOOL EndsWith(const std::string &a, const std::string &b); - - static const char *byte_to_binary(int32_t x); - - static std::string removeCharFromString(std::string &input, char toBeRemoved); - - static const char *fmt(const char *format, ...); - - static const wchar_t *wfmt(const char *format, ...); - - static int32_t strprintf(std::string &str, const char *format, ...); - - static std::string strfmt(const char *format, ...); - - static BOOL char2wchar_t(const char *src, wchar_t *dest); - static int32_t strtokcmp(const char *string, const char *compare, const char *separator); - static int32_t strextcmp(const char *string, const char *extension, char seperator); static const char *FullpathToFilename(const char *path) { if (!path) @@ -81,8 +82,4 @@ public: } } } - - static std::vector stringSplit(const std::string &value, const std::string &splitter); -}; - -#endif /* __STRING_TOOLS_H */ +}; \ No newline at end of file diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp index ba295f2..c4212f7 100644 --- a/source/utils/exports.cpp +++ b/source/utils/exports.cpp @@ -1,15 +1,12 @@ #include "exports.h" #include "../PluginManagement.h" #include "../globals.h" -#include "../plugin/PluginContainer.h" -#include "../plugin/PluginContainerPersistence.h" #include "../plugin/PluginDataFactory.h" -#include "../plugin/PluginDataPersistence.h" #include "../plugin/PluginMetaInformationFactory.h" -#include +#include "utils.h" #include -static void fillPluginInformation(plugin_information *out, const std::shared_ptr &metaInformation) { +static void fillPluginInformation(plugin_information *out, const std::unique_ptr &metaInformation) { out->plugin_information_version = PLUGIN_INFORMATION_VERSION; strncpy(out->author, metaInformation->getAuthor().c_str(), sizeof(out->author) - 1); strncpy(out->buildTimestamp, metaInformation->getBuildTimestamp().c_str(), sizeof(out->buildTimestamp) - 1); @@ -22,56 +19,55 @@ static void fillPluginInformation(plugin_information *out, const std::shared_ptr } extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) { - gLinkOnReload.number_used_plugins = 0; - if (plugin_data_handle_list != nullptr && plugin_data_handle_list_size != 0) { - for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) { - plugin_data_handle handle = plugin_data_handle_list[i]; - auto *pluginData = (PluginData *) handle; - PluginDataPersistence::save(&gLinkOnReload.plugin_data[gLinkOnReload.number_used_plugins], pluginData); + if (plugin_data_handle_list == nullptr || plugin_data_handle_list_size == 0) { - gLinkOnReload.number_used_plugins++; - } - if (gLinkOnReload.number_used_plugins > 0) { - gLinkOnReload.loadOnReload = true; - } - DCFlushRange(&gLinkOnReload, sizeof(gLinkOnReload)); - } else { - DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } - return PLUGIN_BACKEND_API_ERROR_NONE; -} + std::lock_guard lock(gLoadedDataMutex); + for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) { + auto handle = plugin_data_handle_list[i]; + bool found = false; -extern "C" PluginBackendApiErrorType WUPSDeletePluginContainer(const plugin_container_handle *handle_list, uint32_t handle_list_size) { - if (handle_list != nullptr && handle_list_size != 0) { - for (uint32_t i = 0; i < handle_list_size; i++) { - auto handle = handle_list[i]; - auto *pluginContainer = (PluginContainer *) handle; - delete pluginContainer; + for (auto &pluginData : gLoadedData) { + if (pluginData->getHandle() == handle) { + gLoadOnNextLaunch.push_front(pluginData); + found = true; + break; + } + } + if (!found) { + DEBUG_FUNCTION_LINE_ERR("Failed to get plugin data for handle %08X. Skipping it.", handle); } } + return PLUGIN_BACKEND_API_ERROR_NONE; } extern "C" PluginBackendApiErrorType WUPSDeletePluginData(const plugin_data_handle *plugin_data_handle_list, uint32_t plugin_data_handle_list_size) { if (plugin_data_handle_list != nullptr && plugin_data_handle_list_size != 0) { for (uint32_t i = 0; i < plugin_data_handle_list_size; i++) { - auto handle = plugin_data_handle_list[i]; - auto *pluginData = (PluginData *) handle; - delete pluginData; + auto handle = plugin_data_handle_list[i]; + + if (!remove_locked_first_if(gLoadedDataMutex, gLoadedData, [handle](auto &cur) { return cur->getHandle() == handle; })) { + DEBUG_FUNCTION_LINE_ERR("Failed to delete plugin data by handle %08X", handle); + } } } return PLUGIN_BACKEND_API_ERROR_NONE; } extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out) { - std::optional> pluginData; + if (out == nullptr) { + return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; + } + + std::optional> pluginData; if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) { - pluginData = PluginDataFactory::load(path, gPluginDataHeap); + pluginData = PluginDataFactory::load(path); } else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != nullptr && size > 0) { std::vector data(size); memcpy(&data[0], buffer, size); - pluginData = PluginDataFactory::load(data, gPluginDataHeap); + pluginData = PluginDataFactory::load(data); } else { return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } @@ -81,12 +77,9 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationIn return PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC; } - if (out == nullptr) { - DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); - return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; - } else { - auto *pluginDataHandle = new PluginData(*pluginData.value()); - *out = (uint32_t) pluginDataHandle; + else { + *out = pluginData.value()->getHandle(); + gLoadedData.push_front(std::move(pluginData.value())); } return PLUGIN_BACKEND_API_ERROR_NONE; @@ -101,7 +94,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsDataByBuffer(plugin_data_ha } extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_information *output) { - std::optional> pluginInfo; + std::optional> pluginInfo; if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) { std::string pathStr(path); pluginInfo = PluginMetaInformationFactory::loadPlugin(pathStr); @@ -136,17 +129,29 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformationByBuffer(plugin extern "C" PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const plugin_container_handle *plugin_container_handle_list, plugin_data_handle *plugin_data_list, uint32_t buffer_size) { PluginBackendApiErrorType res = PLUGIN_BACKEND_API_ERROR_NONE; - if (plugin_container_handle_list != nullptr && buffer_size != 0) { - for (uint32_t i = 0; i < buffer_size; i++) { - auto handle = plugin_container_handle_list[i]; - auto *container = (PluginContainer *) handle; - auto *pluginData = new PluginData(*container->getPluginData()); - plugin_data_list[i] = (uint32_t) pluginData; - } - } else { - DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); - res = PLUGIN_BACKEND_API_ERROR_INVALID_ARG; + if (plugin_container_handle_list == nullptr || buffer_size == 0) { + return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } + + std::lock_guard lock(gLoadedDataMutex); + for (uint32_t i = 0; i < buffer_size; /* only increase on success*/) { + auto handle = plugin_container_handle_list[i]; + bool found = false; + for (auto &curContainer : gLoadedPlugins) { + if (curContainer->getHandle() == handle) { + auto &pluginData = curContainer->getPluginData(); + plugin_data_list[i] = (uint32_t) pluginData->getHandle(); + gLoadedData.push_front(pluginData); + found = true; + i++; + break; + } + } + if (!found) { + DEBUG_FUNCTION_LINE_ERR("Failed to get container for handle %08X", handle); + } + } + return res; } @@ -154,18 +159,29 @@ extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_contain PluginBackendApiErrorType res = PLUGIN_BACKEND_API_ERROR_NONE; if (plugin_container_handle_list != nullptr && buffer_size != 0) { for (uint32_t i = 0; i < buffer_size; i++) { - auto handle = plugin_container_handle_list[i]; - auto *container = (PluginContainer *) handle; + auto handle = plugin_container_handle_list[i]; + bool found = false; + for (auto &curContainer : gLoadedPlugins) { + if (curContainer->getHandle() == handle) { + auto &metaInfo = curContainer->getMetaInformation(); - plugin_information_list[i].plugin_information_version = PLUGIN_INFORMATION_VERSION; - strncpy(plugin_information_list[i].storageId, container->metaInformation->getStorageId().c_str(), sizeof(plugin_information_list[i].storageId) - 1); - strncpy(plugin_information_list[i].author, container->metaInformation->getAuthor().c_str(), sizeof(plugin_information_list[i].author) - 1); - strncpy(plugin_information_list[i].buildTimestamp, container->metaInformation->getBuildTimestamp().c_str(), sizeof(plugin_information_list[i].buildTimestamp) - 1); - strncpy(plugin_information_list[i].description, container->metaInformation->getDescription().c_str(), sizeof(plugin_information_list[i].description) - 1); - strncpy(plugin_information_list[i].name, container->metaInformation->getName().c_str(), sizeof(plugin_information_list[i].name) - 1); - strncpy(plugin_information_list[i].license, container->metaInformation->getLicense().c_str(), sizeof(plugin_information_list[i].license) - 1); - strncpy(plugin_information_list[i].version, container->metaInformation->getVersion().c_str(), sizeof(plugin_information_list[i].version) - 1); - plugin_information_list[i].size = container->metaInformation->getSize(); + plugin_information_list[i].plugin_information_version = PLUGIN_INFORMATION_VERSION; + strncpy(plugin_information_list[i].storageId, metaInfo->getStorageId().c_str(), sizeof(plugin_information_list[i].storageId) - 1); + strncpy(plugin_information_list[i].author, metaInfo->getAuthor().c_str(), sizeof(plugin_information_list[i].author) - 1); + strncpy(plugin_information_list[i].buildTimestamp, metaInfo->getBuildTimestamp().c_str(), sizeof(plugin_information_list[i].buildTimestamp) - 1); + strncpy(plugin_information_list[i].description, metaInfo->getDescription().c_str(), sizeof(plugin_information_list[i].description) - 1); + strncpy(plugin_information_list[i].name, metaInfo->getName().c_str(), sizeof(plugin_information_list[i].name) - 1); + strncpy(plugin_information_list[i].license, metaInfo->getLicense().c_str(), sizeof(plugin_information_list[i].license) - 1); + strncpy(plugin_information_list[i].version, metaInfo->getVersion().c_str(), sizeof(plugin_information_list[i].version) - 1); + plugin_information_list[i].size = metaInfo->getSize(); + found = true; + + break; + } + } + if (!found) { + DEBUG_FUNCTION_LINE_ERR("FAILED TO FIND CONTAINER FOR HANDLE %08X", handle); + } } } else { DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); @@ -175,17 +191,15 @@ extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_contain } extern "C" PluginBackendApiErrorType WUPSGetLoadedPlugins(plugin_container_handle *io_handles, uint32_t buffer_size, uint32_t *outSize, uint32_t *plugin_information_version) { - DEBUG_FUNCTION_LINE(); if (plugin_information_version == nullptr) { return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } *plugin_information_version = PLUGIN_INFORMATION_VERSION; - auto plugins = PluginContainerPersistence::loadPlugins(gPluginInformation); + auto &plugins = gLoadedPlugins; uint32_t counter = 0; for (auto &plugin : plugins) { if (counter < buffer_size) { - auto *container = new PluginContainer(*plugin); - io_handles[counter] = (uint32_t) container; + io_handles[counter] = plugin->getHandle(); counter++; } else { break; @@ -201,7 +215,6 @@ WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByPath); WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsDataByBuffer); WUMS_EXPORT_FUNCTION(WUPSLoadPluginAsData); WUMS_EXPORT_FUNCTION(WUPSLoadAndLinkByDataHandle); -WUMS_EXPORT_FUNCTION(WUPSDeletePluginContainer); WUMS_EXPORT_FUNCTION(WUPSDeletePluginData); WUMS_EXPORT_FUNCTION(WUPSGetPluginMetaInformation); WUMS_EXPORT_FUNCTION(WUPSGetPluginMetaInformationByPath); diff --git a/source/utils/utils.cpp b/source/utils/utils.cpp index 409d3e6..33e87fd 100644 --- a/source/utils/utils.cpp +++ b/source/utils/utils.cpp @@ -17,7 +17,7 @@ std::string getPluginPath() { IOS_Close(handle); } - return std::string(environmentPath) + "/plugins"; + return std::string(environmentPath).append("/plugins"); } // https://gist.github.com/ccbrown/9722406 diff --git a/source/utils/utils.h b/source/utils/utils.h index 1fab308..f78b150 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -1,7 +1,10 @@ #pragma once +#include +#include #include -#include +#include +#include #ifdef __cplusplus extern "C" { @@ -41,4 +44,33 @@ void dumpHex(const void *data, size_t size); } #endif +template +std::unique_ptr make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::unique_ptr(new (std::nothrow) T(std::forward(args)...)); +} + +template +inline typename std::_MakeUniq::__array make_unique_nothrow(size_t num) noexcept { + return std::unique_ptr(new (std::nothrow) std::remove_extent_t[num]()); +} + +template +std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::shared_ptr(new (std::nothrow) T(std::forward(args)...)); +} + +template +bool remove_locked_first_if(std::mutex &mutex, std::forward_list &list, Predicate pred) { + std::lock_guard lock(mutex); + auto oit = list.before_begin(), it = std::next(oit); + while (it != list.end()) { + if (pred(*it)) { + list.erase_after(oit); + return true; + } + oit = it++; + } + return false; +} + std::string getPluginPath(); \ No newline at end of file