From d943bd4c675b4cedf7543ff8c45a6542e524d997 Mon Sep 17 00:00:00 2001 From: Maschell Date: Wed, 5 Oct 2022 18:16:42 +0200 Subject: [PATCH] Acquire all RPLs modules are using (once) to prevent them from getting unloaded while using them --- wumsloader/src/entry.cpp | 18 ++++++------ wumsloader/src/globals.cpp | 2 +- wumsloader/src/globals.h | 2 +- wumsloader/src/utils/RelocationUtils.cpp | 35 ++++++++++-------------- wumsloader/src/utils/RelocationUtils.h | 5 ++-- 5 files changed, 29 insertions(+), 33 deletions(-) diff --git a/wumsloader/src/entry.cpp b/wumsloader/src/entry.cpp index 52ade72..42c28b2 100644 --- a/wumsloader/src/entry.cpp +++ b/wumsloader/src/entry.cpp @@ -41,19 +41,19 @@ extern "C" int _start(int argc, char **argv) { } void SaveLoadedRPLsInGlobalInformation(module_information_t *globalInformation, - std::vector loadedRPLs) { + std::map &usedRPls) { // free previous allocations. if (globalInformation->acquired_rpls) { free(globalInformation->acquired_rpls); } - globalInformation->number_acquired_rpls = loadedRPLs.size(); - globalInformation->acquired_rpls = (uint32_t *) malloc(loadedRPLs.size() * sizeof(uint32_t)); + globalInformation->number_acquired_rpls = usedRPls.size(); + globalInformation->acquired_rpls = (uint32_t *) malloc(usedRPls.size() * sizeof(uint32_t)); if (!globalInformation->acquired_rpls) { OSFatal("Failed to allocate memory"); } uint32_t i = 0; - for (auto &rpl : loadedRPLs) { - globalInformation->acquired_rpls[i] = (uint32_t) rpl; + for (auto &rpl : usedRPls) { + globalInformation->acquired_rpls[i] = (uint32_t) rpl.second; ++i; } } @@ -62,7 +62,7 @@ void doStart(int argc, char **argv) { init_wut(); initLogging(); - gLoadedRPLs.clear(); + gUsedRPLs.clear(); // If an allocated rpl was not released properly (e.g. if something else calls OSDynload_Acquire without releasing it) // memory gets leaked. Let's clean this up! for (auto &addr : gAllocatedAddresses) { @@ -135,7 +135,7 @@ void doStart(int argc, char **argv) { } DEBUG_FUNCTION_LINE_VERBOSE("Resolve relocations without replacing alloc functions"); - ResolveRelocations(gLoadedModules, true, gLoadedRPLs); + ResolveRelocations(gLoadedModules, true, gUsedRPLs); for (auto &curModule : gLoadedModules) { if (curModule->isInitBeforeRelocationDoneHook()) { @@ -153,11 +153,11 @@ void doStart(int argc, char **argv) { } } else { DEBUG_FUNCTION_LINE("Resolve relocations and replace alloc functions"); - ResolveRelocations(gLoadedModules, false, gLoadedRPLs); + ResolveRelocations(gLoadedModules, false, gUsedRPLs); CallHook(gLoadedModules, WUMS_HOOK_RELOCATIONS_DONE); } - SaveLoadedRPLsInGlobalInformation(&gModuleInformation, gLoadedRPLs); + SaveLoadedRPLsInGlobalInformation(&gModuleInformation, gUsedRPLs); CallHook(gLoadedModules, WUMS_HOOK_INIT_WUT_DEVOPTAB); CallHook(gLoadedModules, WUMS_HOOK_INIT_WUT_SOCKETS); diff --git a/wumsloader/src/globals.cpp b/wumsloader/src/globals.cpp index 5756d81..d007573 100644 --- a/wumsloader/src/globals.cpp +++ b/wumsloader/src/globals.cpp @@ -6,5 +6,5 @@ module_information_t gModuleInformation __attribute__((section(".data"))); std::vector> gLoadedModules __attribute__((section(".data"))); std::unique_ptr gModuleDataInfo __attribute__((section(".data"))); -std::vector gLoadedRPLs __attribute__((section(".data"))); +std::map gUsedRPLs __attribute__((section(".data"))); std::vector gAllocatedAddresses __attribute__((section(".data"))); \ No newline at end of file diff --git a/wumsloader/src/globals.h b/wumsloader/src/globals.h index f15c715..9bf02df 100644 --- a/wumsloader/src/globals.h +++ b/wumsloader/src/globals.h @@ -11,7 +11,7 @@ extern MEMHeapHandle gHeapHandle; extern module_information_t gModuleInformation; extern std::vector> gLoadedModules; extern std::unique_ptr gModuleDataInfo; -extern std::vector gLoadedRPLs; +extern std::map gUsedRPLs; extern std::vector gAllocatedAddresses; #define MEMORY_REGION_START 0x00800000 diff --git a/wumsloader/src/utils/RelocationUtils.cpp b/wumsloader/src/utils/RelocationUtils.cpp index 488d854..d205db9 100644 --- a/wumsloader/src/utils/RelocationUtils.cpp +++ b/wumsloader/src/utils/RelocationUtils.cpp @@ -40,7 +40,7 @@ static void CustomDynLoadFree(void *addr) { } } -bool ResolveRelocations(std::vector> &loadedModules, bool skipMemoryMappingModule, std::vector &loadedRPLs) { +bool ResolveRelocations(std::vector> &loadedModules, bool skipMemoryMappingModule, std::map &usedRPls) { bool wasSuccessful = true; OSDynLoadAllocFn prevDynLoadAlloc = nullptr; @@ -60,7 +60,7 @@ bool ResolveRelocations(std::vector> &loadedModules, // Afterwards we can just rely on the custom heap. bool skipAllocFunction = skipMemoryMappingModule && (std::string_view(curModule->getExportName()) == "homebrew_memorymapping"); DEBUG_FUNCTION_LINE_VERBOSE("Skip alloc replace? %d", skipAllocFunction); - if (!doRelocation(gLoadedModules, relocData, nullptr, 0, skipAllocFunction, loadedRPLs)) { + if (!doRelocation(gLoadedModules, relocData, nullptr, 0, skipAllocFunction, usedRPls)) { wasSuccessful = false; DEBUG_FUNCTION_LINE_ERR("Failed to do Relocations for %s", curModule->getExportName().c_str()); OSFatal("Failed to do Relocations"); @@ -79,8 +79,7 @@ bool doRelocation(const std::vector> &moduleList, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, bool skipAllocReplacement, - std::vector &loadedRPLs) { - std::map moduleCache; + std::map &usedRPls) { for (auto const &curReloc : relocData) { auto &functionName = curReloc->getName(); std::string rplName = curReloc->getImportRPLInformation()->getRPLName(); @@ -109,26 +108,22 @@ bool doRelocation(const std::vector> &moduleList, if (functionAddress == 0) { int32_t isData = curReloc->getImportRPLInformation()->isData(); OSDynLoad_Module rplHandle = nullptr; - if (moduleCache.count(rplName) == 0) { - OSDynLoad_Error err = OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle); - if (err != OS_DYNLOAD_OK || rplHandle == nullptr) { - DEBUG_FUNCTION_LINE_VERBOSE("%s is not yet loaded", rplName.c_str()); - // only acquire if not already loaded. - err = OSDynLoad_Acquire(rplName.c_str(), &rplHandle); - if (err != OS_DYNLOAD_OK) { - DEBUG_FUNCTION_LINE_ERR("Failed to acquire %s", rplName.c_str()); - return false; - } - // Keep track RPLs we have acquired, they will be released on exit (see: AromaBaseModule) - loadedRPLs.push_back(rplHandle); - } - moduleCache[rplName] = rplHandle; + + if (!usedRPls.contains(rplName)) { + DEBUG_FUNCTION_LINE_VERBOSE("Acquire %s", rplName.c_str()); + // Always acquire to increase refcount and make sure it won't get unloaded while we're using it. + OSDynLoad_Acquire(rplName.c_str(), &rplHandle); + // Keep track RPLs we are using. + // They will be released on exit in the AromaBaseModule + usedRPls[rplName] = rplHandle; + } else { + DEBUG_FUNCTION_LINE_VERBOSE("Use from usedRPLs cache! %s", rplName.c_str()); } - rplHandle = moduleCache.at(rplName); + rplHandle = usedRPls[rplName]; OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void **) &functionAddress); if (functionAddress == 0) { - DEBUG_FUNCTION_LINE_ERR("Failed to find export %s of %s", functionName.begin(), rplName.c_str()); + DEBUG_FUNCTION_LINE_ERR("Failed to find export %s of %s", functionName.c_str(), rplName.c_str()); OSFatal("Failed to find export"); return false; } diff --git a/wumsloader/src/utils/RelocationUtils.h b/wumsloader/src/utils/RelocationUtils.h index fcb93c0..49112f2 100644 --- a/wumsloader/src/utils/RelocationUtils.h +++ b/wumsloader/src/utils/RelocationUtils.h @@ -1,15 +1,16 @@ #pragma once #include "module/ModuleData.h" #include +#include #include bool ResolveRelocations(std::vector> &loadedModules, bool skipMemoryMappingModule, - std::vector &loadedRPLs); + std::map &usedRPls); bool doRelocation(const std::vector> &moduleList, const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, bool skipAllocReplacement, - std::vector &loadedRPLs); \ No newline at end of file + std::map &usedRPls); \ No newline at end of file