fix(header): fix read section headers

This commit is contained in:
boykopovar 2026-08-03 21:22:07 +03:00
parent 4d8fc76ff7
commit 340a321cbe
5 changed files with 57 additions and 9 deletions

View File

@ -14,6 +14,7 @@ public:
ElfHeader ReadHeader() const override;
std::vector<ProgramHeader> ReadProgramHeaders() const override;
std::vector<SectionHeader> ReadSectionHeaders() const override;
std::vector<DynamicTag> ReadDynamicTags(const ProgramHeader& dynamicHeader) 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;

View File

@ -14,6 +14,7 @@ public:
[[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<DynamicTag> ReadDynamicTags(const ProgramHeader& dynamicHeader) 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;

View File

@ -73,6 +73,11 @@ struct SymbolExport {
CallSiteInfo CallSites;
};
struct DynamicTag {
std::int64_t Tag;
std::uint64_t Value;
};
struct RelinkerException : std::runtime_error {
FileByteOffset FailureOffset;

View File

@ -168,6 +168,29 @@ std::string ElfReader::_resolveShdrName(std::uint32_t nameOffset, const ElfHeade
return name;
}
std::vector<DynamicTag> ElfReader::ReadDynamicTags(const ProgramHeader& dynamicHeader) const {
_loadFileIntoBuffer();
std::vector<DynamicTag> tags;
FileByteOffset offset = dynamicHeader.Offset;
const FileByteOffset end = dynamicHeader.Offset + dynamicHeader.FileSize;
while (offset + 16 <= end && offset + 16 <= _fileBuffer.size()) {
DynamicTag tag;
tag.Tag = static_cast<std::int64_t>(_readU64At(offset));
tag.Value = _readU64At(offset + 0x08);
if (tag.Tag == 0) {
break;
}
tags.push_back(tag);
offset += 16;
}
return tags;
}
std::vector<std::uint8_t> ElfReader::ReadSection(const SectionHeader& header) const {
_loadFileIntoBuffer();

View File

@ -26,7 +26,12 @@ std::shared_ptr<ICallRegistryWriter> MakeCallRegistryWriter();
static constexpr std::uint32_t PT_LOAD = 1;
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 constexpr std::uint32_t PF_X = 0x1;
static constexpr std::int64_t DT_PLTGOT = 0x00000003;
static constexpr std::int64_t DT_OS_PLTGOT = 0x61000027;
static constexpr std::int64_t DT_PLTRELSZ = 0x00000002;
static constexpr std::int64_t DT_OS_PLTRELSZ = 0x6100002d;
static std::string _relocationTypeName(const std::uint32_t type) {
switch (type) {
@ -62,7 +67,6 @@ int main(int argc, char* argv[]) {
auto header = elfReader->ReadHeader();
auto programHeaders = elfReader->ReadProgramHeaders();
auto sectionHeaders = elfReader->ReadSectionHeaders();
std::vector<std::uint8_t> sceDynlibData;
std::vector<std::uint8_t> textSection;
@ -75,16 +79,30 @@ int main(int argc, char* argv[]) {
sceDynlibData = elfReader->ReadSegment(ph);
}
for (const auto& sh : sectionHeaders) {
if (sh.Name == ".text") {
textSection = elfReader->ReadSection(sh);
textVAddr = sh.MappedAddress;
} else if (sh.Name == ".got" || sh.Name == ".got.plt") {
gotVAddr = sh.MappedAddress;
gotSize = sh.SectionSize;
for (const auto& ph : programHeaders) {
if (ph.Type == PT_LOAD && (ph.Flags & PF_X) != 0) {
textSection = elfReader->ReadSegment(ph);
textVAddr = ph.MappedAddress;
break;
}
}
for (const auto& ph : programHeaders) {
if (ph.Type != PT_DYNAMIC)
continue;
auto dynTags = elfReader->ReadDynamicTags(ph);
for (const auto& tag : dynTags) {
if (tag.Tag == DT_PLTGOT || tag.Tag == DT_OS_PLTGOT)
gotVAddr = tag.Value;
else if (tag.Tag == DT_PLTRELSZ || tag.Tag == DT_OS_PLTRELSZ)
gotSize = tag.Value;
}
break;
}
if (sceDynlibData.empty())
throw Relinker::RelinkerException("SCE_DYNLIBDATA segment not found");