diff --git a/rpcsx-os/linker.cpp b/rpcsx-os/linker.cpp index 912513a2d..d3ce01a4a 100644 --- a/rpcsx-os/linker.cpp +++ b/rpcsx-os/linker.cpp @@ -5,6 +5,7 @@ #include "vfs.hpp" #include "vm.hpp" #include +#include #include #include #include @@ -268,8 +269,11 @@ struct Symbol { std::uint64_t bindMode; }; -static std::unordered_map> g_symTable; -static std::vector g_libraryPathList; +static std::map> g_moduleOverrideTable; + +void rx::linker::override(std::string originalModuleName, std::filesystem::path replacedModulePath) { + g_moduleOverrideTable[std::move(originalModuleName)] = std::move(replacedModulePath); +} Ref rx::linker::loadModule(std::span image, orbis::Process *process) { Ref result{new orbis::Module{}}; @@ -755,3 +759,21 @@ Ref rx::linker::loadModuleFile(const char *path, return loadModule(image, process); } + +Ref rx::linker::loadModuleByName(std::string_view name, orbis::Process *process) { + if (auto it = g_moduleOverrideTable.find(name); it != g_moduleOverrideTable.end()) { + return loadModuleFile(it->second.c_str(), process); + } + + for (auto path : {"/system/common/lib/", "/system/priv/lib/"}) { + auto filePath = std::string(path); + filePath += name; + filePath += ".sprx"; + + if (auto result = rx::linker::loadModuleFile(filePath.c_str(), process)) { + return result; + } + } + + return{}; +} diff --git a/rpcsx-os/linker.hpp b/rpcsx-os/linker.hpp index 61d161ef1..3791e2d4c 100644 --- a/rpcsx-os/linker.hpp +++ b/rpcsx-os/linker.hpp @@ -3,6 +3,7 @@ #include "orbis/module/Module.hpp" #include "orbis/utils/Rc.hpp" #include +#include #include namespace rx::linker { @@ -58,6 +59,8 @@ enum OrbisElfType_t { kElfTypeSceDynamic = 0xfe18 }; -orbis::utils::Ref loadModule(std::span image, orbis::Process *process); -orbis::utils::Ref loadModuleFile(const char *path, orbis::Process *process); +void override(std::string originalModuleName, std::filesystem::path replacedModulePath); +orbis::Ref loadModule(std::span image, orbis::Process *process); +orbis::Ref loadModuleFile(const char *path, orbis::Process *process); +orbis::Ref loadModuleByName(std::string_view name, orbis::Process *process); } // namespace re::loader diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 5f2de80ea..2e651d688 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -534,6 +534,7 @@ static void usage(const char *argv0) { std::printf("%s [...] [args...]\n", argv0); std::printf(" options:\n"); std::printf(" -m, --mount \n"); + std::printf(" -o, --override \n"); std::printf(" --trace\n"); } @@ -685,6 +686,20 @@ int main(int argc, const char *argv[]) { continue; } + if (argv[argIndex] == std::string_view("--override") || + argv[argIndex] == std::string_view("-o")) { + if (argc <= argIndex + 2) { + usage(argv[0]); + return 1; + } + + rx::linker::override(argv[argIndex + 1], argv[argIndex + 2]); + + argIndex += 3; + continue; + } + + break; } diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 1cb7331c1..c1236767e 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -468,23 +468,9 @@ SysResult processNeeded(Thread *thread) { continue; } - hasLoadedNeeded = true; + auto neededModule = rx::linker::loadModuleByName(needed, proc); - std::printf("loading needed: %s\n", needed.c_str()); - bool isLoaded = false; - for (auto path : {"/system/common/lib/", "/system/priv/lib/"}) { - auto loadedNeeded = rx::linker::loadModuleFile( - (std::string(path) + needed + ".sprx").c_str(), proc); - - if (loadedNeeded == nullptr) { - continue; - } - - isLoaded = true; - break; - } - - if (!isLoaded) { + if (neededModule == nullptr) { std::printf("Needed '%s' not found\n", needed.c_str()); return ErrorCode::NOENT; }