fix(patcher): skip pt note and null-page pt load headers

This commit is contained in:
boykopovar 2026-08-03 23:28:43 +03:00
parent b05f877e15
commit e451fde738
2 changed files with 31 additions and 20 deletions

View File

@ -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<std::uint8_t> _buildEntryStub(std::uint64_t stubVaddr, std::uint64_t realEntryVaddr) const;
void _writeInterp(std::vector<std::uint8_t>& buf, std::size_t phEntOff, std::uint64_t interpOff, std::uint64_t interpSize) const;

View File

@ -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<std::uint8_t>& 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<std::uint8_t>& 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<std::uint8_t> 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<std::uint8_t>(ET_DYN & 0xFF);
buf[0x11] = static_cast<std::uint8_t>((ET_DYN >> 8) & 0xFF);
_writeU64(buf, 40, 0);
_writeU16(buf, 60, 0);
_writeU16(buf, 62, 0);
const std::uint64_t phOff = *reinterpret_cast<const std::uint64_t*>(buf.data() + 32);
const std::uint16_t phEntSize = *reinterpret_cast<const std::uint16_t*>(buf.data() + 54);
const std::uint16_t phNum = *reinterpret_cast<const std::uint16_t*>(buf.data() + 56);
std::vector<ProgramHeader> loadSegs;
for (const auto& ph : originalHeaders)
if (ph.Type == PT_LOAD)
loadSegs.push_back(ph);
const auto alignBuf = [](std::vector<std::uint8_t>& b, std::size_t alignment) {
while (b.size() % alignment != 0)
b.push_back(0);
};
const std::uint64_t dynStrOff = static_cast<std::uint64_t>(buf.size());
for (std::uint8_t b : dynSection.DynStrData)
buf.push_back(b);
alignBuf(buf, 24);
const std::uint64_t dynSymOff = static_cast<std::uint64_t>(buf.size());
for (std::uint8_t b : dynSection.DynSymData)
buf.push_back(b);
alignBuf(buf, 24);
const std::uint64_t relaOff = static_cast<std::uint64_t>(buf.size());
for (std::uint8_t b : dynSection.RelaData)
buf.push_back(b);
alignBuf(buf, 24);
const std::uint64_t relaPltOff = static_cast<std::uint64_t>(buf.size());
for (std::uint8_t b : dynSection.RelaPltData)
buf.push_back(b);
alignBuf(buf, 8);
std::vector<std::uint8_t> 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<std::size_t>(phOff) + writtenPh * phEntSize;
if (ph.Type == PT_LOAD) {