2022-07-15 23:46:10 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2022 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "shared/test/common/mocks/mock_modules_zebin.h"
|
|
|
|
|
|
|
|
#include "shared/source/device_binary_format/elf/elf_decoder.h"
|
|
|
|
#include "shared/source/device_binary_format/elf/elf_encoder.h"
|
|
|
|
#include "shared/source/helpers/compiler_hw_info_config.h"
|
|
|
|
|
|
|
|
namespace ZebinTestData {
|
2022-09-22 19:03:51 +08:00
|
|
|
using ELF_IDENTIFIER_CLASS = NEO::Elf::ELF_IDENTIFIER_CLASS;
|
2022-07-15 23:46:10 +08:00
|
|
|
|
2022-09-22 19:03:51 +08:00
|
|
|
template struct ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_32>;
|
|
|
|
template struct ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_64>;
|
|
|
|
|
|
|
|
template ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_32>::ValidEmptyProgram();
|
|
|
|
template ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_64>::ValidEmptyProgram();
|
|
|
|
template <ELF_IDENTIFIER_CLASS numBits>
|
|
|
|
ValidEmptyProgram<numBits>::ValidEmptyProgram() {
|
|
|
|
NEO::Elf::ElfEncoder<numBits> enc;
|
2022-07-15 23:46:10 +08:00
|
|
|
enc.getElfFileHeader().type = NEO::Elf::ET_ZEBIN_EXE;
|
|
|
|
enc.getElfFileHeader().machine = productFamily;
|
|
|
|
auto zeInfo = std::string{"---\nversion : \'" + versionToString(NEO::zeInfoDecoderVersion) + "\'" + "\nkernels : \n - name : " + kernelName + "\n execution_env : \n simd_size : 32\n grf_count : 128\n...\n"};
|
|
|
|
enc.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
|
|
|
|
enc.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "valid_empty_kernel", zeInfo);
|
|
|
|
storage = enc.encode();
|
|
|
|
recalcPtr();
|
|
|
|
}
|
|
|
|
|
2022-09-22 19:03:51 +08:00
|
|
|
template <ELF_IDENTIFIER_CLASS numBits>
|
|
|
|
void ValidEmptyProgram<numBits>::recalcPtr() {
|
|
|
|
elfHeader = reinterpret_cast<NEO::Elf::ElfFileHeader<numBits> *>(storage.data());
|
2022-07-15 23:46:10 +08:00
|
|
|
}
|
|
|
|
|
2022-09-22 19:03:51 +08:00
|
|
|
template NEO::Elf::ElfSectionHeader<ELF_IDENTIFIER_CLASS::EI_CLASS_32> &ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_32>::appendSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
|
|
|
|
template NEO::Elf::ElfSectionHeader<ELF_IDENTIFIER_CLASS::EI_CLASS_64> &ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_64>::appendSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
|
|
|
|
template <ELF_IDENTIFIER_CLASS numBits>
|
|
|
|
NEO::Elf::ElfSectionHeader<numBits> &ValidEmptyProgram<numBits>::appendSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
|
2022-07-15 23:46:10 +08:00
|
|
|
std::string err, warn;
|
2022-09-22 19:03:51 +08:00
|
|
|
auto decoded = NEO::Elf::decodeElf<numBits>(storage, err, warn);
|
|
|
|
NEO::Elf::ElfEncoder<numBits> enc;
|
2022-07-15 23:46:10 +08:00
|
|
|
enc.getElfFileHeader() = *decoded.elfFileHeader;
|
|
|
|
int sectionIt = 0;
|
|
|
|
auto sectionHeaderNamesData = decoded.sectionHeaders[decoded.elfFileHeader->shStrNdx].data;
|
|
|
|
NEO::ConstStringRef sectionHeaderNamesString(reinterpret_cast<const char *>(sectionHeaderNamesData.begin()), sectionHeaderNamesData.size());
|
|
|
|
for (const auto §ion : decoded.sectionHeaders) {
|
|
|
|
switch (section.header->type) {
|
|
|
|
case NEO::Elf::SHN_UNDEF:
|
|
|
|
break;
|
|
|
|
case NEO::Elf::SHT_STRTAB:
|
|
|
|
if (decoded.elfFileHeader->shStrNdx != sectionIt) {
|
|
|
|
enc.appendSection(section.header->type, sectionHeaderNamesString.data() + section.header->name, section.data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
enc.appendSection(section.header->type, sectionHeaderNamesString.data() + section.header->name, section.data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++sectionIt;
|
|
|
|
}
|
|
|
|
enc.appendSection(sectionType, sectionLabel, sectionData);
|
|
|
|
storage = enc.encode();
|
|
|
|
recalcPtr();
|
2022-09-22 19:03:51 +08:00
|
|
|
decoded = NEO::Elf::decodeElf<numBits>(storage, err, warn);
|
2022-07-15 23:46:10 +08:00
|
|
|
sectionHeaderNamesData = decoded.sectionHeaders[decoded.elfFileHeader->shStrNdx].data;
|
|
|
|
sectionHeaderNamesString = NEO::ConstStringRef(reinterpret_cast<const char *>(sectionHeaderNamesData.begin()), sectionHeaderNamesData.size());
|
|
|
|
for (const auto §ion : decoded.sectionHeaders) {
|
|
|
|
if ((sectionType == section.header->type) && (sectionLabel == sectionHeaderNamesString.data() + section.header->name)) {
|
2022-09-22 19:03:51 +08:00
|
|
|
return const_cast<NEO::Elf::ElfSectionHeader<numBits> &>(*section.header);
|
2022-07-15 23:46:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2022-09-22 19:03:51 +08:00
|
|
|
template void ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_32>::removeSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel);
|
|
|
|
template void ValidEmptyProgram<ELF_IDENTIFIER_CLASS::EI_CLASS_64>::removeSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel);
|
|
|
|
template <ELF_IDENTIFIER_CLASS numBits>
|
|
|
|
void ValidEmptyProgram<numBits>::removeSection(uint32_t sectionType, NEO::ConstStringRef sectionLabel) {
|
2022-07-15 23:46:10 +08:00
|
|
|
std::string err, warn;
|
2022-09-22 19:03:51 +08:00
|
|
|
auto decoded = NEO::Elf::decodeElf<numBits>(storage, err, warn);
|
|
|
|
NEO::Elf::ElfEncoder<numBits> enc;
|
2022-07-15 23:46:10 +08:00
|
|
|
enc.getElfFileHeader() = *decoded.elfFileHeader;
|
|
|
|
int sectionIt = 0;
|
|
|
|
auto sectionHeaderNamesData = decoded.sectionHeaders[decoded.elfFileHeader->shStrNdx].data;
|
|
|
|
NEO::ConstStringRef sectionHeaderNamesString(reinterpret_cast<const char *>(sectionHeaderNamesData.begin()), sectionHeaderNamesData.size());
|
|
|
|
for (const auto §ion : decoded.sectionHeaders) {
|
|
|
|
bool add = true;
|
|
|
|
switch (section.header->type) {
|
|
|
|
case NEO::Elf::SHN_UNDEF:
|
|
|
|
add = false;
|
|
|
|
break;
|
|
|
|
case NEO::Elf::SHT_STRTAB:
|
|
|
|
add = (decoded.elfFileHeader->shStrNdx != sectionIt);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
add = ((section.header->type != sectionType) || (sectionHeaderNamesString.data() + section.header->name != sectionLabel));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (add) {
|
|
|
|
enc.appendSection(section.header->type, sectionHeaderNamesString.data() + section.header->name, section.data);
|
|
|
|
}
|
|
|
|
++sectionIt;
|
|
|
|
}
|
|
|
|
if (decoded.elfFileHeader->shNum <= 3) {
|
|
|
|
enc.appendSection(NEO::Elf::SHT_STRTAB, "", {});
|
|
|
|
}
|
|
|
|
storage = enc.encode();
|
|
|
|
recalcPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
ZebinWithExternalFunctionsInfo::ZebinWithExternalFunctionsInfo() {
|
|
|
|
MockElfEncoder<> elfEncoder;
|
|
|
|
auto &elfHeader = elfEncoder.getElfFileHeader();
|
|
|
|
elfHeader.type = NEO::Elf::ET_ZEBIN_EXE;
|
|
|
|
elfHeader.flags = 0U;
|
|
|
|
|
|
|
|
const uint8_t kData[32] = {0U};
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "kernel", kData);
|
|
|
|
auto kernelSectionIdx = elfEncoder.getLastSectionHeaderIndex();
|
|
|
|
|
|
|
|
const uint8_t funData[32] = {0U};
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + NEO::Elf::SectionsNamesZebin::externalFunctions.str(), funData);
|
|
|
|
auto externalFunctionsIdx = elfEncoder.getLastSectionHeaderIndex();
|
|
|
|
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
|
|
|
|
|
|
|
|
NEO::Elf::ElfSymbolEntry<NEO::Elf::EI_CLASS_64> symbols[2];
|
|
|
|
symbols[0].name = decltype(symbols[0].name)(elfEncoder.appendSectionName(fun0Name));
|
|
|
|
symbols[0].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_FUNC | NEO::Elf::SYMBOL_TABLE_BIND::STB_GLOBAL << 4;
|
|
|
|
symbols[0].shndx = decltype(symbols[0].shndx)(externalFunctionsIdx);
|
|
|
|
symbols[0].size = 16;
|
|
|
|
symbols[0].value = 0;
|
|
|
|
|
|
|
|
symbols[1].name = decltype(symbols[1].name)(elfEncoder.appendSectionName(fun1Name));
|
|
|
|
symbols[1].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_FUNC | NEO::Elf::SYMBOL_TABLE_BIND::STB_GLOBAL << 4;
|
|
|
|
symbols[1].shndx = decltype(symbols[1].shndx)(externalFunctionsIdx);
|
|
|
|
symbols[1].size = 16;
|
|
|
|
symbols[1].value = 16;
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SectionsNamesZebin::symtab,
|
|
|
|
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(symbols), sizeof(symbols)));
|
|
|
|
|
|
|
|
NEO::Elf::ElfRel<NEO::Elf::EI_CLASS_64> extFuncSegReloc = {}; // fun0 calls fun1
|
|
|
|
extFuncSegReloc.offset = 0x8;
|
|
|
|
extFuncSegReloc.info = (uint64_t(1) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR;
|
|
|
|
auto &extFuncRelSection = elfEncoder.appendSection(NEO::Elf::SHT_REL, NEO::Elf::SpecialSectionNames::relPrefix.str() + NEO::Elf::SectionsNamesZebin::textPrefix.str() + NEO::Elf::SectionsNamesZebin::externalFunctions.str(),
|
|
|
|
{reinterpret_cast<uint8_t *>(&extFuncSegReloc), sizeof(extFuncSegReloc)});
|
|
|
|
extFuncRelSection.info = externalFunctionsIdx;
|
|
|
|
|
|
|
|
NEO::Elf::ElfRel<NEO::Elf::EI_CLASS_64>
|
|
|
|
kernelSegReloc = {}; // kernel calls fun0
|
|
|
|
kernelSegReloc.offset = 0x8;
|
|
|
|
kernelSegReloc.info = (uint64_t(0) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR;
|
|
|
|
auto &kernelRelSection = elfEncoder.appendSection(NEO::Elf::SHT_REL, NEO::Elf::SpecialSectionNames::relPrefix.str() + NEO::Elf::SectionsNamesZebin::textPrefix.str() + "kernel",
|
|
|
|
{reinterpret_cast<uint8_t *>(&kernelSegReloc), sizeof(kernelSegReloc)});
|
|
|
|
kernelRelSection.info = kernelSectionIdx;
|
|
|
|
|
|
|
|
storage = elfEncoder.encode();
|
|
|
|
recalcPtr();
|
|
|
|
|
|
|
|
nameToSegId["kernel"] = 0;
|
|
|
|
nameToSegId["Intel_Symbol_Table_Void_Program"] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZebinWithExternalFunctionsInfo::recalcPtr() {
|
|
|
|
elfHeader = reinterpret_cast<NEO::Elf::ElfFileHeader<NEO::Elf::EI_CLASS_64> *>(storage.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZebinWithExternalFunctionsInfo::setProductFamily(uint16_t productFamily) {
|
|
|
|
elfHeader->machine = productFamily;
|
|
|
|
}
|
|
|
|
|
|
|
|
NEO::Elf::Elf<NEO::Elf::EI_CLASS_64> ZebinWithExternalFunctionsInfo::getElf() {
|
|
|
|
std::string errors, warnings;
|
|
|
|
auto elf = NEO::Elf::decodeElf({storage.data(), storage.size()}, errors, warnings);
|
|
|
|
return elf;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZebinWithL0TestCommonModule::ZebinWithL0TestCommonModule(const NEO::HardwareInfo &hwInfo, std::initializer_list<appendElfAdditionalSection> additionalSections, bool forceRecompilation) {
|
|
|
|
MockElfEncoder<> elfEncoder;
|
|
|
|
auto &elfHeader = elfEncoder.getElfFileHeader();
|
|
|
|
elfHeader.type = NEO::Elf::ET_ZEBIN_EXE;
|
|
|
|
if (forceRecompilation) {
|
|
|
|
elfHeader.machine = NEO::Elf::EM_NONE;
|
|
|
|
} else {
|
2022-10-05 21:37:57 +08:00
|
|
|
elfHeader.machine = hwInfo.platform.eProductFamily;
|
2022-07-15 23:46:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t testKernelData[0xac0] = {0u};
|
|
|
|
const uint8_t testKernelMemcpyBytesData[0x2c0] = {0u};
|
|
|
|
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "test", testKernelData);
|
2022-09-09 02:32:21 +08:00
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "memcpy_bytes_attr", testKernelMemcpyBytesData);
|
2022-07-15 23:46:10 +08:00
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
|
|
|
|
|
|
|
|
const uint8_t testAdditionalSectionsData[0x10] = {0u};
|
|
|
|
for (const auto &s : additionalSections) {
|
|
|
|
switch (s) {
|
|
|
|
case appendElfAdditionalSection::SPIRV:
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, testAdditionalSectionsData);
|
|
|
|
break;
|
|
|
|
case appendElfAdditionalSection::GLOBAL:
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataGlobal, testAdditionalSectionsData);
|
|
|
|
break;
|
|
|
|
case appendElfAdditionalSection::CONSTANT:
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConst, testAdditionalSectionsData);
|
|
|
|
break;
|
|
|
|
case appendElfAdditionalSection::CONSTANT_STRING:
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConstString.str(), testAdditionalSectionsData);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
storage = elfEncoder.encode();
|
|
|
|
recalcPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZebinWithL0TestCommonModule::recalcPtr() {
|
|
|
|
elfHeader = reinterpret_cast<NEO::Elf::ElfFileHeader<NEO::Elf::EI_CLASS_64> *>(storage.data());
|
|
|
|
}
|
|
|
|
|
2022-11-04 21:06:04 +08:00
|
|
|
template ZebinCopyBufferSimdModule<ELF_IDENTIFIER_CLASS::EI_CLASS_32>::ZebinCopyBufferSimdModule(const NEO::HardwareInfo &hwInfo, uint8_t simdSize);
|
|
|
|
template ZebinCopyBufferSimdModule<ELF_IDENTIFIER_CLASS::EI_CLASS_64>::ZebinCopyBufferSimdModule(const NEO::HardwareInfo &hwInfo, uint8_t simdSize);
|
|
|
|
|
|
|
|
template <ELF_IDENTIFIER_CLASS numBits>
|
|
|
|
ZebinCopyBufferSimdModule<numBits>::ZebinCopyBufferSimdModule(const NEO::HardwareInfo &hwInfo, uint8_t simdSize) {
|
|
|
|
zeInfoSize = static_cast<size_t>(snprintf(nullptr, 0, zeInfoCopyBufferSimdPlaceholder.c_str(), simdSize, simdSize, getLocalIdSize(hwInfo, simdSize)) + 1);
|
|
|
|
zeInfoCopyBuffer.resize(zeInfoSize);
|
|
|
|
snprintf(zeInfoCopyBuffer.data(), zeInfoSize, zeInfoCopyBufferSimdPlaceholder.c_str(), simdSize, simdSize, getLocalIdSize(hwInfo, simdSize));
|
|
|
|
|
|
|
|
MockElfEncoder<numBits> elfEncoder;
|
|
|
|
auto &elfHeader = elfEncoder.getElfFileHeader();
|
|
|
|
elfHeader.type = NEO::Elf::ET_ZEBIN_EXE;
|
|
|
|
elfHeader.machine = hwInfo.platform.eProductFamily;
|
|
|
|
|
|
|
|
const uint8_t testKernelData[0x2c0] = {0u};
|
|
|
|
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "CopyBuffer", testKernelData);
|
|
|
|
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfoCopyBuffer);
|
|
|
|
|
|
|
|
storage = elfEncoder.encode();
|
|
|
|
this->elfHeader = reinterpret_cast<NEO::Elf::ElfFileHeader<numBits> *>(storage.data());
|
|
|
|
}
|
|
|
|
|
2022-07-15 23:46:10 +08:00
|
|
|
}; // namespace ZebinTestData
|