/* * Copyright (C) 2020-2024 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/device_binary_format/elf/elf.h" #include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/utilities/arrayref.h" #include "shared/source/utilities/stackvec.h" #include #include #include #include #include namespace NEO { namespace Elf { template struct MutableSectionHeader { MutableSectionHeader(const std::string &name, const NEO::Elf::ElfSectionHeader &header, const std::vector &data) : name(name), header(header), data(data) { } std::string name; NEO::Elf::ElfSectionHeader header{}; std::vector data; }; template struct MutableProgramHeader { MutableProgramHeader(const NEO::Elf::ElfProgramHeader &header, const std::vector &data) : header(header), data(data) { } NEO::Elf::ElfProgramHeader header = {}; std::vector data; MutableSectionHeader *referencedSectionData = nullptr; }; template struct ElfRewriter { using SectionId = uint32_t; ElfRewriter(NEO::Elf::Elf &src) { elfFileHeader = *src.elfFileHeader; for (const auto &sh : src.sectionHeaders) { this->sectionHeaders.push_back(std::make_unique>(src.getName(sh.header->name), *sh.header, std::vector{sh.data.begin(), sh.data.end()})); } for (const auto &ph : src.programHeaders) { this->programHeaders.push_back(std::make_unique>(*ph.header, std::vector{ph.data.begin(), ph.data.end()})); for (const auto &sh : this->sectionHeaders) { if ((sh->header.offset == ph.header->offset) && (sh->header.size == ph.header->fileSz)) { (*this->programHeaders.rbegin())->referencedSectionData = sh.get(); } } } } std::vector encode() const { NEO::Elf::ElfEncoder encoder{}; for (const auto &sh : this->sectionHeaders) { if (sh->header.type == SHT_STRTAB) { encoder.setInitialStringsTab(sh->data); } } encoder.getElfFileHeader() = elfFileHeader; std::unordered_map *, decltype(NEO::Elf::ElfSectionHeader::offset)> encodedSectionsOffsets; for (const auto &sh : this->sectionHeaders) { if ((sh->header.type == SHT_NULL) || (sh->header.type == SHT_STRTAB)) { continue; } auto nameIdx = encoder.appendSectionName(sh->name); NEO::Elf::ElfSectionHeader header = sh->header; header.name = nameIdx; encodedSectionsOffsets[sh.get()] = encoder.appendSection(header, sh->data).offset; } for (const auto &ph : this->programHeaders) { if (ph->referencedSectionData) { auto &header = ph->header; header.offset = encodedSectionsOffsets[ph->referencedSectionData]; encoder.appendSegment(ph->header, {}); } else { encoder.appendSegment(ph->header, ph->data); } } return encoder.encode(); } StackVec findSections(typename ElfSectionHeaderTypes::Type type, ConstStringRef name) { StackVec ret; for (size_t i = 0; i < this->sectionHeaders.size(); i++) { auto §ion = this->sectionHeaders[i]; if ((type == section->header.type) && (name == section->name)) { ret.push_back(static_cast(i)); } } return ret; } MutableSectionHeader &getSection(SectionId idx) { return *sectionHeaders[idx]; } void removeSection(SectionId idx) { auto sectionHeaderToRemove = std::move(sectionHeaders[idx]); for (auto it = idx + 1; it < sectionHeaders.size(); ++it) { // preserve order sectionHeaders[it - 1] = std::move(sectionHeaders[it]); } sectionHeaders.pop_back(); for (auto &programHeader : programHeaders) { if (sectionHeaderToRemove.get() == programHeader->referencedSectionData) { programHeader->referencedSectionData = nullptr; } } } ElfFileHeader elfFileHeader = {}; protected: StackVec>, 32> sectionHeaders; StackVec>, 32> programHeaders; }; } // namespace Elf } // namespace NEO