Program refactor

* Decouple binary program handling from Program object
* Add binary formats multiplexer
* Improve Elf format support

Change-Id: Ic22aff40173532e14825d70b82ec53fcc5fa9fdf
This commit is contained in:
Jaroslaw Chodor
2020-01-25 19:18:48 +01:00
parent cb964f9e72
commit a53e26342a
96 changed files with 3917 additions and 2023 deletions

View File

@@ -13,6 +13,7 @@ set(NEO_COMPILER_INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface.inl
${CMAKE_CURRENT_SOURCE_DIR}/create_main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/default_cache_config.h
${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations.h
${CMAKE_CURRENT_SOURCE_DIR}/linker.h
${CMAKE_CURRENT_SOURCE_DIR}/linker.cpp
${CMAKE_CURRENT_SOURCE_DIR}/compiler_options/compiler_options_base.h

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -106,8 +106,9 @@ class CompilerInterface {
CompilerInterface &operator=(CompilerInterface &&) = delete;
virtual ~CompilerInterface();
static CompilerInterface *createInstance(std::unique_ptr<CompilerCache> cache, bool requireFcl) {
auto instance = new CompilerInterface();
template <typename CompilerInterfaceT = CompilerInterface>
static CompilerInterfaceT *createInstance(std::unique_ptr<CompilerCache> cache, bool requireFcl) {
auto instance = new CompilerInterfaceT();
if (!instance->initialize(std::move(cache), requireFcl)) {
delete instance;
instance = nullptr;
@@ -137,7 +138,7 @@ class CompilerInterface {
MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSipKernelBinary(NEO::Device &device, SipKernelType type, std::vector<char> &retBinary);
protected:
bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl);
MOCKABLE_VIRTUAL bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl);
MOCKABLE_VIRTUAL bool loadFcl();
MOCKABLE_VIRTUAL bool loadIgc();

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/utilities/arrayref.h"
#include "core/utilities/const_stringref.h"
#include <algorithm>
#include <cstdint>
namespace NEO {
static constexpr ConstStringRef llvmBcMagic = "BC\xc0\xde";
static constexpr ConstStringRef spirvMagic = "\x07\x23\x02\x03";
static constexpr ConstStringRef spirvMagicInv = "\x03\x02\x23\x07";
inline bool hasSameMagic(ConstStringRef expectedMagic, ArrayRef<const uint8_t> binary) {
auto binaryMagicLen = std::min(expectedMagic.size(), binary.size());
ConstStringRef binaryMagic(reinterpret_cast<const char *>(binary.begin()), binaryMagicLen);
return expectedMagic == binaryMagic;
}
inline bool isLlvmBitcode(ArrayRef<const uint8_t> binary) {
return hasSameMagic(llvmBcMagic, binary);
}
inline bool isSpirVBitcode(ArrayRef<const uint8_t> binary) {
return hasSameMagic(spirvMagic, binary) || hasSameMagic(spirvMagicInv, binary);
}
} // namespace NEO

View File

@@ -6,11 +6,22 @@
set(NEO_DEVICE_BINARY_FORMAT
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ocl_elf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_patchtokens.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats.h
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder.h
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper.h
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator.inl
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator.h
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf.h
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder.h
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder.h
${CMAKE_CURRENT_SOURCE_DIR}/elf/ocl_elf.h
)
set_property(GLOBAL PROPERTY NEO_DEVICE_BINARY_FORMAT ${NEO_DEVICE_BINARY_FORMAT})

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "common/compiler_support.h"
#include "core/compiler_interface/intermediate_representations.h"
#include "core/device_binary_format/device_binary_formats.h"
#include "core/device_binary_format/elf/elf_decoder.h"
#include "core/device_binary_format/elf/elf_encoder.h"
#include "core/device_binary_format/elf/ocl_elf.h"
#include <tuple>
namespace NEO {
template <>
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t> binary) {
auto header = Elf::decodeElfFileHeader<Elf::EI_CLASS_64>(binary);
if (nullptr == header) {
return false;
}
switch (header->type) {
default:
return false;
case Elf::ET_OPENCL_EXECUTABLE:
CPP_ATTRIBUTE_FALLTHROUGH;
case Elf::ET_OPENCL_LIBRARY:
CPP_ATTRIBUTE_FALLTHROUGH;
case Elf::ET_OPENCL_OBJECTS:
return true;
}
}
template <>
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice requestedTargetDevice,
std::string &outErrReason, std::string &outWarning) {
auto elf = Elf::decodeElf<Elf::EI_CLASS_64>(archive, outErrReason, outWarning);
if (nullptr == elf.elfFileHeader) {
return {};
}
SingleDeviceBinary ret;
switch (elf.elfFileHeader->type) {
default:
outErrReason = "Not OCL ELF file type";
return {};
case Elf::ET_OPENCL_EXECUTABLE:
ret.format = NEO::DeviceBinaryFormat::Patchtokens;
break;
case Elf::ET_OPENCL_LIBRARY:
ret.format = NEO::DeviceBinaryFormat::OclLibrary;
break;
case Elf::ET_OPENCL_OBJECTS:
ret.format = NEO::DeviceBinaryFormat::OclCompiledObject;
break;
}
for (auto &elfSectionHeader : elf.sectionHeaders) {
auto sectionData = elfSectionHeader.data;
switch (elfSectionHeader.header->type) {
case Elf::SHT_OPENCL_SPIRV:
CPP_ATTRIBUTE_FALLTHROUGH;
case Elf::SHT_OPENCL_LLVM_BINARY:
ret.intermediateRepresentation = sectionData;
break;
case Elf::SHT_OPENCL_DEV_BINARY:
ret.deviceBinary = sectionData;
break;
case Elf::SHT_OPENCL_OPTIONS:
ret.buildOptions = ConstStringRef(reinterpret_cast<const char *>(sectionData.begin()), sectionData.size());
break;
case Elf::SHT_OPENCL_DEV_DEBUG:
ret.debugData = sectionData;
break;
case Elf::SHT_STRTAB:
// ignoring intentionally - identifying sections by types
continue;
case Elf::SHT_NULL:
// ignoring intentionally, inactive section, probably UNDEF
continue;
default:
outErrReason = "Unhandled ELF section";
return {};
}
}
if (NEO::DeviceBinaryFormat::Patchtokens != ret.format) {
ret.deviceBinary.clear();
return ret;
}
if (false == ret.deviceBinary.empty()) {
auto unpackedOclDevBin = unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(ret.deviceBinary, requestedProductAbbreviation, requestedTargetDevice,
outErrReason, outWarning);
if (unpackedOclDevBin.deviceBinary.empty()) {
ret.deviceBinary.clear();
ret.debugData.clear();
} else {
ret.targetDevice = unpackedOclDevBin.targetDevice;
}
}
return ret;
}
template <>
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
// packed binary format
outErrReason = "Device binary format is packed";
return DecodeError::InvalidBinary;
}
template <>
std::vector<uint8_t> packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning) {
using namespace NEO::Elf;
NEO::Elf::ElfEncoder<EI_CLASS_64> elfEncoder;
elfEncoder.getElfFileHeader().type = ET_OPENCL_EXECUTABLE;
if (binary.buildOptions.empty() == false) {
elfEncoder.appendSection(SHT_OPENCL_OPTIONS, SectionNamesOpenCl::buildOptions,
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.buildOptions.data()), binary.buildOptions.size()));
}
if (binary.intermediateRepresentation.empty() == false) {
if (NEO::isSpirVBitcode(binary.intermediateRepresentation)) {
elfEncoder.appendSection(SHT_OPENCL_SPIRV, SectionNamesOpenCl::spirvObject, binary.intermediateRepresentation);
} else if (NEO::isLlvmBitcode(binary.intermediateRepresentation)) {
elfEncoder.appendSection(SHT_OPENCL_LLVM_BINARY, SectionNamesOpenCl::llvmObject, binary.intermediateRepresentation);
} else {
outErrReason = "Unknown intermediate representation format";
return {};
}
}
if (binary.debugData.empty() == false) {
elfEncoder.appendSection(SHT_OPENCL_DEV_DEBUG, SectionNamesOpenCl::deviceDebug, binary.debugData);
}
if (binary.deviceBinary.empty() == false) {
elfEncoder.appendSection(SHT_OPENCL_DEV_BINARY, SectionNamesOpenCl::deviceBinary, binary.deviceBinary);
}
return elfEncoder.encode();
}
} // namespace NEO

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/device_binary_formats.h"
#include "core/device_binary_format/patchtokens_decoder.h"
#include "core/device_binary_format/patchtokens_dumper.h"
#include "core/device_binary_format/patchtokens_validator.h"
#include "core/helpers/debug_helpers.h"
#include "core/program/program_info_from_patchtokens.h"
#include "runtime/utilities/logger.h"
namespace NEO {
template <>
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t> binary) {
return NEO::PatchTokenBinary::isValidPatchTokenBinary(binary);
}
template <>
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice requestedTargetDevice,
std::string &outErrReason, std::string &outWarning) {
auto programHeader = NEO::PatchTokenBinary::decodeProgramHeader(archive);
if (nullptr == programHeader) {
outErrReason = "Invalid program header";
return {};
}
bool validForTarget = (requestedTargetDevice.coreFamily == static_cast<GFXCORE_FAMILY>(programHeader->Device));
validForTarget &= (requestedTargetDevice.maxPointerSizeInBytes >= programHeader->GPUPointerSizeInBytes);
validForTarget &= (iOpenCL::CURRENT_ICBE_VERSION == programHeader->Version);
if (false == validForTarget) {
outErrReason = "Unhandled target device";
return {};
}
SingleDeviceBinary ret = {};
ret.targetDevice = requestedTargetDevice;
ret.format = NEO::DeviceBinaryFormat::Patchtokens;
ret.deviceBinary = archive;
return ret;
}
template <>
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram = {};
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(src.deviceBinary, decodedProgram);
DBG_LOG(LogPatchTokens, NEO::PatchTokenBinary::asString(decodedProgram).c_str());
std::string validatorWarnings;
std::string validatorErrMessage;
auto validatorErr = PatchTokenBinary::validate(decodedProgram, outErrReason, outWarning);
if (DecodeError::Success != validatorErr) {
return validatorErr;
}
NEO::populateProgramInfo(dst, decodedProgram);
return DecodeError::Success;
}
} // namespace NEO

View File

@@ -0,0 +1,16 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/device_binary_formats.h"
namespace NEO {
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning) {
return packDeviceBinary<DeviceBinaryFormat::OclElf>(binary, outErrReason, outWarning);
}
} // namespace NEO

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/utilities/arrayref.h"
#include "core/utilities/const_stringref.h"
#include <cstddef>
#include <cstdint>
#include <igfxfmid.h>
#include <memory>
#include <vector>
namespace NEO {
struct ProgramInfo;
enum class DeviceBinaryFormat : uint8_t {
Unknown,
OclElf,
OclLibrary,
OclCompiledObject,
Patchtokens
};
enum class DecodeError : uint8_t {
Success,
Undefined,
InvalidBinary,
UnhandledBinary
};
inline const char *asString(DecodeError err) {
switch (err) {
default:
return "with invalid binary";
break;
case DecodeError::UnhandledBinary:
return "with unhandled binary";
break;
case DecodeError::Success:
return "decoded successfully";
break;
case DecodeError::Undefined:
return "in undefined status";
break;
}
}
struct TargetDevice {
GFXCORE_FAMILY coreFamily = IGFX_UNKNOWN_CORE;
uint32_t stepping = 0U;
uint32_t maxPointerSizeInBytes = 4U;
};
struct SingleDeviceBinary {
DeviceBinaryFormat format = DeviceBinaryFormat::Unknown;
ArrayRef<const uint8_t> deviceBinary;
ArrayRef<const uint8_t> debugData;
ArrayRef<const uint8_t> intermediateRepresentation;
ConstStringRef buildOptions;
TargetDevice targetDevice;
};
template <DeviceBinaryFormat Format>
bool isDeviceBinaryFormat(const ArrayRef<const uint8_t> binary);
template <>
bool isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>);
template <>
bool isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>);
inline bool isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
return true;
}
if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(binary)) {
return true;
}
return false;
}
template <DeviceBinaryFormat Format>
SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice requestedTargetDevice,
std::string &outErrReason, std::string &outWarning);
template <>
SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice, std::string &, std::string &);
template <>
SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice, std::string &, std::string &);
inline SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice requestedTargetDevice,
std::string &outErrReason, std::string &outWarning) {
SingleDeviceBinary ret = {};
ret.format = DeviceBinaryFormat::Unknown;
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(archive)) {
return unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(archive)) {
return unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
} else {
outErrReason = "Unknown format";
}
return ret;
}
template <DeviceBinaryFormat Format>
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
template <>
std::vector<uint8_t> packDeviceBinary<DeviceBinaryFormat::OclElf>(const SingleDeviceBinary, std::string &, std::string &);
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
inline bool isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
return true;
}
return false;
}
inline bool isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
return (false == isAnyPackedDeviceBinaryFormat(binary)) && isAnyDeviceBinaryFormat(binary);
}
template <DeviceBinaryFormat Format>
DecodeError decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning);
template <>
DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
template <>
DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
inline std::pair<DecodeError, DeviceBinaryFormat> decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
std::pair<DecodeError, DeviceBinaryFormat> ret;
ret.first = DecodeError::InvalidBinary;
ret.second = DeviceBinaryFormat::Unknown;
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(src.deviceBinary)) {
ret.second = DeviceBinaryFormat::OclElf;
ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(dst, src, outErrReason, outWarning);
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(src.deviceBinary)) {
ret.second = DeviceBinaryFormat::Patchtokens;
ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(dst, src, outErrReason, outWarning);
} else {
outErrReason = "Unknown format";
}
return ret;
}
} // namespace NEO

View File

@@ -0,0 +1,343 @@
/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
// Abstract: Defines the types used for ELF headers/sections.
#pragma once
#include "core/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 "core/device_binary_format/elf/elf_decoder.h"
#include "core/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 "core/device_binary_format/elf/elf.h"
#include "core/utilities/arrayref.h"
#include "core/utilities/const_stringref.h"
#include "core/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 "core/device_binary_format/elf/elf_encoder.h"
#include "core/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 "core/device_binary_format/elf/elf.h"
#include "core/helpers/aligned_memory.h"
#include "core/utilities/arrayref.h"
#include "core/utilities/const_stringref.h"
#include "core/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 "core/device_binary_format/elf/elf.h"
#include "core/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

View File

@@ -63,7 +63,7 @@ inline KernelArgFromPatchtokens &getKernelArg(KernelFromPatchtokens &kernel, siz
if (arg.objectType == ArgObjectType::None) {
arg.objectType = type;
} else if ((arg.objectType != type) && (type != ArgObjectType::None)) {
kernel.decodeStatus = DecoderError::InvalidBinary;
kernel.decodeStatus = DecodeError::InvalidBinary;
DBG_LOG(LogPatchTokens, "\n Mismatched metadata for kernel arg :", argNum);
DEBUG_BREAK_IF(true);
}
@@ -425,7 +425,7 @@ inline bool decodeToken(const SPatchItemHeader *token, KernelFromPatchtokens &ou
} break;
}
return out.decodeStatus != DecoderError::InvalidBinary;
return out.decodeStatus != DecodeError::InvalidBinary;
}
inline bool decodeToken(const SPatchItemHeader *token, ProgramFromPatchtokens &out) {
@@ -475,7 +475,7 @@ inline size_t getPatchTokenTotalSize<ProgramFromPatchtokens>(PatchTokensStreamRe
? tokSize + reinterpret_cast<const SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *>(token)->InlineDataSize
: std::numeric_limits<size_t>::max();
case PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO:
return stream.enoughDataLeft<SPatchAllocateConstantMemorySurfaceProgramBinaryInfo>(token)
return stream.enoughDataLeft<SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo>(token)
? tokSize + reinterpret_cast<const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *>(token)->InlineDataSize
: std::numeric_limits<size_t>::max();
}
@@ -499,12 +499,12 @@ inline bool decodePatchList(PatchTokensStreamReader patchListStream, OutT &out)
return decodeSuccess;
}
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPatchtokens &out) {
PatchTokensStreamReader stream{data};
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> kernelBlob, KernelFromPatchtokens &out) {
PatchTokensStreamReader stream{kernelBlob};
auto decodePos = stream.data.begin();
out.decodeStatus = DecoderError::Undefined;
out.decodeStatus = DecodeError::Undefined;
if (stream.notEnoughDataLeft<SKernelBinaryHeaderCommon>(decodePos)) {
out.decodeStatus = DecoderError::InvalidBinary;
out.decodeStatus = DecodeError::InvalidBinary;
return false;
}
@@ -513,7 +513,7 @@ bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPat
auto kernelInfoBlobSize = sizeof(SKernelBinaryHeaderCommon) + out.header->KernelNameSize + out.header->KernelHeapSize + out.header->GeneralStateHeapSize + out.header->DynamicStateHeapSize + out.header->SurfaceStateHeapSize + out.header->PatchListSize;
if (stream.notEnoughDataLeft(decodePos, kernelInfoBlobSize)) {
out.decodeStatus = DecoderError::InvalidBinary;
out.decodeStatus = DecodeError::InvalidBinary;
return false;
}
@@ -539,11 +539,11 @@ bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPat
out.blobs.patchList = ArrayRef<const uint8_t>(decodePos, out.header->PatchListSize);
if (false == decodePatchList(out.blobs.patchList, out)) {
out.decodeStatus = DecoderError::InvalidBinary;
out.decodeStatus = DecodeError::InvalidBinary;
return false;
}
out.decodeStatus = DecoderError::Success;
out.decodeStatus = DecodeError::Success;
return true;
}
@@ -586,12 +586,12 @@ inline bool decodeKernels(ProgramFromPatchtokens &decodedProgram) {
return decodeSuccess;
}
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> blob, ProgramFromPatchtokens &out) {
out.blobs.programInfo = blob;
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> programBlob, ProgramFromPatchtokens &out) {
out.blobs.programInfo = programBlob;
bool decodeSuccess = decodeProgramHeader(out);
decodeSuccess = decodeSuccess && decodeKernels(out);
decodeSuccess = decodeSuccess && decodePatchList(out.blobs.patchList, out);
out.decodeStatus = decodeSuccess ? DecoderError::Success : DecoderError::InvalidBinary;
out.decodeStatus = decodeSuccess ? DecodeError::Success : DecodeError::InvalidBinary;
return decodeSuccess;
}
@@ -631,6 +631,15 @@ const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumen
return ret;
}
const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob) {
ProgramFromPatchtokens program;
program.blobs.programInfo = programBlob;
if (false == decodeProgramHeader(program)) {
return nullptr;
}
return program.header;
}
} // namespace PatchTokenBinary
} // namespace NEO

