mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-11 16:45:25 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
36
core/compiler_interface/intermediate_representations.h
Normal file
36
core/compiler_interface/intermediate_representations.h
Normal 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
|
||||
@@ -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})
|
||||
|
||||
158
core/device_binary_format/device_binary_format_ocl_elf.cpp
Normal file
158
core/device_binary_format/device_binary_format_ocl_elf.cpp
Normal 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
|
||||
@@ -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
|
||||
16
core/device_binary_format/device_binary_formats.cpp
Normal file
16
core/device_binary_format/device_binary_formats.cpp
Normal 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
|
||||
153
core/device_binary_format/device_binary_formats.h
Normal file
153
core/device_binary_format/device_binary_formats.h
Normal 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
|
||||
343
core/device_binary_format/elf/elf.h
Normal file
343
core/device_binary_format/elf/elf.h
Normal 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
|
||||
89
core/device_binary_format/elf/elf_decoder.cpp
Normal file
89
core/device_binary_format/elf/elf_decoder.cpp
Normal 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
|
||||
67
core/device_binary_format/elf/elf_decoder.h
Normal file
67
core/device_binary_format/elf/elf_decoder.h
Normal 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
|
||||
178
core/device_binary_format/elf/elf_encoder.cpp
Normal file
178
core/device_binary_format/elf/elf_encoder.cpp
Normal 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> §ionHeader, 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 §ionHeader : 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 *>(§ionHeader), reinterpret_cast<uint8_t *>(§ionHeader + 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
|
||||
72
core/device_binary_format/elf/elf_encoder.h
Normal file
72
core/device_binary_format/elf/elf_encoder.h
Normal 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> §ionHeader, 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 §ionData) {
|
||||
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
|
||||
59
core/device_binary_format/elf/ocl_elf.h
Normal file
59
core/device_binary_format/elf/ocl_elf.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
26
core/device_binary_format/patchtokens_validator.h
Normal file
26
core/device_binary_format/patchtokens_validator.h
Normal 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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
196
core/elf/types.h
196
core/elf/types.h
@@ -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
|
||||
@@ -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
|
||||
@@ -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 &§ionNode) {
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 §ion) { 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 §ion) { 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 §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
|
||||
auto deviceBinarySection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
|
||||
|
||||
auto deviceDebugSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
|
||||
|
||||
auto buildOptionsSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { 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()));
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
343
core/unit_tests/device_binary_format/elf/elf_decoder_tests.cpp
Normal file
343
core/unit_tests/device_binary_format/elf/elf_decoder_tests.cpp
Normal 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 *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 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 *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 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 *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 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 *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 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());
|
||||
}
|
||||
457
core/unit_tests/device_binary_format/elf/elf_encoder_tests.cpp
Normal file
457
core/unit_tests/device_binary_format/elf/elf_encoder_tests.cpp
Normal 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 §Undef64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto §SkipMe64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
auto §SectionNames64 = *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 §SectionNames32 = *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 §ProgBits = *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 §ProgBits = *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 §NoBits = *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 §NoBits = *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 *>(§ionUndef), reinterpret_cast<uint8_t *>(§ionUndef + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionProgBits), reinterpret_cast<uint8_t *>(§ionProgBits + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionSectionNames), reinterpret_cast<uint8_t *>(§ionSectionNames + 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 §ion : 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));
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user