diff --git a/Jenkinsfile b/Jenkinsfile index be4b4cfed4..c084187443 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,4 @@ #!groovy neoDependenciesRev='787198-1060' strategy='EQUAL' -allowedCD=294 +allowedCD=283 diff --git a/elf/writer.cpp b/elf/writer.cpp index 82822e9b26..e308725239 100644 --- a/elf/writer.cpp +++ b/elf/writer.cpp @@ -20,266 +20,99 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "writer.h" -#include "runtime/helpers/string.h" #include -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; -} +// Need for linux compatibility with memcpy_s +#include "runtime/helpers/string.h" -/******************************************************************************\ - Destructor: CElfWriter::~CElfWriter -\******************************************************************************/ -CElfWriter::~CElfWriter() { - SSectionNode *pNode = nullptr; +namespace CLElfLib { +void CElfWriter::resolveBinary(ElfBinaryStorage &binary) { + SElf64SectionHeader *curSectionHeader = nullptr; + char *data = nullptr; + char *stringTable = nullptr; + char *curString = nullptr; + + if (binary.size() < getTotalBinarySize()) { + binary.resize(getTotalBinarySize()); + } + + // get a pointer to the first section header + curSectionHeader = reinterpret_cast(binary.data() + sizeof(SElf64Header)); + + // get a pointer to the data + data = binary.data() + + sizeof(SElf64Header) + + ((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry + + // get a pointer to the string table + stringTable = binary.data() + sizeof(SElf64Header) + + ((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry + dataSize; + + curString = stringTable; // Walk through the section nodes - while (m_nodeQueue.empty() == false) { - pNode = m_nodeQueue.front(); - m_nodeQueue.pop(); + while (nodeQueue.empty() == false) { + // Copy data into the section header + const auto &queueFront = nodeQueue.front(); - // delete the node and it's data - if (pNode) { - if (pNode->pData) { - delete[] pNode->pData; - pNode->pData = nullptr; - } + curSectionHeader->Type = queueFront.type; + curSectionHeader->Flags = queueFront.flag; + curSectionHeader->DataSize = queueFront.dataSize; + curSectionHeader->DataOffset = data - binary.data(); + curSectionHeader->Name = static_cast(curString - stringTable); + curSectionHeader = reinterpret_cast(reinterpret_cast(curSectionHeader) + sizeof(SElf64SectionHeader)); - delete pNode; - pNode = nullptr; + // copy the data, move the data pointer + memcpy_s(data, queueFront.dataSize, queueFront.data.c_str(), queueFront.dataSize); + data += queueFront.dataSize; + + // copy the name into the string table, move the string pointer + if (queueFront.name.size() > 0) { + memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size()); + curString += queueFront.name.size(); } + *(curString++) = '\0'; // NOLINT + + nodeQueue.pop(); } + + // add the string table section header + SElf64SectionHeader stringSectionHeader = {0}; + stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL; + stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE; + stringSectionHeader.DataOffset = stringTable - &binary[0]; + stringSectionHeader.DataSize = stringTableSize; + stringSectionHeader.Name = 0; + + // Copy into the last section header + memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader), + &stringSectionHeader, sizeof(SElf64SectionHeader)); + + // Add to our section number + numSections++; + + // patch up the ELF header + patchElfHeader(*reinterpret_cast(binary.data())); } -/******************************************************************************\ - 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); +void CElfWriter::patchElfHeader(SElf64Header &binary) { + // Setup the identity + binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0; + binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1; + binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2; + binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3; + binary.Identity[ELFConstants::idIdxClass] = static_cast(E_EH_CLASS::EH_CLASS_64); + binary.Identity[ELFConstants::idIdxVersion] = static_cast(E_EHT_VERSION::EH_VERSION_CURRENT); - if (!pWriter->initialize()) { - destroy(pWriter); - } - - return pWriter; + // Add other non-zero info + binary.Type = type; + binary.Machine = machine; + binary.Flags = static_cast(flag); + binary.ElfHeaderSize = static_cast(sizeof(SElf64Header)); + binary.SectionHeaderEntrySize = static_cast(sizeof(SElf64SectionHeader)); + binary.NumSectionHeaderEntries = numSections; + binary.SectionHeadersOffset = static_cast(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(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(pCurString - pStringTable); - pCurSectionHeader = reinterpret_cast(reinterpret_cast(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(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(E_EH_CLASS::EH_CLASS_64); - pElfHeader->Identity[ELFConstants::idIdxVersion] = static_cast(E_EHT_VERSION::EH_VERSION_CURRENT); - - // Add other non-zero info - pElfHeader->Type = m_type; - pElfHeader->Machine = m_machine; - pElfHeader->Flags = static_cast(m_flags); - pElfHeader->ElfHeaderSize = static_cast(sizeof(SElf64Header)); - pElfHeader->SectionHeaderEntrySize = static_cast(sizeof(SElf64SectionHeader)); - pElfHeader->NumSectionHeaderEntries = m_numSections; - pElfHeader->SectionHeadersOffset = static_cast(sizeof(SElf64Header)); - pElfHeader->SectionNameTableIndex = m_numSections - 1; // last index - - return true; - } - - return false; -} - } // namespace CLElfLib diff --git a/elf/writer.h b/elf/writer.h index e814ffa4af..ad4d959ebb 100644 --- a/elf/writer.h +++ b/elf/writer.h @@ -24,35 +24,23 @@ #include #include -#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; 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 + SSectionNode(E_SH_TYPE type, E_SH_FLAG flag, T1 &&name, T2 &&data, uint32_t dataSize) + : type(type), flag(flag), name(std::forward(name)), data(std::forward(data)), dataSize(dataSize) {} + + ~SSectionNode() = default; }; /******************************************************************************\ @@ -60,46 +48,57 @@ struct SSectionNode { Class: CElfWriter 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. \******************************************************************************/ 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 + void addSection(T &§ionNode) { + 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(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 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 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 diff --git a/offline_compiler/offline_compiler.cpp b/offline_compiler/offline_compiler.cpp index 4d7089e874..b764b9ded0 100644 --- a/offline_compiler/offline_compiler.cpp +++ b/offline_compiler/offline_compiler.cpp @@ -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; + elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast(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(irBinarySize))); - // 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(§ionNode); - - 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(§ionNode); - } - - // 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(§ionNode); - } - - 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; + // Add the device binary if it exists + 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(genBinarySize))); } - 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); } diff --git a/offline_compiler/offline_compiler.h b/offline_compiler/offline_compiler.h index d50d096989..310831b7f5 100644 --- a/offline_compiler/offline_compiler.h +++ b/offline_compiler/offline_compiler.h @@ -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 #include #include @@ -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; diff --git a/runtime/program/compile.cpp b/runtime/program/compile.cpp index de63eb99a9..a6e454a4fe 100644 --- a/runtime/program/compile.cpp +++ b/runtime/program/compile.cpp @@ -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(sourceCode.size() + 1u)); // add main program's source - pElfWriter->addSection(§ionNode); + 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(§ionNode); + + sectionNode.dataSize = static_cast(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 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(compileDataSize); inputArgs.pOptions = options.c_str(); - inputArgs.OptionsSize = (uint32_t)options.length(); + inputArgs.OptionsSize = static_cast(options.length()); inputArgs.pInternalOptions = internalOptions.c_str(); - inputArgs.InternalOptionsSize = (uint32_t)internalOptions.length(); + inputArgs.InternalOptionsSize = static_cast(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) { diff --git a/runtime/program/get_info.cpp b/runtime/program/get_info.cpp index f367b8fec7..aaf84bbe39 100644 --- a/runtime/program/get_info.cpp +++ b/runtime/program/get_info.cpp @@ -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) { diff --git a/runtime/program/link.cpp b/runtime/program/link.cpp index 50baeae286..9d61ff31bb 100644 --- a/runtime/program/link.cpp +++ b/runtime/program/link.cpp @@ -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 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(pInputProgObj->irBinarySize); - pElfWriter->addSection(§ionNode); + 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(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) { diff --git a/runtime/program/process_elf_binary.cpp b/runtime/program/process_elf_binary.cpp index 571033b3a3..7828a3b3aa 100644 --- a/runtime/program/process_elf_binary.cpp +++ b/runtime/program/process_elf_binary.cpp @@ -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(pBinary), reinterpret_cast(reinterpret_cast(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(§ionNode); - - 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(§ionNode); - } else { - sectionNode.Name = "Intel(R) OpenCL LLVM Object"; - sectionNode.pData = (char *)irBinary; - sectionNode.DataSize = (uint32_t)irBinarySize; - elfRetVal = pElfWriter->addSection(§ionNode); - } - } - - // 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(§ionNode); - } - - // 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(§ionNode); - } - - 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); + elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast(strlen(options.c_str()) + 1u))); + std::string irBinaryTemp = irBinary ? std::string(irBinary, irBinarySize) : ""; + // Add the LLVM component if available + 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(irBinarySize))); + // Add the device binary if it exists + 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(genBinarySize))); } + + // 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(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 diff --git a/runtime/program/program.cpp b/runtime/program/program.cpp index daff0b728e..2d2049f62c 100644 --- a/runtime/program/program.cpp +++ b/runtime/program/program.cpp @@ -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(irBinarySize); - pElfWriter->addSection(§ionNode); + 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(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(dataSize); + inputArgs.pInput = data.data(); + inputArgs.InputSize = static_cast(dataSize); inputArgs.pOptions = options.c_str(); - inputArgs.OptionsSize = static_cast(options.length()); + inputArgs.OptionsSize = static_cast(options.length()); inputArgs.pInternalOptions = internalOptions.c_str(); - inputArgs.InternalOptionsSize = static_cast(internalOptions.length()); + inputArgs.InternalOptionsSize = static_cast(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) { diff --git a/runtime/program/program.h b/runtime/program/program.h index ed3723393b..514107a3b7 100644 --- a/runtime/program/program.h +++ b/runtime/program/program.h @@ -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 @@ -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; diff --git a/unit_tests/elflib/elflib_tests.cpp b/unit_tests/elflib/elflib_tests.cpp index 2e0dff1cca..c4fc4329c6 100644 --- a/unit_tests/elflib/elflib_tests.cpp +++ b/unit_tests/elflib/elflib_tests.cpp @@ -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(§ionNode); - 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(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(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(E_EH_CLASS::EH_CLASS_64)); + EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxVersion] == static_cast(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(0)); + EXPECT_TRUE(elfHeader.ElfHeaderSize == static_cast(sizeof(SElf64Header))); + EXPECT_TRUE(elfHeader.SectionHeaderEntrySize == static_cast(sizeof(SElf64SectionHeader))); + EXPECT_TRUE(elfHeader.NumSectionHeaderEntries == 1); + EXPECT_TRUE(elfHeader.SectionHeadersOffset == static_cast(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(§ionNode); + 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(§ionNode); + 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); +} \ No newline at end of file diff --git a/unit_tests/offline_compiler/mock/mock_offline_compiler.h b/unit_tests/offline_compiler/mock/mock_offline_compiler.h index 2184d01e58..69e3f2a7d4 100644 --- a/unit_tests/offline_compiler/mock/mock_offline_compiler.h +++ b/unit_tests/offline_compiler/mock/mock_offline_compiler.h @@ -93,7 +93,7 @@ class MockOfflineCompiler : public OfflineCompiler { } char *getElfBinary() { - return elfBinary; + return elfBinary.data(); } size_t getElfBinarySize() { diff --git a/unit_tests/program/process_elf_binary_tests.cpp b/unit_tests/program/process_elf_binary_tests.cpp index afe61b415e..941ba46af3 100644 --- a/unit_tests/program/process_elf_binary_tests.cpp +++ b/unit_tests/program/process_elf_binary_tests.cpp @@ -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(elfBinary), elfBinarySize); + reinterpret_cast(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(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); }