From f146a3d069b8b2adf73fee6e6a3c0907f94fa374 Mon Sep 17 00:00:00 2001 From: SamG-Coder <13449963+SamG-Coder@users.noreply.github.com> Date: Fri, 25 Sep 2026 06:00:07 +1000 Subject: [PATCH] fix(windows): expose shared libc for internal runtime imports --- .../src/windows/WindowsImportBuilder.cpp | 5 ++++ .../WindowsDependencyDiagnosticsTests.cpp | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) 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())