fix(relinker): map executable section addresses through load segments

This commit is contained in:
tototomate123 2026-10-08 16:47:53 +02:00
parent 5edae35361
commit 7ea423f78b
1 changed files with 21 additions and 4 deletions

View File

@ -1,5 +1,7 @@
#include <elfpatcher/general/SectionHeaderTableBuilder.hpp>
#include <elfpatcher/general/ElfConstants.hpp>
#include <io/BufferUtils.hpp>
#include <stdexcept>
namespace Elfpatcher {
@ -38,6 +40,21 @@ void SectionHeaderTableBuilder::WriteTable(
std::vector<std::uint8_t>& buf,
const SectionHeaderTableRequest& request
) const {
const auto phOffset = Io::ReadU64(buf, kEhdrPhOffOffset);
const auto phCount = Io::ReadU16(buf, kEhdrPhNumOffset);
const auto phStride = Io::ReadU16(buf, kEhdrPhEntSizeOffset);
const auto mappedAddress = [&](std::uint64_t offset) {
for (std::uint16_t index = 0; index < phCount; ++index) {
const auto header = phOffset + index * phStride;
if (Io::ReadU32(buf, header) != PT_LOAD) continue;
const auto start = Io::ReadU64(buf, header + 8);
const auto size = Io::ReadU64(buf, header + 32);
if (offset >= start && offset - start < size)
return Io::ReadU64(buf, header + 16) + offset - start;
}
throw std::runtime_error("Allocated output section is outside load segments");
};
const auto shStrTabOff = static_cast<std::uint64_t>(buf.size());
constexpr std::uint64_t shStrTabSize = sizeof(kShStrTabBlob);
for (const char i : kShStrTabBlob)
@ -48,10 +65,10 @@ void SectionHeaderTableBuilder::WriteTable(
_writeSectionHeader(buf, shOff + kShdrEntrySize * 0, 0, SHT_NULL, 0, 0, 0, 0, 0, 0, 0, 0);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 1, kShStrTabNameOffset, SHT_STRTAB, 0, shStrTabOff, shStrTabOff, shStrTabSize, 0, 0, kNoSpecialAlignment, 0);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 2, kDynStrNameOffset, SHT_STRTAB, SHF_ALLOC, request.DynStrOffset, request.DynStrOffset, request.DynStrSize, 0, 0, kNoSpecialAlignment, 0);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 3, kDynSymNameOffset, SHT_DYNSYM, SHF_ALLOC, request.DynSymOffset, request.DynSymOffset, request.DynSymSize, kDynSymLinkToStrTab, kDynSymInfoFirstGlobal, kDynSymAlign, kSymEntrySize);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 4, kDynamicNameOffset, SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE, request.DynamicSegmentOffset, request.DynamicSegmentOffset, request.DynamicSegmentSize, kDynamicLinkToStrTab, 0, kDynSymAlign, kDynEntrySize);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 5, kTextNameOffset, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, request.StubOffset, request.StubOffset, request.StubSize, 0, 0, kNoSpecialAlignment, 0);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 2, kDynStrNameOffset, SHT_STRTAB, SHF_ALLOC, mappedAddress(request.DynStrOffset), request.DynStrOffset, request.DynStrSize, 0, 0, kNoSpecialAlignment, 0);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 3, kDynSymNameOffset, SHT_DYNSYM, SHF_ALLOC, mappedAddress(request.DynSymOffset), request.DynSymOffset, request.DynSymSize, kDynSymLinkToStrTab, kDynSymInfoFirstGlobal, kDynSymAlign, kSymEntrySize);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 4, kDynamicNameOffset, SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE, mappedAddress(request.DynamicSegmentOffset), request.DynamicSegmentOffset, request.DynamicSegmentSize, kDynamicLinkToStrTab, 0, kDynSymAlign, kDynEntrySize);
_writeSectionHeader(buf, shOff + kShdrEntrySize * 5, kTextNameOffset, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, mappedAddress(request.StubOffset), request.StubOffset, request.StubSize, 0, 0, kNoSpecialAlignment, 0);
_byteWriter->WriteU64(buf, kEhdrShOffOffset, shOff);
_byteWriter->WriteU16(buf, kEhdrShEntSizeOffset, static_cast<std::uint16_t>(kShdrEntrySize));