diff --git a/core/elfpatcher/include/elfpatcher/general/SegmentFilter.hpp b/core/elfpatcher/include/elfpatcher/general/SegmentFilter.hpp index 48012d2e6..4d404c68d 100644 --- a/core/elfpatcher/include/elfpatcher/general/SegmentFilter.hpp +++ b/core/elfpatcher/include/elfpatcher/general/SegmentFilter.hpp @@ -11,7 +11,6 @@ public: private: [[nodiscard]] bool _isSceSpecificSegment(std::uint32_t type) const; - [[nodiscard]] bool _isNullPageLoad(const Domain::ProgramHeader& ph) const; }; } diff --git a/core/elfpatcher/src/general/ProgramHeaderLayoutBuilder.cpp b/core/elfpatcher/src/general/ProgramHeaderLayoutBuilder.cpp index 2be7bc93c..4d722ebdc 100644 --- a/core/elfpatcher/src/general/ProgramHeaderLayoutBuilder.cpp +++ b/core/elfpatcher/src/general/ProgramHeaderLayoutBuilder.cpp @@ -29,7 +29,7 @@ void ProgramHeaderLayoutBuilder::_writeProgramHeader(std::vector& Domain::ProgramHeader ProgramHeaderLayoutBuilder::_makeLoadHeader(std::uint64_t offset, std::uint64_t vaddr, std::uint64_t size) const { Domain::ProgramHeader ph{}; ph.Type = PT_LOAD; - ph.Flags = PF_R | PF_W; + ph.Flags = PF_R | PF_W | PF_X; ph.Offset = offset; ph.MappedAddress = vaddr; ph.PhysicalAddress = vaddr; @@ -130,21 +130,11 @@ std::uint16_t ProgramHeaderLayoutBuilder::WriteLayout( const ProgramHeaderLayoutRequest& request ) const { std::uint16_t keptCount = 0; - std::uint64_t keptMinVaddr = UINT64_MAX; - std::uint64_t keptMinVaddrAlign = kDefaultLoadAlignment; for (const auto& ph : request.OriginalHeaders) { if (_segmentFilter->ShouldSkip(ph)) continue; keptCount++; - if (ph.Type == PT_LOAD && ph.MappedAddress < keptMinVaddr) { - keptMinVaddr = ph.MappedAddress; - keptMinVaddrAlign = ph.Alignment; - } } - if (keptMinVaddr == UINT64_MAX) - throw Domain::RelinkerException("No kept PT_LOAD segment to anchor the header block against"); - if (keptMinVaddrAlign == 0) - throw Domain::RelinkerException("Lowest kept PT_LOAD has zero alignment"); const std::uint16_t neededPh = keptCount + kSyntheticProgramHeaderCount; if (neededPh > request.PhNum) @@ -153,14 +143,9 @@ std::uint16_t ProgramHeaderLayoutBuilder::WriteLayout( ", available " + std::to_string(request.PhNum)); const std::uint64_t headerBlockSize = request.PhOff + static_cast(neededPh) * request.PhEntSize; - if (headerBlockSize >= keptMinVaddr) - throw Domain::RelinkerException( - "Header block does not fit below the lowest kept PT_LOAD: need " + - std::to_string(headerBlockSize) + " bytes, only " + std::to_string(keptMinVaddr) + " available"); - - const std::uint64_t headerBlockVaddr = (keptMinVaddr - headerBlockSize) & ~(keptMinVaddrAlign - 1); - if (headerBlockVaddr + headerBlockSize > keptMinVaddr) - throw Domain::RelinkerException("Header block would overlap the lowest kept PT_LOAD after alignment"); + const std::uint64_t headerBlockAlign = kDefaultLoadAlignment; + const std::uint64_t headerBlockVaddr = + (request.ExtraBlockVaddr + request.ExtraBlockSize + headerBlockAlign - 1) & ~(headerBlockAlign - 1); if (request.DynamicSegmentOffset < request.ExtraBlockOffset) throw Domain::RelinkerException("Dynamic segment offset lies before the extra block"); @@ -181,7 +166,7 @@ std::uint16_t ProgramHeaderLayoutBuilder::WriteLayout( writtenPh++; const std::size_t headerLoadEntOff = static_cast(request.PhOff) + writtenPh * request.PhEntSize; - _writeProgramHeader(buf, headerLoadEntOff, _makeHeaderBlockLoad(headerBlockVaddr, headerBlockSize, keptMinVaddrAlign)); + _writeProgramHeader(buf, headerLoadEntOff, _makeHeaderBlockLoad(headerBlockVaddr, headerBlockSize, headerBlockAlign)); writtenPh++; for (const auto& ph : request.OriginalHeaders) { diff --git a/core/elfpatcher/src/general/SegmentFilter.cpp b/core/elfpatcher/src/general/SegmentFilter.cpp index 2da71afd8..d775393c1 100644 --- a/core/elfpatcher/src/general/SegmentFilter.cpp +++ b/core/elfpatcher/src/general/SegmentFilter.cpp @@ -10,14 +10,9 @@ bool SegmentFilter::_isSceSpecificSegment(const std::uint32_t type) const { || (type >= PT_LOOS && type <= PT_HIOS); } -bool SegmentFilter::_isNullPageLoad(const Domain::ProgramHeader& ph) const { - return ph.Type == PT_LOAD && ph.MappedAddress == 0; -} - bool SegmentFilter::ShouldSkip(const Domain::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; } diff --git a/core/elfpatcher/src/linux/LinuxElfPatcher.cpp b/core/elfpatcher/src/linux/LinuxElfPatcher.cpp index 1ee380a03..8358682a9 100644 --- a/core/elfpatcher/src/linux/LinuxElfPatcher.cpp +++ b/core/elfpatcher/src/linux/LinuxElfPatcher.cpp @@ -107,10 +107,11 @@ std::vector LinuxElfPatcher::Patch( const std::uint64_t realEntryVaddr = *reinterpret_cast(buf.data() + kEhdrEntryOffset); const auto stubOff = static_cast(buf.size()); - const auto stubBytes = _entryStubBuilder->BuildEntryStub(stubOff, realEntryVaddr); + const auto stubVaddr = vaddrOfExtraBlockOffset(stubOff); + const auto stubBytes = _entryStubBuilder->BuildEntryStub(stubVaddr, realEntryVaddr); for (std::uint8_t b : stubBytes) buf.push_back(b); - _byteWriter->WriteU64(buf, kEhdrEntryOffset, stubOff); + _byteWriter->WriteU64(buf, kEhdrEntryOffset, stubVaddr); static constexpr char kInterp[] = "/lib64/ld-linux-x86-64.so.2"; const auto interpOff = static_cast(buf.size());