View File

@@ -7,10 +7,12 @@
#pragma once
#include "core/device_binary_format/device_binary_formats.h"
#include "core/helpers/ptr_math.h"
#include "core/utilities/arrayref.h"
#include "core/utilities/stackvec.h"
#include "igfxfmid.h"
#include "patch_g7.h"
#include "patch_list.h"
#include "patch_shared.h"
@@ -19,6 +21,7 @@
#include <cstdint>
#include <limits>
#include <memory>
#include <utility>
namespace NEO {
@@ -26,12 +29,6 @@ namespace PatchTokenBinary {
using namespace iOpenCL;
enum class DecoderError {
Success = 0,
Undefined = 1,
InvalidBinary = 2,
};
enum class ArgObjectType : uint32_t {
None = 0,
Buffer,
@@ -100,7 +97,7 @@ struct KernelArgFromPatchtokens {
using StackVecKernelArgs = StackVec<KernelArgFromPatchtokens, 12>;
struct KernelFromPatchtokens {
DecoderError decodeStatus = DecoderError::Undefined;
DecodeError decodeStatus = DecodeError::Undefined;
const SKernelBinaryHeaderCommon *header = nullptr;
ArrayRef<const char> name;
@@ -167,7 +164,7 @@ struct KernelFromPatchtokens {
};
struct ProgramFromPatchtokens {
DecoderError decodeStatus = DecoderError::Undefined;
DecodeError decodeStatus = DecodeError::Undefined;
const SProgramBinaryHeader *header = nullptr;
struct {
@@ -195,8 +192,8 @@ struct KernelArgAttributesFromPatchtokens {
ArrayRef<const char> typeQualifiers;
};
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> blob, KernelFromPatchtokens &out);
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> blob, ProgramFromPatchtokens &out);
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> kernelBlob, KernelFromPatchtokens &out);
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> programBlob, ProgramFromPatchtokens &out);
uint32_t calcKernelChecksum(const ArrayRef<const uint8_t> kernelBlob);
bool hasInvalidChecksum(const KernelFromPatchtokens &decodedKernel);
@@ -214,6 +211,12 @@ inline const uint8_t *getInlineData(const SPatchString *ptr) {
const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumentInfo *ptr);
const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob);
inline bool isValidPatchTokenBinary(const ArrayRef<const uint8_t> programBlob) {
return nullptr != decodeProgramHeader(programBlob);
}
} // namespace PatchTokenBinary
} // namespace NEO

View File

@@ -710,21 +710,6 @@ void dumpVecIfNotEmpty(const T &vector, const std::string &vectorName, std::stri
}
}
const char *asString(DecoderError err) {
switch (err) {
default:
DEBUG_BREAK_IF(err != DecoderError::InvalidBinary);
return "with invalid binary";
break;
case DecoderError::Success:
return "decoded successfully";
break;
case DecoderError::Undefined:
return "in undefined status";
break;
}
}
std::string asString(const ProgramFromPatchtokens &prog) {
std::stringstream stream;
stream << "Program of size : " << prog.blobs.programInfo.size()

View File

@@ -1,11 +1,11 @@
/*
* Copyright (C) 2019-2020 Intel Corporation
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/device_binary_format/patchtokens_validator.h"
#include "core/device_binary_format/patchtokens_decoder.h"
#include "core/helpers/hw_info.h"
@@ -19,35 +19,23 @@ namespace NEO {
namespace PatchTokenBinary {
enum class ValidatorError {
Success = 0,
Undefined = 1,
InvalidBinary = 2,
NotEnoughSlm = 3,
};
bool allowUnhandledTokens = true;
constexpr bool isDeviceSupported(GFXCORE_FAMILY device) {
return (device < (sizeof(familyEnabled) / sizeof(familyEnabled[0]))) && familyEnabled[device];
}
template <typename UknownTokenValidatorT>
inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
size_t sharedLocalMemorySize,
const UknownTokenValidatorT &tokenValidator,
std::string &outErrReason, std::string &outWarnings) {
if (decodedProgram.decodeStatus != PatchTokenBinary::DecoderError::Success) {
DecodeError validate(const ProgramFromPatchtokens &decodedProgram,
std::string &outErrReason, std::string &outWarnings) {
if (decodedProgram.decodeStatus != DecodeError::Success) {
outErrReason = "ProgramFromPatchtokens wasn't successfully decoded";
return ValidatorError::InvalidBinary;
return DecodeError::InvalidBinary;
}
if (decodedProgram.programScopeTokens.allocateConstantMemorySurface.size() > 1) {
outErrReason = "Unhandled number of global constants surfaces > 1";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
if (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size() > 1) {
outErrReason = "Unhandled number of global variables surfaces > 1";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
for (const auto &globalConstantPointerToken : decodedProgram.programScopeTokens.constantPointer) {
@@ -59,7 +47,7 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
if (isUnhandled) {
outErrReason = "Unhandled SPatchConstantPointerProgramBinaryInfo";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
}
@@ -72,50 +60,45 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
if (isUnhandled) {
outErrReason = "Unhandled SPatchGlobalPointerProgramBinaryInfo";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
}
for (const auto &unhandledToken : decodedProgram.unhandledTokens) {
if (false == tokenValidator.isSafeToSkipUnhandledToken(unhandledToken->Token)) {
outErrReason = "Unhandled required program-scope Patch Token : " + std::to_string(unhandledToken->Token);
return ValidatorError::InvalidBinary;
} else {
if (allowUnhandledTokens) {
outWarnings = "Unknown program-scope Patch Token : " + std::to_string(unhandledToken->Token);
} else {
outErrReason = "Unhandled required program-scope Patch Token : " + std::to_string(unhandledToken->Token);
return DecodeError::UnhandledBinary;
}
}
UNRECOVERABLE_IF(nullptr == decodedProgram.header);
if (decodedProgram.header->Version != CURRENT_ICBE_VERSION) {
outErrReason = "Unhandled Version of Patchtokens: expected: " + std::to_string(CURRENT_ICBE_VERSION) + ", got: " + std::to_string(decodedProgram.header->Version);
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
if ((decodedProgram.header->GPUPointerSizeInBytes != 4U) && (decodedProgram.header->GPUPointerSizeInBytes != 8U)) {
outErrReason = "Invalid pointer size";
return ValidatorError::InvalidBinary;
}
if (false == isDeviceSupported(static_cast<GFXCORE_FAMILY>(decodedProgram.header->Device))) {
outErrReason = "Unsupported device binary, device GFXCORE_FAMILY : " + std::to_string(decodedProgram.header->Device);
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
for (const auto &decodedKernel : decodedProgram.kernels) {
if (decodedKernel.decodeStatus != PatchTokenBinary::DecoderError::Success) {
if (decodedKernel.decodeStatus != DecodeError::Success) {
outErrReason = "KernelFromPatchtokens wasn't successfully decoded";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
UNRECOVERABLE_IF(nullptr == decodedKernel.header);
if (hasInvalidChecksum(decodedKernel)) {
outErrReason = "KernelFromPatchtokens has invalid checksum";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
if (nullptr == decodedKernel.tokens.executionEnvironment) {
outErrReason = "Missing execution environment";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
} else {
switch (decodedKernel.tokens.executionEnvironment->LargestCompiledSIMDSize) {
case 1:
@@ -128,14 +111,7 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
break;
default:
outErrReason = "Invalid LargestCompiledSIMDSize";
return ValidatorError::InvalidBinary;
}
}
if (decodedKernel.tokens.allocateLocalSurface) {
if (sharedLocalMemorySize < decodedKernel.tokens.allocateLocalSurface->TotalInlineLocalMemorySize) {
outErrReason = "KernelFromPatchtokens requires too much SLM";
return ValidatorError::NotEnoughSlm;
return DecodeError::UnhandledBinary;
}
}
@@ -147,26 +123,26 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
auto accessQualifier = KernelArgMetadata::parseAccessQualifier(parseLimitedString(argInfoInlineData.accessQualifier.begin(), argInfoInlineData.accessQualifier.size()));
if (KernelArgMetadata::AccessQualifier::Unknown == accessQualifier) {
outErrReason = "Unhandled access qualifier";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
auto addressQualifier = KernelArgMetadata::parseAddressSpace(parseLimitedString(argInfoInlineData.addressQualifier.begin(), argInfoInlineData.addressQualifier.size()));
if (KernelArgMetadata::AddressSpaceQualifier::Unknown == addressQualifier) {
outErrReason = "Unhandled address qualifier";
return ValidatorError::InvalidBinary;
return DecodeError::UnhandledBinary;
}
}
for (const auto &unhandledToken : decodedKernel.unhandledTokens) {
if (false == tokenValidator.isSafeToSkipUnhandledToken(unhandledToken->Token)) {
outErrReason = "Unhandled required kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
return ValidatorError::InvalidBinary;
} else {
if (allowUnhandledTokens) {
outWarnings = "Unknown kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
} else {
outErrReason = "Unhandled required kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
return DecodeError::UnhandledBinary;
}
}
}
return ValidatorError::Success;
return DecodeError::Success;
}
} // namespace PatchTokenBinary

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/device_binary_format/device_binary_formats.h"
#include <string>
namespace NEO {
namespace PatchTokenBinary {
extern bool allowUnhandledTokens;
struct ProgramFromPatchtokens;
DecodeError validate(const ProgramFromPatchtokens &decodedProgram,
std::string &outErrReason, std::string &outWarnings);
} // namespace PatchTokenBinary
} // namespace NEO

View File

@@ -1,23 +0,0 @@
#
# Copyright (C) 2017-2019 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
add_library(elflib STATIC EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/reader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/reader.h
${CMAKE_CURRENT_SOURCE_DIR}/types.h
${CMAKE_CURRENT_SOURCE_DIR}/writer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/writer.h
)
create_project_source_tree(elflib)
target_include_directories(elflib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(elflib PRIVATE ${NEO_SOURCE_DIR})
set_target_properties(elflib PROPERTIES FOLDER "elflib")
set_target_properties(elflib PROPERTIES POSITION_INDEPENDENT_CODE ON)

View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "reader.h"
#include <string.h>
namespace CLElfLib {
CElfReader::CElfReader(ElfBinaryStorage &elfBinary) {
validateElfBinary(elfBinary);
}
void CElfReader::validateElfBinary(ElfBinaryStorage &elfBinary) {
const char *nameTable = nullptr;
const char *end = nullptr;
size_t ourSize = 0u;
size_t entrySize = 0u;
size_t indexedSectionHeaderOffset = 0u;
beginBinary = elfBinary.data();
if (elfBinary.size() >= sizeof(SElf64Header)) {
// calculate a pointer to the end
end = beginBinary + elfBinary.size();
elf64Header = reinterpret_cast<const SElf64Header *>(elfBinary.data());
if (!((elf64Header->Identity[ELFConstants::idIdxMagic0] == ELFConstants::elfMag0) &&
(elf64Header->Identity[ELFConstants::idIdxMagic1] == ELFConstants::elfMag1) &&
(elf64Header->Identity[ELFConstants::idIdxMagic2] == ELFConstants::elfMag2) &&
(elf64Header->Identity[ELFConstants::idIdxMagic3] == ELFConstants::elfMag3) &&
(elf64Header->Identity[ELFConstants::idIdxClass] == static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64)))) {
throw ElfException();
}
ourSize += elf64Header->ElfHeaderSize;
} else {
throw ElfException();
}
entrySize = elf64Header->SectionHeaderEntrySize;
if (elf64Header->SectionNameTableIndex < elf64Header->NumSectionHeaderEntries) {
indexedSectionHeaderOffset = static_cast<size_t>(elf64Header->SectionHeadersOffset) + (elf64Header->SectionNameTableIndex * entrySize);
if ((beginBinary + indexedSectionHeaderOffset) <= end) {
nameTable = beginBinary + indexedSectionHeaderOffset;
}
}
for (uint16_t i = 0u; i < elf64Header->NumSectionHeaderEntries; ++i) {
indexedSectionHeaderOffset = static_cast<size_t>(elf64Header->SectionHeadersOffset) + (i * entrySize);
// check section header offset
if ((beginBinary + indexedSectionHeaderOffset) > end) {
throw ElfException();
}
const SElf64SectionHeader *sectionHeader = nullptr;
sectionHeader = reinterpret_cast<const SElf64SectionHeader *>(beginBinary + indexedSectionHeaderOffset);
// check section data
if ((beginBinary + sectionHeader->DataOffset + sectionHeader->DataSize) > end) {
throw ElfException();
}
// check section name index
if ((nameTable + sectionHeader->Name) > end) {
throw ElfException();
}
SElf64SectionHeader stringSectionHeader = {0};
stringSectionHeader.Type = sectionHeader->Type;
stringSectionHeader.Flags = sectionHeader->Flags;
stringSectionHeader.DataOffset = sectionHeader->DataOffset;
stringSectionHeader.DataSize = sectionHeader->DataSize;
stringSectionHeader.Name = sectionHeader->Name;
sectionHeaders.push_back(std::move(stringSectionHeader));
// tally up the sizes
ourSize += static_cast<size_t>(sectionHeader->DataSize);
ourSize += static_cast<size_t>(entrySize);
}
if (ourSize != elfBinary.size()) {
throw ElfException();
}
}
char *CElfReader::getSectionData(Elf64_Off dataOffset) {
return beginBinary + dataOffset;
}
const SElf64Header *CElfReader::getElfHeader() {
return elf64Header;
}
} // namespace CLElfLib

View File

@@ -1,39 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "types.h"
namespace CLElfLib {
using ElfSectionHeaderStorage = std::vector<SElf64SectionHeader>;
/******************************************************************************\
Class: CElfReader
Description: Class to provide simpler interaction with the ELF standard
binary object. SElf64Header defines the ELF header type and
SElf64SectionHeader defines the section header type.
\******************************************************************************/
class CElfReader {
public:
CElfReader(ElfBinaryStorage &elfBinary);
ElfSectionHeaderStorage &getSectionHeaders() {
return sectionHeaders;
}
const SElf64Header *getElfHeader();
char *getSectionData(Elf64_Off dataOffset);
protected:
void validateElfBinary(ElfBinaryStorage &elfBinary);
ElfSectionHeaderStorage sectionHeaders;
char *beginBinary;
const SElf64Header *elf64Header;
};
} // namespace CLElfLib

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
// Abstract: Defines the types used for ELF headers/sections.
#pragma once
#include <inttypes.h>
#include <stddef.h>
#include <vector>
namespace CLElfLib {
struct ElfException : std::exception {
};
using ElfBinaryStorage = std::vector<char>;
/******************************************************************************\
ELF Enumerates
\******************************************************************************/
// E_ID_IDX - Defines a file as being ELF
enum class E_ID_IDX : uint32_t {
ID_IDX_MAGIC0 = 0,
ID_IDX_MAGIC1 = 1,
ID_IDX_MAGIC2 = 2,
ID_IDX_MAGIC3 = 3,
ID_IDX_CLASS = 4,
ID_IDX_VERSION = 5,
ID_IDX_OSABI = 6,
ID_IDX_ABI_VERSION = 7,
ID_IDX_PADDING = 8,
ID_IDX_NUM_BYTES = 16,
};
// E_EHT_CLASS - Describes what data types the ELF structures will use.
enum class E_EH_CLASS : uint32_t {
EH_CLASS_NONE = 0,
EH_CLASS_32 = 1, // Use Elf32 data types
EH_CLASS_64 = 2, // Use Elf64 data types
};
// E_EHT_TYPE - List of pre-defined types header types.
// OS-specific codes start at 0xfe00 and run to 0xfeff.
// Processor-specific codes start at 0xff00 and end at 0xffff.
enum class E_EH_TYPE : uint16_t {
EH_TYPE_NONE = 0,
EH_TYPE_RELOCATABLE = 1,
EH_TYPE_EXECUTABLE = 2,
EH_TYPE_DYNAMIC = 3,
EH_TYPE_CORE = 4,
EH_TYPE_OPENCL_SOURCE = 0xff01, // format used to pass CL text sections to FE
EH_TYPE_OPENCL_OBJECTS = 0xff02, // format used to pass LLVM objects / store LLVM binary output
EH_TYPE_OPENCL_LIBRARY = 0xff03, // format used to store LLVM archive output
EH_TYPE_OPENCL_EXECUTABLE = 0xff04, // format used to store executable output
EH_TYPE_OPENCL_DEBUG = 0xff05, // format used to store debug output
};
// E_EH_MACHINE - List of pre-defined machine types.
// For OpenCL, currently, we do not need this information, so this is not
// fully defined.
enum class E_EH_MACHINE : uint16_t {
EH_MACHINE_NONE = 0,
//EHT_MACHINE_LO_RSVD = 1, // Beginning of range of reserved types.
//EHT_MACHINE_HI_RSVD = 200, // End of range of reserved types.
};
// E_EHT_VERSION - ELF header version options.
enum class E_EHT_VERSION : uint32_t {
EH_VERSION_INVALID = 0,
EH_VERSION_CURRENT = 1,
};
// E_SH_TYPE - List of pre-defined section header types.
// Processor-specific codes start at 0xff00 and end at 0xffff.
enum class E_SH_TYPE : uint32_t {
SH_TYPE_NULL = 0,
SH_TYPE_PROG_BITS = 1,
SH_TYPE_SYM_TBL = 2,
SH_TYPE_STR_TBL = 3,
SH_TYPE_RELO_ADDS = 4,
SH_TYPE_HASH = 5,
SH_TYPE_DYN = 6,
SH_TYPE_NOTE = 7,
SH_TYPE_NOBITS = 8,
SH_TYPE_RELO_NO_ADDS = 9,
SH_TYPE_SHLIB = 10,
SH_TYPE_DYN_SYM_TBL = 11,
SH_TYPE_INIT = 14,
SH_TYPE_FINI = 15,
SH_TYPE_PRE_INIT = 16,
SH_TYPE_GROUP = 17,
SH_TYPE_SYMTBL_SHNDX = 18,
SH_TYPE_OPENCL_SOURCE = 0xff000000, // CL source to link into LLVM binary
SH_TYPE_OPENCL_HEADER = 0xff000001, // CL header to link into LLVM binary
SH_TYPE_OPENCL_LLVM_TEXT = 0xff000002, // LLVM text
SH_TYPE_OPENCL_LLVM_BINARY = 0xff000003, // LLVM byte code
SH_TYPE_OPENCL_LLVM_ARCHIVE = 0xff000004, // LLVM archives(s)
SH_TYPE_OPENCL_DEV_BINARY = 0xff000005, // Device binary (coherent by default)
SH_TYPE_OPENCL_OPTIONS = 0xff000006, // CL Options
SH_TYPE_OPENCL_PCH = 0xff000007, // PCH (pre-compiled headers)
SH_TYPE_OPENCL_DEV_DEBUG = 0xff000008, // Device debug
SH_TYPE_SPIRV = 0xff000009, // SPIRV
SH_TYPE_NON_COHERENT_DEV_BINARY = 0xff00000a, // Non-coherent Device binary
};
// E_SH_FLAG - List of section header flags.
enum class E_SH_FLAG : uint64_t {
SH_FLAG_NONE = 0x0,
SH_FLAG_WRITE = 0x1,
SH_FLAG_ALLOC = 0x2,
SH_FLAG_EXEC_INSTR = 0x4,
SH_FLAG_MERGE = 0x8,
SH_FLAG_STRINGS = 0x10,
SH_FLAG_INFO_LINK = 0x20,
SH_FLAG_LINK_ORDER = 0x40,
SH_FLAG_OS_NONCONFORM = 0x100,
SH_FLAG_GROUP = 0x200,
SH_FLAG_TLS = 0x400,
SH_FLAG_MASK_OS = 0x0ff00000,
SH_FLAG_MASK_PROC = 0xf0000000,
};
/******************************************************************************\
ELF-64 Data Types
\******************************************************************************/
#if !defined(_UAPI_LINUX_ELF_H)
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef uint16_t Elf64_Short; // Renaming Elf64_Half to Elf64_Short to avoid a conflict with Android
#endif
/******************************************************************************\
ELF Constants
\******************************************************************************/
namespace ELFConstants {
static const unsigned char elfMag0 = 0x7f; // ELFHeader.Identity[ELF_ID_MAGIC0]
static const unsigned char elfMag1 = 'E'; // ELFHeader.Identity[ELF_ID_MAGIC1]
static const unsigned char elfMag2 = 'L'; // ELFHeader.Identity[ELF_ID_MAGIC2]
static const unsigned char elfMag3 = 'F'; // ELFHeader.Identity[ELF_ID_MAGIC3]
static const unsigned int elfAlignBytes = 16; // Alignment set to 16-bytes
static const uint32_t idIdxMagic0 = 0;
static const uint32_t idIdxMagic1 = 1;
static const uint32_t idIdxMagic2 = 2;
static const uint32_t idIdxMagic3 = 3;
static const uint32_t idIdxClass = 4;
static const uint32_t idIdxVersion = 5;
static const uint32_t idIdxOsabi = 6;
static const uint32_t idIdxAbiVersion = 7;
static const uint32_t idIdxPadding = 8;
static const uint32_t idIdxNumBytes = 16;
} // namespace ELFConstants
/******************************************************************************\
ELF-64 Header
\******************************************************************************/
struct SElf64Header {
unsigned char Identity[ELFConstants::idIdxNumBytes];
E_EH_TYPE Type;
E_EH_MACHINE Machine;
Elf64_Word Version;
Elf64_Addr EntryAddress;
Elf64_Off ProgramHeadersOffset;
Elf64_Off SectionHeadersOffset;
Elf64_Word Flags;
Elf64_Short ElfHeaderSize;
Elf64_Short ProgramHeaderEntrySize;
Elf64_Short NumProgramHeaderEntries;
Elf64_Short SectionHeaderEntrySize;
Elf64_Short NumSectionHeaderEntries;
Elf64_Short SectionNameTableIndex;
};
/******************************************************************************\
ELF-64 Section Header
\******************************************************************************/
struct SElf64SectionHeader {
Elf64_Word Name;
E_SH_TYPE Type;
E_SH_FLAG Flags;
Elf64_Addr Address;
Elf64_Off DataOffset;
Elf64_Xword DataSize;
Elf64_Word Link;
Elf64_Word Info;
Elf64_Xword Alignment;
Elf64_Xword EntrySize;
};
} // namespace CLElfLib

