diff --git a/source/NotificationsUtils.cpp b/source/NotificationsUtils.cpp index 1d3ede3..c7270d0 100644 --- a/source/NotificationsUtils.cpp +++ b/source/NotificationsUtils.cpp @@ -57,7 +57,7 @@ void NotificationMainLoop() { } } -bool DisplayNotificationMessage(std::string &text, NotificationModuleNotificationType type, float duration) { +bool DisplayNotificationMessage(std::string_view text, NotificationModuleNotificationType type, float duration) { if (!gNotificationModuleLoaded) { return false; } @@ -68,7 +68,7 @@ bool DisplayNotificationMessage(std::string &text, NotificationModuleNotificatio if (!param) { return false; } - strncpy(param->text, text.c_str(), sizeof(param->text) - 1); + strncpy(param->text, text.data(), sizeof(param->text) - 1); param->type = type; param->duration = duration; @@ -84,11 +84,11 @@ bool DisplayNotificationMessage(std::string &text, NotificationModuleNotificatio return true; } -bool DisplayInfoNotificationMessage(std::string &text, float duration) { +bool DisplayInfoNotificationMessage(std::string_view text, float duration) { return DisplayNotificationMessage(text, NOTIFICATION_MODULE_NOTIFICATION_TYPE_INFO, duration); } -bool DisplayErrorNotificationMessage(std::string &text, float duration) { +bool DisplayErrorNotificationMessage(std::string_view text, float duration) { return DisplayNotificationMessage(text, NOTIFICATION_MODULE_NOTIFICATION_TYPE_ERROR, duration); } @@ -101,7 +101,7 @@ void StartNotificationThread() { constexpr int32_t messageSize = sizeof(sNotificationMessages) / sizeof(sNotificationMessages[0]); OSInitMessageQueue(&sNotificationQueue, sNotificationMessages, messageSize); - sNotificationsThread = std::make_unique(NotificationMainLoop); + sNotificationsThread = make_unique_nothrow(NotificationMainLoop); } void StopNotificationThread() { diff --git a/source/NotificationsUtils.h b/source/NotificationsUtils.h index 8950ece..9cec7de 100644 --- a/source/NotificationsUtils.h +++ b/source/NotificationsUtils.h @@ -6,6 +6,6 @@ void StartNotificationThread(); void StopNotificationThread(); -bool DisplayInfoNotificationMessage(std::string &text, float duration); +bool DisplayInfoNotificationMessage(std::string_view text, float duration); -bool DisplayErrorNotificationMessage(std::string &text, float duration); \ No newline at end of file +bool DisplayErrorNotificationMessage(std::string_view text, float duration); \ No newline at end of file diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index 262d6c1..402957d 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -1,7 +1,6 @@ #include "PluginManagement.h" #include "NotificationsUtils.h" #include "hooks.h" -#include "patcher/hooks_patcher_static.h" #include "plugin/PluginContainer.h" #include "plugin/PluginInformationFactory.h" #include "plugin/PluginMetaInformationFactory.h" @@ -10,19 +9,58 @@ #include "utils/utils.h" #include #include -#include #include #include -#include + +std::vector> +PluginManagement::loadPlugins(const std::set> &pluginDataList, std::vector &trampolineData) { + std::vector> plugins; + + uint32_t trampolineID = 0; + for (const auto &pluginData : pluginDataList) { + PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN; + + auto metaInfo = PluginMetaInformationFactory::loadPlugin(*pluginData, error); + if (metaInfo && error == PLUGIN_PARSE_ERROR_NONE) { + auto info = PluginInformationFactory::load(*pluginData, trampolineData, trampolineID++); + if (!info) { + auto errMsg = string_format("Failed to load plugin: %s", metaInfo->getName().c_str()); + DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); + DisplayErrorNotificationMessage(errMsg, 15.0f); + continue; + } + std::string nameCpy = metaInfo->getName(); + auto container = make_unique_nothrow(std::move(metaInfo), std::move(info), pluginData); + if (!container) { + DEBUG_FUNCTION_LINE_ERR("Failed to create PluginContainer, skipping %s", nameCpy.c_str()); + continue; + } + plugins.push_back(std::move(container)); + } else { + auto errMsg = string_format("Failed to load plugin: %s", pluginData->getSource().c_str()); + if (error == PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION) { + errMsg += ". Incompatible version."; + } + DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); + DisplayErrorNotificationMessage(errMsg, 15.0f); + } + } + + if (!PluginManagement::DoFunctionPatches(plugins)) { + DEBUG_FUNCTION_LINE_ERR("Failed to patch functions"); + OSFatal("Failed to patch functions"); + } + + return plugins; +} bool PluginManagement::doRelocation(const std::vector> &relocData, - relocation_trampoline_entry_t *tramp_data, - uint32_t tramp_length, + std::vector &trampData, uint32_t trampolineID, std::map &usedRPls) { for (auto const &cur : relocData) { - uint32_t functionAddress = 0; - const std::string &functionName = cur->getName(); + uint32_t functionAddress = 0; + auto &functionName = cur->getName(); if (functionName == "MEMAllocFromDefaultHeap") { OSDynLoad_Module rplHandle; @@ -39,8 +77,8 @@ bool PluginManagement::doRelocation(const std::vectorgetImportRPLInformation()->getRPLName(); - int32_t isData = cur->getImportRPLInformation()->isData(); + auto rplName = cur->getImportRPLInformation().getRPLName(); + int32_t isData = cur->getImportRPLInformation().isData(); OSDynLoad_Module rplHandle = nullptr; if (!usedRPls.contains(rplName)) { @@ -68,7 +106,7 @@ bool PluginManagement::doRelocation(const std::vectorgetType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT, trampolineID)) { + if (!ElfUtils::elfLinkOne(cur->getType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, trampData, RELOC_TYPE_IMPORT, trampolineID)) { DEBUG_FUNCTION_LINE_ERR("elfLinkOne failed"); return false; } @@ -83,18 +121,18 @@ bool PluginManagement::doRelocation(const std::vector> &plugins, - relocation_trampoline_entry_t *trampData, uint32_t tramp_size, + std::vector &trampData, std::map &usedRPls) { - for (uint32_t i = 0; i < tramp_size; i++) { - if (trampData[i].status == RELOC_TRAMP_IMPORT_DONE) { - trampData[i].status = RELOC_TRAMP_FREE; + for (auto &cur : trampData) { + if (cur.status == RELOC_TRAMP_IMPORT_DONE) { + cur.status = RELOC_TRAMP_FREE; } } @@ -104,12 +142,11 @@ bool PluginManagement::doRelocations(const std::vectorgetMetaInformation()->getName().c_str()); - if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), + for (const 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(), + pluginContainer->getPluginInformation().getTrampolineId(), usedRPls)) { return false; } @@ -122,7 +159,7 @@ bool PluginManagement::doRelocations(const std::vector> &plugins) { for (const auto &cur : std::ranges::reverse_view(plugins)) { - for (const auto &curFunction : std::ranges::reverse_view(cur->getPluginInformation()->getFunctionDataList())) { + for (const auto &curFunction : std::ranges::reverse_view(cur->getPluginInformation().getFunctionDataList())) { if (!curFunction->RemovePatch()) { return false; } @@ -133,8 +170,9 @@ bool PluginManagement::RestoreFunctionPatches(const std::vector> &plugins) { for (const auto &cur : plugins) { - for (const auto &curFunction : cur->getPluginInformation()->getFunctionDataList()) { + for (const auto &curFunction : cur->getPluginInformation().getFunctionDataList()) { if (!curFunction->AddPatch()) { + DEBUG_FUNCTION_LINE_ERR("Failed to add function patch for: plugin %s", cur->getMetaInformation().getName().c_str()); return false; } } @@ -146,45 +184,4 @@ void PluginManagement::callInitHooks(const 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) { - PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN; - - auto metaInfo = PluginMetaInformationFactory::loadPlugin(pluginData, error); - if (metaInfo && error == PLUGIN_PARSE_ERROR_NONE) { - auto info = PluginInformationFactory::load(pluginData, trampoline_data, trampoline_data_length, trampolineID++); - if (!info) { - auto errMsg = string_format("Failed to load plugin: %s", metaInfo.value()->getName().c_str()); - DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); - DisplayErrorNotificationMessage(errMsg, 15.0f); - 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 { - auto errMsg = string_format("Failed to load plugin: %s", pluginData->mSource.c_str()); - if (error == PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION) { - errMsg += ". Incompatible version."; - } - DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); - DisplayErrorNotificationMessage(errMsg, 15.0f); - } - } - - 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 bca2137..d71d284 100644 --- a/source/PluginManagement.h +++ b/source/PluginManagement.h @@ -2,25 +2,25 @@ #include "plugin/PluginContainer.h" #include -#include #include #include +#include #include class PluginManagement { public: - static std::vector> loadPlugins(const std::forward_list> &pluginList, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length); + static std::vector> loadPlugins( + const std::set> &pluginDataList, + std::vector &trampolineData); static void callInitHooks(const std::vector> &plugins); static bool doRelocations(const std::vector> &plugins, - relocation_trampoline_entry_t *trampData, - uint32_t tramp_size, + std::vector &trampData, std::map &usedRPls); static bool doRelocation(const std::vector> &relocData, - relocation_trampoline_entry_t *tramp_data, - uint32_t tramp_length, + std::vector &trampData, uint32_t trampolineID, std::map &usedRPls); diff --git a/source/config/WUPSConfig.h b/source/config/WUPSConfig.h index 05329a4..ebc6494 100644 --- a/source/config/WUPSConfig.h +++ b/source/config/WUPSConfig.h @@ -26,12 +26,12 @@ class WUPSConfig { public: - explicit WUPSConfig(const std::string &name) { + explicit WUPSConfig(std::string_view name) { this->name = name; } ~WUPSConfig() { - for (auto &element : categories) { + for (const auto &element : categories) { delete element; } } @@ -52,7 +52,7 @@ public: \return On success, the created and inserted category will be returned. **/ - std::optional addCategory(const std::string &categoryName) { + std::optional addCategory(std::string_view categoryName) { auto curCat = new (std::nothrow) WUPSConfigCategory(categoryName); if (curCat == nullptr) { return {}; diff --git a/source/config/WUPSConfigCategory.h b/source/config/WUPSConfigCategory.h index 14fb958..85117da 100644 --- a/source/config/WUPSConfigCategory.h +++ b/source/config/WUPSConfigCategory.h @@ -24,12 +24,12 @@ class WUPSConfigCategory { public: - explicit WUPSConfigCategory(const std::string &name) { + explicit WUPSConfigCategory(std::string_view name) { this->name = name; } ~WUPSConfigCategory() { - for (auto &element : items) { + for (const auto &element : items) { delete element; } } diff --git a/source/config/WUPSConfigItem.h b/source/config/WUPSConfigItem.h index e60ae21..8dadb2f 100644 --- a/source/config/WUPSConfigItem.h +++ b/source/config/WUPSConfigItem.h @@ -30,7 +30,7 @@ public: Sets the display name of this WUPSConfigItem This is the value which will be shown in the configuration menu. **/ - virtual void setDisplayName(const std::string &_displayName) { + virtual void setDisplayName(std::string_view _displayName) { this->displayName = _displayName; } @@ -47,7 +47,7 @@ public: to be unique in the context of this WUPSConfig. Items in different categories are NOT allowed to have the config ID. **/ - virtual void setConfigID(const std::string &_configID) { + virtual void setConfigID(std::string_view _configID) { this->configID = _configID; } @@ -162,7 +162,7 @@ public: return defaultValue != getCurrentValueDisplay(); } - WUPSConfigItem(const std::string &_configID, const std::string &_displayName, WUPSConfigCallbacks_t callbacks, void *_context) { + WUPSConfigItem(std::string_view _configID, std::string_view _displayName, WUPSConfigCallbacks_t callbacks, void *_context) { this->configID = _configID; this->displayName = _displayName; this->context = _context; diff --git a/source/fs/FSUtils.cpp b/source/fs/FSUtils.cpp index e0a5f90..de79899 100644 --- a/source/fs/FSUtils.cpp +++ b/source/fs/FSUtils.cpp @@ -1,26 +1,23 @@ #include "fs/FSUtils.h" -#include "fs/CFile.hpp" #include "utils/logger.h" #include "utils/utils.h" #include #include #include -#include +#include #include +#include -int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) { - //! always initialze input - *inbuffer = NULL; - if (size) { - *size = 0; - } +int32_t FSUtils::LoadFileToMem(std::string_view filepath, std::vector &buffer) { + //! always initialize input + buffer.clear(); - int32_t iFd = open(filepath, O_RDONLY); + int32_t iFd = open(filepath.data(), O_RDONLY); if (iFd < 0) { return -1; } - struct stat file_stat; + struct stat file_stat {}; int rc = fstat(iFd, &file_stat); if (rc < 0) { close(iFd); @@ -28,11 +25,7 @@ int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_ } uint32_t filesize = file_stat.st_size; - auto *buffer = (uint8_t *) memalign(0x40, ROUNDUP(filesize, 0x40)); - if (buffer == nullptr) { - close(iFd); - return -2; - } + buffer.resize(filesize); uint32_t blocksize = 0x80000; uint32_t done = 0; @@ -42,7 +35,7 @@ int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_ if (done + blocksize > filesize) { blocksize = filesize - done; } - readBytes = read(iFd, buffer + done, blocksize); + readBytes = read(iFd, buffer.data() + done, blocksize); if (readBytes <= 0) { break; } @@ -52,99 +45,17 @@ int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_ ::close(iFd); if (done != filesize) { - free(buffer); - buffer = nullptr; + buffer.clear(); return -3; } - *inbuffer = buffer; - - //! sign is optional input - if (size) { - *size = filesize; - } - - return filesize; -} - -int32_t FSUtils::CheckFile(const char *filepath) { - if (!filepath) - return 0; - - struct stat filestat; - - char dirnoslash[strlen(filepath) + 2]; - snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath); - - while (dirnoslash[strlen(dirnoslash) - 1] == '/') - dirnoslash[strlen(dirnoslash) - 1] = '\0'; - - char *notRoot = strrchr(dirnoslash, '/'); - if (!notRoot) { - strcat(dirnoslash, "/"); - } - - if (stat(dirnoslash, &filestat) == 0) - return 1; - return 0; } -int32_t FSUtils::CreateSubfolder(const char *fullpath) { - if (!fullpath) - return 0; - - int32_t result = 0; - - char dirnoslash[strlen(fullpath) + 1]; - strcpy(dirnoslash, fullpath); - - int32_t pos = strlen(dirnoslash) - 1; - while (dirnoslash[pos] == '/') { - dirnoslash[pos] = '\0'; - pos--; +bool FSUtils::CreateSubfolder(std::string_view fullpath) { + std::error_code err; + if (!std::filesystem::create_directories(fullpath, err)) { + return std::filesystem::exists(fullpath, err); } - - if (CheckFile(dirnoslash)) { - return 1; - } else { - char parentpath[strlen(dirnoslash) + 2]; - strcpy(parentpath, dirnoslash); - char *ptr = strrchr(parentpath, '/'); - - if (!ptr) { - //!Device root directory (must be with '/') - strcat(parentpath, "/"); - struct stat filestat; - if (stat(parentpath, &filestat) == 0) - return 1; - - return 0; - } - - ptr++; - ptr[0] = '\0'; - - result = CreateSubfolder(parentpath); - } - - if (!result) - return 0; - - if (mkdir(dirnoslash, 0777) == -1) { - return 0; - } - - return 1; -} - -int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) { - CFile file(path, CFile::WriteOnly); - if (!file.isOpen()) { - DEBUG_FUNCTION_LINE("Failed to open %s\n", path); - return 0; - } - int32_t written = file.write((const uint8_t *) buffer, size); - file.close(); - return written; + return true; } diff --git a/source/fs/FSUtils.h b/source/fs/FSUtils.h index 7899406..698df58 100644 --- a/source/fs/FSUtils.h +++ b/source/fs/FSUtils.h @@ -1,18 +1,12 @@ -#ifndef __FS_UTILS_H_ -#define __FS_UTILS_H_ +#pragma once +#include +#include #include class FSUtils { public: - static int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size); + static int32_t LoadFileToMem(std::string_view filepath, std::vector &buffer); - //! todo: C++ class - static int32_t CreateSubfolder(const char *fullpath); - - static int32_t CheckFile(const char *filepath); - - static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size); + static bool CreateSubfolder(std::string_view fullpath); }; - -#endif // __FS_UTILS_H_ diff --git a/source/globals.cpp b/source/globals.cpp index 709c8be..a0fe619 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -4,10 +4,10 @@ StoredBuffer gStoredTVBuffer __attribute__((section(".data"))) = {}; StoredBuffer gStoredDRCBuffer __attribute__((section(".data"))) = {}; std::vector> gLoadedPlugins __attribute__((section(".data"))); -relocation_trampoline_entry_t *gTrampData __attribute__((section(".data"))) = nullptr; +std::vector gTrampData __attribute__((section(".data"))); -std::forward_list> gLoadedData __attribute__((section(".data"))); -std::forward_list> gLoadOnNextLaunch __attribute__((section(".data"))); +std::set> gLoadedData __attribute__((section(".data"))); +std::set> gLoadOnNextLaunch __attribute__((section(".data"))); std::mutex gLoadedDataMutex __attribute__((section(".data"))); std::map gUsedRPLs __attribute__((section(".data"))); std::vector gAllocatedAddresses __attribute__((section(".data"))); diff --git a/source/globals.h b/source/globals.h index 76adc34..5e8012b 100644 --- a/source/globals.h +++ b/source/globals.h @@ -16,11 +16,11 @@ extern StoredBuffer gStoredTVBuffer; extern StoredBuffer gStoredDRCBuffer; #define TRAMP_DATA_SIZE 1024 -extern relocation_trampoline_entry_t *gTrampData; +extern std::vector gTrampData; extern std::vector> gLoadedPlugins; -extern std::forward_list> gLoadedData; -extern std::forward_list> gLoadOnNextLaunch; +extern std::set> gLoadedData; +extern std::set> gLoadOnNextLaunch; extern std::mutex gLoadedDataMutex; extern std::map gUsedRPLs; extern std::vector gAllocatedAddresses; diff --git a/source/hooks.cpp b/source/hooks.cpp index 5f9e916..6b4508a 100644 --- a/source/hooks.cpp +++ b/source/hooks.cpp @@ -33,15 +33,15 @@ static const char **hook_names = (const char *[]){ 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 (auto &plugin : plugins) { - CallHook(plugin, hook_type); + for (const auto &plugin : plugins) { + CallHook(*plugin, hook_type); } } -void CallHook(const std::unique_ptr &plugin, wups_loader_hook_type_t hook_type) { - for (const auto &hook : plugin->getPluginInformation()->getHookDataList()) { +void CallHook(const PluginContainer &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); + DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s for plugin %s [%d]", hook_names[hook->getType()], plugin.getMetaInformation().getName().c_str(), hook_type); void *func_ptr = hook->getFunctionPointer(); if (func_ptr != nullptr) { switch (hook_type) { @@ -74,7 +74,7 @@ void CallHook(const std::unique_ptr &plugin, wups_loader_hook_t 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(); + 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 diff --git a/source/hooks.h b/source/hooks.h index 6d0a05c..8d426c9 100644 --- a/source/hooks.h +++ b/source/hooks.h @@ -7,4 +7,4 @@ void CallHook(const std::vector> &plugins, 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 +void CallHook(const PluginContainer &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 886d0ed..fabf56a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -26,7 +26,7 @@ WUMS_INITIALIZE() { NotificationModuleStatus res; if ((res = NotificationModule_InitLibrary()) != NOTIFICATION_MODULE_RESULT_SUCCESS) { - DEBUG_FUNCTION_LINE_ERR("Failed to init NotificationModule"); + DEBUG_FUNCTION_LINE_ERR("Failed to init NotificationModule: %s (%d)", NotificationModule_GetStatusStr(res), res); gNotificationModuleLoaded = false; } else { gNotificationModuleLoaded = true; @@ -38,6 +38,7 @@ WUMS_INITIALIZE() { OSFatal("homebrew_wupsbackend: Failed to AddPatch function"); } } + deinitLogging(); } @@ -59,7 +60,7 @@ WUMS_APPLICATION_ENDS() { CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_SOCKETS); CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB); - for (auto &pair : gUsedRPLs) { + for (const auto &pair : gUsedRPLs) { OSDynLoad_Release(pair.second); } gUsedRPLs.clear(); @@ -85,7 +86,7 @@ WUMS_APPLICATION_STARTS() { // If an allocated rpl was not released properly (e.g. if something else calls OSDynload_Acquire without releasing it) memory get leaked. // Let's clean this up! - for (auto &addr : gAllocatedAddresses) { + for (const auto &addr : gAllocatedAddresses) { DEBUG_FUNCTION_LINE_WARN("Memory allocated by OSDynload was not freed properly, let's clean it up! (%08X)", addr); free((void *) addr); } @@ -96,13 +97,11 @@ WUMS_APPLICATION_STARTS() { std::lock_guard lock(gLoadedDataMutex); - 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 (gTrampData.empty()) { + gTrampData = std::vector(TRAMP_DATA_SIZE); + for (auto &cur : gTrampData) { + cur.status = RELOC_TRAMP_FREE; } - memset(gTrampData, 0, sizeof(relocation_trampoline_entry_t) * TRAMP_DATA_SIZE); } if (gLoadedPlugins.empty()) { @@ -111,7 +110,7 @@ WUMS_APPLICATION_STARTS() { DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str()); auto pluginData = PluginDataFactory::loadDir(pluginPath); - gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData, TRAMP_DATA_SIZE); + gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData); initNeeded = true; } @@ -138,10 +137,12 @@ WUMS_APPLICATION_STARTS() { PluginManagement::RestoreFunctionPatches(gLoadedPlugins); DEBUG_FUNCTION_LINE("Unload existing plugins."); gLoadedPlugins.clear(); - memset(gTrampData, 0, sizeof(relocation_trampoline_entry_t) * TRAMP_DATA_SIZE); + for (auto &cur : gTrampData) { + cur.status = RELOC_TRAMP_FREE; + } DEBUG_FUNCTION_LINE("Load new plugins"); - gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData, TRAMP_DATA_SIZE); + gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData); initNeeded = true; } @@ -150,9 +151,9 @@ WUMS_APPLICATION_STARTS() { gLoadedData.clear(); if (!gLoadedPlugins.empty()) { - if (!PluginManagement::doRelocations(gLoadedPlugins, gTrampData, TRAMP_DATA_SIZE, gUsedRPLs)) { + if (!PluginManagement::doRelocations(gLoadedPlugins, gTrampData, gUsedRPLs)) { DEBUG_FUNCTION_LINE_ERR("Relocations failed"); - OSFatal("Relocations failed"); + OSFatal("WiiUPluginLoaderBackend: Relocations failed.\n See crash logs for more information."); } // PluginManagement::memsetBSS(plugins); @@ -179,13 +180,13 @@ WUMS_APPLICATION_STARTS() { void CheckCleanupCallbackUsage(const std::vector> &plugins) { auto *curThread = OSGetCurrentThread(); for (const auto &cur : plugins) { - auto textSection = cur->getPluginInformation()->getSectionInfo(".text"); - if (!textSection.has_value()) { + auto textSection = cur->getPluginInformation().getSectionInfo(".text"); + if (!textSection) { continue; } - uint32_t startAddress = textSection.value()->getAddress(); - uint32_t endAddress = textSection.value()->getAddress() + textSection.value()->getSize(); - auto *pluginName = cur->getMetaInformation()->getName().c_str(); + uint32_t startAddress = textSection->getAddress(); + uint32_t endAddress = textSection->getAddress() + textSection->getSize(); + auto *pluginName = cur->getMetaInformation().getName().c_str(); { __OSLockScheduler(curThread); int state = OSDisableInterrupts(); diff --git a/source/patcher/hooks_patcher_static.cpp b/source/patcher/hooks_patcher_static.cpp index 3b90110..d085947 100644 --- a/source/patcher/hooks_patcher_static.cpp +++ b/source/patcher/hooks_patcher_static.cpp @@ -120,24 +120,20 @@ DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol, uint32_t symbolNameBufferLength, char *moduleNameBuffer, uint32_t moduleNameBufferLength) { - for (auto &plugin : gLoadedPlugins) { - auto sectionInfoOpt = plugin->getPluginInformation()->getSectionInfo(".text"); - if (!sectionInfoOpt) { + for (const auto &plugin : gLoadedPlugins) { + auto sectionInfo = plugin->getPluginInformation().getSectionInfo(".text"); + if (!sectionInfo) { continue; } - 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); + strncpy(moduleNameBuffer, plugin->getMetaInformation().getName().c_str(), moduleNameBufferLength - 1); + auto functionSymbolData = plugin->getPluginInformation().getNearestFunctionSymbolData(addr); + if (functionSymbolData) { + strncpy(symbolNameBuffer, functionSymbolData->getName().c_str(), moduleNameBufferLength - 1); if (outDistance) { *outDistance = addr - (uint32_t) functionSymbolData->getAddress(); } @@ -157,28 +153,25 @@ DECL_FUNCTION(uint32_t, SC17_FindClosestSymbol, } DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t bufSize) { - for (auto &plugin : gLoadedPlugins) { - auto sectionInfoOpt = plugin->getPluginInformation()->getSectionInfo(".text"); - if (!sectionInfoOpt) { + for (const auto &plugin : gLoadedPlugins) { + auto sectionInfo = plugin->getPluginInformation().getSectionInfo(".text"); + if (!sectionInfo) { continue; } - auto §ionInfo = sectionInfoOpt.value(); - if (!sectionInfo->isInSection(addr)) { continue; } - auto pluginNameLen = strlen(plugin->getMetaInformation()->getName().c_str()); + 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->getMetaInformation()->getName().c_str(), bufSize - 1); + strncpy(buffer, plugin->getMetaInformation().getName().c_str(), bufSize - 1); - auto functionSymbolDataOpt = plugin->getPluginInformation()->getNearestFunctionSymbolData(addr); - if (functionSymbolDataOpt) { - auto &functionSymbolData = functionSymbolDataOpt.value(); + auto functionSymbolData = plugin->getPluginInformation().getNearestFunctionSymbolData(addr); + if (functionSymbolData) { buffer[pluginNameLen] = '|'; buffer[pluginNameLen + 1] = '\0'; strncpy(buffer + pluginNameLen + 1, functionSymbolData->getName().c_str(), spaceLeftInBuffer - 1); diff --git a/source/plugin/FunctionData.h b/source/plugin/FunctionData.h index a0a3d79..5d496fb 100644 --- a/source/plugin/FunctionData.h +++ b/source/plugin/FunctionData.h @@ -24,18 +24,23 @@ class FunctionData { public: - FunctionData(void *paddress, void *vaddress, std::string name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall, + FunctionData(void *paddress, void *vaddress, std::string_view name, function_replacement_library_type_t library, void *replaceAddr, void *replaceCall, FunctionPatcherTargetProcess targetProcess) { this->paddress = paddress; this->vaddress = vaddress; - this->name = std::move(name); + this->name = name; this->library = library; this->targetProcess = targetProcess; this->replaceAddr = replaceAddr; this->replaceCall = replaceCall; } - ~FunctionData() = default; + ~FunctionData() { + if (handle != 0) { + DEBUG_FUNCTION_LINE_WARN("Destroying FunctionData while it was still patched. This should never happen."); + RemovePatch(); + } + } [[nodiscard]] const std::string &getName() const { return this->name; @@ -81,7 +86,7 @@ public: }}; if (FunctionPatcher_AddFunctionPatch(&functionData, &handle, nullptr) != FUNCTION_PATCHER_RESULT_SUCCESS) { - DEBUG_FUNCTION_LINE_ERR("Failed to add patch for function"); + DEBUG_FUNCTION_LINE_ERR("Failed to add patch for function (\"%s\" PA:%08X VA:%08X)", this->name.c_str(), this->paddress, this->vaddress); return false; } } else { diff --git a/source/plugin/FunctionSymbolData.h b/source/plugin/FunctionSymbolData.h index 5471461..3b61af6 100644 --- a/source/plugin/FunctionSymbolData.h +++ b/source/plugin/FunctionSymbolData.h @@ -24,31 +24,31 @@ class FunctionSymbolData { public: FunctionSymbolData(const FunctionSymbolData &o2) = default; - FunctionSymbolData(std::string &name, void *address, uint32_t size) : name(name), - address(address), - size(size) { + FunctionSymbolData(std::string_view name, void *address, uint32_t size) : mName(name), + mAddress(address), + mSize(size) { } bool operator<(const FunctionSymbolData &rhs) const { - return (uint32_t) address < (uint32_t) rhs.address; + return (uint32_t) mAddress < (uint32_t) rhs.mAddress; } virtual ~FunctionSymbolData() = default; [[nodiscard]] const std::string &getName() const { - return name; + return mName; } [[nodiscard]] void *getAddress() const { - return address; + return mAddress; } [[nodiscard]] uint32_t getSize() const { - return size; + return mSize; } private: - std::string name; - void *address; - uint32_t size; + std::string mName; + void *mAddress; + uint32_t mSize; }; \ No newline at end of file diff --git a/source/plugin/ImportRPLInformation.h b/source/plugin/ImportRPLInformation.h index ab6e408..e7dc226 100644 --- a/source/plugin/ImportRPLInformation.h +++ b/source/plugin/ImportRPLInformation.h @@ -24,24 +24,24 @@ class ImportRPLInformation { public: - explicit ImportRPLInformation(std::string name) { - this->name = std::move(name); + explicit ImportRPLInformation(std::string_view name) { + this->mName = name; } ~ImportRPLInformation() = default; [[nodiscard]] const std::string &getName() const { - return name; + return mName; } [[nodiscard]] std::string getRPLName() const { - return name.substr(strlen(".dimport_")); + return mName.substr(strlen(".dimport_")); } [[nodiscard]] bool isData() const { - return name.starts_with(".dimport_"); + return mName.starts_with(".dimport_"); } private: - std::string name; + std::string mName; }; diff --git a/source/plugin/PluginContainer.h b/source/plugin/PluginContainer.h index 84a18e8..4945403 100644 --- a/source/plugin/PluginContainer.h +++ b/source/plugin/PluginContainer.h @@ -26,28 +26,29 @@ class PluginContainer { public: 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)) { + : mMetaInformation(std::move(metaInformation)), + mPluginInformation(std::move(pluginInformation)), + mPluginData(std::move(pluginData)) { } - [[nodiscard]] const std::unique_ptr &getMetaInformation() const { - return this->metaInformation; + [[nodiscard]] const PluginMetaInformation &getMetaInformation() const { + return *this->mMetaInformation; } - [[nodiscard]] const std::unique_ptr &getPluginInformation() const { - return pluginInformation; + [[nodiscard]] const PluginInformation &getPluginInformation() const { + return *this->mPluginInformation; } - [[nodiscard]] const std::shared_ptr &getPluginData() const { - return pluginData; + [[nodiscard]] std::shared_ptr getPluginDataCopy() const { + return mPluginData; } uint32_t getHandle() { return (uint32_t) this; } - const std::unique_ptr metaInformation; - const std::unique_ptr pluginInformation; - const std::shared_ptr pluginData; +private: + const std::unique_ptr mMetaInformation; + const std::unique_ptr mPluginInformation; + const std::shared_ptr mPluginData; }; diff --git a/source/plugin/PluginData.cpp b/source/plugin/PluginData.cpp deleted file mode 100644 index 2670d26..0000000 --- a/source/plugin/PluginData.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "PluginData.h" -#include "utils/logger.h" -#include "utils/utils.h" - -PluginData::PluginData(const std::vector &input, std::string source) : length(input.size()), mSource(std::move(source)) { - 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); - } -} diff --git a/source/plugin/PluginData.h b/source/plugin/PluginData.h index 5b3ebae..a181956 100644 --- a/source/plugin/PluginData.h +++ b/source/plugin/PluginData.h @@ -21,17 +21,31 @@ #include #include #include +#include +#include #include class PluginData { public: - explicit PluginData(const std::vector &buffer, std::string source); + explicit PluginData(std::vector &&buffer, std::string_view source) : mBuffer(std::move(buffer)), mSource(source) { + } - uint32_t getHandle() { + explicit PluginData(std::span buffer, std::string_view source) : mBuffer(buffer.begin(), buffer.end()), mSource(source) { + } + + [[nodiscard]] uint32_t getHandle() const { return (uint32_t) this; } - size_t length = 0; - std::unique_ptr buffer; + [[nodiscard]] std::span getBuffer() const { + return mBuffer; + } + + [[nodiscard]] const std::string &getSource() const { + return mSource; + } + +private: + std::vector mBuffer; std::string mSource; }; diff --git a/source/plugin/PluginDataFactory.cpp b/source/plugin/PluginDataFactory.cpp index 6de7847..61c84b7 100644 --- a/source/plugin/PluginDataFactory.cpp +++ b/source/plugin/PluginDataFactory.cpp @@ -23,10 +23,9 @@ #include #include #include -#include -std::forward_list> PluginDataFactory::loadDir(const std::string &path) { - std::forward_list> result; +std::set> PluginDataFactory::loadDir(std::string_view path) { + std::set> result; struct dirent *dp; DIR *dfd; @@ -35,8 +34,8 @@ std::forward_list> PluginDataFactory::loadDir(const return result; } - if ((dfd = opendir(path.c_str())) == nullptr) { - DEBUG_FUNCTION_LINE_ERR("Couldn't open dir %s", path.c_str()); + if ((dfd = opendir(path.data())) == nullptr) { + DEBUG_FUNCTION_LINE_ERR("Couldn't open dir %s", path.data()); return result; } @@ -45,15 +44,15 @@ std::forward_list> PluginDataFactory::loadDir(const continue; } if (std::string_view(dp->d_name).starts_with('.') || std::string_view(dp->d_name).starts_with('_') || !std::string_view(dp->d_name).ends_with(".wps")) { - DEBUG_FUNCTION_LINE_WARN("Skip file %s/%s", path.c_str(), dp->d_name); + DEBUG_FUNCTION_LINE_WARN("Skip file %s/%s", path.data(), dp->d_name); continue; } - auto full_file_path = string_format("%s/%s", path.c_str(), dp->d_name); + auto full_file_path = string_format("%s/%s", path.data(), dp->d_name); DEBUG_FUNCTION_LINE("Loading plugin: %s", full_file_path.c_str()); auto pluginData = load(full_file_path); if (pluginData) { - result.push_front(std::move(pluginData.value())); + result.insert(std::move(pluginData)); } else { auto errMsg = string_format("Failed to load plugin: %s", full_file_path.c_str()); DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); @@ -66,33 +65,21 @@ std::forward_list> PluginDataFactory::loadDir(const return result; } -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_ERR("Failed to load %s into memory", filename.c_str()); - return {}; +std::unique_ptr PluginDataFactory::load(std::string_view filename) { + std::vector buffer; + if (FSUtils::LoadFileToMem(filename, buffer) < 0) { + DEBUG_FUNCTION_LINE_ERR("Failed to load %s into memory", filename.data()); + return nullptr; } - std::vector result; - result.resize(fsize); - memcpy(&result[0], buffer, fsize); - free(buffer); - DEBUG_FUNCTION_LINE_VERBOSE("Loaded file!"); - - return load(result, filename); + return load(std::move(buffer), filename); } -std::optional> PluginDataFactory::load(const std::vector &buffer, const std::string &source) { +std::unique_ptr PluginDataFactory::load(std::vector &&buffer, std::string_view source) { if (buffer.empty()) { - return {}; + return nullptr; } - auto res = make_unique_nothrow(buffer, source); - if (!res) { - return {}; - } - - return res; + return make_unique_nothrow(std::move(buffer), source); } diff --git a/source/plugin/PluginDataFactory.h b/source/plugin/PluginDataFactory.h index e09f46e..205329b 100644 --- a/source/plugin/PluginDataFactory.h +++ b/source/plugin/PluginDataFactory.h @@ -22,14 +22,15 @@ #include #include #include +#include #include #include class PluginDataFactory { public: - static std::forward_list> loadDir(const std::string &path); + static std::set> loadDir(std::string_view path); - static std::optional> load(const std::string &path); + static std::unique_ptr load(std::string_view path); - static std::optional> load(const std::vector &buffer, const std::string &source); + static std::unique_ptr load(std::vector &&buffer, std::string_view source); }; diff --git a/source/plugin/PluginInformation.h b/source/plugin/PluginInformation.h index 8f43f75..ee2a8f2 100644 --- a/source/plugin/PluginInformation.h +++ b/source/plugin/PluginInformation.h @@ -23,6 +23,8 @@ #include "PluginMetaInformation.h" #include "RelocationData.h" #include "SectionInfo.h" +#include "utils/HeapMemoryFixedSize.h" +#include "utils/utils.h" #include #include #include @@ -32,109 +34,101 @@ #include struct FunctionSymbolDataComparator { - bool operator()(const std::shared_ptr &lhs, - const std::shared_ptr &rhs) const { - return (uint32_t) lhs->getAddress() < (uint32_t) rhs->getAddress(); + bool operator()(const std::unique_ptr &lhs, + const std::unique_ptr &rhs) const { + return *lhs < *rhs; } }; class PluginInformation { public: void addHookData(std::unique_ptr hook_data) { - hook_data_list.push_back(std::move(hook_data)); + mHookDataList.push_back(std::move(hook_data)); } [[nodiscard]] const std::vector> &getHookDataList() const { - return hook_data_list; + return mHookDataList; } void addFunctionData(std::unique_ptr function_data) { - function_data_list.push_back(std::move(function_data)); + mFunctionDataList.push_back(std::move(function_data)); } [[nodiscard]] const std::vector> &getFunctionDataList() const { - return function_data_list; + return mFunctionDataList; } void addRelocationData(std::unique_ptr relocation_data) { - relocation_data_list.push_back(std::move(relocation_data)); + mRelocationDataList.push_back(std::move(relocation_data)); } [[nodiscard]] const std::vector> &getRelocationDataList() const { - return relocation_data_list; + return mRelocationDataList; } - - void addFunctionSymbolData(std::shared_ptr symbol_data) { - symbol_data_list.insert(std::move(symbol_data)); + void addFunctionSymbolData(std::unique_ptr symbol_data) { + mSymbolDataList.insert(std::move(symbol_data)); } - [[nodiscard]] const std::set, FunctionSymbolDataComparator> &getFunctionSymbolDataList() const { - return symbol_data_list; + void addSectionInfo(std::unique_ptr sectionInfo) { + mSectionInfoList[sectionInfo->getName()] = std::move(sectionInfo); } - void addSectionInfo(std::shared_ptr sectionInfo) { - section_info_list[sectionInfo->getName()] = std::move(sectionInfo); + [[nodiscard]] const std::map> &getSectionInfoList() const { + return mSectionInfoList; } - [[nodiscard]] const std::map> &getSectionInfoList() const { - return section_info_list; - } - - [[nodiscard]] std::optional> getSectionInfo(const std::string §ionName) const { + [[nodiscard]] SectionInfo *getSectionInfo(const std::string §ionName) const { if (getSectionInfoList().contains(sectionName)) { - return section_info_list.at(sectionName); + return mSectionInfoList.at(sectionName).get(); } - return std::nullopt; + return nullptr; } - void setTrampolineId(uint8_t _trampolineId) { - this->trampolineId = _trampolineId; + void setTrampolineId(uint8_t trampolineId) { + this->mTrampolineId = trampolineId; } [[nodiscard]] uint8_t getTrampolineId() const { - return trampolineId; + return mTrampolineId; } - [[nodiscard]] std::optional> getNearestFunctionSymbolData(uint32_t address) const { - std::shared_ptr result; + [[nodiscard]] FunctionSymbolData *getNearestFunctionSymbolData(uint32_t address) const { + FunctionSymbolData *result = nullptr; bool foundHit = false; - for (auto &cur : symbol_data_list) { + for (auto &cur : mSymbolDataList) { if (foundHit && address < (uint32_t) cur->getAddress()) { break; } if (address >= (uint32_t) cur->getAddress()) { - result = cur; + result = cur.get(); foundHit = true; } } - if (result) { - return result; - } - return {}; + return result; } - void *getTextMemoryAddress() { - return allocatedTextMemoryAddress.get(); + [[nodiscard]] const HeapMemoryFixedSize &getTextMemory() const { + return mAllocatedTextMemoryAddress; } - void *getDataMemoryAddress() { - return allocatedDataMemoryAddress.get(); + [[nodiscard]] const HeapMemoryFixedSize &getDataMemory() const { + return mAllocatedDataMemoryAddress; } private: - 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; + std::vector> mHookDataList; + std::vector> mFunctionDataList; + std::vector> mRelocationDataList; + std::set, FunctionSymbolDataComparator> mSymbolDataList; + std::map> mSectionInfoList; - uint8_t trampolineId = 0; + uint8_t mTrampolineId = 0; - std::unique_ptr allocatedTextMemoryAddress; - std::unique_ptr allocatedDataMemoryAddress; + HeapMemoryFixedSize mAllocatedTextMemoryAddress; + HeapMemoryFixedSize mAllocatedDataMemoryAddress; friend class PluginInformationFactory; }; diff --git a/source/plugin/PluginInformationFactory.cpp b/source/plugin/PluginInformationFactory.cpp index e7ecbf0..da3d6d2 100644 --- a/source/plugin/PluginInformationFactory.cpp +++ b/source/plugin/PluginInformationFactory.cpp @@ -18,6 +18,7 @@ #include "PluginInformationFactory.h" #include "../utils/ElfUtils.h" #include "../utils/utils.h" +#include "utils/HeapMemoryFixedSize.h" #include "utils/wiiu_zlib.hpp" #include #include @@ -27,33 +28,34 @@ using namespace ELFIO; -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) { - DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr"); - return {}; +std::unique_ptr +PluginInformationFactory::load(const PluginData &pluginData, std::vector &trampolineData, uint8_t trampolineId) { + auto buffer = pluginData.getBuffer(); + if (buffer.empty()) { + DEBUG_FUNCTION_LINE_ERR("Buffer was empty"); + return nullptr; } elfio reader(new wiiu_zlib); - if (!reader.load(reinterpret_cast(pluginData->buffer.get()), pluginData->length)) { + if (!reader.load(reinterpret_cast(buffer.data()), buffer.size())) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); - return {}; + return nullptr; } auto pluginInfo = make_unique_nothrow(); if (!pluginInfo) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate PluginInformation"); - return {}; + return nullptr; } uint32_t sec_num = reader.sections.size(); - auto destinations = make_unique_nothrow(sec_num); - if (!destinations) { + auto destinationsData = make_unique_nothrow(sec_num); + if (!destinationsData) { DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array"); - return {}; + return nullptr; } + std::span destinations(destinationsData.get(), sec_num); uint32_t totalSize = 0; @@ -80,22 +82,18 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re } } - auto text_data = make_unique_nothrow(text_size); + HeapMemoryFixedSize text_data(text_size); if (!text_data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .text section (%d bytes)", text_size); - return {}; + return nullptr; } - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", text_size / 1024); - - auto data_data = make_unique_nothrow(data_size); + HeapMemoryFixedSize data_data(data_size); if (!data_data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .data section (%d bytes)", data_size); - return {}; + return nullptr; } - DEBUG_FUNCTION_LINE_VERBOSE("Allocated %d kb", data_size / 1024); - for (uint32_t i = 0; i < sec_num; ++i) { section *psec = reader.sections[i]; if (psec->get_type() == 0x80000002 || psec->get_name() == ".wut_load_bounds") { @@ -108,29 +106,29 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re uint32_t destination = address; if ((address >= 0x02000000) && address < 0x10000000) { - destination += (uint32_t) text_data.get(); + destination += (uint32_t) text_data.data(); destination -= 0x02000000; - destinations[psec->get_index()] = (uint8_t *) text_data.get(); + destinations[psec->get_index()] = (uint8_t *) text_data.data(); - if (destination + sectionSize > (uint32_t) text_data.get() + text_size) { - DEBUG_FUNCTION_LINE_ERR("Tried to overflow .text buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.get() + text_size); + if (destination + sectionSize > (uint32_t) text_data.data() + text_size) { + DEBUG_FUNCTION_LINE_ERR("Tried to overflow .text buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.data() + text_data.size()); OSFatal("WUPSLoader: Tried to overflow buffer"); } } else if ((address >= 0x10000000) && address < 0xC0000000) { - destination += (uint32_t) data_data.get(); + destination += (uint32_t) data_data.data(); destination -= 0x10000000; - destinations[psec->get_index()] = (uint8_t *) data_data.get(); + destinations[psec->get_index()] = (uint8_t *) data_data.data(); - if (destination + sectionSize > (uint32_t) data_data.get() + data_size) { - DEBUG_FUNCTION_LINE_ERR("Tried to overflow .data buffer. %08X > %08X", destination + sectionSize, (uint32_t) data_data.get() + data_size); + if (destination + sectionSize > (uint32_t) data_data.data() + data_data.size()) { + DEBUG_FUNCTION_LINE_ERR("Tried to overflow .data buffer. %08X > %08X", destination + sectionSize, (uint32_t) text_data.data() + text_data.size()); OSFatal("WUPSLoader: Tried to overflow buffer"); } } else if (address >= 0xC0000000) { DEBUG_FUNCTION_LINE_ERR("Loading section from 0xC0000000 is NOT supported"); - return std::nullopt; + return nullptr; } else { DEBUG_FUNCTION_LINE_ERR("Unhandled case"); - return std::nullopt; + return nullptr; } const char *p = psec->get_data(); @@ -146,7 +144,7 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re auto sectionInfo = make_unique_nothrow(psec->get_name(), destination, sectionSize); if (!sectionInfo) { DEBUG_FUNCTION_LINE_ERR("Failed to allocat SectionInfo"); - return {}; + return nullptr; } pluginInfo->addSectionInfo(std::move(sectionInfo)); @@ -163,30 +161,30 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re 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.get(), (uint32_t) data_data.get(), trampoline_data, trampoline_data_length, + if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data.data(), (uint32_t) data_data.data(), trampolineData, trampolineId)) { DEBUG_FUNCTION_LINE_ERR("linkSection failed"); - return {}; + return nullptr; } } } - if (!PluginInformationFactory::addImportRelocationData(pluginInfo, reader, destinations)) { + if (!PluginInformationFactory::addImportRelocationData(*pluginInfo, reader, destinations)) { DEBUG_FUNCTION_LINE_ERR("addImportRelocationData failed"); - return {}; + return nullptr; } - 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); + DCFlushRange((void *) text_data.data(), text_data.size()); + ICInvalidateRange((void *) text_data.data(), text_data.size()); + DCFlushRange((void *) data_data.data(), data_data.size()); + ICInvalidateRange((void *) data_data.data(), data_data.size()); pluginInfo->setTrampolineId(trampolineId); auto secInfo = pluginInfo->getSectionInfo(".wups.hooks"); - if (secInfo && secInfo.value()->getSize() > 0) { - size_t entries_count = secInfo.value()->getSize() / sizeof(wups_loader_hook_t); - auto *entries = (wups_loader_hook_t *) secInfo.value()->getAddress(); + if (secInfo && secInfo->getSize() > 0) { + size_t entries_count = secInfo->getSize() / sizeof(wups_loader_hook_t); + auto *entries = (wups_loader_hook_t *) secInfo->getAddress(); if (entries != nullptr) { for (size_t j = 0; j < entries_count; j++) { wups_loader_hook_t *hook = &entries[j]; @@ -194,7 +192,7 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re auto hookData = make_unique_nothrow((void *) hook->target, hook->type); if (!hookData) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate HookData"); - return {}; + return nullptr; } pluginInfo->addHookData(std::move(hookData)); } @@ -202,14 +200,14 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re } secInfo = pluginInfo->getSectionInfo(".wups.load"); - if (secInfo && secInfo.value()->getSize() > 0) { - size_t entries_count = secInfo.value()->getSize() / sizeof(wups_loader_entry_t); - auto *entries = (wups_loader_entry_t *) secInfo.value()->getAddress(); + if (secInfo && secInfo->getSize() > 0) { + size_t entries_count = secInfo->getSize() / sizeof(wups_loader_entry_t); + auto *entries = (wups_loader_entry_t *) secInfo->getAddress(); if (entries != nullptr) { for (size_t j = 0; j < entries_count; j++) { wups_loader_entry_t *cur_function = &entries[j]; DEBUG_FUNCTION_LINE_VERBOSE("Saving function \"%s\" of plugin . PA:%08X VA:%08X Library: %08X, target: %08X, call_addr: %08X", - cur_function->_function.name /*,pluginData->getPluginInformation()->getName().c_str()*/, + cur_function->_function.name /*,mPluginData->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); @@ -222,7 +220,7 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re (FunctionPatcherTargetProcess) cur_function->_function.targetProcess); if (!functionData) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionData"); - return {}; + return nullptr; } pluginInfo->addFunctionData(std::move(functionData)); } @@ -248,18 +246,18 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re if (symbols.get_symbol(j, name, value, size, bind, type, section, other)) { if (type == STT_FUNC) { // We only care about functions. - auto sectionVal = reader.sections[section]; - auto offsetVal = value - sectionVal->get_address(); - auto sectionOpt = pluginInfo->getSectionInfo(sectionVal->get_name()); - if (!sectionOpt.has_value()) { + auto sectionVal = reader.sections[section]; + auto offsetVal = value - sectionVal->get_address(); + auto sectionInfo = pluginInfo->getSectionInfo(sectionVal->get_name()); + if (!sectionInfo) { continue; } - auto finalAddress = offsetVal + sectionOpt.value()->getAddress(); + auto finalAddress = offsetVal + sectionInfo->getAddress(); auto functionSymbolData = make_unique_nothrow(name, (void *) finalAddress, (uint32_t) size); if (!functionSymbolData) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate FunctionSymbolData"); - return {}; + return nullptr; } pluginInfo->addFunctionSymbolData(std::move(functionSymbolData)); } @@ -272,17 +270,18 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re if (totalSize > text_size + data_size) { DEBUG_FUNCTION_LINE_ERR("We didn't allocate enough memory!!"); - return std::nullopt; + return nullptr; } + // Save the addresses for the allocated memory. This way we can free it again :) - pluginInfo->allocatedDataMemoryAddress = std::move(data_data); - pluginInfo->allocatedTextMemoryAddress = std::move(text_data); + pluginInfo->mAllocatedDataMemoryAddress = std::move(data_data); + pluginInfo->mAllocatedTextMemoryAddress = std::move(text_data); return pluginInfo; } -bool PluginInformationFactory::addImportRelocationData(const std::unique_ptr &pluginInfo, const elfio &reader, const std::unique_ptr &destinations) { +bool PluginInformationFactory::addImportRelocationData(PluginInformation &pluginInfo, const elfio &reader, std::span destinations) { std::map> infoMap; uint32_t sec_num = reader.sections.size(); @@ -352,16 +351,15 @@ bool PluginInformationFactory::addImportRelocationData(const std::unique_ptraddRelocationData(std::move(relocationData)); + pluginInfo.addRelocationData(std::move(relocationData)); } } } 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, - uint32_t trampoline_data_length, - uint8_t trampolineId) { +bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, + std::vector &trampolineData, uint8_t trampolineId) { uint32_t sec_num = reader.sections.size(); for (uint32_t i = 0; i < sec_num; ++i) { @@ -431,7 +429,7 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section } // DEBUG_FUNCTION_LINE_VERBOSE("sym_value %08X adjusted_sym_value %08X offset %08X adjusted_offset %08X", (uint32_t) sym_value, adjusted_sym_value, (uint32_t) offset, adjusted_offset); - if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampoline_data, trampoline_data_length, RELOC_TYPE_FIXED, trampolineId)) { + if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampolineData, RELOC_TYPE_FIXED, trampolineId)) { DEBUG_FUNCTION_LINE_ERR("Link failed"); return false; } diff --git a/source/plugin/PluginInformationFactory.h b/source/plugin/PluginInformationFactory.h index 2560e2e..10d0bac 100644 --- a/source/plugin/PluginInformationFactory.h +++ b/source/plugin/PluginInformationFactory.h @@ -27,17 +27,15 @@ #include #include - class PluginInformationFactory { public: - static std::optional> - load(const std::shared_ptr &pluginData, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, - uint8_t trampolineId); + static std::unique_ptr + load(const PluginData &pluginData, std::vector &trampolineData, uint8_t trampolineId); static bool - 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); + linkSection(const ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, + std::vector &trampolineData, uint8_t trampolineId); - static bool addImportRelocationData(const std::unique_ptr &pluginInfo, const ELFIO::elfio &reader, const std::unique_ptr &destinations); + static bool + addImportRelocationData(PluginInformation &pluginInfo, const ELFIO::elfio &reader, std::span destinations); }; diff --git a/source/plugin/PluginMetaInformationFactory.cpp b/source/plugin/PluginMetaInformationFactory.cpp index e9e72a0..1c2bda2 100644 --- a/source/plugin/PluginMetaInformationFactory.cpp +++ b/source/plugin/PluginMetaInformationFactory.cpp @@ -22,55 +22,34 @@ #include "utils/wiiu_zlib.hpp" #include -std::optional> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr &pluginData, PluginParseErrors &error) { - if (!pluginData->buffer) { +std::unique_ptr PluginMetaInformationFactory::loadPlugin(const PluginData &pluginData, PluginParseErrors &error) { + return loadPlugin(pluginData.getBuffer(), error); +} + +std::unique_ptr PluginMetaInformationFactory::loadPlugin(std::string_view filePath, PluginParseErrors &error) { + std::vector buffer; + if (FSUtils::LoadFileToMem(filePath, buffer) < 0) { + DEBUG_FUNCTION_LINE_ERR("Failed to load file to memory"); + error = PLUGIN_PARSE_ERROR_IO_ERROR; + return {}; + } + return loadPlugin(buffer, error); +} + +std::unique_ptr PluginMetaInformationFactory::loadPlugin(std::span buffer, PluginParseErrors &error) { + if (buffer.empty()) { error = PLUGIN_PARSE_ERROR_BUFFER_EMPTY; DEBUG_FUNCTION_LINE_ERR("Buffer is empty"); return {}; } ELFIO::elfio reader(new wiiu_zlib); - if (!reader.load(reinterpret_cast(pluginData->buffer.get()), pluginData->length)) { - error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED; - DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); - return {}; - } - return loadPlugin(reader, error); -} -std::optional> PluginMetaInformationFactory::loadPlugin(const std::string &filePath, PluginParseErrors &error) { - ELFIO::elfio reader(new wiiu_zlib); - - uint8_t *buffer = nullptr; - uint32_t length = 0; - if (FSUtils::LoadFileToMem(filePath.c_str(), &buffer, &length) < 0) { - DEBUG_FUNCTION_LINE_ERR("Failed to load file to memory"); - error = PLUGIN_PARSE_ERROR_IO_ERROR; - return {}; - } - - if (!reader.load(reinterpret_cast(buffer), length)) { - error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED; - DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); - return {}; - } - auto res = loadPlugin(reader, error); - free(buffer); - return res; -} - -std::optional> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size, PluginParseErrors &error) { - ELFIO::elfio reader(new wiiu_zlib); - - if (!reader.load(reinterpret_cast(buffer), size)) { + if (!reader.load(reinterpret_cast(buffer.data()), buffer.size())) { error = PLUGIN_PARSE_ERROR_ELFIO_PARSE_FAILED; DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file"); - return std::nullopt; + return nullptr; } - return loadPlugin(reader, error); -} - -std::optional> PluginMetaInformationFactory::loadPlugin(const ELFIO::elfio &reader, PluginParseErrors &error) { size_t pluginSize = 0; auto pluginInfo = std::unique_ptr(new PluginMetaInformation); @@ -127,7 +106,7 @@ std::optional> PluginMetaInformationFacto if (value != "0.7.1") { error = PLUGIN_PARSE_ERROR_INCOMPATIBLE_VERSION; DEBUG_FUNCTION_LINE_ERR("Warning: Ignoring plugin - Unsupported WUPS version: %s.", value.c_str()); - return std::nullopt; + return nullptr; } } } diff --git a/source/plugin/PluginMetaInformationFactory.h b/source/plugin/PluginMetaInformationFactory.h index cf8a093..052a320 100644 --- a/source/plugin/PluginMetaInformationFactory.h +++ b/source/plugin/PluginMetaInformationFactory.h @@ -36,11 +36,9 @@ enum PluginParseErrors { class PluginMetaInformationFactory { public: - static std::optional> loadPlugin(const std::shared_ptr &pluginData, PluginParseErrors &error); + static std::unique_ptr loadPlugin(const PluginData &pluginData, PluginParseErrors &error); - static std::optional> loadPlugin(const std::string &filePath, PluginParseErrors &error); + static std::unique_ptr loadPlugin(std::string_view filePath, PluginParseErrors &error); - static std::optional> loadPlugin(char *buffer, size_t size, PluginParseErrors &error); - - static std::optional> loadPlugin(const ELFIO::elfio &reader, PluginParseErrors &error); + static std::unique_ptr loadPlugin(std::span buffer, PluginParseErrors &error); }; diff --git a/source/plugin/RelocationData.h b/source/plugin/RelocationData.h index 89963f0..d9775be 100644 --- a/source/plugin/RelocationData.h +++ b/source/plugin/RelocationData.h @@ -57,8 +57,8 @@ public: return name; } - [[nodiscard]] const std::shared_ptr &getImportRPLInformation() const { - return rplInfo; + [[nodiscard]] const ImportRPLInformation &getImportRPLInformation() const { + return *rplInfo; } private: diff --git a/source/utils/ConfigUtils.cpp b/source/utils/ConfigUtils.cpp index 92aba6a..3cceec1 100644 --- a/source/utils/ConfigUtils.cpp +++ b/source/utils/ConfigUtils.cpp @@ -122,12 +122,11 @@ void ConfigUtils::displayMenu() { std::vector configs; for (auto &plugin : gLoadedPlugins) { ConfigDisplayItem cfg; - cfg.name = plugin->metaInformation->getName(); - cfg.author = plugin->metaInformation->getAuthor(); - cfg.version = plugin->metaInformation->getVersion(); - - for (auto &hook : plugin->getPluginInformation()->getHookDataList()) { + cfg.name = plugin->getMetaInformation().getName(); + cfg.author = plugin->getMetaInformation().getAuthor(); + cfg.version = plugin->getMetaInformation().getVersion(); + for (const auto &hook : plugin->getPluginInformation().getHookDataList()) { if (hook->getType() == WUPS_LOADER_HOOK_GET_CONFIG /*WUPS_LOADER_HOOK_GET_CONFIG*/) { if (hook->getFunctionPointer() == nullptr) { break; diff --git a/source/utils/ElfUtils.cpp b/source/utils/ElfUtils.cpp index 17d7fdf..de50b62 100644 --- a/source/utils/ElfUtils.cpp +++ b/source/utils/ElfUtils.cpp @@ -1,13 +1,14 @@ #include #include #include +#include #include "ElfUtils.h" #include "utils/logger.h" // See https://github.com/decaf-emu/decaf-emu/blob/43366a34e7b55ab9d19b2444aeb0ccd46ac77dea/src/libdecaf/src/cafe/loader/cafe_loader_reloc.cpp#L144 -bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, - RelocationType reloc_type, uint8_t trampolineId) { +bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, + std::vector &trampolineData, RelocationType reloc_type, uint8_t trampolineId) { if (type == R_PPC_NONE) { return true; } @@ -76,21 +77,21 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des // } auto distance = static_cast(value) - static_cast(target); if (distance > 0x1FFFFFC || distance < -0x1FFFFFC) { - if (trampoline_data == nullptr) { + if (trampolineData.empty()) { DEBUG_FUNCTION_LINE_ERR("***24-bit relative branch cannot hit target. Trampoline isn't provided"); DEBUG_FUNCTION_LINE_ERR("***value %08X - target %08X = distance %08X", value, target, distance); return false; } else { relocation_trampoline_entry_t *freeSlot = nullptr; - for (uint32_t i = 0; i < trampoline_data_length; i++) { + for (auto &cur : trampolineData) { // We want to override "old" relocations of imports // Pending relocations have the status RELOC_TRAMP_IMPORT_IN_PROGRESS. // When all relocations are done successfully, they will be turned into RELOC_TRAMP_IMPORT_DONE // so they can be overridden/updated/reused on the next application launch. // // Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded. - if (trampoline_data[i].status == RELOC_TRAMP_FREE) { - freeSlot = &(trampoline_data[i]); + if (cur.status == RELOC_TRAMP_FREE) { + freeSlot = &cur; break; } } diff --git a/source/utils/ElfUtils.h b/source/utils/ElfUtils.h index 0a1f532..f12ae21 100644 --- a/source/utils/ElfUtils.h +++ b/source/utils/ElfUtils.h @@ -46,6 +46,6 @@ uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fi class ElfUtils { public: - static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, + static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, std::vector &trampolineData, RelocationType reloc_type, uint8_t trampolineId); }; diff --git a/source/utils/HeapMemoryFixedSize.h b/source/utils/HeapMemoryFixedSize.h new file mode 100644 index 0000000..3d655eb --- /dev/null +++ b/source/utils/HeapMemoryFixedSize.h @@ -0,0 +1,45 @@ +#pragma once +#include "utils.h" +#include +#include + +class HeapMemoryFixedSize { +public: + HeapMemoryFixedSize() = default; + + explicit HeapMemoryFixedSize(std::size_t size) : mData(make_unique_nothrow(size)), mSize(mData ? size : 0) {} + + // Delete the copy constructor and copy assignment operator + HeapMemoryFixedSize(const HeapMemoryFixedSize &) = delete; + HeapMemoryFixedSize &operator=(const HeapMemoryFixedSize &) = delete; + + HeapMemoryFixedSize(HeapMemoryFixedSize &&other) noexcept + : mData(std::move(other.mData)), mSize(other.mSize) { + other.mSize = 0; + } + + HeapMemoryFixedSize &operator=(HeapMemoryFixedSize &&other) noexcept { + if (this != &other) { + mData = std::move(other.mData); + mSize = other.mSize; + other.mSize = 0; + } + return *this; + } + + explicit operator bool() const { + return mData != nullptr; + } + + [[nodiscard]] const void *data() const { + return mData.get(); + } + + [[nodiscard]] std::size_t size() const { + return mSize; + } + +private: + std::unique_ptr mData{}; + std::size_t mSize{}; +}; \ No newline at end of file diff --git a/source/utils/StorageUtils.cpp b/source/utils/StorageUtils.cpp index 0c8b13e..fa3afc7 100644 --- a/source/utils/StorageUtils.cpp +++ b/source/utils/StorageUtils.cpp @@ -122,7 +122,7 @@ WUPSStorageError StorageUtils::CloseStorage(const char *plugin_id, wups_storage_ std::string folderPath = getPluginPath() + "/config/"; std::string filePath = folderPath + plugin_id + ".json"; - FSUtils::CreateSubfolder(folderPath.c_str()); + FSUtils::CreateSubfolder(folderPath); CFile file(filePath, CFile::WriteOnly); if (!file.isOpen()) { diff --git a/source/utils/StringTools.h b/source/utils/StringTools.h index f657937..cf7a39d 100644 --- a/source/utils/StringTools.h +++ b/source/utils/StringTools.h @@ -34,8 +34,8 @@ #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' +std::string string_format(std::string_view format, Args... args) { + int size_s = std::snprintf(nullptr, 0, format.data(), args...) + 1; // Extra space for '\0' auto size = static_cast(size_s); auto buf = make_unique_nothrow(size); if (!buf) { @@ -43,11 +43,10 @@ std::string string_format(const std::string &format, Args... args) { OSFatal("string_format failed, not enough memory"); return std::string(""); } - std::snprintf(buf.get(), size, format.c_str(), args...); + std::snprintf(buf.get(), size, format.data(), args...); return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside } - class StringTools { public: static std::string truncate(const std::string &str, size_t width, bool show_ellipsis = true); diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp index 940c8d4..f409cce 100644 --- a/source/utils/exports.cpp +++ b/source/utils/exports.cpp @@ -6,35 +6,36 @@ #include "utils.h" #include -static void fillPluginInformation(plugin_information *out, const std::unique_ptr &metaInformation) { +static void fillPluginInformation(plugin_information *out, const PluginMetaInformation &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); - strncpy(out->description, metaInformation->getDescription().c_str(), sizeof(out->description) - 1); - strncpy(out->name, metaInformation->getName().c_str(), sizeof(out->name) - 1); - strncpy(out->license, metaInformation->getLicense().c_str(), sizeof(out->license) - 1); - strncpy(out->version, metaInformation->getVersion().c_str(), sizeof(out->version) - 1); - strncpy(out->storageId, metaInformation->getStorageId().c_str(), sizeof(out->storageId) - 1); - out->size = metaInformation->getSize(); + strncpy(out->author, metaInformation.getAuthor().c_str(), sizeof(out->author) - 1); + strncpy(out->buildTimestamp, metaInformation.getBuildTimestamp().c_str(), sizeof(out->buildTimestamp) - 1); + strncpy(out->description, metaInformation.getDescription().c_str(), sizeof(out->description) - 1); + strncpy(out->name, metaInformation.getName().c_str(), sizeof(out->name) - 1); + strncpy(out->license, metaInformation.getLicense().c_str(), sizeof(out->license) - 1); + strncpy(out->version, metaInformation.getVersion().c_str(), sizeof(out->version) - 1); + strncpy(out->storageId, metaInformation.getStorageId().c_str(), sizeof(out->storageId) - 1); + out->size = metaInformation.getSize(); } extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(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) { - return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } + 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; - for (auto &pluginData : gLoadedData) { + for (const auto &pluginData : gLoadedData) { if (pluginData->getHandle() == handle) { - gLoadOnNextLaunch.push_front(pluginData); + gLoadOnNextLaunch.insert(pluginData); found = true; break; } } + if (!found) { DEBUG_FUNCTION_LINE_ERR("Failed to get plugin data for handle %08X. Skipping it.", handle); } @@ -45,9 +46,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const plugin_da 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]; - + for (auto &handle : std::span(plugin_data_handle_list, plugin_data_handle_list_size)) { 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); } @@ -61,13 +60,11 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationIn return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } - std::optional> pluginData; + std::unique_ptr pluginData; if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) { 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, ""); + pluginData = make_unique_nothrow(std::span((uint8_t *) buffer, size), ""); } else { return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } @@ -75,11 +72,9 @@ extern "C" PluginBackendApiErrorType WUPSLoadPluginAsData(GetPluginInformationIn if (!pluginData) { DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC"); return PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC; - } - - else { - *out = pluginData.value()->getHandle(); - gLoadedData.push_front(std::move(pluginData.value())); + } else { + *out = pluginData->getHandle(); + gLoadedData.insert(std::move(pluginData)); } return PLUGIN_BACKEND_API_ERROR_NONE; @@ -94,13 +89,17 @@ 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; + if (output == nullptr) { + DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); + return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; + } + + std::unique_ptr pluginInfo; PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN; if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) { - std::string pathStr(path); - pluginInfo = PluginMetaInformationFactory::loadPlugin(pathStr, error); + pluginInfo = PluginMetaInformationFactory::loadPlugin(path, error); } else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != nullptr && size > 0) { - pluginInfo = PluginMetaInformationFactory::loadPlugin(buffer, size, error); + pluginInfo = PluginMetaInformationFactory::loadPlugin(std::span((uint8_t *) buffer, size), error); } else { DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; @@ -110,13 +109,8 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginMetaInformation(GetPluginInfor DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_FILE_NOT_FOUND"); return PLUGIN_BACKEND_API_ERROR_FILE_NOT_FOUND; } + fillPluginInformation(output, *pluginInfo); - if (output == nullptr) { - DEBUG_FUNCTION_LINE_ERR("PLUGIN_BACKEND_API_ERROR_INVALID_ARG"); - return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; - } else { - fillPluginInformation(output, pluginInfo.value()); - } return PLUGIN_BACKEND_API_ERROR_NONE; } @@ -135,21 +129,21 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const } std::lock_guard lock(gLoadedDataMutex); - for (uint32_t i = 0; i < buffer_size; /* only increase on success*/) { + for (uint32_t i = 0; i < buffer_size; i++) { auto handle = plugin_container_handle_list[i]; bool found = false; - for (auto &curContainer : gLoadedPlugins) { + for (const auto &curContainer : gLoadedPlugins) { if (curContainer->getHandle() == handle) { - auto &pluginData = curContainer->getPluginData(); + auto pluginData = curContainer->getPluginDataCopy(); plugin_data_list[i] = (uint32_t) pluginData->getHandle(); - gLoadedData.push_front(pluginData); + gLoadedData.insert(std::move(pluginData)); found = true; - i++; break; } } if (!found) { DEBUG_FUNCTION_LINE_ERR("Failed to get container for handle %08X", handle); + return PLUGIN_BACKEND_API_INVALID_HANDLE; } } @@ -162,19 +156,19 @@ extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const plugin_contain for (uint32_t i = 0; i < buffer_size; i++) { auto handle = plugin_container_handle_list[i]; bool found = false; - for (auto &curContainer : gLoadedPlugins) { + for (const auto &curContainer : gLoadedPlugins) { if (curContainer->getHandle() == handle) { - auto &metaInfo = curContainer->getMetaInformation(); + const auto &metaInfo = curContainer->getMetaInformation(); 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(); + 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; @@ -196,9 +190,8 @@ extern "C" PluginBackendApiErrorType WUPSGetLoadedPlugins(plugin_container_handl return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } *plugin_information_version = PLUGIN_INFORMATION_VERSION; - auto &plugins = gLoadedPlugins; uint32_t counter = 0; - for (auto &plugin : plugins) { + for (const auto &plugin : gLoadedPlugins) { if (counter < buffer_size) { io_handles[counter] = plugin->getHandle(); counter++; @@ -248,10 +241,10 @@ extern "C" PluginBackendApiErrorType WUPSGetSectionInformationForPlugin(const pl } if (handle != 0 && plugin_section_list != nullptr && buffer_size != 0) { bool found = false; - for (auto &curContainer : gLoadedPlugins) { + for (const auto &curContainer : gLoadedPlugins) { if (curContainer->getHandle() == handle) { - found = true; - auto §ionInfoList = curContainer->getPluginInformation()->getSectionInfoList(); + found = true; + const auto §ionInfoList = curContainer->getPluginInformation().getSectionInfoList(); uint32_t offset = 0; for (auto const &[key, sectionInfo] : sectionInfoList) { @@ -292,10 +285,10 @@ extern "C" PluginBackendApiErrorType WUPSGetSectionMemoryAddresses(plugin_contai if (handle == 0 || textAddress == nullptr || dataAddress == nullptr) { return PLUGIN_BACKEND_API_ERROR_INVALID_ARG; } - for (auto &curContainer : gLoadedPlugins) { + for (const auto &curContainer : gLoadedPlugins) { if (curContainer->getHandle() == handle) { - *textAddress = curContainer->getPluginInformation()->getTextMemoryAddress(); - *dataAddress = curContainer->getPluginInformation()->getDataMemoryAddress(); + *textAddress = (void *) curContainer->getPluginInformation().getTextMemory().data(); + *dataAddress = (void *) curContainer->getPluginInformation().getDataMemory().data(); return PLUGIN_BACKEND_API_ERROR_NONE; } } diff --git a/source/utils/utils.h b/source/utils/utils.h index 26a3bb2..50a4f51 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -1,11 +1,13 @@ #pragma once +#include #include #include #include #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -60,17 +62,16 @@ std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std:: 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) { +template +bool remove_locked_first_if(std::mutex &mutex, Container &container, 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++; + + auto it = std::find_if(container.begin(), container.end(), pred); + if (it != container.end()) { + container.erase(it); + return true; } + return false; }