150 lines
5.4 KiB
C++
150 lines
5.4 KiB
C++
/*
|
|
* 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 <queue>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace NEO {
|
|
|
|
namespace Elf {
|
|
|
|
struct StringSectionBuilder {
|
|
StringSectionBuilder() {
|
|
stringTable.push_back('\0');
|
|
undefStringIdx = 0U;
|
|
}
|
|
|
|
void setInitialStringsTab(ArrayRef<const uint8_t> data) {
|
|
DEBUG_BREAK_IF(stringTable.size() > 1);
|
|
stringTable.assign(reinterpret_cast<const char *>(data.begin()), reinterpret_cast<const char *>(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<uint32_t>(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<uint32_t>(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<const uint8_t> data() const {
|
|
return ArrayRef<const uint8_t>::fromAny(stringTable.data(), stringTable.size());
|
|
}
|
|
|
|
uint32_t undef() const {
|
|
return undefStringIdx;
|
|
}
|
|
|
|
protected:
|
|
std::vector<char> stringTable;
|
|
std::unordered_map<std::string, uint32_t> stringOffsetsMap;
|
|
uint32_t undefStringIdx;
|
|
};
|
|
|
|
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
|
struct ElfEncoder {
|
|
ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true,
|
|
typename ElfSectionHeaderTypes<numBits>::AddrAlign defaultDataAlignment = 8U);
|
|
|
|
void setInitialStringsTab(ArrayRef<const uint8_t> data) {
|
|
strSecBuilder.setInitialStringsTab(data);
|
|
}
|
|
|
|
ElfSectionHeader<numBits> &appendSection(const ElfSectionHeader<numBits> §ionHeader, const ArrayRef<const uint8_t> sectionData);
|
|
ElfProgramHeader<numBits> &appendSegment(const ElfProgramHeader<numBits> &programHeader, const ArrayRef<const uint8_t> segmentData);
|
|
|
|
ElfSectionHeader<numBits> &appendSection(SectionHeaderType sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
|
|
ElfProgramHeader<numBits> &appendSegment(ProgramHeaderType segmentType, const ArrayRef<const uint8_t> segmentData);
|
|
uint32_t getSectionHeaderIndex(const ElfSectionHeader<numBits> §ionHeader);
|
|
void appendProgramHeaderLoad(size_t sectionId, uint64_t vAddr, uint64_t segSize);
|
|
|
|
template <typename SectionHeaderEnumT>
|
|
ElfSectionHeader<numBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
|
|
return appendSection(static_cast<SectionHeaderType>(sectionType), sectionLabel, sectionData); // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange)
|
|
}
|
|
|
|
template <typename SectionHeaderEnumT>
|
|
ElfSectionHeader<numBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const std::string §ionData) {
|
|
return appendSection(static_cast<SectionHeaderType>(sectionType), sectionLabel, // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange)
|
|
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(sectionData.c_str()), sectionData.size() + 1));
|
|
}
|
|
|
|
uint32_t appendSectionName(ConstStringRef str);
|
|
|
|
std::vector<uint8_t> encode() const;
|
|
|
|
ElfFileHeader<numBits> &getElfFileHeader() {
|
|
return elfFileHeader;
|
|
}
|
|
|
|
protected:
|
|
bool addUndefSectionHeader = false;
|
|
bool addHeaderSectionNamesSection = false;
|
|
typename ElfSectionHeaderTypes<numBits>::AddrAlign defaultDataAlignment = 8U;
|
|
uint64_t maxDataAlignmentNeeded = 1U;
|
|
ElfFileHeader<numBits> elfFileHeader;
|
|
StackVec<ElfProgramHeader<numBits>, 32> programHeaders;
|
|
StackVec<ElfSectionHeader<numBits>, 32> sectionHeaders;
|
|
std::vector<uint8_t> data;
|
|
StringSectionBuilder strSecBuilder;
|
|
struct ProgramSectionID {
|
|
size_t programId;
|
|
size_t sectionId;
|
|
};
|
|
StackVec<ProgramSectionID, 32> programSectionLookupTable;
|
|
uint32_t shStrTabNameOffset = 0;
|
|
};
|
|
|
|
struct NoteToEncode {
|
|
std::string name;
|
|
std::string desc;
|
|
uint32_t type;
|
|
};
|
|
|
|
template <ElfIdentifierClass numBits = EI_CLASS_64>
|
|
std::vector<uint8_t> encodeNoteSectionData(ArrayRef<const NoteToEncode> notes);
|
|
extern template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_64>(ArrayRef<const NoteToEncode> notes);
|
|
extern template std::vector<uint8_t> encodeNoteSectionData<EI_CLASS_32>(ArrayRef<const NoteToEncode> notes);
|
|
|
|
extern template struct ElfEncoder<EI_CLASS_32>;
|
|
extern template struct ElfEncoder<EI_CLASS_64>;
|
|
|
|
} // namespace Elf
|
|
|
|
} // namespace NEO
|