View File

@@ -1,105 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "writer.h"
#include <cstring>
// Need for linux compatibility with memcpy_s
#include "core/helpers/string.h"
namespace CLElfLib {
void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
SElf64SectionHeader *curSectionHeader = nullptr;
char *data = nullptr;
char *stringTable = nullptr;
char *curString = nullptr;
if (binary.size() < getTotalBinarySize()) {
binary.resize(getTotalBinarySize());
}
// get a pointer to the first section header
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(binary.data() + sizeof(SElf64Header));
// get a pointer to the data
data = binary.data() +
sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
// get a pointer to the string table
stringTable = binary.data() + sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
dataSize;
curString = stringTable;
// Walk through the section nodes
while (nodeQueue.empty() == false) {
// Copy data into the section header
const auto &queueFront = nodeQueue.front();
curSectionHeader->Type = queueFront.type;
curSectionHeader->Flags = queueFront.flag;
curSectionHeader->DataSize = queueFront.dataSize;
curSectionHeader->DataOffset = data - binary.data();
curSectionHeader->Name = static_cast<Elf64_Word>(curString - stringTable);
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(curSectionHeader) + sizeof(SElf64SectionHeader));
// copy the data, move the data pointer
memcpy_s(data, queueFront.dataSize, queueFront.data.c_str(), queueFront.dataSize);
data += queueFront.dataSize;
// copy the name into the string table, move the string pointer
if (queueFront.name.size() > 0) {
memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size());
curString += queueFront.name.size();
}
*(curString++) = '\0'; // NOLINT
nodeQueue.pop();
}
// add the string table section header
SElf64SectionHeader stringSectionHeader = {0};
stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL;
stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE;
stringSectionHeader.DataOffset = stringTable - &binary[0];
stringSectionHeader.DataSize = stringTableSize;
stringSectionHeader.Name = 0;
// Copy into the last section header
memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader),
&stringSectionHeader, sizeof(SElf64SectionHeader));
// Add to our section number
numSections++;
// patch up the ELF header
patchElfHeader(*reinterpret_cast<SElf64Header *>(binary.data()));
}
void CElfWriter::patchElfHeader(SElf64Header &binary) {
// Setup the identity
binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
binary.Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
binary.Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
// Add other non-zero info
binary.Type = type;
binary.Machine = machine;
binary.Flags = static_cast<uint32_t>(flag);
binary.ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
binary.NumSectionHeaderEntries = numSections;
binary.SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionNameTableIndex = numSections - 1; // last index
}
} // namespace CLElfLib

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "types.h"
#include <queue>
#include <string>
namespace CLElfLib {
struct SSectionNode {
E_SH_TYPE type = E_SH_TYPE::SH_TYPE_NULL;
E_SH_FLAG flag = E_SH_FLAG::SH_FLAG_NONE;
std::string name;
std::string data;
uint32_t dataSize = 0u;
SSectionNode() = default;
template <typename T1, typename T2>
SSectionNode(E_SH_TYPE type, E_SH_FLAG flag, T1 &&name, T2 &&data, uint32_t dataSize)
: type(type), flag(flag), name(std::forward<T1>(name)), data(std::forward<T2>(data)), dataSize(dataSize) {}
~SSectionNode() = default;
};
/******************************************************************************\
Class: CElfWriter
Description: Class to provide simpler interaction with the ELF standard
binary object. SElf64Header defines the ELF header type and
SElf64SectionHeader defines the section header type.
\******************************************************************************/
class CElfWriter {
public:
CElfWriter(
E_EH_TYPE type,
E_EH_MACHINE machine,
Elf64_Xword flag) : type(type), machine(machine), flag(flag) {
addSection(SSectionNode());
}
~CElfWriter() {}
template <typename T>
void addSection(T &&sectionNode) {
size_t nameSize = 0;
uint32_t dataSize = 0;
nameSize = sectionNode.name.size() + 1u;
dataSize = sectionNode.dataSize;
// push the node onto the queue
nodeQueue.push(std::forward<T>(sectionNode));
// increment the sizes for each section
this->dataSize += dataSize;
stringTableSize += nameSize;
numSections++;
}
void resolveBinary(ElfBinaryStorage &binary);
size_t getTotalBinarySize() {
return sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
dataSize + stringTableSize;
}
protected:
E_EH_TYPE type = E_EH_TYPE::EH_TYPE_NONE;
E_EH_MACHINE machine = E_EH_MACHINE::EH_MACHINE_NONE;
Elf64_Xword flag = 0U;
std::queue<SSectionNode> nodeQueue;
uint32_t dataSize = 0U;
uint32_t numSections = 0U;
size_t stringTableSize = 0U;
void patchElfHeader(SElf64Header &pBinary);
};
} // namespace CLElfLib

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -94,13 +94,13 @@ inline int memmove_s(void *dst, size_t numberOfElements, const void *src, size_t
#endif
template <typename T = char[]>
inline std::unique_ptr<T> makeCopy(const void *src, size_t size) {
template <typename T = char>
inline std::unique_ptr<T[]> makeCopy(const void *src, size_t size) {
if (size == 0) {
return nullptr;
}
using ElT = typename std::remove_all_extents<T>::type;
std::unique_ptr<T> copiedData(reinterpret_cast<ElT *>(new char[size]));
std::unique_ptr<T[]> copiedData(new ElT[size]);
memcpy_s(copiedData.get(), size, src, size);
return copiedData;
}

View File

@@ -18,4 +18,24 @@ ProgramInfo::~ProgramInfo() {
kernelInfos.clear();
}
size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo) {
uint32_t ret = 0U;
for (const auto &kernelInfo : programInfo.kernelInfos) {
if (nullptr == kernelInfo->patchInfo.localsurface) {
continue;
}
ret = std::max(ret, kernelInfo->patchInfo.localsurface->TotalInlineLocalMemorySize);
}
return ret;
}
bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo) {
for (const auto &kernelInfo : programInfo.kernelInfos) {
if (WorkloadInfo::undefinedOffset != kernelInfo->workloadInfo.localMemoryStatelessWindowStartAddressOffset) {
return true;
}
}
return false;
}
} // namespace NEO

View File

@@ -8,8 +8,8 @@
#pragma once
#include "core/compiler_interface/linker.h"
#include "core/utilities/stackvec.h"
#include <cstddef>
#include <memory>
#include <vector>
@@ -42,4 +42,7 @@ struct ProgramInfo {
std::vector<KernelInfo *> kernelInfos;
};
size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo);
bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo);
} // namespace NEO

View File

@@ -25,11 +25,11 @@ bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens
return false;
}
void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, const DeviceInfoKernelPayloadConstants &constants, uint32_t kernelNum) {
void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, uint32_t kernelNum) {
auto kernelInfo = std::make_unique<KernelInfo>();
const PatchTokenBinary::KernelFromPatchtokens &decodedKernel = decodedProgram.kernels[kernelNum];
NEO::populateKernelInfo(*kernelInfo, decodedKernel, decodedProgram.header->GPUPointerSizeInBytes, constants);
NEO::populateKernelInfo(*kernelInfo, decodedKernel, decodedProgram.header->GPUPointerSizeInBytes);
if (decodedKernel.tokens.programSymbolTable) {
dst.prepareLinkerInputStorage();
@@ -44,9 +44,9 @@ void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramF
dst.kernelInfos.push_back(kernelInfo.release());
}
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants) {
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src) {
for (uint32_t i = 0; i < src.kernels.size(); ++i) {
populateSingleKernelInfo(dst, src, constants, i);
populateSingleKernelInfo(dst, src, i);
}
if (src.programScopeTokens.allocateConstantMemorySurface.empty() == false) {

View File

@@ -12,7 +12,6 @@
namespace NEO {
struct ProgramInfo;
struct DeviceInfoKernelPayloadConstants;
namespace PatchTokenBinary {
struct ProgramFromPatchtokens;
@@ -25,6 +24,6 @@ inline uint64_t readMisalignedUint64(const uint64_t *address) {
bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens &src);
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants);
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src);
} // namespace NEO

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2019 Intel Corporation
# Copyright (C) 2019-2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -9,6 +9,7 @@ set(NEO_CORE_COMPILER_INTERFACE_TESTS
${CMAKE_CURRENT_SOURCE_DIR}/compiler_cache_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/compiler_options_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/linker_mock.h
${CMAKE_CURRENT_SOURCE_DIR}/linker_tests.cpp
)

View File

