/* * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/device_binary_format/elf/elf.h" #include "shared/source/utilities/arrayref.h" #include "shared/source/utilities/const_stringref.h" #include "shared/source/utilities/stackvec.h" #include #include #include #include namespace NEO { namespace Elf { struct StringSectionBuilder { StringSectionBuilder() { stringTable.push_back('\0'); undefStringIdx = 0U; } void setInitialStringsTab(ArrayRef data) { DEBUG_BREAK_IF(stringTable.size() > 1); stringTable.assign(reinterpret_cast(data.begin()), reinterpret_cast(data.end())); if (stringTable.size() < 1) { stringTable.push_back('\0'); } if (*stringTable.rbegin() != '\0') { stringTable.push_back('\0'); } auto it = stringTable.begin() + 1; while (it != stringTable.end()) { stringOffsetsMap[std::string(&*it)] = static_cast(it - stringTable.begin()); while (*it != '\0') { ++it; } ++it; } } uint32_t appendString(ConstStringRef str) { if (str.empty()) { return undefStringIdx; } auto existingEntry = stringOffsetsMap.find(str.str()); if (stringOffsetsMap.end() != existingEntry) { return existingEntry->second; } uint32_t offset = static_cast(stringTable.size()); stringTable.insert(stringTable.end(), str.begin(), str.end()); if (str[str.size() - 1] != '\0') { stringTable.push_back('\0'); } stringOffsetsMap[str.str()] = offset; return offset; } ArrayRef data() const { return ArrayRef::fromAny(stringTable.data(), stringTable.size()); } uint32_t undef() const { return undefStringIdx; } protected: std::vector stringTable; std::unordered_map stringOffsetsMap; uint32_t undefStringIdx; }; template struct ElfEncoder { ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true, typename ElfSectionHeaderTypes::AddrAlign defaultDataAlignment = 8U); void setInitialStringsTab(ArrayRef data) { strSecBuilder.setInitialStringsTab(data); } ElfSectionHeader &appendSection(const ElfSectionHeader §ionHeader, const ArrayRef sectionData); ElfProgramHeader &appendSegment(const ElfProgramHeader &programHeader, const ArrayRef segmentData); ElfSectionHeader &appendSection(SectionHeaderType sectionType, ConstStringRef sectionLabel, const ArrayRef sectionData); ElfProgramHeader &appendSegment(ProgramHeaderType segmentType, const ArrayRef segmentData); uint32_t getSectionHeaderIndex(const ElfSectionHeader §ionHeader); void appendProgramHeaderLoad(size_t sectionId, uint64_t vAddr, uint64_t segSize); template ElfSectionHeader &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const ArrayRef sectionData) { return appendSection(static_cast(sectionType), sectionLabel, sectionData); // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange) } template ElfSectionHeader &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const std::string §ionData) { return appendSection(static_cast(sectionType), sectionLabel, // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange) ArrayRef(reinterpret_cast(sectionData.c_str()), sectionData.size() + 1)); } uint32_t appendSectionName(ConstStringRef str); std::vector encode() const; ElfFileHeader &getElfFileHeader() { return elfFileHeader; } protected: bool addUndefSectionHeader = false; bool addHeaderSectionNamesSection = false; typename ElfSectionHeaderTypes::AddrAlign defaultDataAlignment = 8U; uint64_t maxDataAlignmentNeeded = 1U; ElfFileHeader elfFileHeader; StackVec, 32> programHeaders; StackVec, 32> sectionHeaders; std::vector data; StringSectionBuilder strSecBuilder; struct ProgramSectionID { size_t programId; size_t sectionId; }; StackVec programSectionLookupTable; uint32_t shStrTabNameOffset = 0; }; struct NoteToEncode { std::string name; std::string desc; uint32_t type; }; template std::vector encodeNoteSectionData(ArrayRef notes); extern template std::vector encodeNoteSectionData(ArrayRef notes); extern template std::vector encodeNoteSectionData(ArrayRef notes); extern template struct ElfEncoder; extern template struct ElfEncoder; } // namespace Elf } // namespace NEO