diff --git a/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp b/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp index 99368fb49..d74b68fd1 100644 --- a/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp +++ b/core/relinker/relinker/src/guest/GuestModuleBuilder.cpp @@ -12,6 +12,25 @@ namespace Relinker { +namespace { + +std::vector ReadNeededNames(const Domain::SysVDynamicSection& dynamic) { + if (dynamic.DynamicSegmentData.size() % 16 != 0) throw Domain::RelinkerException("Invalid executable dependency table"); + std::vector names; + for (std::size_t offset = 0; offset < dynamic.DynamicSegmentData.size(); offset += 16) { + if (Io::ReadU64(dynamic.DynamicSegmentData, offset) != 1) throw Domain::RelinkerException("Unexpected executable dependency tag"); + const auto nameOffset = Io::ReadU64(dynamic.DynamicSegmentData, offset + 8); + if (nameOffset >= dynamic.DynStrData.size()) throw Domain::RelinkerException("Invalid dependency string offset"); + const auto start = dynamic.DynStrData.begin() + static_cast(nameOffset); + const auto end = std::find(start, dynamic.DynStrData.end(), 0); + if (end == dynamic.DynStrData.end()) throw Domain::RelinkerException("Unterminated dependency string"); + names.emplace_back(start, end); + } + return names; +} + +} + std::vector GuestModuleBuilder::Build(const std::filesystem::path& inputPath, const std::filesystem::path& outputPath, Domain::SysVDynamicSection& dynamic, const bool windows, const bool toIntel, ISyscallScanner& syscallScanner, const bool lazyBinding, const std::string& runPath, const std::set& excludedModules) const { const auto root = std::filesystem::absolute(inputPath).parent_path(); const auto singular = root / "sce_module"; @@ -47,16 +66,9 @@ std::vector GuestModuleBuilder::Build(const std::filesystem::path if (isElf(entry.path())) paths.push_back(entry.path()); } } - if (dynamic.DynamicSegmentData.size() % 16 != 0) throw Domain::RelinkerException("Invalid executable dependency table"); + const auto neededNames = ReadNeededNames(dynamic); std::set missingNeeded; - for (std::size_t offset = 0; offset < dynamic.DynamicSegmentData.size(); offset += 16) { - if (Io::ReadU64(dynamic.DynamicSegmentData, offset) != 1) continue; - const auto nameOffset = Io::ReadU64(dynamic.DynamicSegmentData, offset + 8); - if (nameOffset >= dynamic.DynStrData.size()) throw Domain::RelinkerException("Invalid dependency string offset"); - const auto start = dynamic.DynStrData.begin() + static_cast(nameOffset); - const auto end = std::find(start, dynamic.DynStrData.end(), 0); - if (end == dynamic.DynStrData.end()) throw Domain::RelinkerException("Unterminated dependency string"); - const std::string name(start, end); + for (const auto& name : neededNames) { if (excludedModules.contains(name)) continue; if (std::none_of(paths.begin(), paths.end(), [&](const auto& path) { return path.filename().string() == name; })) missingNeeded.insert(name); } @@ -204,16 +216,7 @@ std::vector GuestModuleBuilder::Build(const std::filesystem::path if (name.empty() || name.find_first_of("/\\:$") != std::string::npos) throw Domain::RelinkerException("Invalid host dependency: " + name); if (uniqueHosts.insert(name).second) hostLibraries.push_back(name); }; - if (dynamic.DynamicSegmentData.size() % 16 != 0) throw Domain::RelinkerException("Invalid executable dependency table"); - for (std::size_t offset = 0; offset < dynamic.DynamicSegmentData.size(); offset += 16) { - if (Io::ReadU64(dynamic.DynamicSegmentData, offset) != 1) throw Domain::RelinkerException("Unexpected executable dependency tag"); - const auto nameOffset = Io::ReadU64(dynamic.DynamicSegmentData, offset + 8); - if (nameOffset >= dynamic.DynStrData.size()) throw Domain::RelinkerException("Invalid dependency string offset"); - const auto start = dynamic.DynStrData.begin() + nameOffset; - const auto end = std::find(start, dynamic.DynStrData.end(), 0); - if (end == dynamic.DynStrData.end()) throw Domain::RelinkerException("Unterminated dependency string"); - addHost(std::string(start, end)); - } + for (const auto& name : neededNames) addHost(name); for (const auto& image : images) for (const auto& dependency : image.Dependencies) addHost(dependency); if (uniqueHosts.contains("libSceLibcInternal.prx") && uniqueHosts.insert("libc.prx").second) hostLibraries.push_back("libc.prx"); dynamic.DynamicSegmentData.clear();