@@ -133,6 +133,15 @@ TEST(CompilerInterface, WhenInitializeIsCalledThenFailIfOneOfRequiredCompilersIs
EXPECT_FALSE(initSuccess);
}
TEST(CompilerInterfaceCreateInstance, WhenInitializeFailedThenReturnNull) {
struct FailInitializeCompilerInterface : CompilerInterface {
bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl) override {
return false;
}
};
EXPECT_EQ(nullptr, CompilerInterface::createInstance<FailInitializeCompilerInterface>(std::make_unique<CompilerCache>(CompilerCacheConfig{}), false));
}
TEST_F(CompilerInterfaceTest, WhenCompilingToIsaThenSuccessIsReturned) {
TranslationOutput translationOutput;
auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput);

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/compiler_interface/intermediate_representations.h"
#include "test.h"
TEST(HasSameMagic, WhenMagicIsMatchedThenReturnTrue) {
EXPECT_TRUE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcdefg").toArrayRef<const uint8_t>()));
}
TEST(HasSameMagic, WhenBinaryIsNullptrThenReturnFalse) {
EXPECT_FALSE(NEO::hasSameMagic("abcd", {}));
}
TEST(HasSameMagic, WhenBinaryIsShorterThanExpectedMagicThenReturnFalse) {
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("ab").toArrayRef<const uint8_t>()));
}
TEST(HasSameMagic, WhenMagicIsNotMatchedThenReturnFalse) {
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcefg").toArrayRef<const uint8_t>()));
}
static constexpr uint8_t llvmBinary[] = "BC\xc0\xde ";
TEST(IsLlvmBitcode, WhenLlvmMagicWasFoundThenBinaryIsValidLLvm) {
EXPECT_TRUE(NEO::isLlvmBitcode(llvmBinary));
}
TEST(IsLlvmBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidLLvm) {
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>()));
}
TEST(IsLlvmBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidLLvm) {
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>(llvmBinary, 2)));
}
TEST(IsLlvmBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidLLvm) {
const uint8_t notLlvmBinary[] = "ABCDEFGHIJKLMNO";
EXPECT_FALSE(NEO::isLlvmBitcode(notLlvmBinary));
}
static constexpr uint32_t spirv[16] = {0x03022307};
static constexpr uint32_t spirvInvEndianes[16] = {0x07230203};
TEST(IsSpirVBitcode, WhenSpirvMagicWasFoundThenBinaryIsValidSpirv) {
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirv), sizeof(spirv))));
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), sizeof(spirvInvEndianes))));
}
TEST(IsSpirVBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidSpirv) {
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>()));
}
TEST(IsSpirVBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidSpirv) {
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), 2)));
}
TEST(IsSpirVBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidSpirv) {
const uint8_t notSpirvBinary[] = "ABCDEFGHIJKLMNO";
EXPECT_FALSE(NEO::isSpirVBitcode(notSpirvBinary));
}

View File

@@ -6,6 +6,11 @@
set(NEO_DEVICE_BINARY_FORMAT_TESTS
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ocl_elf_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_patchtokens_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_tests.h

View File

@@ -0,0 +1,397 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/compiler_interface/intermediate_representations.h"
#include "core/device_binary_format/device_binary_formats.h"
#include "core/device_binary_format/elf/elf_decoder.h"
#include "core/device_binary_format/elf/elf_encoder.h"
#include "core/device_binary_format/elf/ocl_elf.h"
#include "core/program/program_info.h"
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
#include "test.h"
#include <algorithm>
#include <tuple>
TEST(IsDeviceBinaryFormatOclElf, GivenElfThenReturnsTrueIfProperElfFileTypeDetected) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_DEBUG;
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_SOURCE;
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_NONE;
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_EXEC;
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_32> elfEnc32;
elfEnc32.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc32.encode()));
}
TEST(UnpackSingleDeviceBinaryOclElf, WhenFailedToDecodeElfThenUnpackingFails) {
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>({}, "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_STREQ("Invalid or missing ELF header", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryOclElf, GivenNotOclElfThenUnpackingFails) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_STREQ("Not OCL ELF file type", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfThenSetsProperOutputFormat) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
std::string unpackErrors;
std::string unpackWarnings;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(NEO::spirvMagic.begin(), NEO::spirvMagic.size()));
auto elfData = elfEnc64.encode();
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::OclLibrary, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(NEO::isSpirVBitcode(unpackResult.intermediateRepresentation));
EXPECT_EQ(NEO::spirvMagic.size(), unpackResult.intermediateRepresentation.size());
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, ArrayRef<const uint8_t>::fromAny(NEO::llvmBcMagic.begin(), NEO::llvmBcMagic.size()));
elfData = elfEnc64.encode();
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::OclCompiledObject, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(NEO::isLlvmBitcode(unpackResult.intermediateRepresentation));
EXPECT_EQ(NEO::llvmBcMagic.size(), unpackResult.intermediateRepresentation.size());
}
TEST(UnpackSingleDeviceBinaryOclElf, GivenValidOclElfExecutableThenReadsAllSectionProperly) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
targetDevice.stepping = patchtokensProgram.header->SteppingId;
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
const uint8_t intermediateRepresentation[] = "235711";
const uint8_t debugData[] = "313739";
std::string buildOptions = "buildOpts";
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
std::string unpackErrors;
std::string unpackWarnings;
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
{
auto encWithLlvm = elfEnc64;
encWithLlvm.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, intermediateRepresentation);
auto elfData = encWithLlvm.encode();
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
}
{
auto encWithSpirV = elfEnc64;
encWithSpirV.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
auto elfData = encWithSpirV.encode();
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
}
}
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWithUnhandledSectionThenUnpackingFails) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
std::string unpackErrors;
std::string unpackWarnings;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
elfEnc64.appendSection(NEO::Elf::SHT_NOBITS, "my_data", {});
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_STREQ("Unhandled ELF section", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWhenPatchtokensBinaryIsBrokenThenReadsAllSectionProperly) {
const uint8_t intermediateRepresentation[] = "235711";
const uint8_t debugData[] = "313739";
const uint8_t deviceBinary[] = "not_patchtokens";
std::string buildOptions = "buildOpts";
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
std::string unpackErrors;
std::string unpackWarnings;
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, deviceBinary);
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
EXPECT_FALSE(unpackErrors.empty());
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
EXPECT_FALSE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
}
TEST(DecodeSingleDeviceBinaryOclElf, WhenUsedAsSingleDeviceBinaryThenDecodingFails) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
;
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
auto elfData = elfEnc64.encode();
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
targetDevice.stepping = patchtokensProgram.header->SteppingId;
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
NEO::SingleDeviceBinary deviceBinary;
deviceBinary.targetDevice = targetDevice;
deviceBinary.deviceBinary = elfData;
std::string unpackErrors;
std::string unpackWarnings;
NEO::ProgramInfo programInfo;
NEO::DecodeError error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(programInfo, deviceBinary, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_FALSE(unpackErrors.empty());
EXPECT_STREQ("Device binary format is packed", unpackErrors.c_str());
}
TEST(PackDeviceBinaryOclElf, WhenPackingEmptyDataThenEmptyOclElfIsEmitted) {
NEO::SingleDeviceBinary singleBinary;
std::string packErrors;
std::string packWarnings;
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
EXPECT_TRUE(packWarnings.empty());
EXPECT_TRUE(packErrors.empty());
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
std::string decodeElfErrors;
std::string decodeElfWarnings;
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
EXPECT_TRUE(decodeElfErrors.empty());
EXPECT_TRUE(decodeElfWarnings.empty());
ASSERT_NE(nullptr, elf.elfFileHeader);
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
EXPECT_EQ(0U, elf.elfFileHeader->shNum);
}
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWithUnknownIntermediateRepresentationThenFail) {
const uint8_t intermediateRepresentation[] = "not_llvm_and_not_spirv";
NEO::SingleDeviceBinary singleBinary;
singleBinary.intermediateRepresentation = intermediateRepresentation;
std::string packErrors;
std::string packWarnings;
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
EXPECT_TRUE(packedData.empty());
EXPECT_TRUE(packWarnings.empty());
EXPECT_FALSE(packErrors.empty());
EXPECT_STREQ("Unknown intermediate representation format", packErrors.c_str());
}
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWitIntermediateRepresentationThenChoosesProperSectionBasedOnMagic) {
using namespace NEO::Elf;
auto spirV = NEO::spirvMagic;
auto llvmBc = NEO::llvmBcMagic;
NEO::SingleDeviceBinary singleBinary;
{
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
std::string packErrors;
std::string packWarnings;
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
EXPECT_FALSE(packedData.empty());
EXPECT_TRUE(packWarnings.empty());
EXPECT_TRUE(packErrors.empty());
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
std::string decodeElfErrors;
std::string decodeElfWarnings;
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
EXPECT_TRUE(decodeElfErrors.empty());
EXPECT_TRUE(decodeElfWarnings.empty());
ASSERT_NE(nullptr, elf.elfFileHeader);
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
auto spirVSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
ASSERT_NE(nullptr, spirVSection);
ASSERT_EQ(spirV.size(), spirVSection->data.size());
EXPECT_EQ(0, memcmp(spirV.begin(), spirVSection->data.begin(), spirV.size()));
}
{
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(llvmBc.begin(), llvmBc.size());
std::string packErrors;
std::string packWarnings;
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
EXPECT_FALSE(packedData.empty());
EXPECT_TRUE(packWarnings.empty());
EXPECT_TRUE(packErrors.empty());
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
std::string decodeElfErrors;
std::string decodeElfWarnings;
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
EXPECT_TRUE(decodeElfErrors.empty());
EXPECT_TRUE(decodeElfWarnings.empty());
ASSERT_NE(nullptr, elf.elfFileHeader);
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
auto llvmSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_LLVM_BINARY; });
ASSERT_NE(nullptr, llvmSection);
ASSERT_EQ(llvmBc.size(), llvmSection->data.size());
EXPECT_EQ(0, memcmp(llvmBc.begin(), llvmSection->data.begin(), llvmBc.size()));
}
}
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryThenSectionsAreProperlyPopulated) {
using namespace NEO::Elf;
NEO::SingleDeviceBinary singleBinary;
auto spirV = NEO::spirvMagic;
const uint8_t debugData[] = "313739";
const uint8_t deviceBinary[] = "23571113";
std::string buildOptions = "buildOpts";
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
singleBinary.debugData = debugData;
singleBinary.deviceBinary = deviceBinary;
singleBinary.buildOptions = buildOptions;
std::string packErrors;
std::string packWarnings;
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
EXPECT_TRUE(packErrors.empty());
EXPECT_TRUE(packWarnings.empty());
std::string decodeElfErrors;
std::string decodeElfWarnings;
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
EXPECT_TRUE(decodeElfErrors.empty());
EXPECT_TRUE(decodeElfWarnings.empty());
ASSERT_NE(nullptr, elf.elfFileHeader);
auto spirvSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
auto deviceBinarySection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
auto deviceDebugSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
auto buildOptionsSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
[](const Elf<>::SectionHeaderAndData &section) { return section.header->type == NEO::Elf::SHT_OPENCL_OPTIONS; });
ASSERT_NE(nullptr, spirvSection);
ASSERT_EQ(spirV.size(), spirvSection->data.size());
EXPECT_EQ(0, memcmp(spirV.begin(), spirvSection->data.begin(), spirV.size()));
ASSERT_NE(nullptr, deviceBinarySection);
ASSERT_EQ(sizeof(deviceBinary), deviceBinarySection->data.size());
EXPECT_EQ(0, memcmp(deviceBinary, deviceBinarySection->data.begin(), sizeof(deviceBinary)));
ASSERT_NE(nullptr, deviceDebugSection);
ASSERT_EQ(sizeof(debugData), deviceDebugSection->data.size());
EXPECT_EQ(0, memcmp(debugData, deviceDebugSection->data.begin(), sizeof(debugData)));
ASSERT_NE(nullptr, buildOptionsSection);
ASSERT_EQ(buildOptions.size(), buildOptionsSection->data.size());
EXPECT_EQ(0, memcmp(buildOptions.c_str(), buildOptionsSection->data.begin(), buildOptions.size()));
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/device_binary_formats.h"
#include "core/program/program_info.h"
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
#include "test.h"
TEST(IsDeviceBinaryFormatPatchtokens, GiveValidBinaryReturnTrue) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage));
}
TEST(IsDeviceBinaryFormatPatchtokens, GiveInvalidBinaryReturnTrue) {
const uint8_t binary[] = "not_patchtokens";
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(binary));
}
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenFailedToDecodeHeaderThenUnpackingFails) {
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>({}, "", {}, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryAndMatchedWithRequestedTargetDeviceThenReturnSelf) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
targetDevice.stepping = programTokens.header->SteppingId;
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
EXPECT_EQ(targetDevice.coreFamily, unpackResult.targetDevice.coreFamily);
EXPECT_EQ(targetDevice.stepping, unpackResult.targetDevice.stepping);
EXPECT_EQ(targetDevice.maxPointerSizeInBytes, unpackResult.targetDevice.maxPointerSizeInBytes);
EXPECT_FALSE(unpackResult.deviceBinary.empty());
EXPECT_EQ(programTokens.storage.data(), unpackResult.deviceBinary.begin());
EXPECT_EQ(programTokens.storage.size(), unpackResult.deviceBinary.size());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_TRUE(unpackErrors.empty());
}
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryForDifferentCoreFamilyDeviceThenUnpackingFails) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device + 1);
targetDevice.stepping = programTokens.header->SteppingId;
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_FALSE(unpackErrors.empty());
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPatchTokensVerionThenUnpackingFails) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
programTokens.headerMutable->Version += 1;
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
targetDevice.stepping = programTokens.header->SteppingId;
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_FALSE(unpackErrors.empty());
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
}
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPointerSizeThenUnpackingFails) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
programTokens.headerMutable->GPUPointerSizeInBytes = 8U;
NEO::TargetDevice targetDevice;
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
targetDevice.stepping = programTokens.header->SteppingId;
targetDevice.maxPointerSizeInBytes = 4U;
std::string unpackErrors;
std::string unpackWarnings;
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(unpackResult.deviceBinary.empty());
EXPECT_TRUE(unpackResult.debugData.empty());
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
EXPECT_TRUE(unpackResult.buildOptions.empty());
EXPECT_TRUE(unpackWarnings.empty());
EXPECT_FALSE(unpackErrors.empty());
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
}
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenInvalidBinaryThenReturnError) {
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", decodeErrors.c_str());
}
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenValidBinaryThenOutputIsProperlyPopulated) {
PatchTokensTestData::ValidProgramWithKernel programTokens;
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = programTokens.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::Success, error);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
ASSERT_EQ(1U, programInfo.kernelInfos.size());
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/device_binary_formats.h"
#include "core/device_binary_format/elf/elf_encoder.h"
#include "core/device_binary_format/elf/ocl_elf.h"
#include "core/program/program_info.h"
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
#include "test.h"
TEST(DecodeError, WhenStringRepresentationIsNeededThenAsStringEncodesProperly) {
EXPECT_STREQ("decoded successfully", NEO::asString(NEO::DecodeError::Success));
EXPECT_STREQ("in undefined status", NEO::asString(NEO::DecodeError::Undefined));
EXPECT_STREQ("with invalid binary", NEO::asString(NEO::DecodeError::InvalidBinary));
EXPECT_STREQ("with unhandled binary", NEO::asString(NEO::DecodeError::UnhandledBinary));
}
TEST(IsAnyDeviceBinaryFormat, GivenNoneOfKnownFormatsThenReturnsFalse) {
const uint8_t data[] = "none of known formats";
EXPECT_FALSE(NEO::isAnyDeviceBinaryFormat(data));
}
TEST(IsAnyDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(patchtokensProgram.storage));
}
TEST(IsAnyDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(elfEnc.encode()));
}
TEST(UnpackSingleDeviceBinary, GivenUnknownBinaryThenReturnError) {
const uint8_t data[] = "none of known formats";
ConstStringRef requestedProductAbbreviation = "unk";
NEO::TargetDevice requestedTargetDevice;
std::string outErrors;
std::string outWarnings;
auto unpacked = NEO::unpackSingleDeviceBinary(data, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
EXPECT_TRUE(unpacked.buildOptions.empty());
EXPECT_TRUE(unpacked.debugData.empty());
EXPECT_TRUE(unpacked.deviceBinary.empty());
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpacked.format);
EXPECT_EQ(0U, unpacked.targetDevice.coreFamily);
EXPECT_EQ(0U, unpacked.targetDevice.stepping);
EXPECT_EQ(4U, unpacked.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(outWarnings.empty());
EXPECT_STREQ("Unknown format", outErrors.c_str());
}
TEST(UnpackSingleDeviceBinary, GivenPatchtoknsBinaryThenReturnSelf) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
ConstStringRef requestedProductAbbreviation = "unk";
NEO::TargetDevice requestedTargetDevice;
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
requestedTargetDevice.stepping = patchtokensProgram.header->Device;
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
std::string outErrors;
std::string outWarnings;
auto unpacked = NEO::unpackSingleDeviceBinary(patchtokensProgram.storage, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
EXPECT_TRUE(unpacked.buildOptions.empty());
EXPECT_TRUE(unpacked.debugData.empty());
EXPECT_FALSE(unpacked.deviceBinary.empty());
EXPECT_EQ(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin());
EXPECT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(outWarnings.empty());
EXPECT_TRUE(outErrors.empty());
}
TEST(UnpackSingleDeviceBinary, GivenOclElfBinaryThenReturnPatchtokensBinary) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
ConstStringRef requestedProductAbbreviation = "unk";
NEO::TargetDevice requestedTargetDevice;
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
requestedTargetDevice.stepping = patchtokensProgram.header->Device;
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
std::string outErrors;
std::string outWarnings;
auto elfData = elfEnc.encode();
auto unpacked = NEO::unpackSingleDeviceBinary(elfData, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
EXPECT_TRUE(unpacked.buildOptions.empty());
EXPECT_TRUE(unpacked.debugData.empty());
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
EXPECT_TRUE(outWarnings.empty());
EXPECT_TRUE(outErrors.empty());
EXPECT_FALSE(unpacked.deviceBinary.empty());
ASSERT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin(), unpacked.deviceBinary.size()));
}
TEST(IsAnyPackedDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
const uint8_t data[] = "none of known formats";
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(data));
}
TEST(IsAnyPackedDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsFalse) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(patchtokensProgram.storage));
}
TEST(IsAnyPackedDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
EXPECT_TRUE(NEO::isAnyPackedDeviceBinaryFormat(elfEnc.encode()));
}
TEST(IsAnySingleDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
const uint8_t data[] = "none of known formats";
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(data));
}
TEST(IsAnySingleDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
EXPECT_TRUE(NEO::isAnySingleDeviceBinaryFormat(patchtokensProgram.storage));
}
TEST(IsAnySingleDeviceBinaryFormat, GivenOclElfFormatThenReturnsFalse) {
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(elfEnc.encode()));
}
TEST(DecodeSingleDeviceBinary, GivenUnknownFormatThenReturnFalse) {
const uint8_t data[] = "none of known formats";
NEO::ProgramInfo programInfo;
std::string decodeErrors;
std::string decodeWarnings;
NEO::SingleDeviceBinary bin;
bin.deviceBinary = data;
NEO::DecodeError status;
NEO::DeviceBinaryFormat format;
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, format);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_STREQ("Unknown format", decodeErrors.c_str());
}
TEST(DecodeSingleDeviceBinary, GivenPatchTokensFormatThenDecodingSucceeds) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
NEO::ProgramInfo programInfo;
std::string decodeErrors;
std::string decodeWarnings;
NEO::SingleDeviceBinary bin;
bin.deviceBinary = patchtokensProgram.storage;
NEO::DecodeError status;
NEO::DeviceBinaryFormat format;
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::Success, status);
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, format);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_TRUE(decodeErrors.empty());
}
TEST(DecodeSingleDeviceBinary, GivenOclElfFormatThenDecodingFails) {
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
auto elfData = elfEnc.encode();
NEO::ProgramInfo programInfo;
std::string decodeErrors;
std::string decodeWarnings;
NEO::SingleDeviceBinary bin;
bin.deviceBinary = elfData;
NEO::DecodeError status;
NEO::DeviceBinaryFormat format;
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
EXPECT_EQ(NEO::DeviceBinaryFormat::OclElf, format);
EXPECT_TRUE(decodeWarnings.empty());
EXPECT_STREQ("Device binary format is packed", decodeErrors.c_str());
}
TEST(PackDeviceBinary, GivenRequestToPackThenUsesOclElfFormat) {
NEO::SingleDeviceBinary deviceBinary;
std::string packErrors;
std::string packWarnings;
auto packed = NEO::packDeviceBinary(deviceBinary, packErrors, packWarnings);
EXPECT_TRUE(packErrors.empty());
EXPECT_TRUE(packWarnings.empty());
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packed));
}

