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 #!groovy
neoDependenciesRev='787198-1060' neoDependenciesRev='787198-1060'
strategy='EQUAL' strategy='EQUAL'
allowedCD=294 allowedCD=283

View File

@@ -20,266 +20,99 @@
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "writer.h" #include "writer.h"
#include "runtime/helpers/string.h"
#include <cstring> #include <cstring>
namespace CLElfLib { // Need for linux compatibility with memcpy_s
/******************************************************************************\ #include "runtime/helpers/string.h"
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;
}
/******************************************************************************\ namespace CLElfLib {
Destructor: CElfWriter::~CElfWriter void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
\******************************************************************************/ SElf64SectionHeader *curSectionHeader = nullptr;
CElfWriter::~CElfWriter() { char *data = nullptr;
SSectionNode *pNode = 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 // Walk through the section nodes
while (m_nodeQueue.empty() == false) { while (nodeQueue.empty() == false) {
pNode = m_nodeQueue.front(); // Copy data into the section header
m_nodeQueue.pop(); const auto &queueFront = nodeQueue.front();
// delete the node and it's data curSectionHeader->Type = queueFront.type;
if (pNode) { curSectionHeader->Flags = queueFront.flag;
if (pNode->pData) { curSectionHeader->DataSize = queueFront.dataSize;
delete[] pNode->pData; curSectionHeader->DataOffset = data - binary.data();
pNode->pData = nullptr; curSectionHeader->Name = static_cast<Elf64_Word>(curString - stringTable);
} curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(curSectionHeader) + sizeof(SElf64SectionHeader));
delete pNode; // copy the data, move the data pointer
pNode = nullptr; 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) {
Member Function: CElfWriter::Create // Setup the identity
\******************************************************************************/ binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
CElfWriter *CElfWriter::create( binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
E_EH_TYPE type, binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
E_EH_MACHINE machine, binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
Elf64_Xword flags) { binary.Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
CElfWriter *pWriter = new CElfWriter(type, machine, flags); binary.Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
if (!pWriter->initialize()) { // Add other non-zero info
destroy(pWriter); binary.Type = type;
} binary.Machine = machine;
binary.Flags = static_cast<uint32_t>(flag);
return pWriter; 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
} }
/******************************************************************************\
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));
// get a pointer to the data
pData = pBinary +
sizeof(SElf64Header) +
((m_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;
pCurString = pStringTable;
// Walk through the section nodes
while (m_nodeQueue.empty() == false) {
pNode = m_nodeQueue.front();
if (pNode) {
m_nodeQueue.pop();
// 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));
// copy the data, move the data pointer
memcpy_s(pData, pNode->DataSize, pNode->pData, pNode->DataSize);
pData += pNode->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();
}
*(pCurString++) = '\0'; // NOLINT
// delete the node and it's data
if (pNode->pData) {
delete[] pNode->pData;
pNode->pData = nullptr;
}
delete pNode;
pNode = nullptr;
}
}
// 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.Name = 0;
// Copy into the last section header
memcpy_s(pCurSectionHeader, sizeof(SElf64SectionHeader),
&stringSectionHeader, sizeof(SElf64SectionHeader));
// Add to our section number
m_numSections++;
// patch up the ELF header
retVal = patchElfHeader(pBinary);
}
if (retVal) {
binarySize = m_totalBinarySize;
}
return retVal;
}
/******************************************************************************\
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) {
// 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);
// 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;
}
} // namespace CLElfLib } // namespace CLElfLib

View File

@@ -24,35 +24,23 @@
#include <queue> #include <queue>
#include <string> #include <string>
#if defined(_WIN32)
#define ELF_CALL __stdcall
#else
#define ELF_CALL
#endif
using namespace std;
namespace CLElfLib { namespace CLElfLib {
static const unsigned int g_scElfHeaderAlignment = 16; // allocation alignment restriction using ElfBinaryStorage = std::vector<char>;
static const unsigned int g_scInitialElfSize = 2048; // initial elf size (in bytes)
static const unsigned int g_scInitNumSectionHeaders = 8;
struct SSectionNode { struct SSectionNode {
E_SH_TYPE Type; E_SH_TYPE type = E_SH_TYPE::SH_TYPE_NULL;
E_SH_FLAG Flags; E_SH_FLAG flag = E_SH_FLAG::SH_FLAG_NONE;
string Name; std::string name;
char *pData; std::string data;
unsigned int DataSize; uint32_t dataSize = 0u;
SSectionNode() { SSectionNode() = default;
Type = E_SH_TYPE::SH_TYPE_NULL;
Flags = E_SH_FLAG::SH_FLAG_NONE;
pData = nullptr;
DataSize = 0;
}
~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;
}; };
/******************************************************************************\ /******************************************************************************\
@@ -60,46 +48,57 @@ struct SSectionNode {
Class: CElfWriter Class: CElfWriter
Description: Class to provide simpler interaction with the ELF standard Description: Class to provide simpler interaction with the ELF standard
binary object. SElf64Header defines the ELF header type and binary object. SElf64Header defines the ELF header type and
SElf64SectionHeader defines the section header type. SElf64SectionHeader defines the section header type.
\******************************************************************************/ \******************************************************************************/
class CElfWriter { class CElfWriter {
public: public:
static CElfWriter *ELF_CALL create( CElfWriter(
E_EH_TYPE type, E_EH_TYPE type,
E_EH_MACHINE machine, 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( template <typename T>
SSectionNode *pSectionNode); void addSection(T &&sectionNode) {
size_t nameSize = 0;
uint32_t dataSize = 0;
bool ELF_CALL resolveBinary( nameSize = sectionNode.name.size() + 1u;
char *const pBinary, dataSize = sectionNode.dataSize;
size_t &dataSize);
bool ELF_CALL initialize(); // push the node onto the queue
bool ELF_CALL patchElfHeader(char *const pBinary); 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: protected:
ELF_CALL CElfWriter( E_EH_TYPE type = E_EH_TYPE::EH_TYPE_NONE;
E_EH_TYPE type, E_EH_MACHINE machine = E_EH_MACHINE::EH_MACHINE_NONE;
E_EH_MACHINE machine, Elf64_Xword flag = 0U;
Elf64_Xword flags);
ELF_CALL ~CElfWriter(); std::queue<SSectionNode> nodeQueue;
E_EH_TYPE m_type = E_EH_TYPE::EH_TYPE_NONE; uint32_t dataSize = 0U;
E_EH_MACHINE m_machine = E_EH_MACHINE::EH_MACHINE_NONE; uint32_t numSections = 0U;
Elf64_Xword m_flags = 0U; size_t stringTableSize = 0U;
std::queue<SSectionNode *> m_nodeQueue; void patchElfHeader(SElf64Header &pBinary);
uint32_t m_dataSize = 0U;
uint32_t m_numSections = 0U;
size_t m_stringTableSize = 0U;
size_t m_totalBinarySize = 0U;
}; };
} // namespace CLElfLib } // namespace CLElfLib

View File

@@ -98,7 +98,6 @@ OfflineCompiler::OfflineCompiler() = default;
OfflineCompiler::~OfflineCompiler() { OfflineCompiler::~OfflineCompiler() {
delete[] irBinary; delete[] irBinary;
delete[] genBinary; delete[] genBinary;
delete[] elfBinary;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -613,7 +612,7 @@ std::string getDevicesTypes() {
prefixes.push_back(hardwarePrefix[j]); prefixes.push_back(hardwarePrefix[j]);
} }
ostringstream os; std::ostringstream os;
for (auto it = prefixes.begin(); it != prefixes.end(); it++) { for (auto it = prefixes.begin(); it != prefixes.end(); it++) {
if (it != prefixes.begin()) if (it != prefixes.begin())
os << ","; os << ",";
@@ -675,60 +674,27 @@ void OfflineCompiler::storeBinary(
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool OfflineCompiler::generateElfBinary() { bool OfflineCompiler::generateElfBinary() {
bool retVal = true; bool retVal = true;
CLElfLib::CElfWriter *pElfWriter = nullptr;
if (!genBinary || !genBinarySize) { if (!genBinary || !genBinarySize) {
retVal = false; retVal = false;
} }
if (retVal) { 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) { 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)));
CLElfLib::SSectionNode sectionNode; 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)));
// Always add the options string // Add the device binary if it exists
sectionNode.Name = "BuildOptions"; if (genBinary) {
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS; std::string genBinaryTemp = genBinary ? std::string(genBinary, genBinarySize) : "";
sectionNode.pData = (char *)options.c_str(); 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)));
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);
}
// 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 (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; return retVal;
@@ -787,12 +753,12 @@ void OfflineCompiler::writeOutAllFiles() {
} }
} }
if (elfBinary) { if (!elfBinary.empty()) {
std::string elfOutputFile = generateFilePath(outputDirectory, fileBase, ".bin") + generateOptsSuffix(); std::string elfOutputFile = generateFilePath(outputDirectory, fileBase, ".bin") + generateOptsSuffix();
writeDataToFile( writeDataToFile(
elfOutputFile.c_str(), elfOutputFile.c_str(),
elfBinary, elfBinary.data(),
elfBinarySize); elfBinarySize);
} }

