diff --git a/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp b/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp index e1091def8..ef4790b78 100644 --- a/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp +++ b/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp @@ -1,6 +1,7 @@ #include "prx/libc/include/General.hpp" #include #include +#include #include #include #include @@ -57,6 +58,13 @@ char* APS5_VABI dlerror_nid_postfix() { pendingError = false; return loaderError.data(); } +static std::filesystem::path RelinkedModulePath(const std::filesystem::path& path) { + auto relinked = path; + relinked += ".guest.prx"; + std::error_code error; + return std::filesystem::is_regular_file(relinked, error) ? relinked : path; +} + void* APS5_VABI dlopen_nid_postfix(const char* path, int flags) { if ((flags & ~0x103) || (flags & 3) == 0 || (flags & 3) == 3) { Error("dlopen: unsupported flags"); return nullptr; @@ -70,7 +78,7 @@ void* APS5_VABI dlopen_nid_postfix(const char* path, int flags) { module->owned = false; } else { if (!*path) { Error("dlopen: empty module path"); return nullptr; } - const auto resolved = ResolvePath_nid_no_patch(path); + const auto resolved = RelinkedModulePath(ResolvePath_nid_no_patch(path)); module->native = LoadLibraryExW(resolved.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); } if (!module->native) { @@ -79,7 +87,7 @@ void* APS5_VABI dlopen_nid_postfix(const char* path, int flags) { Error(message); return nullptr; } #else - const auto resolved = path ? ResolvePath_nid_no_patch(path).string() : std::string{}; + const auto resolved = path ? RelinkedModulePath(ResolvePath_nid_no_patch(path)).string() : std::string{}; const int nativeFlags = ((flags & 3) == 1 ? RTLD_LAZY : RTLD_NOW) | ((flags & 0x100) ? RTLD_GLOBAL : RTLD_LOCAL); module->native = ::dlopen(path ? resolved.c_str() : nullptr, nativeFlags); diff --git a/core/libs/tests/GuestDynamicLoader.cpp b/core/libs/tests/GuestDynamicLoader.cpp index 2fa27e917..04b369b73 100644 --- a/core/libs/tests/GuestDynamicLoader.cpp +++ b/core/libs/tests/GuestDynamicLoader.cpp @@ -1,5 +1,7 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include +#include +#include #include extern "C" { void* APS5_VABI dlopen_nid_postfix(const char*, int); @@ -37,4 +39,20 @@ int main(int argc, char** argv) { Require(add && add(2, 3) == 5); Require(dlclose_nid_postfix(second) == 0); Require(dlclose_nid_postfix(second) == -1); + + const std::filesystem::path guest = "anyps5-relinked-module-for-test.prx"; + auto relinked = guest; + relinked += ".guest.prx"; + { + std::ofstream elf(guest, std::ios::binary); + elf.write("\x7f" "ELF", 4); + } + std::filesystem::copy_file(argv[1], relinked, std::filesystem::copy_options::overwrite_existing); + void* redirected = dlopen_nid_postfix(guest.string().c_str(), 2); + Require(redirected != nullptr); + add = reinterpret_cast(dlsym_nid_postfix(redirected, "GuestModuleAdd")); + Require(add && add(40, 2) == 42); + Require(dlclose_nid_postfix(redirected) == 0); + std::filesystem::remove(guest); + std::filesystem::remove(relinked); }