View File

@@ -0,0 +1,343 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/elf/elf_decoder.h"
#include "test.h"
using namespace NEO::Elf;
TEST(ElfDecoder, WhenEmptyDataThenElfHeaderDecodingFails) {
ArrayRef<const uint8_t> empty;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(empty));
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(empty));
}
TEST(ElfDecoder, WhenValidHaderThenElfHeaderDecodingSucceeds) {
ElfFileHeader<EI_CLASS_64> header64;
EXPECT_EQ(&header64, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
ElfFileHeader<EI_CLASS_32> header32;
EXPECT_EQ(&header32, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
}
TEST(ElfDecoder, WhenNotEngoughDataThenElfHeaderDecodingFails) {
ElfFileHeader<EI_CLASS_64> header64;
auto header64Data = ArrayRef<const uint8_t>::fromAny(&header64, 1U);
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>(header64Data.begin(), header64Data.begin() + header64Data.size() - 1)));
ElfFileHeader<EI_CLASS_32> header32;
auto header32Data = ArrayRef<const uint8_t>::fromAny(&header32, 1U);
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>(header32Data.begin(), header32Data.begin() + header32Data.size() - 1)));
}
TEST(ElfDecoder, WhenInvalidElfMagicThenElfHeaderDecodingFails) {
ElfFileHeader<EI_CLASS_64> header;
header.identity.magic[0] = 5;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
header = ElfFileHeader<EI_CLASS_64>{};
header.identity.magic[1] = 5;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
header = ElfFileHeader<EI_CLASS_64>{};
header.identity.magic[2] = 5;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
header = ElfFileHeader<EI_CLASS_64>{};
header.identity.magic[3] = 5;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
header = ElfFileHeader<EI_CLASS_64>{};
EXPECT_EQ(&header, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
}
TEST(ElfDecoder, WhenMismatchedClassThenElfHeaderDecodingFails) {
ElfFileHeader<EI_CLASS_64> header64;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
ElfFileHeader<EI_CLASS_32> header32;
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
}
TEST(ElfDecoder, WhenNotElfThenCheckNumBitsReturnsClassNone) {
ArrayRef<const uint8_t> empty;
EXPECT_EQ(EI_CLASS_NONE, getElfNumBits(empty));
}
TEST(ElfDecoder, WhenValidElfThenCheckNumBitsReturnsProperClass) {
ElfFileHeader<EI_CLASS_64> header64;
EXPECT_EQ(EI_CLASS_64, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
ElfFileHeader<EI_CLASS_32> header32;
EXPECT_EQ(EI_CLASS_32, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
}
TEST(ElfDecoder, WhenNotElfThenIsElfReturnsFalse) {
ArrayRef<const uint8_t> empty;
EXPECT_FALSE(isElf(empty));
}
TEST(ElfDecoder, WhenValidElfThenIsElfReturnsTrue) {
ElfFileHeader<EI_CLASS_64> header64;
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
ElfFileHeader<EI_CLASS_32> header32;
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
}
TEST(ElfDecoder, WhenValidEmptyElfThenHeaderIsProperlyDecodedAndNoWarningsOrErrorsEmitted) {
ElfFileHeader<EI_CLASS_64> header64;
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U), decodeErrors, decodeWarnings);
EXPECT_EQ(&header64, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_TRUE(decodeWarnings.empty());
decodeWarnings.clear();
decodeErrors.clear();
ElfFileHeader<EI_CLASS_32> header32;
auto elf32 = decodeElf<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U), decodeErrors, decodeWarnings);
EXPECT_EQ(&header32, elf32.elfFileHeader);
EXPECT_TRUE(elf32.programHeaders.empty());
EXPECT_TRUE(elf32.sectionHeaders.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenInvalidElfHeaderThenDecodingFails) {
ElfFileHeader<EI_CLASS_64> header;
header.identity.magic[0] = 5;
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Invalid or missing ELF header", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableOffsetThenDecodingFails) {
ElfFileHeader<EI_CLASS_64> header;
header.phOff = sizeof(header) + 1;
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
EXPECT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableOffsetThenDecodingFails) {
ElfFileHeader<EI_CLASS_64> header;
header.shOff = sizeof(header) + 1;
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
ASSERT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenValidProgramHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.phOff = header.ehSize;
header.phNum = 2;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfProgramHeader<EI_CLASS_64> programHeader0;
programHeader0.fileSz = sizeof(programHeader0) * 2;
programHeader0.offset = header.phOff;
ElfProgramHeader<EI_CLASS_64> programHeader1;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
EXPECT_TRUE(elf64.sectionHeaders.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_TRUE(decodeWarnings.empty());
ASSERT_EQ(2U, elf64.programHeaders.size());
EXPECT_EQ(reinterpret_cast<decltype(programHeader0) *>(storage.data() + header.phOff), elf64.programHeaders[0].header);
EXPECT_EQ(reinterpret_cast<decltype(programHeader1) *>(storage.data() + header.phOff + header.phEntSize), elf64.programHeaders[1].header);
EXPECT_TRUE(elf64.programHeaders[1].data.empty());
EXPECT_FALSE(elf64.programHeaders[0].data.empty());
EXPECT_EQ(storage.data() + programHeader0.offset, elf64.programHeaders[0].data.begin());
EXPECT_EQ(programHeader0.fileSz, elf64.programHeaders[0].data.size());
}
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableEntriesThenDecodingFails) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.phOff = header.ehSize;
header.phNum = 3;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfProgramHeader<EI_CLASS_64> programHeader0;
ElfProgramHeader<EI_CLASS_64> programHeader1;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
ASSERT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderDataThenDecodingFails) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.phOff = header.ehSize;
header.phNum = 2;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfProgramHeader<EI_CLASS_64> programHeader0;
programHeader0.fileSz = sizeof(programHeader0) * 2;
programHeader0.offset = header.phOff;
ElfProgramHeader<EI_CLASS_64> programHeader1;
programHeader1.fileSz = sizeof(programHeader0) * 3;
programHeader1.offset = header.phOff;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
ASSERT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds program header offset/filesz, program header idx : 1", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenValidSectionHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.shOff = header.ehSize;
header.shNum = 2;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
sectionHeader0.size = sizeof(sectionHeader0) * 2;
sectionHeader0.offset = header.shOff;
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader0), reinterpret_cast<const uint8_t *>(&sectionHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader1), reinterpret_cast<const uint8_t *>(&sectionHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_TRUE(decodeWarnings.empty());
ASSERT_EQ(2U, elf64.sectionHeaders.size());
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
}
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableEntriesThenDecodingFails) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.shOff = header.ehSize;
header.shNum = 3;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader0), reinterpret_cast<const uint8_t *>(&sectionHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader1), reinterpret_cast<const uint8_t *>(&sectionHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
ASSERT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderDataThenDecodingFails) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.shOff = header.ehSize;
header.shNum = 2;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
sectionHeader0.size = sizeof(sectionHeader0) * 2;
sectionHeader0.offset = header.shOff;
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
sectionHeader1.size = sizeof(sectionHeader0) * 3;
sectionHeader1.offset = header.shOff;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader0), reinterpret_cast<const uint8_t *>(&sectionHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader1), reinterpret_cast<const uint8_t *>(&sectionHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(nullptr, elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(elf64.sectionHeaders.empty());
ASSERT_FALSE(decodeErrors.empty());
EXPECT_STREQ("Out of bounds section header offset/size, section header idx : 1", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty());
}
TEST(ElfDecoder, WhenSectionDoesNotHaveDataInFileThenDataIsSetAsEmpty) {
std::vector<uint8_t> storage;
ElfFileHeader<EI_CLASS_64> header;
header.shOff = header.ehSize;
header.shNum = 2;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
sectionHeader0.size = sizeof(sectionHeader0) * 2;
sectionHeader0.offset = header.shOff;
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
sectionHeader1.size = sizeof(sectionHeader0) * 3;
sectionHeader1.offset = header.shOff;
sectionHeader1.type = SHT_NOBITS;
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader0), reinterpret_cast<const uint8_t *>(&sectionHeader0 + 1));
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&sectionHeader1), reinterpret_cast<const uint8_t *>(&sectionHeader1 + 1));
std::string decodeWarnings;
std::string decodeErrors;
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
EXPECT_TRUE(elf64.programHeaders.empty());
EXPECT_TRUE(decodeErrors.empty());
EXPECT_TRUE(decodeWarnings.empty());
ASSERT_EQ(2U, elf64.sectionHeaders.size());
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
}

View File

