diff --git a/core/relinker/elfpatcher/src/windows/WindowsImportBuilder.cpp b/core/relinker/elfpatcher/src/windows/WindowsImportBuilder.cpp index d1b54e371..7a449830c 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsImportBuilder.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsImportBuilder.cpp @@ -48,6 +48,11 @@ std::vector WindowsImportBuilder::ReadLibraries(const Domain::SysVD throw Domain::RelinkerException("Invalid or duplicate DT_NEEDED library: " + name); result.push_back(std::move(name)); } + // AnyPS5 implements the C runtime in libc.prx. Windows GetProcAddress + // does not search a module's dependencies as ELF symbol lookup does. + // Keep the requested module first, then make its shared runtime visible. + if (unique.contains("libSceLibcInternal.prx") && !unique.contains("libc.prx")) + result.push_back("libc.prx"); return result; } diff --git a/core/relinker/elfpatcher/tests/WindowsDependencyDiagnosticsTests.cpp b/core/relinker/elfpatcher/tests/WindowsDependencyDiagnosticsTests.cpp index 77f0a6f89..9866f1f07 100644 --- a/core/relinker/elfpatcher/tests/WindowsDependencyDiagnosticsTests.cpp +++ b/core/relinker/elfpatcher/tests/WindowsDependencyDiagnosticsTests.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,29 @@ namespace { namespace Fs = std::filesystem; using namespace Elfpatcher::Windows; +void checkRuntimeDependencies() { + const auto check = [](const std::vector& input, const std::vector& expected) { + Domain::SysVDynamicSection dynamic; + for (const auto& name : input) { + const auto offset = dynamic.DynStrData.size(); + dynamic.DynStrData.insert(dynamic.DynStrData.end(), name.begin(), name.end()); + dynamic.DynStrData.push_back(0); + const auto position = dynamic.DynamicSegmentData.size(); + dynamic.DynamicSegmentData.resize(position + 16); + Io::WriteU64(dynamic.DynamicSegmentData, position, 1); + Io::WriteU64(dynamic.DynamicSegmentData, position + 8, offset); + } + if (WindowsImportBuilder{}.ReadLibraries(dynamic) != expected) + throw std::runtime_error("Incorrect Windows runtime dependency visibility"); + }; + check({}, {}); + check({"libkernel.prx"}, {"libkernel.prx"}); + check({"libSceLibcInternal.prx", "libkernel.prx"}, + {"libSceLibcInternal.prx", "libkernel.prx", "libc.prx"}); + check({"libc.prx", "libSceLibcInternal.prx"}, + {"libc.prx", "libSceLibcInternal.prx"}); +} + void writeFile(const Fs::path& path, const std::vector& bytes) { std::ofstream stream(path, std::ios::binary); if (!stream.write(reinterpret_cast(bytes.data()), static_cast(bytes.size()))) @@ -154,6 +178,7 @@ void expectDiagnostic(const Fs::path& runner, const std::vector& ex int main() { try { + checkRuntimeDependencies(); std::vector filename(32768); const auto size = GetModuleFileNameA(nullptr, filename.data(), static_cast(filename.size())); if (size == 0 || size >= filename.size())