refactor(relinker): read the executable's DT_NEEDED entries in one place

This commit is contained in:
overlordxrz-source 2026-10-08 01:56:07 +00:00
parent 9619edff72
commit cd51d8b1bf
1 changed files with 22 additions and 19 deletions

View File

@ -12,6 +12,25 @@
namespace Relinker {
namespace {
std::vector<std::string> ReadNeededNames(const Domain::SysVDynamicSection& dynamic) {
if (dynamic.DynamicSegmentData.size() % 16 != 0) throw Domain::RelinkerException("Invalid executable dependency table");
std::vector<std::string> 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<std::ptrdiff_t>(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<GuestArtifact> 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<std::string>& excludedModules) const {
const auto root = std::filesystem::absolute(inputPath).parent_path();
const auto singular = root / "sce_module";
@ -47,16 +66,9 @@ std::vector<GuestArtifact> 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<std::string> 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<std::ptrdiff_t>(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<GuestArtifact> 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();