@@ -0,0 +1,457 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "core/device_binary_format/elf/elf_encoder.h"
#include "core/utilities/range.h"
#include "test.h"
using namespace NEO::Elf;
TEST(ElfEncoder, WhenEmptyDataThenEncodedElfContainsOnlyHeader) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
auto &identity64 = header64.identity;
EXPECT_EQ(elfMagic[0], identity64.magic[0]);
EXPECT_EQ(elfMagic[1], identity64.magic[1]);
EXPECT_EQ(elfMagic[2], identity64.magic[2]);
EXPECT_EQ(elfMagic[3], identity64.magic[3]);
EXPECT_EQ(EI_CLASS_64, identity64.eClass);
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity64.data);
EXPECT_EQ(EV_CURRENT, identity64.version);
EXPECT_EQ(0U, identity64.osAbi);
EXPECT_EQ(0U, identity64.abiVersion);
EXPECT_EQ(ET_NONE, header64.type);
EXPECT_EQ(EM_NONE, header64.machine);
EXPECT_EQ(1U, header64.version);
EXPECT_EQ(0U, header64.entry);
EXPECT_EQ(0U, header64.phOff);
EXPECT_EQ(0U, header64.shOff);
EXPECT_EQ(0U, header64.flags);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
EXPECT_EQ(0U, header64.phNum);
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
EXPECT_EQ(0U, header64.shNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
ElfEncoder<EI_CLASS_32> elfEncoder32(false, false);
auto elfData32 = elfEncoder32.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), elfData32.size());
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
auto &identity32 = header32.identity;
EXPECT_EQ(elfMagic[0], identity32.magic[0]);
EXPECT_EQ(elfMagic[1], identity32.magic[1]);
EXPECT_EQ(elfMagic[2], identity32.magic[2]);
EXPECT_EQ(elfMagic[3], identity32.magic[3]);
EXPECT_EQ(EI_CLASS_32, identity32.eClass);
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity32.data);
EXPECT_EQ(EV_CURRENT, identity32.version);
EXPECT_EQ(0U, identity32.osAbi);
EXPECT_EQ(0U, identity32.abiVersion);
EXPECT_EQ(ET_NONE, header32.type);
EXPECT_EQ(EM_NONE, header32.machine);
EXPECT_EQ(1U, header32.version);
EXPECT_EQ(0U, header32.entry);
EXPECT_EQ(0U, header32.phOff);
EXPECT_EQ(0U, header32.shOff);
EXPECT_EQ(0U, header32.flags);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), header32.ehSize);
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_32>), header32.phEntSize);
EXPECT_EQ(0U, header32.phNum);
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_32>), header32.shEntSize);
EXPECT_EQ(0U, header32.shNum);
EXPECT_EQ(SHN_UNDEF, header32.shStrNdx);
}
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNotNeededThenNotEmitted) {
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.shOff);
EXPECT_EQ(0U, header64.shNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
}
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNeededThenEmitted) {
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
elfEncoder64.appendSection(SHT_NULL, ".my_name_is_important", {});
auto elfData64 = elfEncoder64.encode();
char expectedSectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.phOff);
EXPECT_EQ(header64.ehSize, header64.shOff);
EXPECT_EQ(0U, header64.flags);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
EXPECT_EQ(0U, header64.phNum);
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
EXPECT_EQ(3U, header64.shNum);
EXPECT_EQ(2U, header64.shStrNdx);
auto &sectUndef64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
auto &sectSkipMe64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>));
auto &sectSectionNames64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_64>));
const char *sectionNames64Data = reinterpret_cast<char *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>));
EXPECT_EQ(0U, sectUndef64.name);
EXPECT_EQ(SHT_NULL, sectUndef64.type);
EXPECT_EQ(SHF_NONE, sectUndef64.flags);
EXPECT_EQ(0U, sectUndef64.addr);
EXPECT_EQ(0U, sectUndef64.offset);
EXPECT_EQ(0U, sectUndef64.size);
EXPECT_EQ(SHN_UNDEF, sectUndef64.link);
EXPECT_EQ(0U, sectUndef64.info);
EXPECT_EQ(0U, sectUndef64.addralign);
EXPECT_EQ(0U, sectUndef64.entsize);
EXPECT_EQ(11U, sectSkipMe64.name);
EXPECT_EQ(SHT_NULL, sectSkipMe64.type);
EXPECT_EQ(SHF_NONE, sectSkipMe64.flags);
EXPECT_EQ(0U, sectSkipMe64.addr);
EXPECT_EQ(0U, sectSkipMe64.offset);
EXPECT_EQ(0U, sectSkipMe64.size);
EXPECT_EQ(SHN_UNDEF, sectSkipMe64.link);
EXPECT_EQ(0U, sectSkipMe64.info);
EXPECT_EQ(8U, sectSkipMe64.addralign);
EXPECT_EQ(0U, sectSkipMe64.entsize);
EXPECT_EQ(1U, sectSectionNames64.name);
EXPECT_EQ(SHT_STRTAB, sectSectionNames64.type);
EXPECT_EQ(SHF_NONE, sectSectionNames64.flags);
EXPECT_EQ(0U, sectSectionNames64.addr);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>), sectSectionNames64.offset);
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames64.size);
EXPECT_EQ(SHN_UNDEF, sectSectionNames64.link);
EXPECT_EQ(0U, sectSectionNames64.info);
EXPECT_EQ(8U, sectSectionNames64.addralign);
EXPECT_EQ(0U, sectSectionNames64.entsize);
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames64Data, sizeof(expectedSectionNamesData)));
ElfEncoder<EI_CLASS_32> elfEncoder32(true, true);
elfEncoder32.appendSection(SHT_NULL, ".my_name_is_important", {});
auto elfData32 = elfEncoder32.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData32.size());
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
EXPECT_EQ(header32.ehSize, header32.shOff);
auto &sectSectionNames32 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_32> *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_32>));
const char *sectionNames32Data = reinterpret_cast<char *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>));
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>), sectSectionNames32.offset);
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames32.size);
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames32Data, sizeof(expectedSectionNamesData)));
}
TEST(ElfEncoder, WhenAppendingSectionWithDataThenOffsetsAreProperlyUpdated) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
const uint8_t data[] = "235711131719";
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", data);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.phOff);
EXPECT_EQ(header64.ehSize, header64.shOff);
EXPECT_EQ(1U, header64.shNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
auto &sectProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
auto sectProgBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>);
EXPECT_EQ(0U, sectProgBits.name);
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
EXPECT_EQ(0U, sectProgBits.addr);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>), sectProgBits.offset);
EXPECT_EQ(sizeof(data), sectProgBits.size);
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
EXPECT_EQ(0U, sectProgBits.info);
EXPECT_EQ(8U, sectProgBits.addralign);
EXPECT_EQ(0U, sectProgBits.entsize);
EXPECT_EQ(0, memcmp(data, sectProgBitsData, sizeof(data)));
}
TEST(ElfEncoder, WhenAppendingSectionWithoutDataThenOffsetsAreLeftIntact) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", {});
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.phOff);
EXPECT_EQ(header64.ehSize, header64.shOff);
EXPECT_EQ(1U, header64.shNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
auto &sectProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
EXPECT_EQ(0U, sectProgBits.name);
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
EXPECT_EQ(0U, sectProgBits.addr);
EXPECT_EQ(0U, sectProgBits.offset);
EXPECT_EQ(0U, sectProgBits.size);
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
EXPECT_EQ(0U, sectProgBits.info);
EXPECT_EQ(8U, sectProgBits.addralign);
EXPECT_EQ(0U, sectProgBits.entsize);
}
TEST(ElfEncoder, WhenAppendingSectionWithNoBitsTypeThenDataIsIgnored) {
{
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
const uint8_t data[] = "235711131719";
elfEncoder64.appendSection(SHT_NOBITS, ".my_name_is_not_important", data);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.phOff);
EXPECT_EQ(header64.ehSize, header64.shOff);
EXPECT_EQ(1U, header64.shNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
auto &sectNoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
EXPECT_EQ(0U, sectNoBits.name);
EXPECT_EQ(SHT_NOBITS, sectNoBits.type);
EXPECT_EQ(SHF_NONE, sectNoBits.flags);
EXPECT_EQ(0U, sectNoBits.addr);
EXPECT_EQ(0U, sectNoBits.offset);
EXPECT_EQ(0U, sectNoBits.size);
EXPECT_EQ(SHN_UNDEF, sectNoBits.link);
EXPECT_EQ(0U, sectNoBits.info);
EXPECT_EQ(8U, sectNoBits.addralign);
EXPECT_EQ(0U, sectNoBits.entsize);
}
{
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
const uint8_t data[] = "235711131719";
elfEncoder64.appendSection(static_cast<uint32_t>(SHT_NOBITS), ".my_name_is_not_important", data).size = sizeof(data);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
auto &sectNoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
EXPECT_EQ(0U, sectNoBits.offset);
EXPECT_EQ(sizeof(data), sectNoBits.size);
}
}
TEST(ElfEncoder, WhenAppendingSegmentWithDataThenOffsetsAreProperlyUpdated) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
const uint8_t data[] = "235711131719";
elfEncoder64.appendSegment(PT_LOAD, data);
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.shOff);
EXPECT_EQ(header64.ehSize, header64.phOff);
EXPECT_EQ(1U, header64.phNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
auto segLoadBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>);
EXPECT_EQ(PT_LOAD, segLoad.type);
EXPECT_EQ(PF_NONE, segLoad.flags);
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>), segLoad.offset);
EXPECT_EQ(0U, segLoad.vAddr);
EXPECT_EQ(0U, segLoad.pAddr);
EXPECT_EQ(sizeof(data), segLoad.fileSz);
EXPECT_EQ(0U, segLoad.memSz);
EXPECT_EQ(8U, segLoad.align);
EXPECT_EQ(0, memcmp(data, segLoadBitsData, sizeof(data)));
}
TEST(ElfEncoder, WhenAppendingSegmentWithoutDataThenOffsetsAreLeftIntact) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
elfEncoder64.appendSegment(PT_LOAD, {});
auto elfData64 = elfEncoder64.encode();
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>), elfData64.size());
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
EXPECT_EQ(0U, header64.shOff);
EXPECT_EQ(header64.ehSize, header64.phOff);
EXPECT_EQ(1U, header64.phNum);
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
EXPECT_EQ(PT_LOAD, segLoad.type);
EXPECT_EQ(PF_NONE, segLoad.flags);
EXPECT_EQ(0U, segLoad.offset);
EXPECT_EQ(0U, segLoad.vAddr);
EXPECT_EQ(0U, segLoad.pAddr);
EXPECT_EQ(0U, segLoad.fileSz);
EXPECT_EQ(0U, segLoad.memSz);
EXPECT_EQ(8U, segLoad.align);
}
TEST(ElfEncoder, WhenAppendingBothSectionAndSegmentThenProperElfIsEmited) {
const uint8_t segmentData[] = "235711131719";
const uint8_t sectionData[] = "232931374143";
const uint8_t sectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
ElfFileHeader<EI_CLASS_64> header;
header.type = ET_EXEC;
header.entry = 16U;
header.phOff = static_cast<decltype(header.phOff)>(sizeof(header));
header.shOff = static_cast<decltype(header.shOff)>(sizeof(header) + sizeof(ElfProgramHeader<EI_CLASS_64>));
header.flags = 4U;
header.phNum = 1U;
header.shNum = 3U;
header.shStrNdx = 2U;
ElfProgramHeader<EI_CLASS_64> segment;
segment.type = PT_LOAD;
segment.flags = PF_R | PF_X;
segment.offset = static_cast<decltype(segment.offset)>(header.shOff + sizeof(ElfSectionHeader<EI_CLASS_64>) * 3);
segment.vAddr = 4096U;
segment.pAddr = 4096U * 16;
segment.fileSz = static_cast<decltype(segment.fileSz)>(sizeof(segmentData));
segment.memSz = 8192U;
segment.align = 8U;
ElfSectionHeader<EI_CLASS_64> sectionUndef;
ElfSectionHeader<EI_CLASS_64> sectionProgBits;
sectionProgBits.name = 11U;
sectionProgBits.type = SHT_PROGBITS;
sectionProgBits.flags = SHF_ALLOC;
sectionProgBits.addr = 16U;
sectionProgBits.offset = static_cast<decltype(sectionProgBits.offset)>(segment.offset + alignUp(static_cast<size_t>(segment.fileSz), static_cast<size_t>(segment.align)));
sectionProgBits.size = static_cast<decltype(sectionProgBits.size)>(sizeof(sectionData));
sectionProgBits.link = SHN_UNDEF;
sectionProgBits.info = 0U;
sectionProgBits.addralign = 16U;
sectionProgBits.entsize = 0U;
ElfSectionHeader<EI_CLASS_64> sectionSectionNames;
sectionSectionNames.name = 1U;
sectionSectionNames.type = SHT_STRTAB;
sectionSectionNames.flags = SHF_NONE;
sectionSectionNames.addr = 0U;
sectionSectionNames.offset = static_cast<decltype(sectionSectionNames.offset)>(sectionProgBits.offset + alignUp(static_cast<size_t>(sectionProgBits.size), static_cast<size_t>(sectionProgBits.addralign)));
sectionSectionNames.size = static_cast<decltype(sectionSectionNames.size)>(sizeof(sectionNamesData));
sectionSectionNames.link = SHN_UNDEF;
sectionSectionNames.info = 0U;
sectionSectionNames.addralign = 8U;
sectionSectionNames.entsize = 0U;
std::vector<uint8_t> handMade;
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&header), reinterpret_cast<uint8_t *>(&header + 1));
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&segment), reinterpret_cast<uint8_t *>(&segment + 1));
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&sectionUndef), reinterpret_cast<uint8_t *>(&sectionUndef + 1));
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&sectionProgBits), reinterpret_cast<uint8_t *>(&sectionProgBits + 1));
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&sectionSectionNames), reinterpret_cast<uint8_t *>(&sectionSectionNames + 1));
handMade.insert(handMade.end(), segmentData, segmentData + sizeof(segmentData));
handMade.resize(static_cast<size_t>(sectionProgBits.offset), 0U);
handMade.insert(handMade.end(), sectionData, sectionData + sizeof(sectionData));
handMade.resize(static_cast<size_t>(sectionSectionNames.offset), 0U);
handMade.insert(handMade.end(), sectionNamesData, sectionNamesData + sizeof(sectionNamesData));
handMade.resize(static_cast<size_t>(sectionSectionNames.offset + alignUp(sizeof(sectionNamesData), 8U)), 0U);
ElfEncoder<EI_CLASS_64> elfEncoder64;
{
auto &encodedHeader = elfEncoder64.getElfFileHeader();
encodedHeader.type = ET_EXEC;
encodedHeader.entry = 16U;
encodedHeader.flags = 4U;
auto &encodedSegment = elfEncoder64.appendSegment(PT_LOAD, segmentData);
encodedSegment.type = PT_LOAD;
encodedSegment.flags = PF_R | PF_X;
encodedSegment.vAddr = 4096U;
encodedSegment.pAddr = 4096U * 16;
encodedSegment.memSz = 8192U;
encodedSegment.align = 8U;
ElfSectionHeader<EI_CLASS_64> encodedSectionProgBits;
encodedSectionProgBits.name = elfEncoder64.appendSectionName(".my_name_is_important");
encodedSectionProgBits.type = SHT_PROGBITS;
encodedSectionProgBits.flags = SHF_ALLOC;
encodedSectionProgBits.addr = 16U;
encodedSectionProgBits.link = SHN_UNDEF;
encodedSectionProgBits.info = 0U;
encodedSectionProgBits.addralign = 16U;
encodedSectionProgBits.entsize = 0U;
elfEncoder64.appendSection(encodedSectionProgBits, sectionData);
}
auto generated = elfEncoder64.encode();
EXPECT_EQ(handMade, generated);
}
TEST(ElfEncoder, WhenDefaultAlignmentIsRaisedThenSegmentDataAbideByIt) {
const uint8_t segmentData[] = "235711131719";
const uint8_t sectionData[] = "232931374143475";
static constexpr size_t alignment = 128U;
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
elfEncoder64.appendSegment(PT_LOAD, segmentData);
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
auto elfData64 = elfEncoder64.encode();
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
auto programHeaders = reinterpret_cast<NEO::Elf::ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.phOff));
for (const auto &section : NEO::CreateRange(sectionHeaders, header64.shNum)) {
EXPECT_EQ(0U, section.offset % 8U);
}
for (const auto &segment : NEO::CreateRange(programHeaders, header64.phNum)) {
EXPECT_EQ(0U, segment.offset % alignment);
EXPECT_LE(alignment, segment.align);
}
}
TEST(ElfEncoder, WhenDefaultAlignmentIsLoweredThenSectionAndSegmentDataAbideByIt) {
const uint8_t segmentData[] = "235711131719";
const uint8_t sectionData[] = "232931374143475";
static constexpr size_t alignment = 1U;
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
elfEncoder64.appendSegment(PT_LOAD, segmentData);
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
auto elfData64 = elfEncoder64.encode();
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
NEO::Elf::ElfSectionHeader<EI_CLASS_64> *sectionNamesSection = sectionHeaders + header64.shStrNdx;
size_t unpaddedSize = sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(NEO::Elf::ElfSectionHeader<EI_CLASS_64>) + sizeof(NEO::Elf::ElfProgramHeader<EI_CLASS_64>);
unpaddedSize += sizeof(segmentData) + sizeof(sectionData) + static_cast<size_t>(sectionNamesSection->size);
EXPECT_EQ(unpaddedSize, elfData64.size());
}
TEST(ElfEncoder, WhenAppendingEmptySectionNameThenAlwaysReturn0AsOffset) {
ElfEncoder<EI_CLASS_64> elfEncoder64(false, true);
auto offset0 = elfEncoder64.appendSectionName({});
auto offset1 = elfEncoder64.appendSectionName({});
auto offset2 = elfEncoder64.appendSectionName({});
EXPECT_EQ(0U, offset0);
EXPECT_EQ(0U, offset1);
EXPECT_EQ(0U, offset2);
}
TEST(ElfEncoder, WhenAppendingSectionNameThenEmplacedStringIsAlwaysNullterminated) {
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
auto strOffset = elfEncoder64.appendSectionName(ConstStringRef("abc", 2));
auto strOffset2 = elfEncoder64.appendSectionName(ConstStringRef("de", 3));
auto strOffset3 = elfEncoder64.appendSectionName(ConstStringRef("g"));
elfEncoder64.appendSection(SHT_NOBITS, "my_name_is_important", {});
EXPECT_EQ(strOffset + 3, strOffset2);
EXPECT_EQ(strOffset2 + 3, strOffset3);
auto elfData = elfEncoder64.encode();
auto header = reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData.data());
auto sectionNamesSection = reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData.data() + static_cast<size_t>(header->shOff + header->shStrNdx * header->shEntSize));
EXPECT_STREQ("ab", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset));
EXPECT_STREQ("de", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset2));
EXPECT_STREQ("g", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset3));
}

View File

