[rpcsx-os/linker] Implement module overriding with -o flag

This commit is contained in:
DH 2023-06-29 13:51:08 +03:00
parent 3d5ea2120c
commit c7f7242c63
4 changed files with 46 additions and 20 deletions

View file

@ -5,6 +5,7 @@
#include "vfs.hpp" #include "vfs.hpp"
#include "vm.hpp" #include "vm.hpp"
#include <elf.h> #include <elf.h>
#include <map>
#include <memory> #include <memory>
#include <orbis/thread/Process.hpp> #include <orbis/thread/Process.hpp>
#include <sys/mman.h> #include <sys/mman.h>
@ -268,8 +269,11 @@ struct Symbol {
std::uint64_t bindMode; std::uint64_t bindMode;
}; };
static std::unordered_map<std::uint64_t, std::vector<Symbol>> g_symTable; static std::map<std::string, std::filesystem::path, std::less<>> g_moduleOverrideTable;
static std::vector<std::string> g_libraryPathList;
void rx::linker::override(std::string originalModuleName, std::filesystem::path replacedModulePath) {
g_moduleOverrideTable[std::move(originalModuleName)] = std::move(replacedModulePath);
}
Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image, orbis::Process *process) { Ref<orbis::Module> rx::linker::loadModule(std::span<std::byte> image, orbis::Process *process) {
Ref<orbis::Module> result{new orbis::Module{}}; Ref<orbis::Module> result{new orbis::Module{}};
@ -755,3 +759,21 @@ Ref<orbis::Module> rx::linker::loadModuleFile(const char *path,
return loadModule(image, process); return loadModule(image, process);
} }
Ref<orbis::Module> 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{};
}

View file

@ -3,6 +3,7 @@
#include "orbis/module/Module.hpp" #include "orbis/module/Module.hpp"
#include "orbis/utils/Rc.hpp" #include "orbis/utils/Rc.hpp"
#include <cstddef> #include <cstddef>
#include <filesystem>
#include <span> #include <span>
namespace rx::linker { namespace rx::linker {
@ -58,6 +59,8 @@ enum OrbisElfType_t {
kElfTypeSceDynamic = 0xfe18 kElfTypeSceDynamic = 0xfe18
}; };
orbis::utils::Ref<orbis::Module> loadModule(std::span<std::byte> image, orbis::Process *process); void override(std::string originalModuleName, std::filesystem::path replacedModulePath);
orbis::utils::Ref<orbis::Module> loadModuleFile(const char *path, orbis::Process *process); orbis::Ref<orbis::Module> loadModule(std::span<std::byte> image, orbis::Process *process);
orbis::Ref<orbis::Module> loadModuleFile(const char *path, orbis::Process *process);
orbis::Ref<orbis::Module> loadModuleByName(std::string_view name, orbis::Process *process);
} // namespace re::loader } // namespace re::loader

View file

@ -534,6 +534,7 @@ static void usage(const char *argv0) {
std::printf("%s [<options>...] <virtual path to elf> [args...]\n", argv0); std::printf("%s [<options>...] <virtual path to elf> [args...]\n", argv0);
std::printf(" options:\n"); std::printf(" options:\n");
std::printf(" -m, --mount <host path> <virtual path>\n"); std::printf(" -m, --mount <host path> <virtual path>\n");
std::printf(" -o, --override <original module name> <virtual path to overriden module>\n");
std::printf(" --trace\n"); std::printf(" --trace\n");
} }
@ -685,6 +686,20 @@ int main(int argc, const char *argv[]) {
continue; 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; break;
} }

View file

@ -468,23 +468,9 @@ SysResult processNeeded(Thread *thread) {
continue; continue;
} }
hasLoadedNeeded = true; auto neededModule = rx::linker::loadModuleByName(needed, proc);
std::printf("loading needed: %s\n", needed.c_str()); if (neededModule == nullptr) {
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) {
std::printf("Needed '%s' not found\n", needed.c_str()); std::printf("Needed '%s' not found\n", needed.c_str());
return ErrorCode::NOENT; return ErrorCode::NOENT;
} }