fix(windows): expose shared libc for internal runtime imports

This commit is contained in:
SamG-Coder 2026-09-25 06:00:07 +10:00
parent 6ba24a895c
commit f146a3d069
2 changed files with 30 additions and 0 deletions

View File

@ -48,6 +48,11 @@ std::vector<std::string> 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;
}

View File

@ -3,6 +3,7 @@
#include <windows.h>
#include <elfpatcher/windows/WindowsDependencyStubBuilder.hpp>
#include <elfpatcher/windows/WindowsPeWriter.hpp>
#include <elfpatcher/windows/WindowsImportBuilder.hpp>
#include <io/BufferUtils.hpp>
#include <filesystem>
#include <fstream>
@ -14,6 +15,29 @@ namespace {
namespace Fs = std::filesystem;
using namespace Elfpatcher::Windows;
void checkRuntimeDependencies() {
const auto check = [](const std::vector<std::string>& input, const std::vector<std::string>& 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<std::uint8_t>& bytes) {
std::ofstream stream(path, std::ios::binary);
if (!stream.write(reinterpret_cast<const char*>(bytes.data()), static_cast<std::streamsize>(bytes.size())))
@ -154,6 +178,7 @@ void expectDiagnostic(const Fs::path& runner, const std::vector<std::string>& ex
int main() {
try {
checkRuntimeDependencies();
std::vector<char> filename(32768);
const auto size = GetModuleFileNameA(nullptr, filename.data(), static_cast<DWORD>(filename.size()));
if (size == 0 || size >= filename.size())