diff --git a/core/relinker/include/relinker/output/ElfPatcher.hpp b/core/relinker/include/relinker/output/ElfPatcher.hpp index 681382666..be68b9bb0 100644 --- a/core/relinker/include/relinker/output/ElfPatcher.hpp +++ b/core/relinker/include/relinker/output/ElfPatcher.hpp @@ -18,6 +18,7 @@ private: static constexpr std::uint32_t PT_LOAD = 1; static constexpr std::uint32_t PT_DYNAMIC = 2; static constexpr std::uint32_t PT_INTERP = 3; + static constexpr std::uint32_t PT_NOTE = 4; static constexpr std::uint32_t PT_GNU_RELRO = 0x6474e552; static constexpr std::uint32_t PF_X = 0x1; static constexpr std::uint32_t PF_W = 0x2; @@ -42,6 +43,7 @@ private: [[nodiscard]] bool _isSceSpecificSegment(std::uint32_t type) const; [[nodiscard]] bool _isNullPageLoad(const ProgramHeader& ph) const; + [[nodiscard]] bool _shouldSkip(const ProgramHeader& ph) const; [[nodiscard]] ProgramHeader _makeLoadHeader(std::uint64_t offset, std::uint64_t size) const; [[nodiscard]] std::vector _buildEntryStub(std::uint64_t stubVaddr, std::uint64_t realEntryVaddr) const; void _writeInterp(std::vector& buf, std::size_t phEntOff, std::uint64_t interpOff, std::uint64_t interpSize) const; diff --git a/core/relinker/src/output/ElfPatcher.cpp b/core/relinker/src/output/ElfPatcher.cpp index 5ae2bc514..bfb1ef49d 100644 --- a/core/relinker/src/output/ElfPatcher.cpp +++ b/core/relinker/src/output/ElfPatcher.cpp @@ -11,6 +11,10 @@ bool ElfPatcher::_isSceSpecificSegment(std::uint32_t type) const { || (type >= 0x61000000 && type <= 0x6fffffff); } +bool ElfPatcher::_isNullPageLoad(const ProgramHeader& ph) const { + return ph.Type == PT_LOAD && ph.MappedAddress == 0; +} + void ElfPatcher::_writeU16(std::vector& buf, std::size_t offset, std::uint16_t v) const { std::memcpy(buf.data() + offset, &v, 2); } @@ -49,14 +53,10 @@ void ElfPatcher::_writeProgramHeader(std::vector& buf, std::size_t _writeU64(buf, offset + 48, ph.Alignment); } -bool ElfPatcher::_isNullPageLoad(const ProgramHeader& ph) const { - return ph.Type == PT_LOAD && ph.MappedAddress == 0; -} - ProgramHeader ElfPatcher::_makeLoadHeader(std::uint64_t offset, std::uint64_t size) const { ProgramHeader ph{}; ph.Type = PT_LOAD; - ph.Flags = PF_R | PF_X; + ph.Flags = PF_R; ph.Offset = offset; ph.MappedAddress = offset; ph.PhysicalAddress = offset; @@ -101,11 +101,15 @@ std::vector ElfPatcher::_buildEntryStub(std::uint64_t stubVaddr, s } std::uint32_t ElfPatcher::_fixLoadFlags(std::uint32_t originalFlags) const { - std::uint32_t flags = originalFlags; - if ((flags & (PF_R | PF_W | PF_X)) == 0) - flags |= PF_R; - flags |= PF_R; - return flags; + return originalFlags | PF_R; +} + +bool ElfPatcher::_shouldSkip(const ProgramHeader& ph) const { + if (_isSceSpecificSegment(ph.Type)) return true; + if (ph.Type == PT_DYNAMIC) return true; + if (_isNullPageLoad(ph)) return true; + if (ph.Type == PT_NOTE && ph.MappedAddress == 0 && ph.FileSize > 0) return true; + return false; } void ElfPatcher::PatchAndWrite( @@ -127,33 +131,42 @@ void ElfPatcher::PatchAndWrite( buf[8] = 0; buf[0x10] = static_cast(ET_DYN & 0xFF); buf[0x11] = static_cast((ET_DYN >> 8) & 0xFF); + _writeU64(buf, 40, 0); + _writeU16(buf, 60, 0); + _writeU16(buf, 62, 0); const std::uint64_t phOff = *reinterpret_cast(buf.data() + 32); const std::uint16_t phEntSize = *reinterpret_cast(buf.data() + 54); const std::uint16_t phNum = *reinterpret_cast(buf.data() + 56); - std::vector loadSegs; - for (const auto& ph : originalHeaders) - if (ph.Type == PT_LOAD) - loadSegs.push_back(ph); + const auto alignBuf = [](std::vector& b, std::size_t alignment) { + while (b.size() % alignment != 0) + b.push_back(0); + }; const std::uint64_t dynStrOff = static_cast(buf.size()); for (std::uint8_t b : dynSection.DynStrData) buf.push_back(b); + alignBuf(buf, 24); const std::uint64_t dynSymOff = static_cast(buf.size()); for (std::uint8_t b : dynSection.DynSymData) buf.push_back(b); + alignBuf(buf, 24); const std::uint64_t relaOff = static_cast(buf.size()); for (std::uint8_t b : dynSection.RelaData) buf.push_back(b); + alignBuf(buf, 24); const std::uint64_t relaPltOff = static_cast(buf.size()); for (std::uint8_t b : dynSection.RelaPltData) buf.push_back(b); + alignBuf(buf, 8); std::vector dynSegBuf; + for (std::uint8_t b : dynSection.DynamicSegmentData) + dynSegBuf.push_back(b); _appendDynEntry(dynSegBuf, DT_STRTAB, dynStrOff); _appendDynEntry(dynSegBuf, DT_STRSZ, dynSection.DynStrData.size()); _appendDynEntry(dynSegBuf, DT_SYMTAB, dynSymOff); @@ -192,9 +205,7 @@ void ElfPatcher::PatchAndWrite( std::uint16_t keptCount = 0; for (const auto& ph : originalHeaders) { - if (_isSceSpecificSegment(ph.Type)) - continue; - if (ph.Type == PT_DYNAMIC) + if (_shouldSkip(ph)) continue; keptCount++; } @@ -206,9 +217,7 @@ void ElfPatcher::PatchAndWrite( std::uint16_t writtenPh = 0; for (const auto& ph : originalHeaders) { - if (_isSceSpecificSegment(ph.Type)) - continue; - if (ph.Type == PT_DYNAMIC) + if (_shouldSkip(ph)) continue; const std::size_t phEntOff = static_cast(phOff) + writtenPh * phEntSize; if (ph.Type == PT_LOAD) {