@@ -191,7 +191,7 @@ TEST(KernelDecoder, GivenValidEmptyKernelThenDecodingOfHeaderSucceeds) {
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
ASSERT_NE(nullptr, decodedKernel.header);
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
EXPECT_EQ(kernelToEncode.name, decodedKernel.name);
@@ -211,7 +211,7 @@ TEST(KernelDecoder, GivenEmptyKernelWhenBlobSmallerThanKernelHeaderThenDecodingF
kernelToEncode.blobs.kernelInfo.begin() + sizeof(iOpenCL::SKernelBinaryHeader) - 1);
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(brokenBlob, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
}
TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProperlySet) {
@@ -246,7 +246,7 @@ TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProp
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
@@ -274,37 +274,37 @@ TEST(KernelDecoder, GivenEmptyKernelWhenBlobDoesntHaveEnoughSpaceForHeaderDataTh
kernelHeader->KernelNameSize = outOfBoundsSize;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->KernelNameSize = originalHeader.KernelNameSize;
kernelHeader->KernelHeapSize = outOfBoundsSize;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->KernelHeapSize = originalHeader.KernelHeapSize;
kernelHeader->GeneralStateHeapSize = outOfBoundsSize;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->GeneralStateHeapSize = originalHeader.GeneralStateHeapSize;
kernelHeader->DynamicStateHeapSize = outOfBoundsSize;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->DynamicStateHeapSize = originalHeader.DynamicStateHeapSize;
kernelHeader->SurfaceStateHeapSize = outOfBoundsSize;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->SurfaceStateHeapSize = originalHeader.SurfaceStateHeapSize;
kernelHeader->PatchListSize = outOfBoundsSize;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
kernelHeader->PatchListSize = originalHeader.PatchListSize;
}
@@ -347,7 +347,7 @@ TEST(KernelDecoder, GivenKernelWithValidKernelPatchtokensThenDecodingSucceedsAnd
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
EXPECT_EQ(ptrOffset(storage.data(), patchListOffset), decodedKernel.blobs.patchList.begin());
EXPECT_EQ(ptrOffset(storage.data(), storage.size()), decodedKernel.blobs.patchList.end());
@@ -398,7 +398,7 @@ TEST(KernelDecoder, GivenKernelWithValidStringPatchtokensThenDecodingSucceedsAnd
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
auto base = storage.data();
@@ -446,7 +446,7 @@ TEST(KernelDecoder, GivenKernelWithValidArgInfoPatchtokensThenDecodingSucceedsAn
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
auto base = storage.data();
@@ -507,7 +507,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgPatchtokensThenDecodingSucceeds
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
auto base = storage.data();
@@ -589,7 +589,7 @@ TEST(KernelDecoder, GivenKernelWithValidNonArgCrossThreadDataPatchtokensThenDeco
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
auto base = storage.data();
@@ -644,7 +644,7 @@ TEST(KernelDecoder, GivenKernelWithArgCrossThreadDataPatchtokensWhenSourceIndexI
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
ASSERT_EQ(5U, decodedKernel.unhandledTokens.size());
auto base = storage.data();
@@ -670,7 +670,7 @@ TEST(KernelDecoder, GivenKernelWithUnkownPatchtokensThenDecodingSucceedsButToken
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
ASSERT_EQ(2U, decodedKernel.unhandledTokens.size());
auto base = storage.data();
@@ -716,7 +716,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgMetadataPatchtokensThenDecoding
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
ASSERT_EQ(4U, decodedKernel.tokens.kernelArgs.size());
@@ -776,14 +776,14 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
decodedKernel = {};
@@ -791,77 +791,77 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
decodedKernel = {};
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
}
TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingFailsAndStops) {
@@ -883,7 +883,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
}
@@ -905,7 +905,7 @@ TEST(KernelDecoder, GivenKernelWithByValArgMetadataPatchtokensThenDecodingSuccee
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
ASSERT_EQ(2U, decodedKernel.tokens.kernelArgs.size());
@@ -940,7 +940,7 @@ TEST(KernelDecoder, GivenKernelWithVmeMetadataPatchtokensThenDecodingSucceedsAnd
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
ASSERT_EQ(1U, decodedKernel.tokens.kernelArgs.size());
@@ -971,7 +971,7 @@ TEST(KernelDecoder, GivenKernelWithOutOfBoundsTokenThenDecodingFails) {
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
}
TEST(ProgramDecoder, GivenValidEmptyProgramThenDecodingOfHeaderSucceeds) {
@@ -980,7 +980,7 @@ TEST(ProgramDecoder, GivenValidEmptyProgramThenDecodingOfHeaderSucceeds) {
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
ASSERT_NE(nullptr, decodedProgram.header);
EXPECT_EQ(programToEncode.header, decodedProgram.header);
@@ -998,7 +998,7 @@ TEST(ProgramDecoder, GivenProgramWhenBlobSmallerThanProgramHeaderThenDecodingFai
programToEncode.blobs.programInfo.begin() + sizeof(iOpenCL::SProgramBinaryHeader) - 1);
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(brokenBlob, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenProgramWithInvaidProgramMagicThenDecodingFails) {
@@ -1007,7 +1007,7 @@ TEST(ProgramDecoder, GivenProgramWithInvaidProgramMagicThenDecodingFails) {
programToEncode.headerMutable->Magic += 1;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenProgramWhenBlobDoesntHaveEnoughSpaceForPatchListThenDecodingFails) {
@@ -1016,7 +1016,7 @@ TEST(ProgramDecoder, GivenProgramWhenBlobDoesntHaveEnoughSpaceForPatchListThenDe
programToEncode.headerMutable->PatchListSize = static_cast<uint32_t>(programToEncode.blobs.patchList.size() + 1);
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
@@ -1024,7 +1024,7 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateConstantMemorySurface.size());
EXPECT_EQ(programToEncode.programScopeTokens.allocateConstantMemorySurface[0], decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]);
@@ -1038,7 +1038,7 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
programToEncode.recalcTokPtr();
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
auto base = programToEncode.storage.data();
@@ -1047,13 +1047,22 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
EXPECT_TRUE(tokenOffsetMatched(base, secondConstantSurfaceOff, decodedProgram.programScopeTokens.allocateConstantMemorySurface[1]));
}
TEST(ProgramDecoder, GivenProgramWithConstantSurfaceWhenBlobSmallerThanNeededForPatchTokenThenDecodingFails) {
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
programToEncode.headerMutable->PatchListSize -= programToEncode.constSurfMutable->InlineDataSize + 1;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenProgramWithConstantSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
programToEncode.headerMutable->PatchListSize -= 1;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
@@ -1061,7 +1070,7 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size());
EXPECT_EQ(programToEncode.programScopeTokens.allocateGlobalMemorySurface[0], decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]);
@@ -1075,7 +1084,7 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
programToEncode.recalcTokPtr();
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
auto base = programToEncode.storage.data();
@@ -1084,13 +1093,22 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
EXPECT_TRUE(tokenOffsetMatched(base, secondGlobalSurfaceOff, decodedProgram.programScopeTokens.allocateGlobalMemorySurface[1]));
}
TEST(ProgramDecoder, GivenProgramWithGlobalSurfaceWhenBlobSmallerThanNeededForPatchTokenThenDecodingFails) {
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
programToEncode.headerMutable->PatchListSize -= programToEncode.globalSurfMutable->InlineDataSize + 1;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenProgramWithGlobalSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
programToEncode.headerMutable->PatchListSize -= 1;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenValidProgramWithPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssinged) {
@@ -1106,7 +1124,7 @@ TEST(ProgramDecoder, GivenValidProgramWithPatchtokensThenDecodingSucceedsAndToke
programToEncode.recalcTokPtr();
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
auto base = programToEncode.storage.data();
@@ -1128,7 +1146,7 @@ TEST(ProgramDecoder, GivenProgramWithUnkownPatchtokensThenDecodingSucceedsButTok
programToEncode.constSurfMutable->Size += programToEncode.constSurfMutable->InlineDataSize;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
ASSERT_EQ(1U, decodedProgram.unhandledTokens.size());
EXPECT_EQ(programToEncode.constSurfMutable, decodedProgram.unhandledTokens[0]);
}
@@ -1138,12 +1156,12 @@ TEST(ProgramDecoder, GivenValidProgramWithKernelThenDecodingSucceedsAndTokensAre
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
ASSERT_EQ(1U, decodedProgram.header->NumberOfKernels);
ASSERT_EQ(1U, decodedProgram.kernels.size());
auto decodedKernel = decodedProgram.kernels[0];
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
EXPECT_NE(nullptr, decodedKernel.tokens.allocateLocalSurface);
}
@@ -1155,18 +1173,18 @@ TEST(ProgramDecoder, GivenValidProgramWithTwoKernelsWhenThenDecodingSucceeds) {
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
EXPECT_TRUE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
ASSERT_EQ(2U, decodedProgram.kernels.size());
auto decodedKernel0 = decodedProgram.kernels[0];
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel0.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel0.decodeStatus);
EXPECT_TRUE(decodedKernel0.unhandledTokens.empty());
EXPECT_NE(nullptr, decodedKernel0.tokens.allocateLocalSurface);
auto decodedKernel1 = decodedProgram.kernels[0];
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel1.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel1.decodeStatus);
EXPECT_TRUE(decodedKernel1.unhandledTokens.empty());
EXPECT_NE(nullptr, decodedKernel1.tokens.allocateLocalSurface);
}
@@ -1177,7 +1195,7 @@ TEST(ProgramDecoder, GivenPatchTokenWithZeroSizeThenDecodingFailsAndStops) {
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
}
TEST(ProgramDecoder, GivenProgramWithMultipleKernelsWhenFailsToDecodeKernelThenDecodingFailsAndStops) {
@@ -1188,7 +1206,7 @@ TEST(ProgramDecoder, GivenProgramWithMultipleKernelsWhenFailsToDecodeKernelThenD
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
EXPECT_FALSE(decodeSuccess);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
EXPECT_EQ(1U, decodedProgram.kernels.size());

View File

@@ -14,7 +14,7 @@
TEST(ProgramDumper, GivenEmptyProgramThenProperlyCreatesDumpStringWithWarnig) {
NEO::PatchTokenBinary::ProgramFromPatchtokens emptyProgram = {};
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
emptyProgram.decodeStatus = NEO::DecodeError::Undefined;
std::string generated = NEO::PatchTokenBinary::asString(emptyProgram);
const char *expected =
R"===(Program of size : 0 in undefined status
@@ -24,7 +24,7 @@ Kernels section size : 0
)===";
EXPECT_STREQ(expected, generated.c_str());
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
emptyProgram.decodeStatus = NEO::DecodeError::InvalidBinary;
generated = NEO::PatchTokenBinary::asString(emptyProgram);
expected =
R"===(Program of size : 0 with invalid binary
@@ -34,7 +34,7 @@ Kernels section size : 0
)===";
EXPECT_STREQ(expected, generated.c_str());
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
emptyProgram.decodeStatus = NEO::DecodeError::Success;
generated = NEO::PatchTokenBinary::asString(emptyProgram);
expected =
R"===(Program of size : 0 decoded successfully
@@ -47,7 +47,7 @@ Kernels section size : 0
TEST(KernelDumper, GivenEmptyKernelThenProperlyCreatesDumpStringWithWarnig) {
NEO::PatchTokenBinary::KernelFromPatchtokens emptyKernel = {};
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
emptyKernel.decodeStatus = NEO::DecodeError::Undefined;
std::string generated = NEO::PatchTokenBinary::asString(emptyKernel);
const char *expected =
R"===(Kernel of size : 0 in undefined status
@@ -56,7 +56,7 @@ Kernel-scope tokens section size : 0
)===";
EXPECT_STREQ(expected, generated.c_str());
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
emptyKernel.decodeStatus = NEO::DecodeError::InvalidBinary;
generated = NEO::PatchTokenBinary::asString(emptyKernel);
expected =
R"===(Kernel of size : 0 with invalid binary
@@ -65,7 +65,7 @@ Kernel-scope tokens section size : 0
)===";
EXPECT_STREQ(expected, generated.c_str());
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
emptyKernel.decodeStatus = NEO::DecodeError::Success;
generated = NEO::PatchTokenBinary::asString(emptyKernel);
expected =
R"===(Kernel of size : 0 decoded successfully
@@ -2084,7 +2084,7 @@ TEST(PatchTokenDumper, GivenAnyTokenThenDumpingIsHandled) {
kernelToken->Token = i;
decodedKernel = {};
NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToDecode.blobs.kernelInfo, decodedKernel);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
if (decodedKernel.unhandledTokens.empty()) {
auto dump = NEO::PatchTokenBinary::asString(decodedKernel);
EXPECT_EQ(std::string::npos, dump.find("struct SPatchItemHeader")) << "Update patchtokens_dumper.cpp with definition of new patchtoken : " << i;
@@ -2095,7 +2095,7 @@ TEST(PatchTokenDumper, GivenAnyTokenThenDumpingIsHandled) {
programToken->Token = i;
decodedProgram = {};
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToDecode.blobs.programInfo, decodedProgram);
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
if (decodedProgram.unhandledTokens.empty()) {
auto dump = NEO::PatchTokenBinary::asString(decodedProgram);
EXPECT_EQ(std::string::npos, dump.find("struct SPatchItemHeader")) << "Update patchtokens_dumper.cpp with definition of new patchtoken : " << i;

View File

@@ -83,7 +83,7 @@ struct ValidEmptyProgram : NEO::PatchTokenBinary::ProgramFromPatchtokens {
headerTok.Version = iOpenCL::CURRENT_ICBE_VERSION;
headerTok.Device = renderCoreFamily;
headerTok.GPUPointerSizeInBytes = sizeof(uintptr_t);
this->decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
this->decodeStatus = NEO::DecodeError::Success;
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&headerTok), reinterpret_cast<uint8_t *>((&headerTok) + 1));
recalcTokPtr();
@@ -228,7 +228,7 @@ struct ValidEmptyKernel {
execEnvTokInl.LargestCompiledSIMDSize = 32U;
execEnvTokInl.CompiledSIMD32 = 1U;
headerTokInl.PatchListSize = sizeof(execEnvTokInl);
ret.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
ret.decodeStatus = NEO::DecodeError::Success;
ret.name = "test_kernel";
headerTokInl.KernelNameSize = static_cast<uint32_t>(ret.name.size());
@@ -253,7 +253,7 @@ struct ValidProgramWithKernel : ValidEmptyProgram {
this->headerMutable->NumberOfKernels = 1;
kernOffset = storage.size();
this->kernels.push_back(ValidEmptyKernel::create(storage));
this->kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
this->kernels[0].decodeStatus = NEO::DecodeError::Success;
kernExecEnvOffset = ptrDiff(this->kernels[0].blobs.patchList.begin(), storage.data());
recalcTokPtr();
}

View File

@@ -6,26 +6,17 @@
*/
#include "core/device_binary_format/patchtokens_decoder.h"
#include "core/device_binary_format/patchtokens_validator.inl"
#include "core/device_binary_format/patchtokens_validator.h"
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
struct UknownTokenValidator {
UknownTokenValidator(bool isSafeToSkip = true) : isSafeToSkip(isSafeToSkip) {
}
bool isSafeToSkipUnhandledToken(uint32_t token) const {
return isSafeToSkip;
}
bool isSafeToSkip = true;
};
TEST(PatchtokensValidator, GivenValidProgramThenValidationSucceeds) {
PatchTokensTestData::ValidEmptyProgram prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -34,16 +25,16 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationF
PatchTokensTestData::ValidEmptyProgram prog;
std::string error, warning;
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.decodeStatus = NEO::DecodeError::Undefined;
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
warning.clear();
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.decodeStatus = NEO::DecodeError::InvalidBinary;
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -52,7 +43,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleConstantSurfaceThenValida
PatchTokensTestData::ValidProgramWithConstantSurface prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -63,7 +54,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleConstantSurfacesThenValidatio
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo constSurface2 = *prog.programScopeTokens.allocateConstantMemorySurface[0];
prog.programScopeTokens.allocateConstantMemorySurface.push_back(&constSurface2);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled number of global constants surfaces > 1", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -72,7 +63,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleGlobalSurfaceThenValidati
PatchTokensTestData::ValidProgramWithGlobalSurface prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -83,7 +74,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleGlobalSurfacesThenValidationF
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo globSurface2 = *prog.programScopeTokens.allocateGlobalMemorySurface[0];
prog.programScopeTokens.allocateGlobalMemorySurface.push_back(&globSurface2);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled number of global variables surfaces > 1", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -92,7 +83,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidConstantPointerThenValidati
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -102,7 +93,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferIndexThen
std::string error, warning;
prog.constantPointerMutable->BufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -112,36 +103,36 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGpuPointerSizeThenValidationFa
std::string error, warning;
prog.headerMutable->GPUPointerSizeInBytes = 0U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Invalid pointer size", error.c_str());
EXPECT_TRUE(warning.empty());
prog.headerMutable->GPUPointerSizeInBytes = 1U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 2U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 3U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 4U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 5U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 6U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 7U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 8U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
prog.headerMutable->GPUPointerSizeInBytes = 9U;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
}
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferIndexThenValidationFails) {
@@ -149,7 +140,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferI
std::string error, warning;
prog.constantPointerMutable->ConstantBufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -159,7 +150,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferTypeThenV
std::string error, warning;
prog.constantPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -169,7 +160,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerOffsetThenValid
std::string error, warning;
prog.constantPointerMutable->ConstantPointerOffset = prog.constSurfMutable->InlineDataSize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -179,7 +170,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutConstantSurfaceButWithConstantPoin
std::string error, warning;
prog.programScopeTokens.allocateConstantMemorySurface.clear();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -188,7 +179,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidGlobalPointerThenValidation
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -197,7 +188,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithMixedGlobalVarAndConstSurfacesAn
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -207,13 +198,13 @@ TEST(PatchtokensValidator, GivenInvalidProgramWithMixedGlobalVarAndConstSurfaces
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer progGlobalVar;
progGlobalVar.globalPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progGlobalVar, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progGlobalVar, error, warning));
EXPECT_FALSE(error.empty());
EXPECT_TRUE(warning.empty());
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer progConstVar;
progConstVar.constantPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progConstVar, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progConstVar, error, warning));
EXPECT_FALSE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -223,7 +214,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferIndexThenVa
std::string error, warning;
prog.globalPointerMutable->BufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -233,7 +224,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerGlobalBufferIndex
std::string error, warning;
prog.globalPointerMutable->GlobalBufferIndex = 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -243,7 +234,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferTypeThenVal
std::string error, warning;
prog.globalPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -253,7 +244,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerOffsetThenValidat
std::string error, warning;
prog.globalPointerMutable->GlobalPointerOffset = prog.globalSurfMutable->InlineDataSize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -263,7 +254,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutGlobalSurfaceButWithGlobalPointerT
std::string error, warning;
prog.programScopeTokens.allocateGlobalMemorySurface.clear();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -275,7 +266,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
iOpenCL::SPatchItemHeader unknownToken = {};
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
prog.unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
NEO::PatchTokenBinary::allowUnhandledTokens = false;
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
auto expectedError = "Unhandled required program-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_TRUE(warning.empty());
@@ -288,7 +282,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
iOpenCL::SPatchItemHeader unknownToken = {};
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
prog.unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
NEO::PatchTokenBinary::allowUnhandledTokens = true;
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
auto expectedWarning = "Unknown program-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_TRUE(error.empty());
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
@@ -299,28 +296,17 @@ TEST(PatchtokensValidator, GivenProgramWithUnsupportedPatchTokenVersionThenValid
std::string error, warning;
prog.headerMutable->Version = std::numeric_limits<uint32_t>::max();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
auto expectedError = "Unhandled Version of Patchtokens: expected: " + std::to_string(iOpenCL::CURRENT_ICBE_VERSION) + ", got: " + std::to_string(prog.header->Version);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithUnsupportedPlatformThenValidationFails) {
PatchTokensTestData::ValidEmptyProgram prog;
std::string error, warning;
prog.headerMutable->Device = IGFX_MAX_CORE;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto expectedError = "Unsupported device binary, device GFXCORE_FAMILY : " + std::to_string(prog.header->Device);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_EQ(0U, warning.size());
}
TEST(PatchtokensValidator, GivenValidProgramWithKernelThenValidationSucceeds) {
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -329,16 +315,16 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownSt
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.kernels[0].decodeStatus = NEO::DecodeError::Undefined;
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
warning.clear();
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
prog.kernels[0].decodeStatus = NEO::DecodeError::InvalidBinary;
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -348,7 +334,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidChecksumThe
std::string error, warning;
prog.kernelHeaderMutable->CheckSum += 1;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ("KernelFromPatchtokens has invalid checksum", error.c_str());
EXPECT_TRUE(warning.empty());
}
@@ -357,22 +343,12 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelUsingSlmThenValidationSucc
PatchTokensTestData::ValidProgramWithKernelUsingSlm prog;
std::string error, warning;
size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
//size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenProgramWithKernelUsingSlmWhenKernelRequiresTooMuchSlmThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernelUsingSlm prog;
std::string error, warning;
size_t slmSizeAvailable = -1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::NotEnoughSlm, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
EXPECT_STREQ("KernelFromPatchtokens requires too much SLM", error.c_str());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
@@ -380,7 +356,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
iOpenCL::SPatchItemHeader unknownToken = {};
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
NEO::PatchTokenBinary::allowUnhandledTokens = false;
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
auto expectedError = "Unhandled required kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_STREQ(expectedError.c_str(), error.c_str());
EXPECT_TRUE(warning.empty());
@@ -393,7 +372,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
iOpenCL::SPatchItemHeader unknownToken = {};
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
NEO::PatchTokenBinary::allowUnhandledTokens = true;
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
auto expectedWarning = "Unknown kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
EXPECT_TRUE(error.empty());
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
@@ -403,7 +385,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelArgsHasProperQualifie
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -412,7 +394,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelAndArgThenKernelArgInfoIsOption
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
std::string error, warning;
prog.kernels[0].tokens.kernelArgs[0].argInfo = nullptr;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
@@ -422,7 +404,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAddress
std::string error, warning;
prog.arg0InfoAddressQualifierMutable[2] = '\0';
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
auto expectedError = "Unhandled address qualifier";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
@@ -433,7 +415,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAccessQ
std::string error, warning;
prog.arg0InfoAccessQualifierMutable[2] = '\0';
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
auto expectedError = "Unhandled access qualifier";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
@@ -443,7 +425,7 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentIsMissingThenValid
PatchTokensTestData::ValidProgramWithKernel prog;
std::string error, warning;
prog.kernels[0].tokens.executionEnvironment = nullptr;
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
auto expectedError = "Missing execution environment";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
@@ -454,7 +436,7 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSize
std::string error, warning;
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 0U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
auto expectedError = "Invalid LargestCompiledSIMDSize";
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
@@ -462,77 +444,81 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSize
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 1U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 2U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 3U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 4U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 5U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 6U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 7U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 8U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 9U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_STREQ(expectedError, error.c_str());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 16U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
error.clear();
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 32U;
prog.recalcTokPtr();
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
EXPECT_TRUE(error.empty());
EXPECT_TRUE(warning.empty());
}
TEST(PatchtokensValidator, GivenDefaultStateThenUnhandledPatchtokensAreAllowed) {
EXPECT_TRUE(NEO::PatchTokenBinary::allowUnhandledTokens);
}

View File

@@ -46,7 +46,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenRequiresLocalMemoryWindowVAIsC
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsSurfaceThenGlobalConstantsSectionIsPopulated) {
PatchTokensTestData::ValidProgramWithConstantSurface programTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programTokens, {});
NEO::populateProgramInfo(programInfo, programTokens);
EXPECT_EQ(programInfo.globalConstants.size, programTokens.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize);
EXPECT_EQ(programInfo.globalConstants.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateConstantMemorySurface[0]));
EXPECT_TRUE(programInfo.kernelInfos.empty());
@@ -56,7 +56,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstants
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesSurfaceThenGlobalConstantsSectionIsPopulated) {
PatchTokensTestData::ValidProgramWithGlobalSurface programTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programTokens, {});
NEO::populateProgramInfo(programInfo, programTokens);
EXPECT_EQ(programInfo.globalVariables.size, programTokens.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize);
EXPECT_EQ(programInfo.globalVariables.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateGlobalMemorySurface[0]));
EXPECT_TRUE(programInfo.kernelInfos.empty());
@@ -66,7 +66,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariables
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
@@ -81,7 +81,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstants
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
@@ -96,7 +96,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariables
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresMixedGlobalVarAndConstPointersThenLinkerInputContainsProperRelocations) {
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers programFromTokens;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
EXPECT_TRUE(programInfo.kernelInfos.empty());
ASSERT_NE(nullptr, programInfo.linkerInput);
@@ -135,7 +135,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithSpecificPointerSiz
{
programFromTokens.headerMutable->GPUPointerSizeInBytes = 8;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_NE(nullptr, programInfo.linkerInput);
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr64bit, programInfo.linkerInput->getTraits().pointerSize);
}
@@ -143,7 +143,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithSpecificPointerSiz
{
programFromTokens.headerMutable->GPUPointerSizeInBytes = 4;
NEO::ProgramInfo programInfo;
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_NE(nullptr, programInfo.linkerInput);
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr32bit, programInfo.linkerInput->getTraits().pointerSize);
}
@@ -173,7 +173,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithProgramSymbolTable
receivedNumEntries = numEntries;
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_EQ(mockLinkerInput, programInfo.linkerInput.get());
EXPECT_EQ(1U, mockLinkerInput->decodeGlobalVariablesSymbolTableMockConfig.timesCalled);
@@ -186,7 +186,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsThenKernelI
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
NEO::ProgramInfo programInfo = {};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_EQ(3U, programInfo.kernelInfos.size());
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[0]->gpuPointerSize);
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[1]->gpuPointerSize);
@@ -232,7 +232,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelH
receivedSegmentIds.push_back(instructionsSegmentId);
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_EQ(2U, mockLinkerInput->decodeExportedFunctionsSymbolTableMockConfig.timesCalled);
ASSERT_EQ(2U, receivedData.size());
@@ -283,7 +283,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelH
receivedSegmentIds.push_back(instructionsSegmentId);
return true;
};
NEO::populateProgramInfo(programInfo, programFromTokens, {});
NEO::populateProgramInfo(programInfo, programFromTokens);
ASSERT_EQ(2U, mockLinkerInput->decodeRelocationTableMockConfig.timesCalled);
ASSERT_EQ(2U, receivedData.size());

