refactor(core): add some nodiscard and const
This commit is contained in:
parent
2654c8eb4b
commit
4d8fc76ff7
|
|
@ -9,13 +9,13 @@ namespace Relinker {
|
|||
|
||||
class ElfReader : public IElfReader {
|
||||
public:
|
||||
explicit ElfReader(const std::string& FilePath);
|
||||
explicit ElfReader(const std::string& filePath);
|
||||
|
||||
ElfHeader ReadHeader() const override;
|
||||
std::vector<ProgramHeader> ReadProgramHeaders() const override;
|
||||
std::vector<SectionHeader> ReadSectionHeaders() 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::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;
|
||||
|
||||
private:
|
||||
|
|
@ -23,11 +23,11 @@ private:
|
|||
mutable std::vector<std::uint8_t> _fileBuffer;
|
||||
|
||||
void _loadFileIntoBuffer() const;
|
||||
std::uint64_t _readU64At(FileByteOffset FileByteOffset) const;
|
||||
std::uint32_t _readU32At(FileByteOffset FileByteOffset) const;
|
||||
std::uint16_t _readU16At(FileByteOffset FileByteOffset) const;
|
||||
std::uint8_t _readU8At(FileByteOffset FileByteOffset) const;
|
||||
std::string _resolveShdrName(std::uint32_t NameOffset, const ElfHeader& Header) const;
|
||||
std::uint64_t _readU64At(FileByteOffset fileByteOffset) const;
|
||||
std::uint32_t _readU32At(FileByteOffset fileByteOffset) const;
|
||||
std::uint16_t _readU16At(FileByteOffset fileByteOffset) const;
|
||||
std::uint8_t _readU8At(FileByteOffset fileByteOffset) const;
|
||||
std::string _resolveShdrName(std::uint32_t nameOffset, const ElfHeader& header) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class ICallRegistryWriter {
|
|||
public:
|
||||
virtual ~ICallRegistryWriter() = default;
|
||||
|
||||
virtual std::string WriteCallRegistry(const std::vector<CallRegistryEntry>& Entries) = 0;
|
||||
virtual std::string WriteCallRegistry(const std::vector<CallRegistryEntry>& entries) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ public:
|
|||
virtual ~ICallSiteResolver() = default;
|
||||
|
||||
virtual std::vector<FileByteOffset> ResolveCallSites(
|
||||
const std::vector<std::uint8_t>& TextSection,
|
||||
FileByteOffset TextSectionVAddr,
|
||||
VirtualAddress TargetGotOrPltAddress,
|
||||
ByteCount TargetGotOrPltSize
|
||||
const std::vector<std::uint8_t>& textSection,
|
||||
FileByteOffset textSectionVAddr,
|
||||
VirtualAddress targetGotOrPltAddress,
|
||||
ByteCount targetGotOrPltSize
|
||||
) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ class IElfReader {
|
|||
public:
|
||||
virtual ~IElfReader() = default;
|
||||
|
||||
virtual ElfHeader ReadHeader() const = 0;
|
||||
virtual std::vector<ProgramHeader> ReadProgramHeaders() const = 0;
|
||||
virtual std::vector<SectionHeader> ReadSectionHeaders() const = 0;
|
||||
virtual std::vector<std::uint8_t> ReadSection(const SectionHeader& Header) const = 0;
|
||||
virtual std::vector<std::uint8_t> ReadSegment(const ProgramHeader& Header) const = 0;
|
||||
virtual std::uint64_t GetFileSize() const = 0;
|
||||
[[nodiscard]] virtual ElfHeader ReadHeader() const = 0;
|
||||
[[nodiscard]] virtual std::vector<ProgramHeader> ReadProgramHeaders() const = 0;
|
||||
[[nodiscard]] virtual std::vector<SectionHeader> ReadSectionHeaders() 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ class ISceDynlibParser {
|
|||
public:
|
||||
virtual ~ISceDynlibParser() = default;
|
||||
|
||||
virtual std::vector<LibraryImport> ParseLibraryImports(const std::vector<std::uint8_t>& SceDynlibData) = 0;
|
||||
virtual std::vector<RelocationEntry> ParseRelocationTable(const std::vector<std::uint8_t>& SceDynlibData) = 0;
|
||||
virtual std::vector<LibraryImport> ParseLibraryImports(const std::vector<std::uint8_t>& sceDynlibData) = 0;
|
||||
virtual std::vector<RelocationEntry> ParseRelocationTable(const std::vector<std::uint8_t>& sceDynlibData) = 0;
|
||||
virtual std::vector<NidReference> ExtractNidReferences(
|
||||
const std::vector<RelocationEntry>& Relocations,
|
||||
const std::vector<LibraryImport>& Imports
|
||||
const std::vector<RelocationEntry>& relocations,
|
||||
const std::vector<LibraryImport>& imports
|
||||
) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,15 +9,15 @@ class ISdkRevisionProfile {
|
|||
public:
|
||||
virtual ~ISdkRevisionProfile() = default;
|
||||
|
||||
virtual std::uint32_t GetSceModuleParamHeaderSize() const = 0;
|
||||
virtual std::uint32_t GetSceModuleParamEntrySize() const = 0;
|
||||
virtual std::uint32_t GetSceDynlibDataHeaderSize() const = 0;
|
||||
virtual std::uint32_t GetSceDynlibDataEntrySize() const = 0;
|
||||
virtual std::uint32_t GetRelocationEntrySize() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetSceModuleParamHeaderSize() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetSceModuleParamEntrySize() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetSceDynlibDataHeaderSize() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetSceDynlibDataEntrySize() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetRelocationEntrySize() const = 0;
|
||||
|
||||
virtual std::uint32_t GetImportsOffset() const = 0;
|
||||
virtual std::uint32_t GetImportsCount(const std::vector<std::uint8_t>& Data) const = 0;
|
||||
virtual std::uint32_t GetRelocationTableOffset() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetImportsOffset() const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetImportsCount(const std::vector<std::uint8_t>& data) const = 0;
|
||||
[[nodiscard]] virtual std::uint32_t GetRelocationTableOffset() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ public:
|
|||
virtual ~ISysVDynamicSectionBuilder() = default;
|
||||
|
||||
virtual SysVDynamicSection BuildDynamicSection(
|
||||
const std::vector<NidReference>& NidReferences,
|
||||
const std::vector<std::string>& NeededLibraries
|
||||
const std::vector<NidReference>& nidReferences,
|
||||
const std::vector<std::string>& neededLibraries
|
||||
) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ public:
|
|||
virtual ~ISyscallScanner() = default;
|
||||
|
||||
virtual void ScanCodeSectionForSyscalls(
|
||||
const std::vector<std::uint8_t>& CodeSection,
|
||||
FileByteOffset CodeSectionOffset,
|
||||
FileByteOffset CodeSectionSize
|
||||
const std::vector<std::uint8_t>& codeSection,
|
||||
FileByteOffset codeSectionOffset,
|
||||
FileByteOffset codeSectionSize
|
||||
) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ 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;
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,22 +12,22 @@ class SceDynlibParser : public ISceDynlibParser {
|
|||
public:
|
||||
explicit SceDynlibParser(std::shared_ptr<ISdkRevisionProfile> SdkProfile);
|
||||
|
||||
std::vector<LibraryImport> ParseLibraryImports(const std::vector<std::uint8_t>& SceDynlibData) override;
|
||||
std::vector<RelocationEntry> ParseRelocationTable(const std::vector<std::uint8_t>& SceDynlibData) override;
|
||||
std::vector<LibraryImport> ParseLibraryImports(const std::vector<std::uint8_t>& sceDynlibData) override;
|
||||
std::vector<RelocationEntry> ParseRelocationTable(const std::vector<std::uint8_t>& sceDynlibData) override;
|
||||
std::vector<NidReference> ExtractNidReferences(
|
||||
const std::vector<RelocationEntry>& Relocations,
|
||||
const std::vector<LibraryImport>& Imports
|
||||
const std::vector<RelocationEntry>& relocations,
|
||||
const std::vector<LibraryImport>& imports
|
||||
) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ISdkRevisionProfile> _sdkProfile;
|
||||
|
||||
std::uint32_t _readU32At(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
std::uint16_t _readU16At(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
std::uint8_t _readU8At(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
std::uint64_t _readU64At(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
std::string _extractNidFromRelocationInfo(std::uint64_t Info) const;
|
||||
std::string _getLibraryNameForRelocation(const std::vector<LibraryImport>& Imports, std::uint64_t Info) const;
|
||||
[[nodiscard]] std::uint32_t _readU32At(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
[[nodiscard]] std::uint16_t _readU16At(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
[[nodiscard]] std::uint8_t _readU8At(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
[[nodiscard]] std::uint64_t _readU64At(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
[[nodiscard]] std::string _extractNidFromRelocationInfo(std::uint64_t info) const;
|
||||
[[nodiscard]] std::string _getLibraryNameForRelocation(const std::vector<LibraryImport>& imports, std::uint64_t info) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,23 @@ namespace Relinker {
|
|||
|
||||
class SdkRevisionProfile : public ISdkRevisionProfile {
|
||||
public:
|
||||
explicit SdkRevisionProfile(const std::vector<std::uint8_t>& SceDynlibData);
|
||||
explicit SdkRevisionProfile(const std::vector<std::uint8_t>& sceDynlibData);
|
||||
|
||||
std::uint32_t GetSceModuleParamHeaderSize() const override;
|
||||
std::uint32_t GetSceModuleParamEntrySize() const override;
|
||||
std::uint32_t GetSceDynlibDataHeaderSize() const override;
|
||||
std::uint32_t GetSceDynlibDataEntrySize() const override;
|
||||
std::uint32_t GetRelocationEntrySize() const override;
|
||||
std::uint32_t GetImportsOffset() const override;
|
||||
std::uint32_t GetImportsCount(const std::vector<std::uint8_t>& Data) const override;
|
||||
std::uint32_t GetRelocationTableOffset() const override;
|
||||
[[nodiscard]] std::uint32_t GetSceModuleParamHeaderSize() const override;
|
||||
[[nodiscard]] std::uint32_t GetSceModuleParamEntrySize() const override;
|
||||
[[nodiscard]] std::uint32_t GetSceDynlibDataHeaderSize() const override;
|
||||
[[nodiscard]] std::uint32_t GetSceDynlibDataEntrySize() const override;
|
||||
[[nodiscard]] std::uint32_t GetRelocationEntrySize() const override;
|
||||
[[nodiscard]] std::uint32_t GetImportsOffset() const override;
|
||||
[[nodiscard]] std::uint32_t GetImportsCount(const std::vector<std::uint8_t>& data) const override;
|
||||
[[nodiscard]] std::uint32_t GetRelocationTableOffset() const override;
|
||||
|
||||
private:
|
||||
std::uint32_t _sdkRevision;
|
||||
|
||||
void _detectSdkRevision(const std::vector<std::uint8_t>& Data);
|
||||
std::uint32_t _readU32LittleEndian(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
std::uint16_t _readU16LittleEndian(const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const;
|
||||
void _detectSdkRevision(const std::vector<std::uint8_t>& data);
|
||||
[[nodiscard]] std::uint32_t _readU32LittleEndian(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
[[nodiscard]] std::uint16_t _readU16LittleEndian(const std::vector<std::uint8_t>& data, FileByteOffset fileByteOffset) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ struct SymbolExport {
|
|||
struct RelinkerException : std::runtime_error {
|
||||
FileByteOffset FailureOffset;
|
||||
|
||||
explicit RelinkerException(const std::string& Message, FileByteOffset FailureOffset = 0)
|
||||
: std::runtime_error(Message), FailureOffset(FailureOffset) {}
|
||||
explicit RelinkerException(const std::string& Message, const FileByteOffset failureOffset = 0)
|
||||
: std::runtime_error(Message), FailureOffset(failureOffset) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ 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 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);
|
||||
void RegisterLibraryImport(const std::string& library);
|
||||
|
||||
private:
|
||||
std::set<std::string> _importedLibraries;
|
||||
|
|
@ -28,15 +28,15 @@ static std::string _hexOffset(FileByteOffset v) {
|
|||
|
||||
class CallRegistryWriter : public ICallRegistryWriter {
|
||||
public:
|
||||
std::string WriteCallRegistry(const std::vector<CallRegistryEntry>& Entries) override;
|
||||
std::string WriteCallRegistry(const std::vector<CallRegistryEntry>& entries) override;
|
||||
};
|
||||
|
||||
std::string CallRegistryWriter::WriteCallRegistry(const std::vector<CallRegistryEntry>& Entries) {
|
||||
std::string CallRegistryWriter::WriteCallRegistry(const std::vector<CallRegistryEntry>& entries) {
|
||||
std::ostringstream out;
|
||||
out << "[\n";
|
||||
|
||||
for (std::size_t i = 0; i < Entries.size(); ++i) {
|
||||
const auto& e = Entries[i];
|
||||
for (std::size_t i = 0; i < entries.size(); ++i) {
|
||||
const auto& e = entries[i];
|
||||
|
||||
out << " {\n";
|
||||
out << " \"nid\": " << _jsonString(e.Nid) << ",\n";
|
||||
|
|
@ -56,7 +56,7 @@ std::string CallRegistryWriter::WriteCallRegistry(const std::vector<CallRegistry
|
|||
out << " \"callSitesResolved\": " << (e.CallSitesResolved ? "true" : "false") << "\n";
|
||||
out << " }";
|
||||
|
||||
if (i + 1 < Entries.size()) out << ",";
|
||||
if (i + 1 < entries.size()) out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,28 +6,28 @@ namespace Relinker {
|
|||
class CallSiteResolver : public ICallSiteResolver {
|
||||
public:
|
||||
std::vector<FileByteOffset> ResolveCallSites(
|
||||
const std::vector<std::uint8_t>& TextSection,
|
||||
FileByteOffset TextSectionVAddr,
|
||||
VirtualAddress TargetGotOrPltAddress,
|
||||
ByteCount TargetGotOrPltSize) override;
|
||||
const std::vector<std::uint8_t>& textSection,
|
||||
FileByteOffset textSectionVAddr,
|
||||
VirtualAddress targetGotOrPltAddress,
|
||||
ByteCount targetGotOrPltSize) override;
|
||||
};
|
||||
|
||||
std::vector<FileByteOffset> CallSiteResolver::ResolveCallSites(
|
||||
const std::vector<std::uint8_t>& TextSection,
|
||||
FileByteOffset TextSectionVAddr,
|
||||
VirtualAddress TargetGotOrPltAddress,
|
||||
ByteCount TargetGotOrPltSize)
|
||||
const std::vector<std::uint8_t>& textSection,
|
||||
const FileByteOffset textSectionVAddr,
|
||||
const VirtualAddress targetGotOrPltAddress,
|
||||
const ByteCount targetGotOrPltSize)
|
||||
{
|
||||
std::vector<FileByteOffset> sites;
|
||||
|
||||
if (TextSection.size() < 6)
|
||||
if (textSection.size() < 6)
|
||||
return sites;
|
||||
|
||||
const std::size_t limit = TextSection.size() - 5;
|
||||
const std::size_t limit = textSection.size() - 5;
|
||||
|
||||
for (std::size_t i = 0; i <= limit; ++i) {
|
||||
std::uint8_t b0 = TextSection[i];
|
||||
std::uint8_t b1 = TextSection[i + 1];
|
||||
std::uint8_t b0 = textSection[i];
|
||||
std::uint8_t b1 = textSection[i + 1];
|
||||
|
||||
bool isRipRelative = false;
|
||||
std::size_t dispOffset = 0;
|
||||
|
|
@ -37,8 +37,8 @@ std::vector<FileByteOffset> CallSiteResolver::ResolveCallSites(
|
|||
isRipRelative = true;
|
||||
dispOffset = i + 2;
|
||||
instrSize = 6;
|
||||
} else if (b0 == 0x48 && b1 == 0x8B && i + 6 < TextSection.size()) {
|
||||
std::uint8_t modrm = TextSection[i + 2];
|
||||
} else if (b0 == 0x48 && b1 == 0x8B && i + 6 < textSection.size()) {
|
||||
std::uint8_t modrm = textSection[i + 2];
|
||||
if ((modrm & 0xC7) == 0x05) {
|
||||
isRipRelative = true;
|
||||
dispOffset = i + 3;
|
||||
|
|
@ -49,23 +49,23 @@ std::vector<FileByteOffset> CallSiteResolver::ResolveCallSites(
|
|||
if (!isRipRelative)
|
||||
continue;
|
||||
|
||||
if (dispOffset + 3 >= TextSection.size())
|
||||
if (dispOffset + 3 >= textSection.size())
|
||||
continue;
|
||||
|
||||
std::int32_t disp =
|
||||
const auto disp =
|
||||
static_cast<std::int32_t>(
|
||||
static_cast<std::uint32_t>(TextSection[dispOffset]) |
|
||||
(static_cast<std::uint32_t>(TextSection[dispOffset + 1]) << 8) |
|
||||
(static_cast<std::uint32_t>(TextSection[dispOffset + 2]) << 16) |
|
||||
(static_cast<std::uint32_t>(TextSection[dispOffset + 3]) << 24));
|
||||
static_cast<std::uint32_t>(textSection[dispOffset]) |
|
||||
(static_cast<std::uint32_t>(textSection[dispOffset + 1]) << 8) |
|
||||
(static_cast<std::uint32_t>(textSection[dispOffset + 2]) << 16) |
|
||||
(static_cast<std::uint32_t>(textSection[dispOffset + 3]) << 24));
|
||||
|
||||
VirtualAddress nextInstrVAddr = TextSectionVAddr + i + instrSize;
|
||||
VirtualAddress resolvedAddr = static_cast<VirtualAddress>(static_cast<std::int64_t>(nextInstrVAddr) + disp);
|
||||
const VirtualAddress nextInstrVAddr = textSectionVAddr + i + instrSize;
|
||||
auto resolvedAddr = static_cast<VirtualAddress>(static_cast<std::int64_t>(nextInstrVAddr) + disp);
|
||||
|
||||
if (resolvedAddr >= TargetGotOrPltAddress &&
|
||||
resolvedAddr < TargetGotOrPltAddress + TargetGotOrPltSize)
|
||||
if (resolvedAddr >= targetGotOrPltAddress &&
|
||||
resolvedAddr < targetGotOrPltAddress + targetGotOrPltSize)
|
||||
{
|
||||
sites.push_back(TextSectionVAddr + i);
|
||||
sites.push_back(textSectionVAddr + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace Relinker {
|
||||
|
||||
ElfReader::ElfReader(const std::string& FilePath) : _filePath(FilePath) {
|
||||
ElfReader::ElfReader(const std::string& filePath) : _filePath(filePath) {
|
||||
}
|
||||
|
||||
void ElfReader::_loadFileIntoBuffer() const {
|
||||
|
|
@ -27,41 +27,41 @@ void ElfReader::_loadFileIntoBuffer() const {
|
|||
}
|
||||
}
|
||||
|
||||
std::uint8_t ElfReader::_readU8At(FileByteOffset FileByteOffset) const {
|
||||
std::uint8_t ElfReader::_readU8At(FileByteOffset fileByteOffset) const {
|
||||
_loadFileIntoBuffer();
|
||||
if (FileByteOffset >= _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
if (fileByteOffset >= _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
return _fileBuffer[FileByteOffset];
|
||||
return _fileBuffer[fileByteOffset];
|
||||
}
|
||||
|
||||
std::uint16_t ElfReader::_readU16At(FileByteOffset FileByteOffset) const {
|
||||
std::uint16_t ElfReader::_readU16At(FileByteOffset fileByteOffset) const {
|
||||
_loadFileIntoBuffer();
|
||||
if (FileByteOffset + 2 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
if (fileByteOffset + 2 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint16_t value;
|
||||
std::memcpy(&value, _fileBuffer.data() + FileByteOffset, 2);
|
||||
std::memcpy(&value, _fileBuffer.data() + fileByteOffset, 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint32_t ElfReader::_readU32At(FileByteOffset FileByteOffset) const {
|
||||
std::uint32_t ElfReader::_readU32At(FileByteOffset fileByteOffset) const {
|
||||
_loadFileIntoBuffer();
|
||||
if (FileByteOffset + 4 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
if (fileByteOffset + 4 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint32_t value;
|
||||
std::memcpy(&value, _fileBuffer.data() + FileByteOffset, 4);
|
||||
std::memcpy(&value, _fileBuffer.data() + fileByteOffset, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint64_t ElfReader::_readU64At(FileByteOffset FileByteOffset) const {
|
||||
std::uint64_t ElfReader::_readU64At(FileByteOffset fileByteOffset) const {
|
||||
_loadFileIntoBuffer();
|
||||
if (FileByteOffset + 8 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
if (fileByteOffset + 8 > _fileBuffer.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint64_t value;
|
||||
std::memcpy(&value, _fileBuffer.data() + FileByteOffset, 8);
|
||||
std::memcpy(&value, _fileBuffer.data() + fileByteOffset, 8);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ ElfHeader ElfReader::ReadHeader() const {
|
|||
throw RelinkerException("Invalid ELF magic number");
|
||||
}
|
||||
|
||||
ElfHeader header;
|
||||
ElfHeader header{};
|
||||
header.Machine = _readU16At(0x12);
|
||||
header.Type = _readU16At(0x10);
|
||||
header.OsAbi = _readU8At(0x07);
|
||||
|
|
@ -96,13 +96,13 @@ ElfHeader ElfReader::ReadHeader() const {
|
|||
|
||||
std::vector<ProgramHeader> ElfReader::ReadProgramHeaders() const {
|
||||
_loadFileIntoBuffer();
|
||||
ElfHeader header = ReadHeader();
|
||||
const ElfHeader header = ReadHeader();
|
||||
|
||||
std::vector<ProgramHeader> headers;
|
||||
FileByteOffset offset = header.ProgramHeaderOffset;
|
||||
|
||||
for (std::uint16_t i = 0; i < header.ProgramHeaderCount; ++i) {
|
||||
ProgramHeader ph;
|
||||
ProgramHeader ph{};
|
||||
ph.Type = _readU32At(offset);
|
||||
ph.Flags = _readU32At(offset + 0x04);
|
||||
ph.Offset = _readU64At(offset + 0x08);
|
||||
|
|
@ -121,14 +121,14 @@ std::vector<ProgramHeader> ElfReader::ReadProgramHeaders() const {
|
|||
|
||||
std::vector<SectionHeader> ElfReader::ReadSectionHeaders() const {
|
||||
_loadFileIntoBuffer();
|
||||
ElfHeader header = ReadHeader();
|
||||
const ElfHeader header = ReadHeader();
|
||||
|
||||
std::vector<SectionHeader> headers;
|
||||
FileByteOffset offset = header.SectionHeaderOffset;
|
||||
|
||||
for (std::uint16_t i = 0; i < header.SectionHeaderCount; ++i) {
|
||||
SectionHeader sh;
|
||||
std::uint32_t nameOffset = _readU32At(offset);
|
||||
const std::uint32_t nameOffset = _readU32At(offset);
|
||||
sh.Type = _readU32At(offset + 0x04);
|
||||
sh.Flags = _readU64At(offset + 0x08);
|
||||
sh.MappedAddress = _readU64At(offset + 0x10);
|
||||
|
|
@ -147,18 +147,18 @@ std::vector<SectionHeader> ElfReader::ReadSectionHeaders() const {
|
|||
return headers;
|
||||
}
|
||||
|
||||
std::string ElfReader::_resolveShdrName(std::uint32_t NameOffset, const ElfHeader& Header) const {
|
||||
if (Header.SectionHeaderStringIndex == 0) {
|
||||
std::string ElfReader::_resolveShdrName(std::uint32_t nameOffset, const ElfHeader& header) const {
|
||||
if (header.SectionHeaderStringIndex == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
FileByteOffset shstrOffset = Header.SectionHeaderOffset +
|
||||
(Header.SectionHeaderStringIndex * Header.SectionHeaderEntrySize);
|
||||
|
||||
FileByteOffset strTableOffset = _readU64At(shstrOffset + 0x18);
|
||||
FileByteOffset shstrOffset = header.SectionHeaderOffset +
|
||||
(header.SectionHeaderStringIndex * header.SectionHeaderEntrySize);
|
||||
|
||||
const FileByteOffset strTableOffset = _readU64At(shstrOffset + 0x18);
|
||||
|
||||
std::string name;
|
||||
FileByteOffset currentPos = strTableOffset + NameOffset;
|
||||
FileByteOffset currentPos = strTableOffset + nameOffset;
|
||||
|
||||
while (currentPos < _fileBuffer.size() && _fileBuffer[currentPos] != '\0') {
|
||||
name += static_cast<char>(_fileBuffer[currentPos]);
|
||||
|
|
@ -168,25 +168,25 @@ std::string ElfReader::_resolveShdrName(std::uint32_t NameOffset, const ElfHeade
|
|||
return name;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> ElfReader::ReadSection(const SectionHeader& Header) const {
|
||||
std::vector<std::uint8_t> ElfReader::ReadSection(const SectionHeader& header) const {
|
||||
_loadFileIntoBuffer();
|
||||
|
||||
if (Header.Offset + Header.SectionSize > _fileBuffer.size()) {
|
||||
throw RelinkerException("Section offset out of bounds", Header.Offset);
|
||||
if (header.Offset + header.SectionSize > _fileBuffer.size()) {
|
||||
throw RelinkerException("Section offset out of bounds", header.Offset);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> data(_fileBuffer.begin() + Header.Offset, _fileBuffer.begin() + Header.Offset + Header.SectionSize);
|
||||
std::vector<std::uint8_t> data(_fileBuffer.begin() + header.Offset, _fileBuffer.begin() + header.Offset + header.SectionSize);
|
||||
return data;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> ElfReader::ReadSegment(const ProgramHeader& Header) const {
|
||||
std::vector<std::uint8_t> ElfReader::ReadSegment(const ProgramHeader& header) const {
|
||||
_loadFileIntoBuffer();
|
||||
|
||||
if (Header.Offset + Header.FileSize > _fileBuffer.size()) {
|
||||
throw RelinkerException("Segment offset out of bounds", Header.Offset);
|
||||
if (header.Offset + header.FileSize > _fileBuffer.size()) {
|
||||
throw RelinkerException("Segment offset out of bounds", header.Offset);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> data(_fileBuffer.begin() + Header.Offset, _fileBuffer.begin() + Header.Offset + Header.FileSize);
|
||||
std::vector<std::uint8_t> data(_fileBuffer.begin() + header.Offset, _fileBuffer.begin() + header.Offset + header.FileSize);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,46 +15,46 @@ SceDynlibParser::SceDynlibParser(std::shared_ptr<ISdkRevisionProfile> SdkProfile
|
|||
}
|
||||
|
||||
std::uint8_t SceDynlibParser::_readU8At(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset >= Data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset >= data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", fileByteOffset);
|
||||
}
|
||||
return Data[FileByteOffset];
|
||||
return data[fileByteOffset];
|
||||
}
|
||||
|
||||
std::uint16_t SceDynlibParser::_readU16At(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset + 2 > Data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset + 2 > data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint16_t value;
|
||||
std::memcpy(&value, Data.data() + FileByteOffset, 2);
|
||||
std::memcpy(&value, data.data() + fileByteOffset, 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint32_t SceDynlibParser::_readU32At(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset + 4 > Data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset + 4 > data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint32_t value;
|
||||
std::memcpy(&value, Data.data() + FileByteOffset, 4);
|
||||
std::memcpy(&value, data.data() + fileByteOffset, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint64_t SceDynlibParser::_readU64At(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset + 8 > Data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset + 8 > data.size()) {
|
||||
throw RelinkerException("SCE dynlib data offset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint64_t value;
|
||||
std::memcpy(&value, Data.data() + FileByteOffset, 8);
|
||||
std::memcpy(&value, data.data() + fileByteOffset, 8);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<LibraryImport> SceDynlibParser::ParseLibraryImports(
|
||||
const std::vector<std::uint8_t>& SceDynlibData) {
|
||||
std::uint32_t count = _sdkProfile->GetImportsCount(SceDynlibData);
|
||||
const std::vector<std::uint8_t>& sceDynlibData) {
|
||||
std::uint32_t count = _sdkProfile->GetImportsCount(sceDynlibData);
|
||||
std::uint32_t baseOff = _sdkProfile->GetImportsOffset();
|
||||
std::uint32_t entrySize = _sdkProfile->GetSceDynlibDataEntrySize();
|
||||
|
||||
|
|
@ -63,18 +63,18 @@ std::vector<LibraryImport> SceDynlibParser::ParseLibraryImports(
|
|||
|
||||
FileByteOffset cursor = baseOff;
|
||||
for (std::uint32_t i = 0; i < count; ++i) {
|
||||
if (cursor + entrySize > SceDynlibData.size()) {
|
||||
if (cursor + entrySize > sceDynlibData.size()) {
|
||||
throw RelinkerException("Library import entry out of bounds", cursor);
|
||||
}
|
||||
|
||||
std::uint32_t nameOffset = _readU32At(SceDynlibData, cursor);
|
||||
std::uint32_t libraryId = _readU16At(SceDynlibData, cursor + 0x04);
|
||||
std::uint32_t version = _readU16At(SceDynlibData, cursor + 0x06);
|
||||
std::uint32_t nameOffset = _readU32At(sceDynlibData, cursor);
|
||||
std::uint32_t libraryId = _readU16At(sceDynlibData, cursor + 0x04);
|
||||
std::uint32_t version = _readU16At(sceDynlibData, cursor + 0x06);
|
||||
|
||||
std::string name;
|
||||
FileByteOffset namePos = nameOffset;
|
||||
while (namePos < SceDynlibData.size() && SceDynlibData[namePos] != '\0') {
|
||||
name += static_cast<char>(SceDynlibData[namePos]);
|
||||
while (namePos < sceDynlibData.size() && sceDynlibData[namePos] != '\0') {
|
||||
name += static_cast<char>(sceDynlibData[namePos]);
|
||||
++namePos;
|
||||
}
|
||||
|
||||
|
|
@ -91,22 +91,22 @@ std::vector<LibraryImport> SceDynlibParser::ParseLibraryImports(
|
|||
}
|
||||
|
||||
std::vector<RelocationEntry> SceDynlibParser::ParseRelocationTable(
|
||||
const std::vector<std::uint8_t>& SceDynlibData) {
|
||||
std::uint32_t tableOffset = _sdkProfile->GetRelocationTableOffset();
|
||||
std::uint32_t entrySize = _sdkProfile->GetRelocationEntrySize();
|
||||
const std::vector<std::uint8_t>& sceDynlibData) {
|
||||
const std::uint32_t tableOffset = _sdkProfile->GetRelocationTableOffset();
|
||||
const std::uint32_t entrySize = _sdkProfile->GetRelocationEntrySize();
|
||||
|
||||
if (tableOffset >= SceDynlibData.size()) {
|
||||
if (tableOffset >= sceDynlibData.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<RelocationEntry> entries;
|
||||
FileByteOffset cursor = tableOffset;
|
||||
|
||||
while (cursor + entrySize <= SceDynlibData.size()) {
|
||||
while (cursor + entrySize <= sceDynlibData.size()) {
|
||||
RelocationEntry entry;
|
||||
entry.EntryOffset = _readU64At(SceDynlibData, cursor);
|
||||
entry.Info = _readU64At(SceDynlibData, cursor + 0x08);
|
||||
entry.Addend = static_cast<std::int64_t>(_readU64At(SceDynlibData, cursor + 0x10));
|
||||
entry.EntryOffset = _readU64At(sceDynlibData, cursor);
|
||||
entry.Info = _readU64At(sceDynlibData, cursor + 0x08);
|
||||
entry.Addend = static_cast<std::int64_t>(_readU64At(sceDynlibData, cursor + 0x10));
|
||||
entries.push_back(entry);
|
||||
cursor += entrySize;
|
||||
}
|
||||
|
|
@ -114,34 +114,34 @@ std::vector<RelocationEntry> SceDynlibParser::ParseRelocationTable(
|
|||
return entries;
|
||||
}
|
||||
|
||||
std::string SceDynlibParser::_extractNidFromRelocationInfo(std::uint64_t Info) const {
|
||||
std::uint64_t symIndex = Info >> 32;
|
||||
std::string SceDynlibParser::_extractNidFromRelocationInfo(std::uint64_t info) const {
|
||||
std::uint64_t symIndex = info >> 32;
|
||||
std::ostringstream oss;
|
||||
oss << std::hex << symIndex;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string SceDynlibParser::_getLibraryNameForRelocation(
|
||||
const std::vector<LibraryImport>& Imports, std::uint64_t Info) const {
|
||||
std::uint32_t libIndex = static_cast<std::uint32_t>((Info & LIB_INDEX_MASK) >> LIB_INDEX_SHIFT);
|
||||
if (libIndex == 0 || libIndex > Imports.size()) {
|
||||
const std::vector<LibraryImport>& imports, const std::uint64_t info) const {
|
||||
std::uint32_t libIndex = static_cast<std::uint32_t>((info & LIB_INDEX_MASK) >> LIB_INDEX_SHIFT);
|
||||
if (libIndex == 0 || libIndex > imports.size()) {
|
||||
return "";
|
||||
}
|
||||
return Imports[libIndex - 1].LibraryName;
|
||||
return imports[libIndex - 1].LibraryName;
|
||||
}
|
||||
|
||||
std::vector<NidReference> SceDynlibParser::ExtractNidReferences(
|
||||
const std::vector<RelocationEntry>& Relocations,
|
||||
const std::vector<LibraryImport>& Imports) {
|
||||
const std::vector<RelocationEntry>& relocations,
|
||||
const std::vector<LibraryImport>& imports) {
|
||||
std::vector<NidReference> refs;
|
||||
refs.reserve(Relocations.size());
|
||||
refs.reserve(relocations.size());
|
||||
|
||||
for (std::size_t i = 0; i < Relocations.size(); ++i) {
|
||||
const auto& reloc = Relocations[i];
|
||||
for (std::size_t i = 0; i < relocations.size(); ++i) {
|
||||
const auto& reloc = relocations[i];
|
||||
std::uint32_t relocType = static_cast<std::uint32_t>(reloc.Info & RELOC_TYPE_MASK);
|
||||
|
||||
std::string nid = _extractNidFromRelocationInfo(reloc.Info);
|
||||
std::string library = _getLibraryNameForRelocation(Imports, reloc.Info);
|
||||
std::string library = _getLibraryNameForRelocation(imports, reloc.Info);
|
||||
|
||||
NidReference ref;
|
||||
ref.Nid = std::move(nid);
|
||||
|
|
|
|||
|
|
@ -11,36 +11,36 @@ constexpr std::uint32_t SCE_DYNLIBDATA_HEADER_SIZE = 0x10;
|
|||
constexpr std::uint32_t SCE_DYNLIBDATA_ENTRY_SIZE = 0x10;
|
||||
constexpr std::uint32_t RELOCATION_ENTRY_SIZE = 0x18;
|
||||
|
||||
SdkRevisionProfile::SdkRevisionProfile(const std::vector<std::uint8_t>& SceDynlibData)
|
||||
SdkRevisionProfile::SdkRevisionProfile(const std::vector<std::uint8_t>& sceDynlibData)
|
||||
: _sdkRevision(DEFAULT_SDK_REVISION) {
|
||||
_detectSdkRevision(SceDynlibData);
|
||||
_detectSdkRevision(sceDynlibData);
|
||||
}
|
||||
|
||||
void SdkRevisionProfile::_detectSdkRevision(const std::vector<std::uint8_t>& Data) {
|
||||
if (Data.size() < 8) {
|
||||
void SdkRevisionProfile::_detectSdkRevision(const std::vector<std::uint8_t>& data) {
|
||||
if (data.size() < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
_sdkRevision = _readU32LittleEndian(Data, 0x04);
|
||||
_sdkRevision = _readU32LittleEndian(data, 0x04);
|
||||
}
|
||||
|
||||
std::uint32_t SdkRevisionProfile::_readU32LittleEndian(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset + 4 > Data.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset + 4 > data.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint32_t value;
|
||||
std::memcpy(&value, Data.data() + FileByteOffset, 4);
|
||||
std::memcpy(&value, data.data() + fileByteOffset, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uint16_t SdkRevisionProfile::_readU16LittleEndian(
|
||||
const std::vector<std::uint8_t>& Data, FileByteOffset FileByteOffset) const {
|
||||
if (FileByteOffset + 2 > Data.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", FileByteOffset);
|
||||
const std::vector<std::uint8_t>& data, const FileByteOffset fileByteOffset) const {
|
||||
if (fileByteOffset + 2 > data.size()) {
|
||||
throw RelinkerException("FileByteOffset out of bounds", fileByteOffset);
|
||||
}
|
||||
std::uint16_t value;
|
||||
std::memcpy(&value, Data.data() + FileByteOffset, 2);
|
||||
std::memcpy(&value, data.data() + fileByteOffset, 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
@ -68,11 +68,11 @@ std::uint32_t SdkRevisionProfile::GetImportsOffset() const {
|
|||
return SCE_DYNLIBDATA_HEADER_SIZE;
|
||||
}
|
||||
|
||||
std::uint32_t SdkRevisionProfile::GetImportsCount(const std::vector<std::uint8_t>& Data) const {
|
||||
if (Data.size() < 8) {
|
||||
std::uint32_t SdkRevisionProfile::GetImportsCount(const std::vector<std::uint8_t>& data) const {
|
||||
if (data.size() < 8) {
|
||||
return 0;
|
||||
}
|
||||
return _readU32LittleEndian(Data, 0x00);
|
||||
return _readU32LittleEndian(data, 0x00);
|
||||
}
|
||||
|
||||
std::uint32_t SdkRevisionProfile::GetRelocationTableOffset() const {
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ static void _appendElfSym(
|
|||
|
||||
static void _appendRela(
|
||||
std::vector<std::uint8_t>& rela,
|
||||
std::uint64_t offset,
|
||||
std::uint64_t info,
|
||||
const std::uint64_t offset,
|
||||
const std::uint64_t info,
|
||||
std::int64_t addend)
|
||||
{
|
||||
_appendU64(rela, offset);
|
||||
|
|
@ -75,34 +75,34 @@ static void _appendRela(
|
|||
class SysVDynamicSectionBuilder : public ISysVDynamicSectionBuilder {
|
||||
public:
|
||||
SysVDynamicSection BuildDynamicSection(
|
||||
const std::vector<NidReference>& NidReferences,
|
||||
const std::vector<std::string>& NeededLibraries) override;
|
||||
const std::vector<NidReference>& nidReferences,
|
||||
const std::vector<std::string>& neededLibraries) override;
|
||||
};
|
||||
|
||||
SysVDynamicSection SysVDynamicSectionBuilder::BuildDynamicSection(
|
||||
const std::vector<NidReference>& NidReferences,
|
||||
const std::vector<std::string>& NeededLibraries)
|
||||
const std::vector<NidReference>& nidReferences,
|
||||
const std::vector<std::string>& neededLibraries)
|
||||
{
|
||||
SysVDynamicSection result;
|
||||
|
||||
result.DynStrData.push_back(0);
|
||||
|
||||
std::vector<std::uint32_t> neededOffsets;
|
||||
for (const auto& lib : NeededLibraries)
|
||||
for (const auto& lib : neededLibraries)
|
||||
neededOffsets.push_back(_appendStr(result.DynStrData, lib));
|
||||
|
||||
_appendElfSym(result.DynSymData, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
std::uint32_t symIdx = 1;
|
||||
for (const auto& ref : NidReferences) {
|
||||
std::uint32_t nameOff = _appendStr(result.DynStrData, ref.Nid);
|
||||
std::uint8_t info = static_cast<std::uint8_t>((STB_GLOBAL << 4) | STT_FUNC);
|
||||
for (const auto& ref : nidReferences) {
|
||||
const std::uint32_t nameOff = _appendStr(result.DynStrData, ref.Nid);
|
||||
const auto info = static_cast<std::uint8_t>((STB_GLOBAL << 4) | STT_FUNC);
|
||||
_appendElfSym(result.DynSymData, nameOff, info, STV_DEFAULT, 0, 0, 0);
|
||||
|
||||
std::uint32_t relType = ref.RelocationTypeValue;
|
||||
if (relType == 0) relType = R_X86_64_JUMP_SLOT;
|
||||
|
||||
std::uint64_t relaInfo = (static_cast<std::uint64_t>(symIdx) << 32) | relType;
|
||||
const std::uint64_t relaInfo = (static_cast<std::uint64_t>(symIdx) << 32) | relType;
|
||||
|
||||
if (relType == R_X86_64_JUMP_SLOT)
|
||||
_appendRela(result.RelaPltData, ref.RelocationAddress, relaInfo, 0);
|
||||
|
|
@ -114,7 +114,7 @@ SysVDynamicSection SysVDynamicSectionBuilder::BuildDynamicSection(
|
|||
|
||||
std::uint64_t strsz = result.DynStrData.size();
|
||||
|
||||
for (std::uint32_t off : neededOffsets)
|
||||
for (const std::uint32_t off : neededOffsets)
|
||||
_appendDynEntry(result.DynamicSegmentData, DT_NEEDED, off);
|
||||
|
||||
_appendDynEntry(result.DynamicSegmentData, DT_STRTAB, 0);
|
||||
|
|
|
|||
|
|
@ -16,28 +16,28 @@ static constexpr std::uint8_t SYSRET_BYTE1 = 0x07;
|
|||
class SyscallScanner : public ISyscallScanner {
|
||||
public:
|
||||
void ScanCodeSectionForSyscalls(
|
||||
const std::vector<std::uint8_t>& CodeSection,
|
||||
FileByteOffset CodeSectionOffset,
|
||||
FileByteOffset CodeSectionSize) override;
|
||||
const std::vector<std::uint8_t>& codeSection,
|
||||
FileByteOffset codeSectionOffset,
|
||||
FileByteOffset codeSectionSize) override;
|
||||
};
|
||||
|
||||
void SyscallScanner::ScanCodeSectionForSyscalls(
|
||||
const std::vector<std::uint8_t>& CodeSection,
|
||||
FileByteOffset CodeSectionOffset,
|
||||
FileByteOffset CodeSectionSize) {
|
||||
std::size_t limit = std::min(CodeSection.size(), static_cast<std::size_t>(CodeSectionSize));
|
||||
const std::vector<std::uint8_t>& codeSection,
|
||||
const FileByteOffset codeSectionOffset,
|
||||
const FileByteOffset codeSectionSize) {
|
||||
const std::size_t limit = std::min(codeSection.size(), static_cast<std::size_t>(codeSectionSize));
|
||||
|
||||
for (std::size_t i = 0; i + 1 < limit; ++i) {
|
||||
std::uint8_t b0 = CodeSection[i];
|
||||
std::uint8_t b1 = CodeSection[i + 1];
|
||||
std::uint8_t b0 = codeSection[i];
|
||||
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);
|
||||
const bool isSyscall = (b0 == SYSCALL_BYTE0 && b1 == SYSCALL_BYTE1);
|
||||
const bool isInt80 = (b0 == INT80_BYTE0 && b1 == INT80_BYTE1);
|
||||
const bool isSysenter = (b0 == SYSENTER_BYTE0 && b1 == SYSENTER_BYTE1);
|
||||
bool isSysret = (b0 == SYSRET_BYTE0 && b1 == SYSRET_BYTE1);
|
||||
|
||||
if (isSyscall || isInt80 || isSysenter || isSysret) {
|
||||
FileByteOffset instrOffset = CodeSectionOffset + i;
|
||||
FileByteOffset instrOffset = codeSectionOffset + i;
|
||||
std::ostringstream msg;
|
||||
msg << "Forbidden syscall instruction at code offset 0x" << std::hex << instrOffset;
|
||||
throw RelinkerException(msg.str(), instrOffset);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "ValidationPolicy.hpp"
|
||||
#include "relinker/ValidationPolicy.hpp"
|
||||
#include <sstream>
|
||||
|
||||
namespace Relinker {
|
||||
|
|
@ -46,58 +46,58 @@ void ValidationPolicy::_initializeSupportedRelocationTypes() {
|
|||
};
|
||||
}
|
||||
|
||||
void ValidationPolicy::RegisterLibraryImport(const std::string& Library) {
|
||||
void ValidationPolicy::RegisterLibraryImport(const std::string& library) {
|
||||
if (_supportedRelocationTypes.empty()) {
|
||||
_initializeSupportedRelocationTypes();
|
||||
}
|
||||
_importedLibraries.insert(Library);
|
||||
_importedLibraries.insert(library);
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateSyscallAbsence() {
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateRelocationTypeSupported(std::uint32_t RelocationTypeValue, FileByteOffset FileByteOffset) {
|
||||
void ValidationPolicy::ValidateRelocationTypeSupported(const std::uint32_t relocationTypeValue, const FileByteOffset fileByteOffset) {
|
||||
if (_supportedRelocationTypes.empty()) {
|
||||
_initializeSupportedRelocationTypes();
|
||||
}
|
||||
if (_supportedRelocationTypes.find(RelocationTypeValue) == _supportedRelocationTypes.end()) {
|
||||
if (_supportedRelocationTypes.find(relocationTypeValue) == _supportedRelocationTypes.end()) {
|
||||
std::ostringstream msg;
|
||||
msg << "Unsupported relocation type 0x" << std::hex << RelocationTypeValue
|
||||
<< " at offset 0x" << FileByteOffset;
|
||||
throw RelinkerException(msg.str(), FileByteOffset);
|
||||
msg << "Unsupported relocation type 0x" << std::hex << relocationTypeValue
|
||||
<< " at offset 0x" << fileByteOffset;
|
||||
throw RelinkerException(msg.str(), fileByteOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateNidBelongsToLibrary(const std::string& Nid, const std::string& Library) {
|
||||
if (_importedLibraries.find(Library) == _importedLibraries.end()) {
|
||||
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
|
||||
msg << "NID \"" << Nid << "\" references library \"" << library
|
||||
<< "\" which is not in the NEEDED list";
|
||||
throw RelinkerException(msg.str(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidationPolicy::ValidateSceStructureSize(ByteCount ExpectedSize, ByteCount ActualSize, FileByteOffset FileByteOffset) {
|
||||
if (ActualSize != ExpectedSize) {
|
||||
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);
|
||||
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, FileByteOffset 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);
|
||||
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, FileByteOffset CodeOffset) {
|
||||
const std::vector<std::uint8_t>& CodeSection, const FileByteOffset codeOffset) {
|
||||
for (std::size_t i = 0; i + 1 < CodeSection.size(); ++i) {
|
||||
std::uint8_t b0 = CodeSection[i];
|
||||
std::uint8_t b1 = CodeSection[i + 1];
|
||||
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);
|
||||
|
|
@ -105,7 +105,7 @@ void ValidationPolicy::ValidateNoSyscallInstructions(
|
|||
bool isSysret = (b0 == SYSRET_BYTE0 && b1 == SYSRET_BYTE1);
|
||||
|
||||
if (isSyscall || isInt80 || isSysenter || isSysret) {
|
||||
FileByteOffset instrOffset = CodeOffset + i;
|
||||
FileByteOffset instrOffset = codeOffset + i;
|
||||
std::ostringstream msg;
|
||||
msg << "Forbidden syscall instruction at offset 0x" << std::hex << instrOffset;
|
||||
throw RelinkerException(msg.str(), instrOffset);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <relinker/ICallRegistryWriter.hpp>
|
||||
#include <relinker/ISyscallScanner.hpp>
|
||||
#include <relinker/IValidationPolicy.hpp>
|
||||
#include "ValidationPolicy.hpp"
|
||||
#include "relinker/ValidationPolicy.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
|
@ -28,7 +28,7 @@ static constexpr std::uint32_t PT_DYNAMIC = 2;
|
|||
static constexpr std::uint32_t PT_SCE_DYNLIBDATA = 0x61000000;
|
||||
static constexpr std::uint32_t SHT_NULL = 0;
|
||||
|
||||
static std::string _relocationTypeName(std::uint32_t type) {
|
||||
static std::string _relocationTypeName(const std::uint32_t type) {
|
||||
switch (type) {
|
||||
case 1: return "R_X86_64_64";
|
||||
case 6: return "R_X86_64_GLOB_DAT";
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@
|
|||
- Название интерфейса (класса с виртуальными методами без реализации) начинается с `I` (как в C#).
|
||||
- Названия классов, публичных методов: PascalCase.
|
||||
- Названия приватных методов и полей: \_camelCase.
|
||||
- названия аргументов функций: camelCase.
|
||||
- Названия параметров шаблона в стиле C#: `TKey`, `TValue`, `TIterator`.
|
||||
|
|
|
|||
Loading…
Reference in New Issue