View File

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

View File

@@ -42,10 +42,8 @@ cl_int Program::compile(
void *userData) { void *userData) {
cl_int retVal = CL_SUCCESS; cl_int retVal = CL_SUCCESS;
cl_program program; cl_program program;
CLElfLib::CElfWriter *pElfWriter = nullptr;
Program *pHeaderProgObj; Program *pHeaderProgObj;
size_t compileDataSize; size_t compileDataSize;
char *pCompileData = nullptr;
do { do {
if (((deviceList == nullptr) && (numDevices != 0)) || if (((deviceList == nullptr) && (numDevices != 0)) ||
@@ -98,20 +96,12 @@ cl_int Program::compile(
} }
// create ELF writer to process all sources to be compiled // 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); CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_SOURCE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
UNRECOVERABLE_IF(pElfWriter == nullptr);
CLElfLib::SSectionNode sectionNode; 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));
// 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;
// add main program's source // add main program's source
pElfWriter->addSection(&sectionNode); elfWriter.addSection(sectionNode);
for (cl_uint i = 0; i < numInputHeaders; i++) { for (cl_uint i = 0; i < numInputHeaders; i++) {
program = inputHeaders[i]; program = inputHeaders[i];
@@ -124,23 +114,25 @@ cl_int Program::compile(
retVal = CL_INVALID_PROGRAM; retVal = CL_INVALID_PROGRAM;
break; break;
} }
sectionNode.Name = headerIncludeNames[i]; sectionNode.name = headerIncludeNames[i];
sectionNode.Type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER; sectionNode.type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER;
sectionNode.Flags = CLElfLib::E_SH_FLAG::SH_FLAG_NONE; sectionNode.flag = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
// collect required data from the header // collect required data from the header
retVal = pHeaderProgObj->getSource(sectionNode.pData, sectionNode.DataSize); retVal = pHeaderProgObj->getSource(sectionNode.data);
if (retVal != CL_SUCCESS) { if (retVal != CL_SUCCESS) {
break; break;
} }
pElfWriter->addSection(&sectionNode);
sectionNode.dataSize = static_cast<uint32_t>(sectionNode.data.size());
elfWriter.addSection(sectionNode);
} }
if (retVal != CL_SUCCESS) { if (retVal != CL_SUCCESS) {
break; break;
} }
pElfWriter->resolveBinary(nullptr, compileDataSize); compileDataSize = elfWriter.getTotalBinarySize();
pCompileData = new char[compileDataSize]; std::vector<char> compileData(compileDataSize);
pElfWriter->resolveBinary(pCompileData, compileDataSize); elfWriter.resolveBinary(compileData);
CompilerInterface *pCompilerInterface = getCompilerInterface(); CompilerInterface *pCompilerInterface = getCompilerInterface();
if (!pCompilerInterface) { if (!pCompilerInterface) {
@@ -168,12 +160,12 @@ cl_int Program::compile(
} }
} }
inputArgs.pInput = pCompileData; inputArgs.pInput = compileData.data();
inputArgs.InputSize = (uint32_t)compileDataSize; inputArgs.InputSize = static_cast<uint32_t>(compileDataSize);
inputArgs.pOptions = options.c_str(); 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.pInternalOptions = internalOptions.c_str();
inputArgs.InternalOptionsSize = (uint32_t)internalOptions.length(); inputArgs.InternalOptionsSize = static_cast<uint32_t>(internalOptions.length());
inputArgs.pTracingOptions = nullptr; inputArgs.pTracingOptions = nullptr;
inputArgs.TracingOptionsCount = 0; inputArgs.TracingOptionsCount = 0;
@@ -192,8 +184,6 @@ cl_int Program::compile(
programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT; programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
} }
CLElfLib::CElfWriter::destroy(pElfWriter);
delete[] pCompileData;
internalOptions.clear(); internalOptions.clear();
if (funcNotify != nullptr) { 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 * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * 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: case CL_PROGRAM_BINARIES:
resolveProgramBinary(); resolveProgramBinary();
pSrc = elfBinary; pSrc = elfBinary.data();
retSize = sizeof(void **); retSize = sizeof(void **);
srcSize = elfBinarySize; srcSize = elfBinarySize;
if (paramValue != nullptr) { if (paramValue != nullptr) {

View File

@@ -40,12 +40,9 @@ cl_int Program::link(
void *userData) { void *userData) {
cl_int retVal = CL_SUCCESS; cl_int retVal = CL_SUCCESS;
cl_program program; cl_program program;
CLElfLib::CElfWriter *pElfWriter = nullptr;
Program *pInputProgObj; Program *pInputProgObj;
size_t dataSize; size_t dataSize;
char *pData = nullptr;
bool isCreateLibrary; bool isCreateLibrary;
CLElfLib::SSectionNode sectionNode;
do { do {
if (((deviceList == nullptr) && (numDevices != 0)) || if (((deviceList == nullptr) && (numDevices != 0)) ||
@@ -81,7 +78,7 @@ cl_int Program::link(
buildStatus = CL_BUILD_IN_PROGRESS; 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; StackVec<const Program *, 16> inputProgramsInternal;
for (cl_uint i = 0; i < numInputPrograms; i++) { for (cl_uint i = 0; i < numInputPrograms; i++) {
@@ -100,25 +97,17 @@ cl_int Program::link(
retVal = CL_INVALID_PROGRAM; retVal = CL_INVALID_PROGRAM;
break; 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) { if (retVal != CL_SUCCESS) {
break; break;
} }
pElfWriter->resolveBinary(nullptr, dataSize); dataSize = elfWriter.getTotalBinarySize();
pData = new char[dataSize]; CLElfLib::ElfBinaryStorage data(dataSize);
pElfWriter->resolveBinary(pData, dataSize); elfWriter.resolveBinary(data);
CompilerInterface *pCompilerInterface = getCompilerInterface(); CompilerInterface *pCompilerInterface = getCompilerInterface();
if (!pCompilerInterface) { if (!pCompilerInterface) {
@@ -128,7 +117,7 @@ cl_int Program::link(
TranslationArgs inputArgs = {}; TranslationArgs inputArgs = {};
inputArgs.pInput = pData; inputArgs.pInput = data.data();
inputArgs.InputSize = (uint32_t)dataSize; inputArgs.InputSize = (uint32_t)dataSize;
inputArgs.pOptions = options.c_str(); inputArgs.pOptions = options.c_str();
inputArgs.OptionsSize = (uint32_t)options.length(); inputArgs.OptionsSize = (uint32_t)options.length();
@@ -173,8 +162,6 @@ cl_int Program::link(
buildStatus = CL_BUILD_SUCCESS; buildStatus = CL_BUILD_SUCCESS;
} }
CLElfLib::CElfWriter::destroy(pElfWriter);
delete[] pData;
internalOptions.clear(); internalOptions.clear();
if (funcNotify != nullptr) { if (funcNotify != nullptr) {

View File

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

View File

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

View File

@@ -29,6 +29,7 @@
#include "runtime/helpers/base_object.h" #include "runtime/helpers/base_object.h"
#include "runtime/helpers/stdio.h" #include "runtime/helpers/stdio.h"
#include "runtime/helpers/string_helpers.h" #include "runtime/helpers/string_helpers.h"
#include "elf/writer.h"
#include "igfxfmid.h" #include "igfxfmid.h"
#include "patch_list.h" #include "patch_list.h"
#include <vector> #include <vector>
@@ -178,6 +179,8 @@ class Program : public BaseObject<_cl_program> {
cl_int getSource(char *&pBinary, unsigned int &dataSize) const; 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); void storeGenBinary(const void *pSrc, const size_t srcSize);
char *getGenBinary(size_t &genBinarySize) const { char *getGenBinary(size_t &genBinarySize) const {
@@ -297,7 +300,7 @@ class Program : public BaseObject<_cl_program> {
// clang-format off // clang-format off
cl_program_binary_type programBinaryType; cl_program_binary_type programBinaryType;
bool isSpirV = false; bool isSpirV = false;
char* elfBinary; CLElfLib::ElfBinaryStorage elfBinary;
size_t elfBinarySize; size_t elfBinarySize;
char* genBinary; 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) { TEST_F(ElfTests, Create_Reader_NULL_Binary) {
char *pBinary = NULL; char *pBinary = NULL;
CElfReader *pReader = CElfReader::create(pBinary, 1); CElfReader *pReader = CElfReader::create(pBinary, 1);
@@ -68,130 +57,75 @@ TEST_F(ElfTests, Create_Reader_Garbage_Binary) {
delete[] pBinary; delete[] pBinary;
} }
TEST_F(ElfTests, Create_Delete_Reader_Writer_NoCheck) { TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionIsAdded) {
CElfWriter *pWriter = CElfWriter::create( class MockElfWriter : public CElfWriter {
E_EH_TYPE::EH_TYPE_EXECUTABLE, public:
E_EH_MACHINE::EH_MACHINE_NONE, MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
0); using CElfWriter::nodeQueue;
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);
}
}; };
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) { TEST_F(ElfTests, givenCElfWriterWhenPatchElfHeaderThenDefaultAreSet) {
CElfWriter *pWriter = CElfWriter::create( class MockElfWriter : public CElfWriter {
E_EH_TYPE::EH_TYPE_EXECUTABLE, public:
E_EH_MACHINE::EH_MACHINE_NONE, MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
0); using CElfWriter::patchElfHeader;
ASSERT_NE(nullptr, pWriter); };
auto ret = pWriter->patchElfHeader(nullptr); MockElfWriter writer;
EXPECT_FALSE(ret);
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) { TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionCanBeReadByName) {
CElfWriter *pWriter = CElfWriter::create( CElfWriter writer(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0);
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
char sectionData[16]; char sectionData[16];
memset(sectionData, 0xdeadbeef, 4); memset(sectionData, 0xdeadbeef, 4);
SSectionNode sectionNode; writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "Steve", std::string(sectionData, 16u), 16u));
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;
pWriter->addSection(&sectionNode); size_t binarySize = writer.getTotalBinarySize();
size_t binarySize; ElfBinaryStorage binary(binarySize);
pWriter->resolveBinary(NULL, binarySize); writer.resolveBinary(binary);
char *pBinary = new char[binarySize]; CElfReader *pReader = CElfReader::create(binary.data(), binarySize);
if (pBinary) { EXPECT_NE((CElfReader *)nullptr, pReader);
pWriter->resolveBinary(pBinary, binarySize);
}
CElfReader *pReader = CElfReader::create(pBinary, binarySize); char *pData = nullptr;
EXPECT_NE((CElfReader *)NULL, pReader);
char *pData = NULL;
size_t dataSize = 0; size_t dataSize = 0;
auto retVal = pReader->getSectionData("Steve", pData, dataSize); auto retVal = pReader->getSectionData("Steve", pData, dataSize);
@@ -202,45 +136,26 @@ TEST_F(ElfTests, Write_Read_Section_Data_By_Name) {
} }
CElfReader::destroy(pReader); CElfReader::destroy(pReader);
EXPECT_EQ((CElfReader *)NULL, pReader); EXPECT_EQ((CElfReader *)nullptr, pReader);
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
delete[] pBinary;
} }
TEST_F(ElfTests, Write_Read_Section_Data_By_Index) { TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionCanBeReadByID) {
CElfWriter *pWriter = CElfWriter::create( CElfWriter writer(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0);
E_EH_TYPE::EH_TYPE_EXECUTABLE,
E_EH_MACHINE::EH_MACHINE_NONE,
0);
EXPECT_NE((CElfWriter *)NULL, pWriter);
char sectionData[16]; char sectionData[16];
memset(sectionData, 0xdeadbeef, 4); memset(sectionData, 0xdeadbeef, 4);
SSectionNode sectionNode; writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "", std::string(sectionData, 16u), 16u));
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;
pWriter->addSection(&sectionNode); size_t binarySize = writer.getTotalBinarySize();
size_t binarySize; ElfBinaryStorage binary(binarySize);
pWriter->resolveBinary(NULL, binarySize); writer.resolveBinary(binary);
char *pBinary = new char[binarySize]; CElfReader *pReader = CElfReader::create(binary.data(), binarySize);
if (pBinary) { EXPECT_NE((CElfReader *)nullptr, pReader);
pWriter->resolveBinary(pBinary, binarySize);
}
CElfReader *pReader = CElfReader::create(pBinary, binarySize); char *pData = nullptr;
EXPECT_NE((CElfReader *)NULL, pReader);
char *pData = NULL;
size_t dataSize = 0; size_t dataSize = 0;
auto retVal = pReader->getSectionData(1, pData, dataSize); auto retVal = pReader->getSectionData(1, pData, dataSize);
@@ -251,10 +166,5 @@ TEST_F(ElfTests, Write_Read_Section_Data_By_Index) {
} }
CElfReader::destroy(pReader); CElfReader::destroy(pReader);
EXPECT_EQ((CElfReader *)NULL, pReader); EXPECT_EQ((CElfReader *)nullptr, pReader);
}
CElfWriter::destroy(pWriter);
EXPECT_EQ((CElfWriter *)NULL, pWriter);
delete[] pBinary;
}

View File

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

View File

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