View File

@@ -6,11 +6,12 @@
*/
#include "core/program/program_info.h"
#include "runtime/program/kernel_info.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
TEST(ProgramInfoTests, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
TEST(ProgramInfoTests, WhenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
NEO::ProgramInfo programInfo;
EXPECT_EQ(nullptr, programInfo.linkerInput);
programInfo.prepareLinkerInputStorage();
@@ -19,3 +20,45 @@ TEST(ProgramInfoTests, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInp
programInfo.prepareLinkerInputStorage();
EXPECT_EQ(prevLinkerInput, programInfo.linkerInput.get());
}
TEST(GetMaxInlineSlmNeeded, GivenProgramWithoutKernelsThenReturn0) {
NEO::ProgramInfo programInfo;
EXPECT_EQ(0U, NEO::getMaxInlineSlmNeeded(programInfo));
}
TEST(GetMaxInlineSlmNeeded, GivenProgramWithKernelsNotRequirignSlmThenReturn0) {
NEO::ProgramInfo programInfo;
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
EXPECT_EQ(0U, NEO::getMaxInlineSlmNeeded(programInfo));
}
TEST(GetMaxInlineSlmNeeded, GivenProgramWithKernelsThenReturnMaxOfInlineSlmNeededByKernels) {
iOpenCL::SPatchAllocateLocalSurface slmTokens[3] = {};
slmTokens[0].TotalInlineLocalMemorySize = 16;
slmTokens[1].TotalInlineLocalMemorySize = 64;
slmTokens[2].TotalInlineLocalMemorySize = 32;
NEO::ProgramInfo programInfo;
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
programInfo.kernelInfos[0]->patchInfo.localsurface = &slmTokens[0];
programInfo.kernelInfos[1]->patchInfo.localsurface = &slmTokens[1];
programInfo.kernelInfos[2]->patchInfo.localsurface = &slmTokens[2];
EXPECT_EQ(64U, NEO::getMaxInlineSlmNeeded(programInfo));
}
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithoutKernelsThenReturnFalse) {
NEO::ProgramInfo programInfo;
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(programInfo));
}
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithKernelsNotLocalMemoryWindowVAThenReturnFalse) {
NEO::ProgramInfo programInfo;
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(programInfo));
}
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithKernelsWhenSomeOfKernelRequireLocalMemoryWidnowVAThenReturnTrue) {
NEO::ProgramInfo programInfo;
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
programInfo.kernelInfos[1]->workloadInfo.localMemoryStatelessWindowStartAddressOffset = 0U;
EXPECT_TRUE(NEO::requiresLocalMemoryWindowVA(programInfo));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -73,3 +73,28 @@ TEST(ConstStringRef, WhenComparingAgainstContainersThenUsesLexicographicOrdering
EXPECT_TRUE(strTex != constStrText);
EXPECT_TRUE(constStrText != strTex);
}
TEST(ConstStringRef, WhenStrIsCalledThenEmitsProperString) {
static constexpr ConstStringRef constStrText("Text");
std::string str = constStrText.str();
EXPECT_EQ(4U, str.size());
EXPECT_STREQ("Text", str.c_str());
}
TEST(ConstStringRef, WhenDefaultInitializedThenEmpty) {
ConstStringRef str;
EXPECT_TRUE(str.empty());
}
TEST(ConstStringRef, WhenCopyConstructedThenIdenticalAsOrigin) {
static constexpr ConstStringRef a("Text");
static constexpr ConstStringRef b(a);
EXPECT_EQ(a, b);
}
TEST(ConstStringRef, WhenCopyAsignedThenIdenticalAsOrigin) {
static constexpr ConstStringRef a("Text");
ConstStringRef b("OtherText");
b = a;
EXPECT_EQ(a, b);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2019 Intel Corporation
* Copyright (C) 2018-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -1598,6 +1598,16 @@ TEST(ArrayRef, WrapContainers) {
ASSERT_EQ(35, sum(ar3));
}
TEST(ArrayRef, GivenEmptyContainerThenArrayRefIsEmpty) {
StackVec<int, 5> stackVec;
ArrayRef<int> arrayRef(stackVec);
EXPECT_TRUE(arrayRef.empty());
const StackVec<int, 5> &constStackVec = stackVec;
ArrayRef<const int> constArrayRef(constStackVec);
EXPECT_TRUE(constArrayRef.empty());
}
TEST(ArrayRef, ImplicitCoversionToArrayrefOfConst) {
int carray[] = {5, 6, 7, 8, 9};
ArrayRef<int> arrayRef(carray);
@@ -1698,3 +1708,25 @@ TEST(Range, GivenRangeThenValidStandardIteratorsAreAvailable) {
EXPECT_EQ(&*vec.begin(), &*rangeFromVec.begin());
EXPECT_EQ(&*vec.rbegin(), &*rangeFromVec.rbegin());
}
TEST(ArrayRef, WhenFromAnyIsCalledThenPointerIsReinterpretedAndSizeIsAdjusted) {
uint32_t x[2] = {};
auto arrayRefU8 = ArrayRef<const uint8_t>::fromAny(x, 2);
EXPECT_EQ(8U, arrayRefU8.size());
EXPECT_EQ(reinterpret_cast<uint8_t *>(x), arrayRefU8.begin());
}
TEST(ArrayRef, WhenToArrayRefIsCalledThenPointerIsReinterpretedAndSizeIsAdjusted) {
uint32_t x[2] = {};
auto arrayRefU32 = ArrayRef<const uint32_t>::fromAny(x, 2);
auto arrayRefU8 = arrayRefU32.toArrayRef<const uint8_t>();
EXPECT_EQ(8U, arrayRefU8.size());
EXPECT_EQ(reinterpret_cast<uint8_t *>(x), arrayRefU8.begin());
}
TEST(ArrayRef, WhenClearedThenEmpty) {
uint32_t x[2] = {};
auto arrayRefU32 = ArrayRef<const uint32_t>::fromAny(x, 2);
arrayRefU32.clear();
EXPECT_TRUE(arrayRefU32.empty());
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2019 Intel Corporation
* Copyright (C) 2018-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -38,6 +38,11 @@ class ArrayRef {
: begIt((ctr.size() > 0) ? &*ctr.begin() : nullptr), endIt((ctr.size() > 0) ? (&*(ctr.end() - 1) + 1) : nullptr) {
}
template <typename SequentialContainerType>
ArrayRef(const SequentialContainerType &ctr)
: begIt((ctr.size() > 0) ? &*ctr.begin() : nullptr), endIt((ctr.size() > 0) ? (&*(ctr.end() - 1) + 1) : nullptr) {
}
template <size_t Size>
ArrayRef(DataType (&array)[Size])
: begIt(&array[0]), endIt(&array[Size]) {
@@ -55,6 +60,10 @@ class ArrayRef {
return *this;
}
void clear() {
endIt = begIt;
}
size_t size() const {
return endIt - begIt;
}
@@ -96,6 +105,18 @@ class ArrayRef {
return ArrayRef<const DataType>(begIt, endIt);
}
template <typename AnyT>
static ArrayRef<DataType> fromAny(AnyT *any, size_t anyCount) {
static_assert((sizeof(AnyT) == sizeof(DataType)) || ((sizeof(AnyT) % sizeof(DataType)) == 0), "Unhandled type conversion");
return ArrayRef<DataType>(reinterpret_cast<iterator>(any), (anyCount * sizeof(AnyT)) / sizeof(DataType));
}
template <typename AnyT>
ArrayRef<AnyT> toArrayRef() {
static_assert((sizeof(AnyT) == sizeof(DataType)) || ((sizeof(DataType) % sizeof(AnyT)) == 0), "Unhandled type conversion");
return ArrayRef<AnyT>(reinterpret_cast<typename ArrayRef<AnyT>::iterator>(begIt), (this->size() * sizeof(DataType)) / sizeof(AnyT));
}
private:
DataType *begIt = nullptr;
DataType *endIt = nullptr;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation
* Copyright (C) 2019-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -22,6 +22,18 @@ constexpr size_t constLength(const char *string) {
class ConstStringRef {
public:
constexpr ConstStringRef() {
}
constexpr ConstStringRef(const ConstStringRef &rhs) : ptr(rhs.ptr), len(rhs.len) {
}
ConstStringRef &operator=(const ConstStringRef &rhs) {
this->ptr = rhs.ptr;
this->len = rhs.len;
return *this;
}
template <size_t Length>
constexpr ConstStringRef(const char (&array)[Length]) noexcept
: ptr(array), len(((Length > 0) && (array[Length - 1] == '\0')) ? (Length - 1) : Length) {
@@ -43,6 +55,10 @@ class ConstStringRef {
return ptr;
}
std::string str() const {
return std::string(ptr, len);
}
constexpr size_t size() const noexcept {
return len;
}
@@ -64,8 +80,8 @@ class ConstStringRef {
}
protected:
const char *const ptr;
const size_t len;
const char *ptr = nullptr;
size_t len = 0U;
};
constexpr bool equals(const ConstStringRef &lhs, const ConstStringRef &rhs) {