mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
Merge pull request #6325 from amirerfantim/refactor/relinker-remove-dead-code
refactor(relinker): remove functions nothing calls
This commit is contained in:
11 files changed
-175
No files matched your search
@@ -38,7 +38,6 @@ struct MemoryOperand {
|
||||
[[nodiscard]] MemoryOperand DecodeMemoryOperand(const std::uint8_t* data, std::size_t length, std::size_t modRmOffset, std::uint8_t rex, std::vector<std::uint8_t> prefixes);
|
||||
|
||||
void EmitSse(std::vector<std::uint8_t>& out, std::uint8_t prefix, std::initializer_list<std::uint8_t> opcode, std::uint8_t dst, std::uint8_t src);
|
||||
void EmitShiftImm(std::vector<std::uint8_t>& out, std::uint8_t extension, std::uint8_t reg, std::uint8_t imm);
|
||||
void ApplyStubRelocations(std::span<std::uint8_t> body, std::span<const StubRelocation> relocations, std::uint64_t siteAddress, std::uint64_t stubAddress, Domain::FileByteOffset failureOffset);
|
||||
|
||||
class StubBodyBuilder {
|
||||
|
||||
@@ -100,10 +100,6 @@ void EmitSse(std::vector<std::uint8_t>& out, const std::uint8_t prefix, const st
|
||||
_emit(out, prefix, dst, src, opcode, static_cast<std::uint8_t>(kModRmRegister | ((dst & 7) << 3) | (src & 7)));
|
||||
}
|
||||
|
||||
void EmitShiftImm(std::vector<std::uint8_t>& out, const std::uint8_t extension, const std::uint8_t reg, const std::uint8_t imm) {
|
||||
_shiftImm(out, kShiftQwords, extension, reg, imm);
|
||||
}
|
||||
|
||||
void StubBodyBuilder::Sse(const std::uint8_t prefix, const std::initializer_list<std::uint8_t> opcode, const std::uint8_t dst, const std::uint8_t src) {
|
||||
EmitSse(_bytes, prefix, opcode, dst, src);
|
||||
}
|
||||
|
||||
@@ -10,17 +10,9 @@ class ValidationPolicy : public IValidationPolicy {
|
||||
public:
|
||||
ValidationPolicy() = default;
|
||||
|
||||
void ValidateSyscallAbsence() override;
|
||||
void ValidateRelocationTypeSupported(std::uint32_t relocationTypeValue, FileByteOffset fileByteOffset) override;
|
||||
void ValidateNidBelongsToLibrary(const std::string& nid, const std::string& library) override;
|
||||
void ValidateSceStructureSize(ByteCount expectedSize, ByteCount actualSize, FileByteOffset fileByteOffset) override;
|
||||
void ValidateDynamicFieldInterpretable(const std::string& fieldName, FileByteOffset fileByteOffset) override;
|
||||
void ValidateNoSyscallInstructions(const std::vector<std::uint8_t>& codeSection, FileByteOffset codeOffset) override;
|
||||
|
||||
void RegisterLibraryImport(const std::string& library);
|
||||
|
||||
private:
|
||||
std::set<std::string> _importedLibraries;
|
||||
std::set<std::uint32_t> _supportedRelocationTypes;
|
||||
|
||||
void _initializeSupportedRelocationTypes();
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
[[nodiscard]] virtual std::vector<SectionHeader> ReadSectionHeaders() const = 0;
|
||||
[[nodiscard]] virtual std::vector<DynamicTag> ReadDynamicTags(const ProgramHeader& dynamicHeader) const = 0;
|
||||
[[nodiscard]] virtual FileByteOffset TranslateVirtualAddress(VirtualAddress address) const = 0;
|
||||
[[nodiscard]] virtual std::vector<std::uint8_t> ReadSection(const SectionHeader& header) const = 0;
|
||||
[[nodiscard]] virtual std::vector<std::uint8_t> ReadSegment(const ProgramHeader& header) const = 0;
|
||||
[[nodiscard]] virtual std::uint64_t GetFileSize() const = 0;
|
||||
[[nodiscard]] virtual const std::vector<std::uint8_t>& GetRawBytes() const = 0;
|
||||
|
||||
@@ -9,12 +9,7 @@ class IValidationPolicy {
|
||||
public:
|
||||
virtual ~IValidationPolicy() = default;
|
||||
|
||||
virtual void ValidateSyscallAbsence() = 0;
|
||||
virtual void ValidateRelocationTypeSupported(std::uint32_t relocationTypeValue, FileByteOffset fileByteOffset) = 0;
|
||||
virtual void ValidateNidBelongsToLibrary(const std::string& nid, const std::string& library) = 0;
|
||||
virtual void ValidateSceStructureSize(ByteCount expectedSize, ByteCount actualSize, FileByteOffset fileByteOffset) = 0;
|
||||
virtual void ValidateDynamicFieldInterpretable(const std::string& fieldName, FileByteOffset fileByteOffset) = 0;
|
||||
virtual void ValidateNoSyscallInstructions(const std::vector<std::uint8_t>& codeSection, FileByteOffset codeOffset) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ struct GuestImage {
|
||||
|
||||
class GuestImageReader {
|
||||
public:
|
||||
std::vector<std::string> ReadModuleNames(const std::vector<std::uint8_t>& bytes) const;
|
||||
GuestImage Read(const std::filesystem::path& path, std::vector<std::uint8_t> bytes, bool windows = false) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ public:
|
||||
std::vector<SectionHeader> ReadSectionHeaders() const override;
|
||||
std::vector<DynamicTag> ReadDynamicTags(const ProgramHeader& dynamicHeader) const override;
|
||||
FileByteOffset TranslateVirtualAddress(VirtualAddress address) const override;
|
||||
std::vector<std::uint8_t> ReadSection(const SectionHeader& header) const override;
|
||||
std::vector<std::uint8_t> ReadSegment(const ProgramHeader& header) const override;
|
||||
std::uint64_t GetFileSize() const override;
|
||||
const std::vector<std::uint8_t>& GetRawBytes() const override;
|
||||
|
||||
@@ -6,15 +6,6 @@ namespace Relinker {
|
||||
|
||||
using namespace Elfpatcher;
|
||||
|
||||
static constexpr std::uint8_t SYSCALL_BYTE0 = 0x0F;
|
||||
static constexpr std::uint8_t SYSCALL_BYTE1 = 0x05;
|
||||
static constexpr std::uint8_t INT80_BYTE0 = 0xCD;
|
||||
static constexpr std::uint8_t INT80_BYTE1 = 0x80;
|
||||
static constexpr std::uint8_t SYSENTER_BYTE0 = 0x0F;
|
||||
static constexpr std::uint8_t SYSENTER_BYTE1 = 0x34;
|
||||
static constexpr std::uint8_t SYSRET_BYTE0 = 0x0F;
|
||||
static constexpr std::uint8_t SYSRET_BYTE1 = 0x07;
|
||||
|
||||
void ValidationPolicy::_initializeSupportedRelocationTypes() {
|
||||
_supportedRelocationTypes = {
|
||||
R_X86_64_NONE,
|
||||
@@ -37,16 +28,6 @@ void ValidationPolicy::_initializeSupportedRelocationTypes() {
|
||||
};
|
||||
}
|
||||
|
||||
void ValidationPolicy::RegisterLibraryImport(const std::string& library) {
|
||||
if (_supportedRelocationTypes.empty()) {
|
||||
_initializeSupportedRelocationTypes();
|
||||
}
|
||||
_importedLibraries.insert(library);
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateSyscallAbsence() {
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateRelocationTypeSupported(const std::uint32_t relocationTypeValue, const FileByteOffset fileByteOffset) {
|
||||
if (_supportedRelocationTypes.empty()) {
|
||||
_initializeSupportedRelocationTypes();
|
||||
@@ -59,49 +40,4 @@ void ValidationPolicy::ValidateRelocationTypeSupported(const std::uint32_t reloc
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateNidBelongsToLibrary(const std::string& Nid, const std::string& library) {
|
||||
if (_importedLibraries.find(library) == _importedLibraries.end()) {
|
||||
std::ostringstream msg;
|
||||
msg << "NID \"" << Nid << "\" references library \"" << library
|
||||
<< "\" which is not in the NEEDED list";
|
||||
throw RelinkerException(msg.str(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateSceStructureSize(const ByteCount expectedSize, const ByteCount actualSize, const FileByteOffset fileByteOffset) {
|
||||
if (actualSize != expectedSize) {
|
||||
std::ostringstream msg;
|
||||
msg << "SCE structure size mismatch at offset 0x" << std::hex << fileByteOffset
|
||||
<< ": expected " << std::dec << expectedSize << ", got " << actualSize;
|
||||
throw RelinkerException(msg.str(), fileByteOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateDynamicFieldInterpretable(const std::string& fieldName, const FileByteOffset fileByteOffset) {
|
||||
std::ostringstream msg;
|
||||
msg << "Dynamic field \"" << fieldName
|
||||
<< "\" cannot be interpreted at offset 0x" << std::hex << fileByteOffset;
|
||||
throw RelinkerException(msg.str(), fileByteOffset);
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateNoSyscallInstructions(
|
||||
const std::vector<std::uint8_t>& CodeSection, const FileByteOffset codeOffset) {
|
||||
for (std::size_t i = 0; i + 1 < CodeSection.size(); ++i) {
|
||||
const std::uint8_t b0 = CodeSection[i];
|
||||
const std::uint8_t b1 = CodeSection[i + 1];
|
||||
|
||||
bool isSyscall = (b0 == SYSCALL_BYTE0 && b1 == SYSCALL_BYTE1);
|
||||
bool isInt80 = (b0 == INT80_BYTE0 && b1 == INT80_BYTE1);
|
||||
bool isSysenter = (b0 == SYSENTER_BYTE0 && b1 == SYSENTER_BYTE1);
|
||||
bool isSysret = (b0 == SYSRET_BYTE0 && b1 == SYSRET_BYTE1);
|
||||
|
||||
if (isSyscall || isInt80 || isSysenter || isSysret) {
|
||||
FileByteOffset instrOffset = codeOffset + i;
|
||||
std::ostringstream msg;
|
||||
msg << "Forbidden syscall instruction at offset 0x" << std::hex << instrOffset;
|
||||
throw RelinkerException(msg.str(), instrOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,82 +12,6 @@
|
||||
|
||||
namespace Relinker {
|
||||
|
||||
std::vector<std::string> GuestImageReader::ReadModuleNames(const std::vector<std::uint8_t>& bytes) const {
|
||||
if (bytes.size() < 64 || Io::ReadU32(bytes, 0) != 0x464c457f || bytes[4] != 2 || bytes[5] != 1 || bytes[6] != 1 || Io::ReadU16(bytes, 18) != 62)
|
||||
throw Domain::RelinkerException("Expected little-endian ELF64 x86-64 module metadata");
|
||||
const auto type = Io::ReadU16(bytes, 16);
|
||||
if (type != 3 && type != 0xfe18) return {};
|
||||
if (Io::ReadU16(bytes, 52) != 64 || Io::ReadU16(bytes, 54) != 56 || Io::ReadU16(bytes, 56) == 0)
|
||||
throw Domain::RelinkerException("Invalid module metadata program headers");
|
||||
const auto range = [&](std::uint64_t offset, std::uint64_t size) {
|
||||
if (offset > bytes.size() || size > bytes.size() - offset) throw Domain::RelinkerException("Module metadata exceeds file");
|
||||
};
|
||||
range(Io::ReadU64(bytes, 32), static_cast<std::uint64_t>(Io::ReadU16(bytes, 56)) * 56);
|
||||
ElfReader reader(bytes);
|
||||
const auto headers = reader.ReadProgramHeaders();
|
||||
const Domain::ProgramHeader* dynamic = nullptr;
|
||||
const Domain::ProgramHeader* dynlib = nullptr;
|
||||
for (const auto& header : headers) {
|
||||
if (header.Type == 2) {
|
||||
if (dynamic) throw Domain::RelinkerException("Duplicate module metadata dynamic segment");
|
||||
dynamic = &header;
|
||||
}
|
||||
if (header.Type == 0x61000000) {
|
||||
if (dynlib) throw Domain::RelinkerException("Duplicate module metadata dynamic data");
|
||||
dynlib = &header;
|
||||
}
|
||||
}
|
||||
if (!dynamic) throw Domain::RelinkerException("Missing module metadata dynamic segment");
|
||||
std::map<std::uint64_t, std::uint64_t> strings;
|
||||
std::vector<std::uint64_t> modules;
|
||||
for (const auto& tag : reader.ReadDynamicTags(*dynamic)) {
|
||||
if (tag.Tag == 0x6100000d || tag.Tag == 0x61000043) modules.push_back(tag.Value);
|
||||
else if (tag.Tag == 5 || tag.Tag == 10 || tag.Tag == 0x61000035 || tag.Tag == 0x61000037) {
|
||||
if (!strings.emplace(tag.Tag, tag.Value).second) throw Domain::RelinkerException("Duplicate module metadata string tag");
|
||||
}
|
||||
}
|
||||
if (modules.empty()) return {};
|
||||
const auto get = [&](std::uint64_t standard, std::uint64_t sce) {
|
||||
if (strings.contains(standard) == strings.contains(sce)) throw Domain::RelinkerException("Missing or ambiguous module metadata string tag");
|
||||
return strings.at(strings.contains(standard) ? standard : sce);
|
||||
};
|
||||
const auto size = get(10, 0x61000037);
|
||||
const auto address = get(5, 0x61000035);
|
||||
std::uint64_t offset = 0;
|
||||
if (strings.contains(5)) {
|
||||
bool found = false;
|
||||
for (const auto& header : headers) {
|
||||
if (header.Type != 1 || address < header.MappedAddress || address - header.MappedAddress > header.FileSize || size > header.FileSize - (address - header.MappedAddress)) continue;
|
||||
range(header.Offset, header.FileSize);
|
||||
if (found) throw Domain::RelinkerException("Ambiguous module metadata string mapping");
|
||||
offset = header.Offset + address - header.MappedAddress;
|
||||
found = true;
|
||||
}
|
||||
if (!found) throw Domain::RelinkerException("Unmapped module metadata strings");
|
||||
} else {
|
||||
if (!dynlib || address > dynlib->FileSize || size > dynlib->FileSize - address) throw Domain::RelinkerException("Module metadata strings exceed dynamic data");
|
||||
range(dynlib->Offset, dynlib->FileSize);
|
||||
offset = dynlib->Offset + address;
|
||||
}
|
||||
range(offset, size);
|
||||
if (size == 0 || bytes[offset] != 0) throw Domain::RelinkerException("Invalid module metadata strings");
|
||||
std::vector<std::string> names;
|
||||
std::set<std::uint64_t> ids;
|
||||
for (const auto value : modules) {
|
||||
const auto nameOffset = value & 0xffffffffu;
|
||||
if (nameOffset >= size) throw Domain::RelinkerException("Module metadata string offset out of bounds");
|
||||
const auto start = bytes.begin() + static_cast<std::ptrdiff_t>(offset + nameOffset);
|
||||
const auto end = bytes.begin() + static_cast<std::ptrdiff_t>(offset + size);
|
||||
const auto zero = std::find(start, end, 0);
|
||||
if (zero == end) throw Domain::RelinkerException("Unterminated module metadata string");
|
||||
const std::string name(start, zero);
|
||||
if (name.empty() || name.find_first_of("/\\:$\r\n") != std::string::npos) throw Domain::RelinkerException("Invalid module metadata name");
|
||||
if (!ids.insert(value >> 48).second) throw Domain::RelinkerException("Duplicate module metadata export ID");
|
||||
names.push_back(name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
GuestImage GuestImageReader::Read(const std::filesystem::path& path, std::vector<std::uint8_t> bytes, const bool windows) const try {
|
||||
const auto fail = [&](const std::string& message) { throw Domain::RelinkerException(Io::Utf8Path(path) + ": " + message); };
|
||||
const auto range = [&](std::uint64_t offset, std::uint64_t size) {
|
||||
|
||||
@@ -292,16 +292,6 @@ FileByteOffset ElfReader::TranslateVirtualAddress(VirtualAddress address) const
|
||||
throw RelinkerException("Virtual address not mapped by any PT_LOAD segment", address);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> ElfReader::ReadSection(const SectionHeader& header) const {
|
||||
if (!_rangeFits(header.Offset, header.SectionSize, _fileBuffer.size())) {
|
||||
throw RelinkerException("Section offset out of bounds", header.Offset);
|
||||
}
|
||||
|
||||
return std::vector<std::uint8_t>(
|
||||
_fileBuffer.begin() + header.Offset,
|
||||
_fileBuffer.begin() + header.Offset + header.SectionSize);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> ElfReader::ReadSegment(const ProgramHeader& header) const {
|
||||
if (!_rangeFits(header.Offset, header.FileSize, _fileBuffer.size())) {
|
||||
throw RelinkerException("Segment offset out of bounds", header.Offset);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <relinker/pipeline/RelinkerPipeline.hpp>
|
||||
#include <elfpatcher/general/ElfConstants.hpp>
|
||||
#include <relinker/analysis/ValidationPolicy.hpp>
|
||||
#include <relinker/analysis/UnusedNidFilter/PltCompactor.hpp>
|
||||
#include <relinker/analysis/UnusedNidFilter/EhFrameReader.hpp>
|
||||
#include <relinker/analysis/SceCodeExtent.hpp>
|
||||
@@ -230,7 +229,6 @@ RelinkResult RelinkerPipeline::Relink() {
|
||||
|
||||
std::vector<NidReference> nidRefs;
|
||||
std::vector<std::string> neededLibraries;
|
||||
auto policy = std::dynamic_pointer_cast<ValidationPolicy>(validationPolicy);
|
||||
|
||||
const std::vector<std::uint8_t>& raw = elfReader->GetRawBytes();
|
||||
const std::optional<ByteCount> dynSymTabSize = hasTag(DT_OS_SYMTABSZ)
|
||||
@@ -261,7 +259,6 @@ RelinkResult RelinkerPipeline::Relink() {
|
||||
for (auto& [fst, snd] : neededLibraryNamesByStrOffset) {
|
||||
snd = readCStr(fst);
|
||||
neededLibraries.push_back(snd);
|
||||
if (policy) policy->RegisterLibraryImport(snd);
|
||||
}
|
||||
|
||||
std::map<std::uint64_t, std::string> importModules;
|
||||
@@ -382,7 +379,6 @@ RelinkResult RelinkerPipeline::Relink() {
|
||||
}
|
||||
}
|
||||
|
||||
validationPolicy->ValidateSyscallAbsence();
|
||||
|
||||
std::vector<std::pair<ByteCount, std::string>> exportedSymbols;
|
||||
std::vector<VirtualAddress> exportedFunctions;
|
||||
|
||||
Reference in new issue
Block a user