Reimplementation of Elf Writer

- remove is_initialize pattern
- add RAII
- replace dynamic arrays with std::vector<char>
- use fixed width integer types
- remove c-style casting
- reducing the number of code checks
- add camelCase style

Change-Id: If24a595f03865c59c86fed29db280de0084b5663
This commit is contained in:
Kamil Diedrich
2018-07-27 22:59:40 +02:00
committed by sys_ocldev
parent 392277ff00
commit 8226269bbe
14 changed files with 304 additions and 676 deletions

2
Jenkinsfile vendored
View File

@@ -1,4 +1,4 @@
#!groovy
neoDependenciesRev='787198-1060'
strategy='EQUAL'
allowedCD=294
allowedCD=283

View File

@@ -20,266 +20,99 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "writer.h"
#include "runtime/helpers/string.h"
#include <cstring>
// Need for linux compatibility with memcpy_s
#include "runtime/helpers/string.h"
namespace CLElfLib {
/******************************************************************************\
Constructor: CElfWriter::CElfWriter
\******************************************************************************/
CElfWriter::CElfWriter(
E_EH_TYPE type,
E_EH_MACHINE machine,
Elf64_Xword flags) {
m_type = type;
m_machine = machine;
m_flags = flags;
}
void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
SElf64SectionHeader *curSectionHeader = nullptr;
char *data = nullptr;
char *stringTable = nullptr;
char *curString = nullptr;
/******************************************************************************\
Destructor: CElfWriter::~CElfWriter
\******************************************************************************/
CElfWriter::~CElfWriter() {
SSectionNode *pNode = nullptr;
// Walk through the section nodes
while (m_nodeQueue.empty() == false) {
pNode = m_nodeQueue.front();
m_nodeQueue.pop();
// delete the node and it's data
if (pNode) {
if (pNode->pData) {
delete[] pNode->pData;
pNode->pData = nullptr;
if (binary.size() < getTotalBinarySize()) {
binary.resize(getTotalBinarySize());
}
delete pNode;
pNode = nullptr;
}
}
}
/******************************************************************************\
Member Function: CElfWriter::Create
\******************************************************************************/
CElfWriter *CElfWriter::create(
E_EH_TYPE type,
E_EH_MACHINE machine,
Elf64_Xword flags) {
CElfWriter *pWriter = new CElfWriter(type, machine, flags);
if (!pWriter->initialize()) {
destroy(pWriter);
}
return pWriter;
}
/******************************************************************************\
Member Function: CElfWriter::Delete
\******************************************************************************/
void CElfWriter::destroy(
CElfWriter *&pWriter) {
if (pWriter) {
delete pWriter;
pWriter = nullptr;
}
}
/******************************************************************************\
Member Function: CElfWriter::AddSection
\******************************************************************************/
bool CElfWriter::addSection(
SSectionNode *pSectionNode) {
bool retVal = true;
SSectionNode *pNode = nullptr;
size_t nameSize = 0;
unsigned int dataSize = 0;
// The section header must be non-NULL
if (pSectionNode) {
pNode = new SSectionNode();
if (!pNode)
return false;
} else {
return false;
}
pNode->Flags = pSectionNode->Flags;
pNode->Type = pSectionNode->Type;
nameSize = pSectionNode->Name.size() + 1;
dataSize = pSectionNode->DataSize;
pNode->Name = pSectionNode->Name;
// ok to have NULL data
if (dataSize > 0) {
pNode->pData = new char[dataSize];
if (pNode->pData) {
memcpy_s(pNode->pData, dataSize, pSectionNode->pData, dataSize);
pNode->DataSize = dataSize;
} else {
retVal = false;
}
}
if (retVal) {
// push the node onto the queue
m_nodeQueue.push(pNode);
// increment the sizes for each section
m_dataSize += dataSize;
m_stringTableSize += nameSize;
m_numSections++;
} else {
delete pNode;
pNode = nullptr;
}
return retVal;
}
/******************************************************************************\
Member Function: CElfWriter::ResolveBinary
\******************************************************************************/
bool CElfWriter::resolveBinary(
char *const pBinary,
size_t &binarySize) {
bool retVal = true;
SSectionNode *pNode = nullptr;
SElf64SectionHeader *pCurSectionHeader = nullptr;
char *pData = nullptr;
char *pStringTable = nullptr;
char *pCurString = nullptr;
m_totalBinarySize =
sizeof(SElf64Header) +
((m_numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
m_dataSize +
m_stringTableSize;
if (pBinary) {
// get a pointer to the first section header
pCurSectionHeader = reinterpret_cast<SElf64SectionHeader *>(pBinary + sizeof(SElf64Header));
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(binary.data() + sizeof(SElf64Header));
// get a pointer to the data
pData = pBinary +
data = binary.data() +
sizeof(SElf64Header) +
((m_numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
// get a pointer to the string table
pStringTable = pBinary + sizeof(SElf64Header) +
((m_numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
m_dataSize;
stringTable = binary.data() + sizeof(SElf64Header) +
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
dataSize;
pCurString = pStringTable;
curString = stringTable;
// Walk through the section nodes
while (m_nodeQueue.empty() == false) {
pNode = m_nodeQueue.front();
if (pNode) {
m_nodeQueue.pop();
while (nodeQueue.empty() == false) {
// Copy data into the section header
memset(pCurSectionHeader, 0, sizeof(SElf64SectionHeader));
pCurSectionHeader->Type = pNode->Type;
pCurSectionHeader->Flags = pNode->Flags;
pCurSectionHeader->DataSize = pNode->DataSize;
pCurSectionHeader->DataOffset = pData - pBinary;
pCurSectionHeader->Name = static_cast<Elf64_Word>(pCurString - pStringTable);
pCurSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(pCurSectionHeader) + sizeof(SElf64SectionHeader));
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(pData, pNode->DataSize, pNode->pData, pNode->DataSize);
pData += pNode->DataSize;
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 (pNode->Name.size() > 0) {
memcpy_s(pCurString, pNode->Name.size(), pNode->Name.c_str(), pNode->Name.size());
pCurString += pNode->Name.size();
if (queueFront.name.size() > 0) {
memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size());
curString += queueFront.name.size();
}
*(pCurString++) = '\0'; // NOLINT
*(curString++) = '\0'; // NOLINT
// delete the node and it's data
if (pNode->pData) {
delete[] pNode->pData;
pNode->pData = nullptr;
}
delete pNode;
pNode = nullptr;
}
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 = pStringTable - pBinary;
stringSectionHeader.DataSize = m_stringTableSize;
stringSectionHeader.DataOffset = stringTable - &binary[0];
stringSectionHeader.DataSize = stringTableSize;
stringSectionHeader.Name = 0;
// Copy into the last section header
memcpy_s(pCurSectionHeader, sizeof(SElf64SectionHeader),
memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader),
&stringSectionHeader, sizeof(SElf64SectionHeader));
// Add to our section number
m_numSections++;
numSections++;
// patch up the ELF header
retVal = patchElfHeader(pBinary);
}
if (retVal) {
binarySize = m_totalBinarySize;
}
return retVal;
patchElfHeader(*reinterpret_cast<SElf64Header *>(binary.data()));
}
/******************************************************************************\
Member Function: CElfWriter::Initialize
\******************************************************************************/
bool CElfWriter::initialize() {
SSectionNode emptySection;
// Add an empty section 0 (points to "no-bits")
return addSection(&emptySection);
}
/******************************************************************************\
Member Function: CElfWriter::PatchElfHeader
\******************************************************************************/
bool CElfWriter::patchElfHeader(char *const pBinary) {
SElf64Header *pElfHeader = reinterpret_cast<SElf64Header *>(pBinary);
if (pElfHeader) {
void CElfWriter::patchElfHeader(SElf64Header &binary) {
// Setup the identity
memset(pElfHeader, 0x00, sizeof(SElf64Header));
pElfHeader->Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
pElfHeader->Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
pElfHeader->Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
pElfHeader->Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
pElfHeader->Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
pElfHeader->Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
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
pElfHeader->Type = m_type;
pElfHeader->Machine = m_machine;
pElfHeader->Flags = static_cast<uint32_t>(m_flags);
pElfHeader->ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
pElfHeader->SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
pElfHeader->NumSectionHeaderEntries = m_numSections;
pElfHeader->SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
pElfHeader->SectionNameTableIndex = m_numSections - 1; // last index
return true;
}
return false;
binary.Type = type;
binary.Machine = machine;
binary.Flags = static_cast<uint32_t>(flag);
binary.ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
binary.NumSectionHeaderEntries = numSections;
binary.SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
binary.SectionNameTableIndex = numSections - 1; // last index
}
} // namespace CLElfLib

View File

@@ -24,35 +24,23 @@
#include <queue>
#include <string>
#if defined(_WIN32)
#define ELF_CALL __stdcall
#else
#define ELF_CALL
#endif
using namespace std;
namespace CLElfLib {
static const unsigned int g_scElfHeaderAlignment = 16; // allocation alignment restriction
static const unsigned int g_scInitialElfSize = 2048; // initial elf size (in bytes)
static const unsigned int g_scInitNumSectionHeaders = 8;
using ElfBinaryStorage = std::vector<char>;
struct SSectionNode {
E_SH_TYPE Type;
E_SH_FLAG Flags;
string Name;
char *pData;
unsigned int DataSize;
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() {
Type = E_SH_TYPE::SH_TYPE_NULL;
Flags = E_SH_FLAG::SH_FLAG_NONE;
pData = nullptr;
DataSize = 0;
}
SSectionNode() = default;
~SSectionNode() {
}
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;
};
/******************************************************************************\
@@ -66,40 +54,51 @@ struct SSectionNode {
\******************************************************************************/
class CElfWriter {
public:
static CElfWriter *ELF_CALL create(
CElfWriter(
E_EH_TYPE type,
E_EH_MACHINE machine,
Elf64_Xword flags);
Elf64_Xword flag) : type(type), machine(machine), flag(flag) {
addSection(SSectionNode());
}
static void ELF_CALL destroy(CElfWriter *&pElfWriter);
~CElfWriter() {}
bool ELF_CALL addSection(
SSectionNode *pSectionNode);
template <typename T>
void addSection(T &&sectionNode) {
size_t nameSize = 0;
uint32_t dataSize = 0;
bool ELF_CALL resolveBinary(
char *const pBinary,
size_t &dataSize);
nameSize = sectionNode.name.size() + 1u;
dataSize = sectionNode.dataSize;
bool ELF_CALL initialize();
bool ELF_CALL patchElfHeader(char *const pBinary);
// 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:
ELF_CALL CElfWriter(
E_EH_TYPE type,
E_EH_MACHINE machine,
Elf64_Xword flags);
E_EH_TYPE type = E_EH_TYPE::EH_TYPE_NONE;
E_EH_MACHINE machine = E_EH_MACHINE::EH_MACHINE_NONE;
Elf64_Xword flag = 0U;
ELF_CALL ~CElfWriter();
std::queue<SSectionNode> nodeQueue;
E_EH_TYPE m_type = E_EH_TYPE::EH_TYPE_NONE;
E_EH_MACHINE m_machine = E_EH_MACHINE::EH_MACHINE_NONE;
Elf64_Xword m_flags = 0U;
uint32_t dataSize = 0U;
uint32_t numSections = 0U;
size_t stringTableSize = 0U;
std::queue<SSectionNode *> m_nodeQueue;
uint32_t m_dataSize = 0U;
uint32_t m_numSections = 0U;
size_t m_stringTableSize = 0U;
size_t m_totalBinarySize = 0U;
void patchElfHeader(SElf64Header &pBinary);
};
} // namespace CLElfLib

View File

@@ -98,7 +98,6 @@ OfflineCompiler::OfflineCompiler() = default;
OfflineCompiler::~OfflineCompiler() {
delete[] irBinary;
delete[] genBinary;
delete[] elfBinary;
}
////////////////////////////////////////////////////////////////////////////////
@@ -613,7 +612,7 @@ std::string getDevicesTypes() {
prefixes.push_back(hardwarePrefix[j]);
}
ostringstream os;
std::ostringstream os;
for (auto it = prefixes.begin(); it != prefixes.end(); it++) {
if (it != prefixes.begin())
os << ",";
@@ -675,60 +674,27 @@ void OfflineCompiler::storeBinary(
////////////////////////////////////////////////////////////////////////////////
bool OfflineCompiler::generateElfBinary() {
bool retVal = true;
CLElfLib::CElfWriter *pElfWriter = nullptr;
if (!genBinary || !genBinarySize) {
retVal = false;
}
if (retVal) {
pElfWriter = CLElfLib::CElfWriter::create(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
if (pElfWriter) {
CLElfLib::SSectionNode sectionNode;
// Always add the options string
sectionNode.Name = "BuildOptions";
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS;
sectionNode.pData = (char *)options.c_str();
sectionNode.DataSize = (uint32_t)(strlen(options.c_str()) + 1);
retVal = pElfWriter->addSection(&sectionNode);
if (retVal) {
sectionNode.Name = "Intel(R) OpenCL LLVM Object";
sectionNode.Type = isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY;
sectionNode.pData = irBinary;
sectionNode.DataSize = (uint32_t)irBinarySize;
retVal = pElfWriter->addSection(&sectionNode);
}
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast<uint32_t>(strlen(options.c_str()) + 1u)));
std::string irBinaryTemp = irBinary ? std::string(irBinary, irBinarySize) : "";
elfWriter.addSection(CLElfLib::SSectionNode(isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL LLVM Object", std::move(irBinaryTemp), static_cast<uint32_t>(irBinarySize)));
// Add the device binary if it exists
if (retVal && genBinary) {
sectionNode.Name = "Intel(R) OpenCL Device Binary";
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY;
sectionNode.pData = genBinary;
sectionNode.DataSize = (uint32_t)genBinarySize;
retVal = pElfWriter->addSection(&sectionNode);
if (genBinary) {
std::string genBinaryTemp = genBinary ? std::string(genBinary, genBinarySize) : "";
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
}
if (retVal) {
// get the size
retVal = pElfWriter->resolveBinary(elfBinary, elfBinarySize);
}
if (retVal) {
// allocate the binary
elfBinary = new char[elfBinarySize];
retVal = pElfWriter->resolveBinary(elfBinary, elfBinarySize);
}
} else {
retVal = false;
}
CLElfLib::CElfWriter::destroy(pElfWriter);
elfBinarySize = elfWriter.getTotalBinarySize();
elfBinary.resize(elfBinarySize);
elfWriter.resolveBinary(elfBinary);
}
return retVal;
@@ -787,12 +753,12 @@ void OfflineCompiler::writeOutAllFiles() {
}
}
if (elfBinary) {
if (!elfBinary.empty()) {
std::string elfOutputFile = generateFilePath(outputDirectory, fileBase, ".bin") + generateOptsSuffix();
writeDataToFile(
elfOutputFile.c_str(),
elfBinary,
elfBinary.data(),
elfBinarySize);
}

View File

@@ -24,6 +24,7 @@
#include "cif/common/cif_main.h"
#include "ocl_igc_interface/igc_ocl_device_ctx.h"
#include "ocl_igc_interface/fcl_ocl_device_ctx.h"
#include "elf/writer.h"
#include <cstdint>
#include <string>
#include <memory>
@@ -104,7 +105,7 @@ class OfflineCompiler {
bool inputFileLlvm = false;
bool inputFileSpirV = false;
char *elfBinary = nullptr;
CLElfLib::ElfBinaryStorage elfBinary;
size_t elfBinarySize = 0;
char *genBinary = nullptr;
size_t genBinarySize = 0;

View File

@@ -42,10 +42,8 @@ cl_int Program::compile(
void *userData) {
cl_int retVal = CL_SUCCESS;
cl_program program;
CLElfLib::CElfWriter *pElfWriter = nullptr;
Program *pHeaderProgObj;
size_t compileDataSize;
char *pCompileData = nullptr;
do {
if (((deviceList == nullptr) && (numDevices != 0)) ||
@@ -98,20 +96,12 @@ cl_int Program::compile(
}
// create ELF writer to process all sources to be compiled
pElfWriter = CLElfLib::CElfWriter::create(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_SOURCE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
UNRECOVERABLE_IF(pElfWriter == nullptr);
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_SOURCE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
CLElfLib::SSectionNode sectionNode;
// create main section
sectionNode.Name = "CLMain";
sectionNode.pData = (char *)sourceCode.c_str();
sectionNode.DataSize = (unsigned int)(strlen(sourceCode.c_str()) + 1);
sectionNode.Flags = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_SOURCE;
CLElfLib::SSectionNode sectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "CLMain", sourceCode, static_cast<uint32_t>(sourceCode.size() + 1u));
// add main program's source
pElfWriter->addSection(&sectionNode);
elfWriter.addSection(sectionNode);
for (cl_uint i = 0; i < numInputHeaders; i++) {
program = inputHeaders[i];
@@ -124,23 +114,25 @@ cl_int Program::compile(
retVal = CL_INVALID_PROGRAM;
break;
}
sectionNode.Name = headerIncludeNames[i];
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER;
sectionNode.Flags = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
sectionNode.name = headerIncludeNames[i];
sectionNode.type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER;
sectionNode.flag = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
// collect required data from the header
retVal = pHeaderProgObj->getSource(sectionNode.pData, sectionNode.DataSize);
retVal = pHeaderProgObj->getSource(sectionNode.data);
if (retVal != CL_SUCCESS) {
break;
}
pElfWriter->addSection(&sectionNode);
sectionNode.dataSize = static_cast<uint32_t>(sectionNode.data.size());
elfWriter.addSection(sectionNode);
}
if (retVal != CL_SUCCESS) {
break;
}
pElfWriter->resolveBinary(nullptr, compileDataSize);
pCompileData = new char[compileDataSize];
pElfWriter->resolveBinary(pCompileData, compileDataSize);
compileDataSize = elfWriter.getTotalBinarySize();
std::vector<char> compileData(compileDataSize);
elfWriter.resolveBinary(compileData);
CompilerInterface *pCompilerInterface = getCompilerInterface();
if (!pCompilerInterface) {
@@ -168,12 +160,12 @@ cl_int Program::compile(
}
}
inputArgs.pInput = pCompileData;
inputArgs.InputSize = (uint32_t)compileDataSize;
inputArgs.pInput = compileData.data();
inputArgs.InputSize = static_cast<uint32_t>(compileDataSize);
inputArgs.pOptions = options.c_str();
inputArgs.OptionsSize = (uint32_t)options.length();
inputArgs.OptionsSize = static_cast<uint32_t>(options.length());
inputArgs.pInternalOptions = internalOptions.c_str();
inputArgs.InternalOptionsSize = (uint32_t)internalOptions.length();
inputArgs.InternalOptionsSize = static_cast<uint32_t>(internalOptions.length());
inputArgs.pTracingOptions = nullptr;
inputArgs.TracingOptionsCount = 0;
@@ -192,8 +184,6 @@ cl_int Program::compile(
programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
}
CLElfLib::CElfWriter::destroy(pElfWriter);
delete[] pCompileData;
internalOptions.clear();
if (funcNotify != nullptr) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Intel Corporation
* Copyright (c) 2017 - 2018, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -48,7 +48,7 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
case CL_PROGRAM_BINARIES:
resolveProgramBinary();
pSrc = elfBinary;
pSrc = elfBinary.data();
retSize = sizeof(void **);
srcSize = elfBinarySize;
if (paramValue != nullptr) {

View File

@@ -40,12 +40,9 @@ cl_int Program::link(
void *userData) {
cl_int retVal = CL_SUCCESS;
cl_program program;
CLElfLib::CElfWriter *pElfWriter = nullptr;
Program *pInputProgObj;
size_t dataSize;
char *pData = nullptr;
bool isCreateLibrary;
CLElfLib::SSectionNode sectionNode;
do {
if (((deviceList == nullptr) && (numDevices != 0)) ||
@@ -81,7 +78,7 @@ cl_int Program::link(
buildStatus = CL_BUILD_IN_PROGRESS;
pElfWriter = CLElfLib::CElfWriter::create(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
StackVec<const Program *, 16> inputProgramsInternal;
for (cl_uint i = 0; i < numInputPrograms; i++) {
@@ -100,25 +97,17 @@ cl_int Program::link(
retVal = CL_INVALID_PROGRAM;
break;
}
sectionNode.Name = "";
if (pInputProgObj->getIsSpirV()) {
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV;
} else {
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY;
}
sectionNode.Flags = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
sectionNode.pData = pInputProgObj->irBinary;
sectionNode.DataSize = static_cast<unsigned int>(pInputProgObj->irBinarySize);
pElfWriter->addSection(&sectionNode);
elfWriter.addSection(CLElfLib::SSectionNode(pInputProgObj->getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(pInputProgObj->irBinary, pInputProgObj->irBinarySize), static_cast<uint32_t>(pInputProgObj->irBinarySize)));
}
if (retVal != CL_SUCCESS) {
break;
}
pElfWriter->resolveBinary(nullptr, dataSize);
pData = new char[dataSize];
pElfWriter->resolveBinary(pData, dataSize);
dataSize = elfWriter.getTotalBinarySize();
CLElfLib::ElfBinaryStorage data(dataSize);
elfWriter.resolveBinary(data);
CompilerInterface *pCompilerInterface = getCompilerInterface();
if (!pCompilerInterface) {
@@ -128,7 +117,7 @@ cl_int Program::link(
TranslationArgs inputArgs = {};
inputArgs.pInput = pData;
inputArgs.pInput = data.data();
inputArgs.InputSize = (uint32_t)dataSize;
inputArgs.pOptions = options.c_str();
inputArgs.OptionsSize = (uint32_t)options.length();
@@ -173,8 +162,6 @@ cl_int Program::link(
buildStatus = CL_BUILD_SUCCESS;
}
CLElfLib::CElfWriter::destroy(pElfWriter);
delete[] pData;
internalOptions.clear();
if (funcNotify != nullptr) {

View File

@@ -45,13 +45,8 @@ cl_int Program::processElfBinary(
}
if (retVal == CL_SUCCESS) {
delete[] elfBinary;
elfBinarySize = 0;
elfBinary = new char[binarySize];
elfBinarySize = binarySize;
memcpy_s(elfBinary, elfBinarySize, pBinary, binarySize);
elfBinary = CLElfLib::ElfBinaryStorage(reinterpret_cast<const char *>(pBinary), reinterpret_cast<const char *>(reinterpret_cast<const char *>(pBinary) + binarySize));
}
if (retVal == CL_SUCCESS) {
@@ -148,13 +143,10 @@ cl_int Program::processElfBinary(
}
cl_int Program::resolveProgramBinary() {
cl_int retVal = CL_SUCCESS;
CLElfLib::E_EH_TYPE headerType;
CLElfLib::CElfWriter *pElfWriter = nullptr;
if (isProgramBinaryResolved == false) {
delete[] elfBinary;
elfBinary = nullptr;
elfBinary.clear();
elfBinarySize = 0;
switch (programBinaryType) {
@@ -162,7 +154,7 @@ cl_int Program::resolveProgramBinary() {
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE;
if (!genBinary || !genBinarySize) {
retVal = CL_INVALID_BINARY;
return CL_INVALID_BINARY;
}
break;
@@ -170,7 +162,7 @@ cl_int Program::resolveProgramBinary() {
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY;
if (!irBinary || !irBinarySize) {
retVal = CL_INVALID_BINARY;
return CL_INVALID_BINARY;
}
break;
@@ -178,89 +170,40 @@ cl_int Program::resolveProgramBinary() {
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS;
if (!irBinary || !irBinarySize) {
retVal = CL_INVALID_BINARY;
return CL_INVALID_BINARY;
}
break;
default:
retVal = CL_INVALID_BINARY;
return CL_INVALID_BINARY;
}
if (retVal == CL_SUCCESS) {
pElfWriter = CLElfLib::CElfWriter::create(headerType, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
CLElfLib::CElfWriter elfWriter(headerType, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
if (pElfWriter) {
CLElfLib::SSectionNode sectionNode;
// Always add the options string
sectionNode.Name = "BuildOptions";
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS;
sectionNode.pData = (char *)options.c_str();
sectionNode.DataSize = (uint32_t)(strlen(options.c_str()) + 1);
auto elfRetVal = pElfWriter->addSection(&sectionNode);
if (elfRetVal) {
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast<uint32_t>(strlen(options.c_str()) + 1u)));
std::string irBinaryTemp = irBinary ? std::string(irBinary, irBinarySize) : "";
// Add the LLVM component if available
if (getIsSpirV()) {
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV;
} else {
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY;
}
if (headerType == CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY) {
sectionNode.Name = "Intel(R) OpenCL LLVM Archive";
sectionNode.pData = (char *)irBinary;
sectionNode.DataSize = (uint32_t)irBinarySize;
elfRetVal = pElfWriter->addSection(&sectionNode);
} else {
sectionNode.Name = "Intel(R) OpenCL LLVM Object";
sectionNode.pData = (char *)irBinary;
sectionNode.DataSize = (uint32_t)irBinarySize;
elfRetVal = pElfWriter->addSection(&sectionNode);
}
}
elfWriter.addSection(CLElfLib::SSectionNode(getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
headerType == CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY ? "Intel(R) OpenCL LLVM Archive" : "Intel(R) OpenCL LLVM Object", std::move(irBinaryTemp), static_cast<uint32_t>(irBinarySize)));
// Add the device binary if it exists
if (elfRetVal && genBinary) {
sectionNode.Name = "Intel(R) OpenCL Device Binary";
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY;
sectionNode.pData = (char *)genBinary;
sectionNode.DataSize = (uint32_t)genBinarySize;
elfRetVal = pElfWriter->addSection(&sectionNode);
if (genBinary) {
std::string genBinaryTemp = genBinary ? std::string(genBinary, genBinarySize) : "";
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
}
// Add the device debug data if it exists
if (elfRetVal && (debugData != nullptr)) {
sectionNode.Name = "Intel(R) OpenCL Device Debug";
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_DEBUG;
sectionNode.pData = debugData;
sectionNode.DataSize = (uint32_t)debugDataSize;
elfRetVal = pElfWriter->addSection(&sectionNode);
if (debugData != nullptr) {
std::string debugDataTemp = debugData ? std::string(debugData, debugDataSize) : "";
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_DEBUG, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Debug", std::move(debugDataTemp), static_cast<uint32_t>(debugDataSize)));
}
if (elfRetVal) {
elfRetVal = pElfWriter->resolveBinary(elfBinary, elfBinarySize);
}
if (elfRetVal) {
elfBinary = new char[elfBinarySize];
elfRetVal = pElfWriter->resolveBinary(elfBinary, elfBinarySize);
}
if (elfRetVal) {
elfBinarySize = elfWriter.getTotalBinarySize();
elfBinary = CLElfLib::ElfBinaryStorage(elfBinarySize);
elfWriter.resolveBinary(elfBinary);
isProgramBinaryResolved = true;
} else {
retVal = CL_INVALID_BINARY;
return CL_OUT_OF_HOST_MEMORY;
}
} else {
retVal = CL_OUT_OF_HOST_MEMORY;
}
CLElfLib::CElfWriter::destroy(pElfWriter);
}
}
return retVal;
return CL_SUCCESS;
}
} // namespace OCLRT

View File

@@ -47,7 +47,6 @@ Program::Program(Context *context, bool isBuiltIn) : context(context), isBuiltIn
blockKernelManager = new BlockKernelManager();
pDevice = context ? context->getDevice(0) : nullptr;
numDevices = 1;
elfBinary = nullptr;
elfBinarySize = 0;
genBinary = nullptr;
genBinarySize = 0;
@@ -115,8 +114,6 @@ Program::~Program() {
delete[] debugData;
debugData = nullptr;
delete[] elfBinary;
elfBinary = nullptr;
elfBinarySize = 0;
cleanCurrentKernelInfo();
@@ -170,8 +167,6 @@ cl_int Program::createProgramFromBinary(
cl_int Program::rebuildProgramFromIr() {
cl_int retVal = CL_SUCCESS;
size_t dataSize;
char *pData = nullptr;
CLElfLib::CElfWriter *pElfWriter = nullptr;
do {
if (!Program::isValidLlvmBinary(irBinary, irBinarySize)) {
@@ -182,20 +177,14 @@ cl_int Program::rebuildProgramFromIr() {
isSpirV = true;
}
pElfWriter = CLElfLib::CElfWriter::create(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
UNRECOVERABLE_IF(pElfWriter == nullptr);
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
CLElfLib::SSectionNode sectionNode;
sectionNode.Name = "";
sectionNode.Type = isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY;
sectionNode.Flags = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
sectionNode.pData = irBinary;
sectionNode.DataSize = static_cast<unsigned int>(irBinarySize);
pElfWriter->addSection(&sectionNode);
elfWriter.addSection(CLElfLib::SSectionNode(isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(irBinary, irBinarySize), static_cast<uint32_t>(irBinarySize)));
pElfWriter->resolveBinary(nullptr, dataSize);
pData = new char[dataSize];
pElfWriter->resolveBinary(pData, dataSize);
dataSize = elfWriter.getTotalBinarySize();
CLElfLib::ElfBinaryStorage data(dataSize);
elfWriter.resolveBinary(data);
CompilerInterface *pCompilerInterface = getCompilerInterface();
if (nullptr == pCompilerInterface) {
@@ -204,12 +193,12 @@ cl_int Program::rebuildProgramFromIr() {
}
TranslationArgs inputArgs = {};
inputArgs.pInput = pData;
inputArgs.InputSize = static_cast<unsigned int>(dataSize);
inputArgs.pInput = data.data();
inputArgs.InputSize = static_cast<uint32_t>(dataSize);
inputArgs.pOptions = options.c_str();
inputArgs.OptionsSize = static_cast<unsigned int>(options.length());
inputArgs.OptionsSize = static_cast<uint32_t>(options.length());
inputArgs.pInternalOptions = internalOptions.c_str();
inputArgs.InternalOptionsSize = static_cast<unsigned int>(internalOptions.length());
inputArgs.InternalOptionsSize = static_cast<uint32_t>(internalOptions.length());
inputArgs.pTracingOptions = nullptr;
inputArgs.TracingOptionsCount = 0;
@@ -228,9 +217,6 @@ cl_int Program::rebuildProgramFromIr() {
isProgramBinaryResolved = true;
} while (false);
CLElfLib::CElfWriter::destroy(pElfWriter);
delete[] pData;
return retVal;
}
@@ -274,6 +260,16 @@ cl_int Program::getSource(char *&pBinary, unsigned int &dataSize) const {
return retVal;
}
cl_int Program::getSource(std::string &binary) const {
cl_int retVal = CL_INVALID_PROGRAM;
binary = {};
if (!sourceCode.empty()) {
binary = sourceCode;
retVal = CL_SUCCESS;
}
return retVal;
}
void Program::storeGenBinary(
const void *pSrc,
const size_t srcSize) {

View File

@@ -29,6 +29,7 @@
#include "runtime/helpers/base_object.h"
#include "runtime/helpers/stdio.h"
#include "runtime/helpers/string_helpers.h"
#include "elf/writer.h"
#include "igfxfmid.h"
#include "patch_list.h"
#include <vector>
@@ -178,6 +179,8 @@ class Program : public BaseObject<_cl_program> {
cl_int getSource(char *&pBinary, unsigned int &dataSize) const;
cl_int getSource(std::string &binary) const;
void storeGenBinary(const void *pSrc, const size_t srcSize);
char *getGenBinary(size_t &genBinarySize) const {
@@ -297,7 +300,7 @@ class Program : public BaseObject<_cl_program> {
// clang-format off
cl_program_binary_type programBinaryType;
bool isSpirV = false;
char* elfBinary;
CLElfLib::ElfBinaryStorage elfBinary;
size_t elfBinarySize;
char* genBinary;

View File

@@ -39,17 +39,6 @@ struct ElfTests : public MemoryManagementFixture,
}
};
TEST_F(ElfTests, Create_Delete_Writer_Simple) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
}
TEST_F(ElfTests, Create_Reader_NULL_Binary) {
char *pBinary = NULL;
CElfReader *pReader = CElfReader::create(pBinary, 1);
@@ -68,130 +57,75 @@ TEST_F(ElfTests, Create_Reader_Garbage_Binary) {
delete[] pBinary;
}
TEST_F(ElfTests, Create_Delete_Reader_Writer_NoCheck) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
size_t dataSize;
pWriter->resolveBinary(NULL, dataSize);
char *pBinary = new char[dataSize];
if (pBinary) {
pWriter->resolveBinary(pBinary, dataSize);
}
CElfReader *pReader = CElfReader::create(pBinary, dataSize);
ASSERT_NE(nullptr, pReader);
EXPECT_NE(nullptr, pReader->getElfHeader());
CElfReader::destroy(pReader);
EXPECT_EQ((CElfReader *)NULL, pReader);
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
delete[] pBinary;
}
TEST_F(ElfTests, givenNullptrWriterWhenDestroyThenDontCrash) {
CElfWriter *ptr = nullptr;
CElfWriter::destroy(ptr);
}
TEST_F(ElfTests, givenElfWriterWhenNullptrThenFalseIsReturned) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
ASSERT_NE(nullptr, pWriter);
auto ret = pWriter->addSection(nullptr);
EXPECT_FALSE(ret);
CElfWriter::destroy(pWriter);
}
TEST_F(ElfTests, givenElfWriterWhenSectionAndFailuresThenFalseIsReturned) {
InjectedFunction method = [](size_t failureIndex) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
if (nonfailingAllocation == failureIndex) {
ASSERT_NE(nullptr, pWriter);
}
if (pWriter != nullptr) {
char sectionData[16];
memset(sectionData, 0xdeadbeef, 4);
SSectionNode sectionNode;
sectionNode.DataSize = 16;
sectionNode.pData = sectionData;
sectionNode.Flags = E_SH_FLAG::SH_FLAG_WRITE;
sectionNode.Name = "Steve";
sectionNode.Type = E_SH_TYPE::SH_TYPE_OPENCL_SOURCE;
auto ret = pWriter->addSection(&sectionNode);
if (nonfailingAllocation == failureIndex) {
EXPECT_TRUE(ret);
} else {
EXPECT_FALSE(ret);
}
CElfWriter::destroy(pWriter);
}
TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionIsAdded) {
class MockElfWriter : public CElfWriter {
public:
MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
using CElfWriter::nodeQueue;
};
injectFailures(method);
MockElfWriter writer;
std::string data{"data pattern"};
writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "Steve", data, static_cast<uint32_t>(data.size())));
ASSERT_EQ(2u, writer.nodeQueue.size());
// remove first (default) section
writer.nodeQueue.pop();
EXPECT_EQ(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, writer.nodeQueue.front().type);
EXPECT_EQ(E_SH_FLAG::SH_FLAG_WRITE, writer.nodeQueue.front().flag);
EXPECT_EQ("Steve", writer.nodeQueue.front().name);
EXPECT_EQ(data, writer.nodeQueue.front().data);
EXPECT_EQ(static_cast<uint32_t>(data.size()), writer.nodeQueue.front().dataSize);
}
TEST_F(ElfTests, givenElfWriterWhenPatchNullptrThenFalseIsReturned) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
ASSERT_NE(nullptr, pWriter);
TEST_F(ElfTests, givenCElfWriterWhenPatchElfHeaderThenDefaultAreSet) {
class MockElfWriter : public CElfWriter {
public:
MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
using CElfWriter::patchElfHeader;
};
auto ret = pWriter->patchElfHeader(nullptr);
EXPECT_FALSE(ret);
MockElfWriter writer;
CElfWriter::destroy(pWriter);
SElf64Header elfHeader;
writer.patchElfHeader(elfHeader);
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic0] == ELFConstants::elfMag0);
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic1] == ELFConstants::elfMag1);
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic2] == ELFConstants::elfMag2);
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic3] == ELFConstants::elfMag3);
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxClass] == static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64));
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxVersion] == static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT));
EXPECT_TRUE(elfHeader.Type == E_EH_TYPE::EH_TYPE_EXECUTABLE);
EXPECT_TRUE(elfHeader.Machine == E_EH_MACHINE::EH_MACHINE_NONE);
EXPECT_TRUE(elfHeader.Flags == static_cast<uint32_t>(0));
EXPECT_TRUE(elfHeader.ElfHeaderSize == static_cast<uint32_t>(sizeof(SElf64Header)));
EXPECT_TRUE(elfHeader.SectionHeaderEntrySize == static_cast<uint32_t>(sizeof(SElf64SectionHeader)));
EXPECT_TRUE(elfHeader.NumSectionHeaderEntries == 1);
EXPECT_TRUE(elfHeader.SectionHeadersOffset == static_cast<uint32_t>(sizeof(SElf64Header)));
EXPECT_TRUE(elfHeader.SectionNameTableIndex == 0);
}
TEST_F(ElfTests, Write_Read_Section_Data_By_Name) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionCanBeReadByName) {
CElfWriter writer(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0);
char sectionData[16];
memset(sectionData, 0xdeadbeef, 4);
SSectionNode sectionNode;
sectionNode.DataSize = 16;
sectionNode.pData = sectionData;
sectionNode.Flags = E_SH_FLAG::SH_FLAG_WRITE;
sectionNode.Name = "Steve";
sectionNode.Type = E_SH_TYPE::SH_TYPE_OPENCL_SOURCE;
writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "Steve", std::string(sectionData, 16u), 16u));
pWriter->addSection(&sectionNode);
size_t binarySize = writer.getTotalBinarySize();
size_t binarySize;
pWriter->resolveBinary(NULL, binarySize);
ElfBinaryStorage binary(binarySize);
writer.resolveBinary(binary);
char *pBinary = new char[binarySize];
if (pBinary) {
pWriter->resolveBinary(pBinary, binarySize);
}
CElfReader *pReader = CElfReader::create(binary.data(), binarySize);
EXPECT_NE((CElfReader *)nullptr, pReader);
CElfReader *pReader = CElfReader::create(pBinary, binarySize);
EXPECT_NE((CElfReader *)NULL, pReader);
char *pData = NULL;
char *pData = nullptr;
size_t dataSize = 0;
auto retVal = pReader->getSectionData("Steve", pData, dataSize);
@@ -202,45 +136,26 @@ TEST_F(ElfTests, Write_Read_Section_Data_By_Name) {
}
CElfReader::destroy(pReader);
EXPECT_EQ((CElfReader *)NULL, pReader);
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
delete[] pBinary;
EXPECT_EQ((CElfReader *)nullptr, pReader);
}
TEST_F(ElfTests, Write_Read_Section_Data_By_Index) {
CElfWriter *pWriter = CElfWriter::create(
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionCanBeReadByID) {
CElfWriter writer(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0);
char sectionData[16];
memset(sectionData, 0xdeadbeef, 4);
SSectionNode sectionNode;
sectionNode.DataSize = 16;
sectionNode.pData = sectionData;
sectionNode.Flags = E_SH_FLAG::SH_FLAG_WRITE;
sectionNode.Name = "";
sectionNode.Type = E_SH_TYPE::SH_TYPE_OPENCL_SOURCE;
writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "", std::string(sectionData, 16u), 16u));
pWriter->addSection(&sectionNode);
size_t binarySize = writer.getTotalBinarySize();
size_t binarySize;
pWriter->resolveBinary(NULL, binarySize);
ElfBinaryStorage binary(binarySize);
writer.resolveBinary(binary);
char *pBinary = new char[binarySize];
if (pBinary) {
pWriter->resolveBinary(pBinary, binarySize);
}
CElfReader *pReader = CElfReader::create(binary.data(), binarySize);
EXPECT_NE((CElfReader *)nullptr, pReader);
CElfReader *pReader = CElfReader::create(pBinary, binarySize);
EXPECT_NE((CElfReader *)NULL, pReader);
char *pData = NULL;
char *pData = nullptr;
size_t dataSize = 0;
auto retVal = pReader->getSectionData(1, pData, dataSize);
@@ -251,10 +166,5 @@ TEST_F(ElfTests, Write_Read_Section_Data_By_Index) {
}
CElfReader::destroy(pReader);
EXPECT_EQ((CElfReader *)NULL, pReader);
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
delete[] pBinary;
EXPECT_EQ((CElfReader *)nullptr, pReader);
}

View File

@@ -93,7 +93,7 @@ class MockOfflineCompiler : public OfflineCompiler {
}
char *getElfBinary() {
return elfBinary;
return elfBinary.data();
}
size_t getElfBinarySize() {

View File

@@ -38,7 +38,7 @@ TEST_F(ProcessElfBinaryTests, NullBinary) {
cl_int retVal = processElfBinary(nullptr, 0, binaryVersion);
EXPECT_EQ(CL_INVALID_BINARY, retVal);
EXPECT_EQ(nullptr, elfBinary);
EXPECT_TRUE(elfBinary.empty());
EXPECT_EQ(0u, elfBinarySize);
EXPECT_NE(0u, binaryVersion);
}
@@ -50,7 +50,7 @@ TEST_F(ProcessElfBinaryTests, InvalidBinary) {
cl_int retVal = processElfBinary(pBinary, binarySize, binaryVersion);
EXPECT_EQ(CL_INVALID_BINARY, retVal);
EXPECT_EQ(nullptr, elfBinary);
EXPECT_TRUE(elfBinary.empty());
EXPECT_EQ(0u, elfBinarySize);
EXPECT_NE(0u, binaryVersion);
}
@@ -65,7 +65,7 @@ TEST_F(ProcessElfBinaryTests, ValidBinary) {
cl_int retVal = processElfBinary(pBinary, binarySize, binaryVersion);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary, elfBinary, binarySize));
EXPECT_EQ(0, memcmp(pBinary, elfBinary.data(), binarySize));
EXPECT_NE(0u, binaryVersion);
deleteDataReadFromFile(pBinary);
}
@@ -87,17 +87,17 @@ TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
//clGetProgramInfo => SPIR-V stored as ELF binary
cl_int retVal = resolveProgramBinary();
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, elfBinary);
EXPECT_FALSE(elfBinary.empty());
EXPECT_NE(0u, elfBinarySize);
//use ELF reader to parse and validate ELF binary
CLElfLib::CElfReader *pElfReader = CLElfLib::CElfReader::create(
reinterpret_cast<const char *>(elfBinary), elfBinarySize);
reinterpret_cast<const char *>(elfBinary.data()), elfBinarySize);
ASSERT_NE(nullptr, pElfReader);
const CLElfLib::SElf64Header *pElfHeader = pElfReader->getElfHeader();
ASSERT_NE(nullptr, pElfHeader);
EXPECT_EQ(pElfHeader->Type, CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY);
EXPECT_TRUE(CLElfLib::CElfReader::isValidElf64(elfBinary, elfBinarySize));
EXPECT_TRUE(CLElfLib::CElfReader::isValidElf64(elfBinary.data(), elfBinarySize));
//check if ELF binary contains section SH_TYPE_SPIRV
bool hasSpirvSection = false;
@@ -115,7 +115,7 @@ TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
isSpirV = false;
uint32_t elfBinaryVersion;
auto pElfBinary = std::unique_ptr<char>(new char[elfBinarySize]);
memcpy_s(pElfBinary.get(), elfBinarySize, elfBinary, elfBinarySize);
memcpy_s(pElfBinary.get(), elfBinarySize, elfBinary.data(), elfBinarySize);
retVal = processElfBinary(pElfBinary.get(), elfBinarySize, elfBinaryVersion);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_TRUE(isSpirV);
@@ -151,7 +151,7 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe
memcpy_s(pTmpOptions, optionsSize, options.c_str(), optionsSize);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary, elfBinary, binarySize));
EXPECT_EQ(0, memcmp(pBinary, elfBinary.data(), binarySize));
EXPECT_NE(0u, binaryVersion);
// delete program's elf reference to force a resolve
@@ -184,7 +184,7 @@ TEST_F(ProcessElfBinaryTests, BackToBack) {
cl_int retVal = processElfBinary(pBinary, binarySize, binaryVersion);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary, elfBinary, binarySize));
EXPECT_EQ(0, memcmp(pBinary, elfBinary.data(), binarySize));
EXPECT_NE(0u, binaryVersion);
deleteDataReadFromFile(pBinary);
@@ -195,7 +195,7 @@ TEST_F(ProcessElfBinaryTests, BackToBack) {
retVal = processElfBinary(pBinary, binarySize, binaryVersion);
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_EQ(0, memcmp(pBinary, elfBinary, binarySize));
EXPECT_EQ(0, memcmp(pBinary, elfBinary.data(), binarySize));
EXPECT_NE(0u, binaryVersion);
deleteDataReadFromFile(pBinary);
}