Reorganization directory structure [3/n]

Change-Id: If3dfa3f6007f8810a6a1ae1a4f0c7da38544648d
This commit is contained in:
kamdiedrich
2020-02-23 21:00:51 +01:00
committed by sys_ocldev
parent e177b4fc0f
commit e072275ae6
711 changed files with 94 additions and 94 deletions

View File

@@ -0,0 +1,342 @@
/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "utilities/const_stringref.h"
#include <inttypes.h>
#include <stddef.h>
namespace NEO {
namespace Elf {
// Elf identifier class
enum ELF_IDENTIFIER_CLASS : uint8_t {
EI_CLASS_NONE = 0, // undefined
EI_CLASS_32 = 1, // 32-bit elf file
EI_CLASS_64 = 2, // 64-bit elf file
};
// Elf identifier data
enum ELF_IDENTIFIER_DATA : uint8_t {
EI_DATA_NONE = 0, // undefined
EI_DATA_LITTLE_ENDIAN = 1, // little-endian
EI_DATA_BIG_ENDIAN = 2, // big-endian
};
// Target machine
enum ELF_MACHINE : uint16_t {
EM_NONE = 0, // No specific instrution set
};
// Elf version
enum ELF_VERSION_ : uint8_t {
EV_INVALID = 0, // undefined
EV_CURRENT = 1, // current
};
// Elf type
enum ELF_TYPE : uint16_t {
ET_NONE = 0, // undefined
ET_REL = 1, // relocatable
ET_EXEC = 2, // executable
ET_DYN = 3, // shared object
ET_CORE = 4, // core file
ET_LOPROC = 0xff00, // start of processor-specific type
ET_OPENCL_RESERVED_START = 0xff01, // start of Intel OCL ELF_TYPES
ET_OPENCL_RESERVED_END = 0xff05, // end of Intel OCL ELF_TYPES
ET_HIPROC = 0xffff // end of processor-specific types
};
// Section header type
enum SECTION_HEADER_TYPE : uint32_t {
SHT_NULL = 0, // inactive section header
SHT_PROGBITS = 1, // program data
SHT_SYMTAB = 2, // symbol table
SHT_STRTAB = 3, // string table
SHT_RELA = 4, // relocation entries with add
SHT_HASH = 5, // symbol hash table
SHT_DYNAMIC = 6, // dynamic linking info
SHT_NOTE = 7, // notes
SHT_NOBITS = 8, // program "no data" space (bss)
SHT_REL = 9, // relocation entries (without add)
SHT_SHLIB = 10, // reserved
SHT_DYNSYM = 11, // dynamic linker symbol table
SHT_INIT_ARRAY = 14, // array of constructors
SHT_FINI_ARRAY = 15, // array of destructors
SHT_PREINIT_ARRAY = 16, // aaray of pre-constructors
SHT_GROUP = 17, // section group
SHT_SYMTAB_SHNDX = 18, // extended section indices
SHT_NUM = 19, // number of defined types
SHT_LOOS = 0x60000000, // start of os-specifc
SHT_OPENCL_RESERVED_START = 0xff000000, // start of Intel OCL SHT_TYPES
SHT_OPENCL_RESERVED_END = 0xff00000a // end of Intel OCL SHT_TYPES
};
enum SPECIAL_SECTION_HEADER_NUMBER : uint16_t {
SHN_UNDEF = 0U, // undef section
};
enum SECTION_HEADER_FLAGS : uint32_t {
SHF_NONE = 0x0, // no flags
SHF_WRITE = 0x1, // writeable data
SHF_ALLOC = 0x2, // occupies memory during execution
SHF_EXECINSTR = 0x4, // executable machine instructions
SHF_MERGE = 0x10, // data of section can be merged
SHF_STRINGS = 0x20, // data of section is null-terminated strings
SHF_INFO_LINK = 0x40, // section's sh_info is valid index
SHF_LINK_ORDER = 0x80, // has ordering requirements
SHF_OS_NONCONFORM = 0x100, // requires os-specific processing
SHF_GROUP = 0x200, // section is part of section group
SHF_TLS = 0x400, // thread-local storage
SHF_MASKOS = 0x0ff00000, // operating-system-specific flags
SHF_MASKPROC = 0xf0000000, // processor-specific flags
};
enum PROGRAM_HEADER_TYPE {
PT_NULL = 0x0, // unused segment
PT_LOAD = 0x1, // loadable segment
PT_DYNAMIC = 0x2, // dynamic linking information
PT_INTERP = 0x3, // path name to invoke as an interpreter
PT_NOTE = 0x4, // auxiliary information
PT_SHLIB = 0x5, // reserved
PT_PHDR = 0x6, // location and of programe header table
PT_TLS = 0x7, // thread-local storage template
PT_LOOS = 0x60000000, // start os-specifc segments
PT_HIOS = 0x6FFFFFFF, // end of os-specific segments
PT_LOPROC = 0x70000000, // start processor-specific segments
PT_HIPROC = 0x7FFFFFFF // end processor-specific segments
};
enum PROGRAM_HEADER_FLAGS : uint32_t {
PF_NONE = 0x0, // all access denied
PF_X = 0x1, // execute
PF_W = 0x2, // write
PF_R = 0x4, // read
PF_MASKOS = 0x0ff00000, // operating-system-specific flags
PF_MASKPROC = 0xf0000000 // processor-specific flags
};
constexpr const char elfMagic[4] = {0x7f, 'E', 'L', 'F'};
struct ElfFileHeaderIdentity {
ElfFileHeaderIdentity(ELF_IDENTIFIER_CLASS classBits)
: eClass(classBits) {
}
char magic[4] = {elfMagic[0], elfMagic[1], elfMagic[2], elfMagic[3]}; // should match elfMagic
uint8_t eClass = EI_CLASS_NONE; // 32- or 64-bit format
uint8_t data = EI_DATA_LITTLE_ENDIAN; // endianness
uint8_t version = EV_CURRENT; // elf file version
uint8_t osAbi = 0U; // target system
uint8_t abiVersion = 0U; // abi
char padding[7] = {}; // pad to 16 bytes
};
static_assert(sizeof(ElfFileHeaderIdentity) == 16, "");
template <int NumBits>
struct ElfProgramHeaderTypes;
template <>
struct ElfProgramHeaderTypes<EI_CLASS_32> {
using Type = uint32_t;
using Flags = uint32_t;
using Offset = uint32_t;
using VAddr = uint32_t;
using PAddr = uint32_t;
using FileSz = uint32_t;
using MemSz = uint32_t;
using Align = uint32_t;
};
template <>
struct ElfProgramHeaderTypes<EI_CLASS_64> {
using Type = uint32_t;
using Flags = uint32_t;
using Offset = uint64_t;
using VAddr = uint64_t;
using PAddr = uint64_t;
using FileSz = uint64_t;
using MemSz = uint64_t;
using Align = uint64_t;
};
template <int NumBits>
struct ElfProgramHeader;
template <>
struct ElfProgramHeader<EI_CLASS_32> {
ElfProgramHeaderTypes<EI_CLASS_32>::Type type = PT_NULL; // type of segment
ElfProgramHeaderTypes<EI_CLASS_32>::Offset offset = 0U; // absolute offset of segment data in file
ElfProgramHeaderTypes<EI_CLASS_32>::VAddr vAddr = 0U; // VA of segment in memory
ElfProgramHeaderTypes<EI_CLASS_32>::PAddr pAddr = 0U; // PA of segment in memory
ElfProgramHeaderTypes<EI_CLASS_32>::FileSz fileSz = 0U; // size of segment in file
ElfProgramHeaderTypes<EI_CLASS_32>::MemSz memSz = 0U; // size of segment in memory
ElfProgramHeaderTypes<EI_CLASS_32>::Flags flags = PF_NONE; // segment-dependent flags
ElfProgramHeaderTypes<EI_CLASS_32>::Align align = 1U; // alignment
};
template <>
struct ElfProgramHeader<EI_CLASS_64> {
ElfProgramHeaderTypes<EI_CLASS_64>::Type type = PT_NULL; // type of segment
ElfProgramHeaderTypes<EI_CLASS_64>::Flags flags = PF_NONE; // segment-dependent flags
ElfProgramHeaderTypes<EI_CLASS_64>::Offset offset = 0U; // absolute offset of segment data in file
ElfProgramHeaderTypes<EI_CLASS_64>::VAddr vAddr = 0U; // VA of segment in memory
ElfProgramHeaderTypes<EI_CLASS_64>::PAddr pAddr = 0U; // PA of segment in memory
ElfProgramHeaderTypes<EI_CLASS_64>::FileSz fileSz = 0U; // size of segment in file
ElfProgramHeaderTypes<EI_CLASS_64>::MemSz memSz = 0U; // size of segment in memory
ElfProgramHeaderTypes<EI_CLASS_64>::Align align = 1U; // alignment
};
static_assert(sizeof(ElfProgramHeader<EI_CLASS_32>) == 0x20, "");
static_assert(sizeof(ElfProgramHeader<EI_CLASS_64>) == 0x38, "");
template <int NumBits>
struct ElfSectionHeaderTypes;
template <>
struct ElfSectionHeaderTypes<EI_CLASS_32> {
using Name = uint32_t;
using Type = uint32_t;
using Flags = uint32_t;
using Addr = uint32_t;
using Offset = uint32_t;
using Size = uint32_t;
using Link = uint32_t;
using Info = uint32_t;
using AddrAlign = uint32_t;
using EntSize = uint32_t;
};
template <>
struct ElfSectionHeaderTypes<EI_CLASS_64> {
using Name = uint32_t;
using Type = uint32_t;
using Flags = uint64_t;
using Addr = uint64_t;
using Offset = uint64_t;
using Size = uint64_t;
using Link = uint32_t;
using Info = uint32_t;
using AddrAlign = uint64_t;
using EntSize = uint64_t;
};
template <int NumBits>
struct ElfSectionHeader {
typename ElfSectionHeaderTypes<NumBits>::Name name = 0U; // offset to string in string section names
typename ElfSectionHeaderTypes<NumBits>::Type type = SHT_NULL; // section type
typename ElfSectionHeaderTypes<NumBits>::Flags flags = SHF_NONE; // section flags
typename ElfSectionHeaderTypes<NumBits>::Addr addr = 0U; // VA of section in memory
typename ElfSectionHeaderTypes<NumBits>::Offset offset = 0U; // absolute offset of section data in file
typename ElfSectionHeaderTypes<NumBits>::Size size = 0U; // size of section's data
typename ElfSectionHeaderTypes<NumBits>::Link link = SHN_UNDEF; // index of associated section
typename ElfSectionHeaderTypes<NumBits>::Info info = 0U; // extra information
typename ElfSectionHeaderTypes<NumBits>::AddrAlign addralign = 0U; // section alignment
typename ElfSectionHeaderTypes<NumBits>::EntSize entsize = 0U; // section's entries size
};
static_assert(sizeof(ElfSectionHeader<EI_CLASS_32>) == 0x28, "");
static_assert(sizeof(ElfSectionHeader<EI_CLASS_64>) == 0x40, "");
template <ELF_IDENTIFIER_CLASS NumBits>
struct ElfFileHeaderTypes;
template <>
struct ElfFileHeaderTypes<EI_CLASS_32> {
using Type = uint16_t;
using Machine = uint16_t;
using Version = uint32_t;
using Entry = uint32_t;
using PhOff = uint32_t;
using ShOff = uint32_t;
using Flags = uint32_t;
using EhSize = uint16_t;
using PhEntSize = uint16_t;
using PhNum = uint16_t;
using ShEntSize = uint16_t;
using ShNum = uint16_t;
using ShStrNdx = uint16_t;
};
template <>
struct ElfFileHeaderTypes<EI_CLASS_64> {
using Type = uint16_t;
using Machine = uint16_t;
using Version = uint32_t;
using Entry = uint64_t;
using PhOff = uint64_t;
using ShOff = uint64_t;
using Flags = uint32_t;
using EhSize = uint16_t;
using PhEntSize = uint16_t;
using PhNum = uint16_t;
using ShEntSize = uint16_t;
using ShNum = uint16_t;
using ShStrNdx = uint16_t;
};
template <ELF_IDENTIFIER_CLASS NumBits>
struct ElfFileHeader {
ElfFileHeaderIdentity identity = ElfFileHeaderIdentity(NumBits); // elf file identity
typename ElfFileHeaderTypes<NumBits>::Type type = ET_NONE; // elf file type
typename ElfFileHeaderTypes<NumBits>::Machine machine = EM_NONE; // target machine
typename ElfFileHeaderTypes<NumBits>::Version version = 1U; // elf file version
typename ElfFileHeaderTypes<NumBits>::Entry entry = 0U; // entry point (start address)
typename ElfFileHeaderTypes<NumBits>::PhOff phOff = 0U; // absolute offset to program header table in file
typename ElfFileHeaderTypes<NumBits>::ShOff shOff = 0U; // absolute offset to section header table in file
typename ElfFileHeaderTypes<NumBits>::Flags flags = 0U; // target-dependent flags
typename ElfFileHeaderTypes<NumBits>::EhSize ehSize = sizeof(ElfFileHeader<NumBits>); // header size
typename ElfFileHeaderTypes<NumBits>::PhEntSize phEntSize = sizeof(ElfProgramHeader<NumBits>); // size of entries in program header table
typename ElfFileHeaderTypes<NumBits>::PhNum phNum = 0U; // number of entries in pogram header table
typename ElfFileHeaderTypes<NumBits>::ShEntSize shEntSize = sizeof(ElfSectionHeader<NumBits>); // size of entries section header table
typename ElfFileHeaderTypes<NumBits>::ShNum shNum = 0U; // number of entries in section header table
typename ElfFileHeaderTypes<NumBits>::ShStrNdx shStrNdx = SHN_UNDEF; // index of section header table with section names
};
static_assert(sizeof(ElfFileHeader<EI_CLASS_32>) == 0x34, "");
static_assert(sizeof(ElfFileHeader<EI_CLASS_64>) == 0x40, "");
namespace SpecialSectionNames {
static constexpr ConstStringRef bss = ".bss"; // uninitialized memory
static constexpr ConstStringRef comment = ".comment"; // version control information
static constexpr ConstStringRef data = ".data"; // initialized memory
static constexpr ConstStringRef data1 = ".data1"; // initialized memory
static constexpr ConstStringRef debug = ".debug"; // debug symbols
static constexpr ConstStringRef dynamic = ".dynamic"; // dynamic linking information
static constexpr ConstStringRef dynstr = ".dynstr"; // strings for dynamic linking
static constexpr ConstStringRef dynsym = ".dynsym"; // dynamic linking symbol table
static constexpr ConstStringRef fini = ".fini"; // executable instructions of program termination
static constexpr ConstStringRef finiArray = ".fini_array"; // function pointers of termination array
static constexpr ConstStringRef got = ".got"; // global offset table
static constexpr ConstStringRef hash = ".hash"; // symnol hash table
static constexpr ConstStringRef init = ".init"; // executable instructions of program initializaion
static constexpr ConstStringRef initArray = ".init_array"; // function pointers of initialization array
static constexpr ConstStringRef interp = ".interp"; // path name of program interpreter
static constexpr ConstStringRef line = ".line"; // line number info for symbolic debugging
static constexpr ConstStringRef note = ".note"; // note section
static constexpr ConstStringRef plt = ".plt"; // procedure linkage table
static constexpr ConstStringRef preinitArray = ".preinit_array"; // function pointers of pre-initialization array
static constexpr ConstStringRef relPrefix = ".rel"; // prefix of .relNAME - relocations for NAME section
static constexpr ConstStringRef relaPrefix = ".rela"; // prefix of .relaNAME - rela relocations for NAME section
static constexpr ConstStringRef rodata = ".rodata"; // read-only data
static constexpr ConstStringRef rodata1 = ".rodata1"; // read-only data
static constexpr ConstStringRef shStrTab = ".shstrtab"; // section names (strings)
static constexpr ConstStringRef strtab = ".strtab"; // strings
static constexpr ConstStringRef symtab = ".symtab"; // symbol table
static constexpr ConstStringRef symtabShndx = ".symtab_shndx"; // special symbol table section index array
static constexpr ConstStringRef tbss = ".tbss"; // uninitialized thread-local data
static constexpr ConstStringRef tadata = ".tdata"; // initialided thread-local data
static constexpr ConstStringRef tdata1 = ".tdata1"; // initialided thread-local data
static constexpr ConstStringRef text = ".text"; // executable instructions
} // namespace SpecialSectionNames
} // namespace Elf
} // namespace NEO

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "device_binary_format/elf/elf_decoder.h"
#include "helpers/ptr_math.h"
#include <string.h>
namespace NEO {
namespace Elf {
template <ELF_IDENTIFIER_CLASS NumBits>
const ElfFileHeader<NumBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary) {
if (binary.size() < sizeof(ElfFileHeader<NumBits>)) {
return nullptr;
}
const ElfFileHeader<NumBits> *header = reinterpret_cast<const ElfFileHeader<NumBits> *>(binary.begin());
bool validHeader = (header->identity.magic[0] == elfMagic[0]);
validHeader &= (header->identity.magic[1] == elfMagic[1]);
validHeader &= (header->identity.magic[2] == elfMagic[2]);
validHeader &= (header->identity.magic[3] == elfMagic[3]);
validHeader &= (header->identity.eClass == NumBits);
return validHeader ? header : nullptr;
}
template const ElfFileHeader<EI_CLASS_32> *decodeElfFileHeader<EI_CLASS_32>(const ArrayRef<const uint8_t>);
template const ElfFileHeader<EI_CLASS_64> *decodeElfFileHeader<EI_CLASS_64>(const ArrayRef<const uint8_t>);
template <ELF_IDENTIFIER_CLASS NumBits>
Elf<NumBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarning) {
Elf<NumBits> ret = {};
ret.elfFileHeader = decodeElfFileHeader<NumBits>(binary);
if (nullptr == ret.elfFileHeader) {
outErrReason = "Invalid or missing ELF header";
return {};
}
if (ret.elfFileHeader->phOff + ret.elfFileHeader->phNum * ret.elfFileHeader->phEntSize > binary.size()) {
outErrReason = "Out of bounds program headers table";
return {};
}
if (ret.elfFileHeader->shOff + ret.elfFileHeader->shNum * ret.elfFileHeader->shEntSize > binary.size()) {
outErrReason = "Out of bounds section headers table";
return {};
}
const ElfProgramHeader<NumBits> *programHeader = reinterpret_cast<const ElfProgramHeader<NumBits> *>(binary.begin() + ret.elfFileHeader->phOff);
for (decltype(ret.elfFileHeader->phNum) i = 0; i < ret.elfFileHeader->phNum; ++i) {
if (programHeader->offset + programHeader->fileSz > binary.size()) {
outErrReason = "Out of bounds program header offset/filesz, program header idx : " + std::to_string(i);
return {};
}
ArrayRef<const uint8_t> data(binary.begin() + programHeader->offset, static_cast<size_t>(programHeader->fileSz));
ret.programHeaders.push_back({programHeader, data});
programHeader = ptrOffset(programHeader, ret.elfFileHeader->phEntSize);
}
const ElfSectionHeader<NumBits> *sectionHeader = reinterpret_cast<const ElfSectionHeader<NumBits> *>(binary.begin() + ret.elfFileHeader->shOff);
for (decltype(ret.elfFileHeader->shNum) i = 0; i < ret.elfFileHeader->shNum; ++i) {
ArrayRef<const uint8_t> data;
if (SHT_NOBITS != sectionHeader->type) {
if (sectionHeader->offset + sectionHeader->size > binary.size()) {
outErrReason = "Out of bounds section header offset/size, section header idx : " + std::to_string(i);
return {};
}
data = ArrayRef<const uint8_t>(binary.begin() + sectionHeader->offset, static_cast<size_t>(sectionHeader->size));
}
ret.sectionHeaders.push_back({sectionHeader, data});
sectionHeader = ptrOffset(sectionHeader, ret.elfFileHeader->shEntSize);
}
return ret;
}
template Elf<EI_CLASS_32> decodeElf<EI_CLASS_32>(const ArrayRef<const uint8_t>, std::string &, std::string &);
template Elf<EI_CLASS_64> decodeElf<EI_CLASS_64>(const ArrayRef<const uint8_t>, std::string &, std::string &);
} // namespace Elf
} // namespace NEO

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "device_binary_format/elf/elf.h"
#include "utilities/arrayref.h"
#include "utilities/const_stringref.h"
#include "utilities/stackvec.h"
#include <cstdint>
namespace NEO {
namespace Elf {
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
struct Elf {
struct ProgramHeaderAndData {
const ElfProgramHeader<NumBits> *header = nullptr;
ArrayRef<const uint8_t> data;
};
struct SectionHeaderAndData {
const ElfSectionHeader<NumBits> *header;
ArrayRef<const uint8_t> data;
};
const ElfFileHeader<NumBits> *elfFileHeader = nullptr;
StackVec<ProgramHeaderAndData, 32> programHeaders;
StackVec<SectionHeaderAndData, 32> sectionHeaders;
};
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
const ElfFileHeader<NumBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary);
extern template const ElfFileHeader<EI_CLASS_32> *decodeElfFileHeader<EI_CLASS_32>(const ArrayRef<const uint8_t>);
extern template const ElfFileHeader<EI_CLASS_64> *decodeElfFileHeader<EI_CLASS_64>(const ArrayRef<const uint8_t>);
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
Elf<NumBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarning);
extern template Elf<EI_CLASS_32> decodeElf<EI_CLASS_32>(const ArrayRef<const uint8_t>, std::string &, std::string &);
extern template Elf<EI_CLASS_64> decodeElf<EI_CLASS_64>(const ArrayRef<const uint8_t>, std::string &, std::string &);
template <ELF_IDENTIFIER_CLASS NumBits>
inline bool isElf(const ArrayRef<const uint8_t> binary) {
return (nullptr != decodeElfFileHeader<NumBits>(binary));
}
inline bool isElf(const ArrayRef<const uint8_t> binary) {
return isElf<EI_CLASS_32>(binary) || isElf<EI_CLASS_64>(binary);
}
inline ELF_IDENTIFIER_CLASS getElfNumBits(const ArrayRef<const uint8_t> binary) {
if (isElf<EI_CLASS_32>(binary)) {
return EI_CLASS_32;
} else if (isElf<EI_CLASS_64>(binary)) {
return EI_CLASS_64;
}
return EI_CLASS_NONE;
}
} // namespace Elf
} // namespace NEO

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "device_binary_format/elf/elf_encoder.h"
#include "utilities/range.h"
#include <algorithm>
namespace NEO {
namespace Elf {
template <ELF_IDENTIFIER_CLASS NumBits>
ElfEncoder<NumBits>::ElfEncoder(bool addUndefSectionHeader, bool addHeaderSectionNamesSection, uint64_t defaultDataAlignemnt)
: addUndefSectionHeader(addUndefSectionHeader), addHeaderSectionNamesSection(addHeaderSectionNamesSection), defaultDataAlignment(defaultDataAlignemnt) {
// add special strings
UNRECOVERABLE_IF(defaultDataAlignment == 0);
stringTable.push_back('\0');
specialStringsOffsets.undef = 0U;
specialStringsOffsets.shStrTab = this->appendSectionName(SpecialSectionNames::shStrTab);
if (addUndefSectionHeader) {
ElfSectionHeader<NumBits> undefSection;
sectionHeaders.push_back(undefSection);
}
}
template <ELF_IDENTIFIER_CLASS NumBits>
void ElfEncoder<NumBits>::appendSection(const ElfSectionHeader<NumBits> &sectionHeader, const ArrayRef<const uint8_t> sectionData) {
sectionHeaders.push_back(sectionHeader);
if ((SHT_NOBITS != sectionHeader.type) && (false == sectionData.empty())) {
auto sectionDataAlignment = std::min<uint64_t>(defaultDataAlignment, 8U);
auto alignedOffset = alignUp(this->data.size(), static_cast<size_t>(sectionDataAlignment));
auto alignedSize = alignUp(sectionData.size(), static_cast<size_t>(sectionDataAlignment));
this->data.reserve(alignedOffset + alignedSize);
this->data.resize(alignedOffset, 0U);
this->data.insert(this->data.end(), sectionData.begin(), sectionData.end());
this->data.resize(alignedOffset + alignedSize, 0U);
sectionHeaders.rbegin()->offset = static_cast<decltype(sectionHeaders.rbegin()->offset)>(alignedOffset);
sectionHeaders.rbegin()->size = static_cast<decltype(sectionHeaders.rbegin()->size)>(sectionData.size());
}
}
template <ELF_IDENTIFIER_CLASS NumBits>
void ElfEncoder<NumBits>::appendSegment(const ElfProgramHeader<NumBits> &programHeader, const ArrayRef<const uint8_t> segmentData) {
maxDataAlignmentNeeded = std::max<uint64_t>(maxDataAlignmentNeeded, static_cast<uint64_t>(programHeader.align));
programHeaders.push_back(programHeader);
if (false == segmentData.empty()) {
UNRECOVERABLE_IF(programHeader.align == 0);
auto alignedOffset = alignUp(this->data.size(), static_cast<size_t>(programHeader.align));
auto alignedSize = alignUp(segmentData.size(), static_cast<size_t>(programHeader.align));
this->data.reserve(alignedOffset + alignedSize);
this->data.resize(alignedOffset, 0U);
this->data.insert(this->data.end(), segmentData.begin(), segmentData.end());
this->data.resize(alignedOffset + alignedSize, 0U);
programHeaders.rbegin()->offset = static_cast<decltype(programHeaders.rbegin()->offset)>(alignedOffset);
programHeaders.rbegin()->fileSz = static_cast<decltype(programHeaders.rbegin()->fileSz)>(segmentData.size());
}
}
template <ELF_IDENTIFIER_CLASS NumBits>
ElfSectionHeader<NumBits> &ElfEncoder<NumBits>::appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
ElfSectionHeader<NumBits> section = {};
section.type = static_cast<decltype(section.type)>(sectionType);
section.flags = static_cast<decltype(section.flags)>(SHF_NONE);
section.offset = 0U;
section.name = appendSectionName(sectionLabel);
section.addralign = 8U;
appendSection(section, sectionData);
return *sectionHeaders.rbegin();
}
template <ELF_IDENTIFIER_CLASS NumBits>
ElfProgramHeader<NumBits> &ElfEncoder<NumBits>::appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef<const uint8_t> segmentData) {
ElfProgramHeader<NumBits> segment = {};
segment.type = static_cast<decltype(segment.type)>(segmentType);
segment.flags = static_cast<decltype(segment.flags)>(PF_NONE);
segment.offset = 0U;
segment.align = static_cast<decltype(segment.align)>(defaultDataAlignment);
appendSegment(segment, segmentData);
return *programHeaders.rbegin();
}
template <ELF_IDENTIFIER_CLASS NumBits>
uint32_t ElfEncoder<NumBits>::appendSectionName(ConstStringRef str) {
if (str.empty() || (false == addHeaderSectionNamesSection)) {
return specialStringsOffsets.undef;
}
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');
}
return offset;
}
template <ELF_IDENTIFIER_CLASS NumBits>
std::vector<uint8_t> ElfEncoder<NumBits>::encode() const {
ElfFileHeader<NumBits> elfFileHeader = this->elfFileHeader;
StackVec<ElfProgramHeader<NumBits>, 32> programHeaders = this->programHeaders;
StackVec<ElfSectionHeader<NumBits>, 32> sectionHeaders = this->sectionHeaders;
if (addUndefSectionHeader && (1U == sectionHeaders.size())) {
sectionHeaders.clear();
}
ElfSectionHeader<NumBits> sectionHeaderNamesSection;
size_t alignedSectionNamesDataSize = 0U;
size_t dataPaddingBeforeSectionNames = 0U;
if ((false == sectionHeaders.empty()) && addHeaderSectionNamesSection) {
auto alignedDataSize = alignUp(data.size(), static_cast<size_t>(defaultDataAlignment));
dataPaddingBeforeSectionNames = alignedDataSize - data.size();
sectionHeaderNamesSection.type = SHT_STRTAB;
sectionHeaderNamesSection.name = specialStringsOffsets.shStrTab;
sectionHeaderNamesSection.offset = static_cast<decltype(sectionHeaderNamesSection.offset)>(alignedDataSize);
sectionHeaderNamesSection.size = static_cast<decltype(sectionHeaderNamesSection.size)>(stringTable.size());
sectionHeaderNamesSection.addralign = static_cast<decltype(sectionHeaderNamesSection.addralign)>(defaultDataAlignment);
elfFileHeader.shStrNdx = static_cast<decltype(elfFileHeader.shStrNdx)>(sectionHeaders.size());
sectionHeaders.push_back(sectionHeaderNamesSection);
alignedSectionNamesDataSize = alignUp(stringTable.size(), static_cast<size_t>(sectionHeaderNamesSection.addralign));
}
elfFileHeader.phNum = static_cast<decltype(elfFileHeader.phNum)>(programHeaders.size());
elfFileHeader.shNum = static_cast<decltype(elfFileHeader.shNum)>(sectionHeaders.size());
auto programHeadersOffset = elfFileHeader.ehSize;
auto sectionHeadersOffset = programHeadersOffset + elfFileHeader.phEntSize * elfFileHeader.phNum;
if (false == programHeaders.empty()) {
elfFileHeader.phOff = static_cast<decltype(elfFileHeader.phOff)>(programHeadersOffset);
}
if (false == sectionHeaders.empty()) {
elfFileHeader.shOff = static_cast<decltype(elfFileHeader.shOff)>(sectionHeadersOffset);
}
auto dataOffset = alignUp(sectionHeadersOffset + elfFileHeader.shEntSize * elfFileHeader.shNum, static_cast<size_t>(maxDataAlignmentNeeded));
auto stringTabOffset = dataOffset + data.size();
std::vector<uint8_t> ret;
ret.reserve(stringTabOffset + alignedSectionNamesDataSize);
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&elfFileHeader), reinterpret_cast<uint8_t *>(&elfFileHeader + 1));
ret.resize(programHeadersOffset, 0U);
for (auto &programHeader : programHeaders) {
if (0 != programHeader.fileSz) {
programHeader.offset = static_cast<decltype(programHeader.offset)>(programHeader.offset + dataOffset);
}
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&programHeader), reinterpret_cast<uint8_t *>(&programHeader + 1));
ret.resize(ret.size() + elfFileHeader.phEntSize - sizeof(programHeader), 0U);
}
for (auto &sectionHeader : sectionHeaders) {
if ((SHT_NOBITS != sectionHeader.type) && (0 != sectionHeader.size)) {
sectionHeader.offset = static_cast<decltype(sectionHeader.offset)>(sectionHeader.offset + dataOffset);
}
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&sectionHeader), reinterpret_cast<uint8_t *>(&sectionHeader + 1));
ret.resize(ret.size() + elfFileHeader.shEntSize - sizeof(sectionHeader), 0U);
}
ret.resize(dataOffset, 0U);
ret.insert(ret.end(), data.begin(), data.end());
ret.resize(ret.size() + dataPaddingBeforeSectionNames, 0U);
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(stringTable.data()), reinterpret_cast<const uint8_t *>(stringTable.data() + static_cast<size_t>(sectionHeaderNamesSection.size)));
ret.resize(ret.size() + alignedSectionNamesDataSize - static_cast<size_t>(sectionHeaderNamesSection.size), 0U);
return ret;
}
template struct ElfEncoder<EI_CLASS_32>;
template struct ElfEncoder<EI_CLASS_64>;
} // namespace Elf
} // namespace NEO

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "device_binary_format/elf/elf.h"
#include "helpers/aligned_memory.h"
#include "utilities/arrayref.h"
#include "utilities/const_stringref.h"
#include "utilities/stackvec.h"
#include <queue>
#include <string>
namespace NEO {
namespace Elf {
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
struct ElfEncoder {
ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true, uint64_t defaultDataAlignment = 8U);
void appendSection(const ElfSectionHeader<NumBits> &sectionHeader, const ArrayRef<const uint8_t> sectionData);
void appendSegment(const ElfProgramHeader<NumBits> &programHeader, const ArrayRef<const uint8_t> segmentData);
ElfSectionHeader<NumBits> &appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
ElfProgramHeader<NumBits> &appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef<const uint8_t> segmentData);
template <typename SectionHeaderEnumT>
ElfSectionHeader<NumBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
return appendSection(static_cast<SECTION_HEADER_TYPE>(sectionType), sectionLabel, sectionData);
}
template <typename SectionHeaderEnumT>
ElfSectionHeader<NumBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const std::string &sectionData) {
return appendSection(static_cast<SECTION_HEADER_TYPE>(sectionType), sectionLabel,
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;
uint64_t defaultDataAlignment = 8U;
uint64_t maxDataAlignmentNeeded = 1U;
ElfFileHeader<NumBits> elfFileHeader;
StackVec<ElfProgramHeader<NumBits>, 32> programHeaders;
StackVec<ElfSectionHeader<NumBits>, 32> sectionHeaders;
std::vector<uint8_t> data;
std::vector<char> stringTable;
struct {
uint32_t shStrTab = 0;
uint32_t undef = 0;
} specialStringsOffsets;
};
extern template struct ElfEncoder<EI_CLASS_32>;
extern template struct ElfEncoder<EI_CLASS_64>;
} // namespace Elf
} // namespace NEO

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
// Abstract: Defines the types used for ELF headers/sections.
#pragma once
#include "device_binary_format/elf/elf.h"
#include "utilities/const_stringref.h"
#include <inttypes.h>
#include <stddef.h>
namespace NEO {
namespace Elf {
enum ELF_TYPE_OPENCL : uint16_t {
ET_OPENCL_SOURCE = 0xff01, // format used to pass CL text sections to FE
ET_OPENCL_OBJECTS = 0xff02, // format used to pass LLVM objects / store LLVM binary output
ET_OPENCL_LIBRARY = 0xff03, // format used to store LLVM archive output
ET_OPENCL_EXECUTABLE = 0xff04, // format used to store executable output
ET_OPENCL_DEBUG = 0xff05, // format used to store debug output
};
static_assert(sizeof(ELF_TYPE_OPENCL) == sizeof(ELF_TYPE), "");
static_assert(static_cast<uint16_t>(ET_OPENCL_SOURCE) == static_cast<uint16_t>(ET_OPENCL_RESERVED_START), "");
static_assert(static_cast<uint16_t>(ET_OPENCL_DEBUG) == static_cast<uint16_t>(ET_OPENCL_RESERVED_END), "");
enum SHT_OPENCL : uint32_t {
SHT_OPENCL_SOURCE = 0xff000000, // CL source to link into LLVM binary
SHT_OPENCL_HEADER = 0xff000001, // CL header to link into LLVM binary
SHT_OPENCL_LLVM_TEXT = 0xff000002, // LLVM text
SHT_OPENCL_LLVM_BINARY = 0xff000003, // LLVM byte code
SHT_OPENCL_LLVM_ARCHIVE = 0xff000004, // LLVM archives(s)
SHT_OPENCL_DEV_BINARY = 0xff000005, // Device binary (coherent by default)
SHT_OPENCL_OPTIONS = 0xff000006, // CL Options
SHT_OPENCL_PCH = 0xff000007, // PCH (pre-compiled headers)
SHT_OPENCL_DEV_DEBUG = 0xff000008, // Device debug
SHT_OPENCL_SPIRV = 0xff000009, // SPIRV
SHT_NON_COHERENT_DEV_BINARY = 0xff00000a, // Non-coherent Device binary
};
static_assert(sizeof(SHT_OPENCL) == sizeof(SECTION_HEADER_TYPE), "");
static_assert(static_cast<uint32_t>(SHT_OPENCL_SOURCE) == static_cast<uint32_t>(SHT_OPENCL_RESERVED_START), "");
static_assert(static_cast<uint32_t>(SHT_NON_COHERENT_DEV_BINARY) == static_cast<uint32_t>(SHT_OPENCL_RESERVED_END), "");
namespace SectionNamesOpenCl {
static constexpr ConstStringRef buildOptions = "BuildOptions";
static constexpr ConstStringRef spirvObject = "SPIRV Object";
static constexpr ConstStringRef llvmObject = "Intel(R) OpenCL LLVM Object";
static constexpr ConstStringRef deviceDebug = "Intel(R) OpenCL Device Debug";
static constexpr ConstStringRef deviceBinary = "Intel(R) OpenCL Device Binary";
} // namespace SectionNamesOpenCl
} // namespace Elf
} // namespace NEO