diff --git a/opencl/source/kernel/kernel.cpp b/opencl/source/kernel/kernel.cpp index 96bc708f15ad8..93d70ec267d50 100644 --- a/opencl/source/kernel/kernel.cpp +++ b/opencl/source/kernel/kernel.cpp @@ -483,6 +483,11 @@ cl_int Kernel::getArgInfo(cl_uint argIndex, cl_kernel_arg_info paramName, size_t return retVal; } + program->callPopulateZebinExtendedArgsMetadataOnce(clDevice.getRootDeviceIndex()); + if (kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata.empty()) { + return CL_KERNEL_ARG_INFO_NOT_AVAILABLE; + } + const auto &argTraits = args[argIndex].getTraits(); const auto &argMetadata = kernelInfo.kernelDescriptor.explicitArgsExtendedMetadata[argIndex]; diff --git a/opencl/source/program/process_device_binary.cpp b/opencl/source/program/process_device_binary.cpp index 1cc1fb25165c0..5ebb7f5262137 100644 --- a/opencl/source/program/process_device_binary.cpp +++ b/opencl/source/program/process_device_binary.cpp @@ -6,6 +6,7 @@ */ #include "shared/source/device_binary_format/device_binary_formats.h" +#include "shared/source/device_binary_format/zebin_decoder.h" #include "shared/source/helpers/aligned_memory.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/ptr_math.h" @@ -248,6 +249,7 @@ cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) { buildInfos[rootDeviceIndex].globalVarTotalSize = 0u; } } + buildInfos[rootDeviceIndex].kernelMiscInfoPos = src.kernelMiscInfoPos; for (auto &kernelInfo : kernelInfoArray) { cl_int retVal = CL_SUCCESS; @@ -346,4 +348,21 @@ void Program::notifyDebuggerWithDebugData(ClDevice *clDevice) { } } } + +void Program::callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex) { + auto &buildInfo = this->buildInfos[rootDeviceIndex]; + auto extractAndDecodeMetadata = [&]() { + auto refBin = ArrayRef(reinterpret_cast(buildInfo.unpackedDeviceBinary.get()), buildInfo.unpackedDeviceBinarySize); + if (false == NEO::isDeviceBinaryFormat(refBin)) { + return; + } + std::string errors{}, warnings{}; + auto metadataString = extractZeInfoMetadataStringFromZebin(refBin, errors, warnings); + auto decodeError = decodeAndPopulateKernelMiscInfo(buildInfo.kernelMiscInfoPos, buildInfo.kernelInfoArray, metadataString, errors, warnings); + if (NEO::DecodeError::Success != decodeError) { + PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error in decodeAndPopulateKernelMiscInfo: %s\n", errors.c_str()); + } + }; + std::call_once(extractAndDecodeMetadataOnce, extractAndDecodeMetadata); +} } // namespace NEO diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index d6fe71b9f6869..b98eaccc0916f 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -290,6 +290,7 @@ class Program : public BaseObject<_cl_program> { void notifyDebuggerWithDebugData(ClDevice *clDevice); MOCKABLE_VIRTUAL void createDebugZebin(uint32_t rootDeviceIndex); Debug::Segments getZebinSegments(uint32_t rootDeviceIndex); + void callPopulateZebinExtendedArgsMetadataOnce(uint32_t rootDeviceIndex); protected: MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize, ClDevice &clDevice); @@ -356,6 +357,7 @@ class Program : public BaseObject<_cl_program> { std::unique_ptr debugData; size_t debugDataSize = 0U; + size_t kernelMiscInfoPos = std::string::npos; }; std::vector buildInfos; @@ -375,6 +377,8 @@ class Program : public BaseObject<_cl_program> { uint32_t maxRootDeviceIndex = std::numeric_limits::max(); std::mutex lockMutex; uint32_t exposedKernels = 0; + + std::once_flag extractAndDecodeMetadataOnce; }; } // namespace NEO diff --git a/opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp b/opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp index a09fc9c99f99f..14a5b8da8cad2 100644 --- a/opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp +++ b/opencl/test/unit_test/kernel/kernel_arg_info_tests.cpp @@ -8,6 +8,7 @@ #include "shared/test/common/fixtures/memory_management_fixture.h" #include "shared/test/common/helpers/kernel_binary_helper.h" #include "shared/test/common/test_macros/test.h" +#include #include "opencl/source/kernel/kernel.h" #include "opencl/test/unit_test/fixtures/cl_device_fixture.h" @@ -208,3 +209,168 @@ TEST_F(KernelArgInfoTest, GivenParamWhenGettingKernelArgNameThenCorrectValueIsRe EXPECT_EQ(0, strcmp(paramValue, expectedArgName)); delete[] paramValue; } + +TEST_F(KernelArgInfoTest, givenNonZebinBinaryAndNoExplicitArgsMetadataWhenQueryingArgsInfoThenReturnError) { + constexpr auto mockDeviceBinarySize = 0x10; + uint8_t mockDeviceBinary[mockDeviceBinarySize]{0}; + + auto &buildInfo = pProgram->buildInfos[rootDeviceIndex]; + buildInfo.unpackedDeviceBinary.reset(reinterpret_cast(mockDeviceBinary)); + buildInfo.unpackedDeviceBinarySize = mockDeviceBinarySize; + ASSERT_FALSE(NEO::isDeviceBinaryFormat(ArrayRef::fromAny(mockDeviceBinary, mockDeviceBinarySize))); + + auto &kernelDescriptor = const_cast(pKernel->getDescriptor()); + kernelDescriptor.explicitArgsExtendedMetadata.clear(); + ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty()); + + retVal = pKernel->getArgInfo( + 0, + CL_KERNEL_ARG_NAME, + 0, + nullptr, + 0); + + EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal); + buildInfo.unpackedDeviceBinary.release(); +} + +TEST_F(KernelArgInfoTest, givenZebinBinaryAndErrorOnRetrievingArgsMetadataFromKernelsMiscInfoWhenQueryingArgsInfoThenReturnError) { + ZebinTestData::ValidEmptyProgram zebin; + ASSERT_TRUE(isDeviceBinaryFormat(ArrayRef::fromAny(zebin.storage.data(), zebin.storage.size()))); + + auto &buildInfo = pProgram->buildInfos[rootDeviceIndex]; + buildInfo.unpackedDeviceBinary.reset(reinterpret_cast(zebin.storage.data())); + buildInfo.unpackedDeviceBinarySize = zebin.storage.size(); + ASSERT_EQ(std::string::npos, buildInfo.kernelMiscInfoPos); + + auto &kernelDescriptor = const_cast(pKernel->getDescriptor()); + kernelDescriptor.explicitArgsExtendedMetadata.clear(); + ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty()); + + retVal = pKernel->getArgInfo( + 0, + CL_KERNEL_ARG_NAME, + 0, + nullptr, + 0); + + EXPECT_EQ(CL_KERNEL_ARG_INFO_NOT_AVAILABLE, retVal); + buildInfo.unpackedDeviceBinary.release(); +} + +TEST_F(KernelArgInfoTest, givenZebinBinaryWithProperKernelsMiscInfoAndNoExplicitArgsMetadataWhenQueryingArgInfoThenRetrieveItFromKernelsMiscInfo) { + std::string zeInfo = R"===(' +kernels: + - name: CopyBuffer + execution_env: + simd_size: 32 + payload_arguments: + - arg_type: arg_bypointer + offset: 0 + size: 0 + arg_index: 0 + addrmode: stateful + addrspace: global + access_type: readwrite + - arg_type: arg_bypointer + offset: 32 + size: 8 + arg_index: 0 + addrmode: stateless + addrspace: global + access_type: readwrite + - arg_type: enqueued_local_size + offset: 40 + size: 12 +kernels_misc_info: + - name: CopyBuffer + args_info: + - index: 0 + name: a + address_qualifier: __global + access_qualifier: NONE + type_name: 'int*;8' + type_qualifiers: NONE +)==="; + std::vector storage; + MockElfEncoder<> elfEncoder; + auto &elfHeader = elfEncoder.getElfFileHeader(); + elfHeader.type = NEO::Elf::ET_ZEBIN_EXE; + elfHeader.machine = pProgram->getExecutionEnvironment().rootDeviceEnvironments[rootDeviceIndex]->getHardwareInfo()->platform.eProductFamily; + const uint8_t testKernelData[0x10] = {0u}; + + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "CopyBuffer", testKernelData); + elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo); + storage = elfEncoder.encode(); + elfHeader = *reinterpret_cast *>(storage.data()); + + auto &buildInfo = pProgram->buildInfos[rootDeviceIndex]; + + //set kernels_misc_info pos manually, as we are not invoking decodeZebin() or processProgramInfo() in this test + ProgramInfo programInfo; + setKernelMiscInfoPosition(zeInfo, programInfo); + buildInfo.kernelMiscInfoPos = programInfo.kernelMiscInfoPos; + buildInfo.unpackedDeviceBinary.reset(reinterpret_cast(storage.data())); + buildInfo.unpackedDeviceBinarySize = storage.size(); + + auto &kernelDescriptor = const_cast(pKernel->getDescriptor()); + kernelDescriptor.explicitArgsExtendedMetadata.clear(); + ASSERT_TRUE(kernelDescriptor.explicitArgsExtendedMetadata.empty()); + + std::array paramNames = { + CL_KERNEL_ARG_NAME, + CL_KERNEL_ARG_ADDRESS_QUALIFIER, + CL_KERNEL_ARG_ACCESS_QUALIFIER, + CL_KERNEL_ARG_TYPE_NAME, + CL_KERNEL_ARG_TYPE_QUALIFIER, + }; + cl_uint argInd = 0; + constexpr size_t maxParamValueSize{0x10}; + size_t paramValueSize = 0; + size_t paramValueSizeRet = 0; + + for (const auto ¶mName : paramNames) { + char paramValue[maxParamValueSize]{0}; + + retVal = pKernel->getArgInfo( + argInd, + paramName, + paramValueSize, + nullptr, + ¶mValueSizeRet); + EXPECT_NE(0u, paramValueSizeRet); + ASSERT_EQ(CL_SUCCESS, retVal); + + ASSERT_LT(paramValueSizeRet, maxParamValueSize); + paramValueSize = paramValueSizeRet; + + retVal = pKernel->getArgInfo( + argInd, + paramName, + paramValueSize, + paramValue, + nullptr); + ASSERT_EQ(CL_SUCCESS, retVal); + switch (paramName) { + case (CL_KERNEL_ARG_NAME): + EXPECT_EQ(0, strcmp(paramValue, "a")); + break; + case (CL_KERNEL_ARG_ADDRESS_QUALIFIER): + EXPECT_EQ(*(reinterpret_cast(paramValue)), static_cast(CL_KERNEL_ARG_ADDRESS_GLOBAL)); + break; + case (CL_KERNEL_ARG_ACCESS_QUALIFIER): + EXPECT_EQ(*(reinterpret_cast(paramValue)), static_cast(CL_KERNEL_ARG_ACCESS_NONE)); + break; + case (CL_KERNEL_ARG_TYPE_NAME): + EXPECT_EQ(0, strcmp(paramValue, "'int*;8'")); + break; + case (CL_KERNEL_ARG_TYPE_QUALIFIER): + EXPECT_EQ(*(reinterpret_cast(paramValue)), static_cast(CL_KERNEL_ARG_TYPE_NONE)); + break; + default: + ASSERT_TRUE(false); + break; + } + } + buildInfo.unpackedDeviceBinary.release(); +} \ No newline at end of file diff --git a/shared/source/device_binary_format/zebin_decoder.cpp b/shared/source/device_binary_format/zebin_decoder.cpp index 6e47a8e316397..328f0e81e8554 100644 --- a/shared/source/device_binary_format/zebin_decoder.cpp +++ b/shared/source/device_binary_format/zebin_decoder.cpp @@ -1609,12 +1609,12 @@ void populateKernelMiscInfo(KernelDescriptor &dst, KernelMiscArgInfos &kernelMis } } -NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning) { - if (std::string::npos == dst.kernelMiscInfoPos) { +NEO::DecodeError decodeAndPopulateKernelMiscInfo(size_t kernelMiscInfoOffset, std::vector &kernelInfos, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning) { + if (std::string::npos == kernelMiscInfoOffset) { outErrReason.append("DeviceBinaryFormat::Zebin : Position of " + Elf::ZebinKernelMetadata::Tags::kernelMiscInfo.str() + " not set - may be missing in zeInfo.\n"); return DecodeError::InvalidBinary; } - ConstStringRef kernelMiscInfoString(reinterpret_cast(metadataString.begin() + dst.kernelMiscInfoPos), metadataString.size() - dst.kernelMiscInfoPos); + ConstStringRef kernelMiscInfoString(reinterpret_cast(metadataString.begin() + kernelMiscInfoOffset), metadataString.size() - kernelMiscInfoOffset); NEO::KernelInfo *kernelInfo = nullptr; NEO::Yaml::YamlParser parser; @@ -1651,7 +1651,7 @@ NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRe return DecodeError::InvalidBinary; } for (auto &[kName, miscInfos] : kernelArgsMiscInfoVec) { - for (auto dstKernelInfo : dst.kernelInfos) { + for (auto dstKernelInfo : kernelInfos) { if (dstKernelInfo->kernelDescriptor.kernelMetadata.kernelName == kName) { kernelInfo = dstKernelInfo; break; @@ -1810,4 +1810,22 @@ NEO::DecodeError decodeZebin(ProgramInfo &dst, NEO::Elf::Elf &elf, std: return DecodeError::Success; } +template +ConstStringRef extractZeInfoMetadataString(const ArrayRef zebin, std::string &outErrReason, std::string &outWarning) { + auto decodedElf = NEO::Elf::decodeElf(zebin, outErrReason, outWarning); + for (const auto §ionHeader : decodedElf.sectionHeaders) { + if (sectionHeader.header->type == NEO::Elf::SHT_ZEBIN_ZEINFO) { + auto zeInfoData = sectionHeader.data; + return ConstStringRef{reinterpret_cast(zeInfoData.begin()), zeInfoData.size()}; + } + } + return ConstStringRef{}; +} + +ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef zebin, std::string &outErrReason, std::string &outWarning) { + return Elf::isElf(zebin) + ? extractZeInfoMetadataString(zebin, outErrReason, outWarning) + : extractZeInfoMetadataString(zebin, outErrReason, outWarning); +} + } // namespace NEO diff --git a/shared/source/device_binary_format/zebin_decoder.h b/shared/source/device_binary_format/zebin_decoder.h index 5369e62ed5caa..c79749e8add44 100644 --- a/shared/source/device_binary_format/zebin_decoder.h +++ b/shared/source/device_binary_format/zebin_decoder.h @@ -12,6 +12,7 @@ #include "shared/source/device_binary_format/elf/zebin_elf.h" #include "shared/source/device_binary_format/yaml/yaml_parser.h" #include "shared/source/kernel/kernel_descriptor.h" +#include "shared/source/program/kernel_info.h" #include "shared/source/utilities/stackvec.h" #include @@ -153,6 +154,8 @@ NEO::DecodeError readKernelMiscArgumentInfos(const NEO::Yaml::YamlParser &parser void populateKernelMiscInfo(KernelDescriptor &dst, KernelMiscArgInfos &kernelMiscArgInfosVec, std::string &outErrReason, std::string &outWarning); -NEO::DecodeError decodeAndPopulateKernelMiscInfo(ProgramInfo &dst, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning); +NEO::DecodeError decodeAndPopulateKernelMiscInfo(size_t kernelMiscInfoOffset, std::vector &kernelInfos, ConstStringRef metadataString, std::string &outErrReason, std::string &outWarning); + +ConstStringRef extractZeInfoMetadataStringFromZebin(const ArrayRef zebin, std::string &outErrReason, std::string &outWarning); } // namespace NEO diff --git a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp index 717fd58649773..58a7b5c39be3b 100644 --- a/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp +++ b/shared/test/unit_test/device_binary_format/zebin_decoder_tests.cpp @@ -583,7 +583,7 @@ version: '1.19' programInfo.kernelInfos.push_back(kernel2Info); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, zeInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, zeInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::Success, res); EXPECT_TRUE(outErrors.empty()); EXPECT_TRUE(outWarnings.empty()); @@ -648,7 +648,7 @@ TEST(DecodeKernelMiscInfo, givenUnrecognizedEntryInKernelsMiscInfoSectionWhenDec programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfoUnrecognized, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfoUnrecognized, outErrors, outWarnings); EXPECT_EQ(DecodeError::Success, res); EXPECT_TRUE(outErrors.empty()); @@ -678,7 +678,7 @@ TEST(DecodeKernelMiscInfo, givenUnrecognizedEntryInArgsInfoWhenDecodingKernelsMi programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::Success, res); EXPECT_TRUE(outErrors.empty()); @@ -715,7 +715,7 @@ TEST(DecodeKernelMiscInfo, givenKeysWithInvalidValuesInKernelsMiscInfoWhenDecodi programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); EXPECT_NE(std::string::npos, outErrors.find("DeviceBinaryFormat::Zebin::.ze_info : could not read name from : [-] in context of : kernels_misc_info\n")); @@ -751,7 +751,7 @@ TEST(DecodeKernelMiscInfo, givenKeysWithInvalidValuesInArgsInfoWhenDecodingKerne programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfoUnrecognizedArgInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); EXPECT_NE(std::string::npos, outErrors.find("DeviceBinaryFormat::Zebin::.ze_info : could not read address_qualifier from : [-] in context of : kernels_misc_info\n")); @@ -775,7 +775,7 @@ TEST(DecodeKernelMiscInfo, givenArgsInfoEntryWithMissingMembersWhenDecodingKerne programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfoEmptyArgsInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfoEmptyArgsInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::Success, res); EXPECT_TRUE(outErrors.empty()); std::array missingMembers = { @@ -801,7 +801,7 @@ TEST(DecodeKernelMiscInfo, whenDecodingKernelsMiscInfoSectionAndParsingErrorIsEn programInfo.kernelMiscInfoPos = 0u; std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); } @@ -821,7 +821,7 @@ TEST(DecodeKernelMiscInfo, givenKernelMiscInfoEntryWithMissingKernelNameWhenDeco programInfo.kernelMiscInfoPos = 0u; std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); auto expectedError{"DeviceBinaryFormat::Zebin : Error : Missing kernel name in kernels_misc_info section.\n"}; @@ -848,7 +848,7 @@ TEST(DecodeKernelMiscInfo, givenKernelMiscInfoEntryAndProgramInfoWihoutCorrespon programInfo.kernelInfos.push_back(kernelInfo); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, kernelMiscInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, kernelMiscInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); auto expectedError{"DeviceBinaryFormat::Zebin : Error : Cannot find kernel info for kernel some_kernel.\n"}; @@ -872,7 +872,7 @@ version: '1.19' setKernelMiscInfoPosition(zeInfo, programInfo); EXPECT_EQ(std::string::npos, programInfo.kernelMiscInfoPos); std::string outWarnings, outErrors; - auto res = decodeAndPopulateKernelMiscInfo(programInfo, zeInfo, outErrors, outWarnings); + auto res = decodeAndPopulateKernelMiscInfo(programInfo.kernelMiscInfoPos, programInfo.kernelInfos, zeInfo, outErrors, outWarnings); EXPECT_EQ(DecodeError::InvalidBinary, res); auto expectedError{"DeviceBinaryFormat::Zebin : Position of kernels_misc_info not set - may be missing in zeInfo.\n"}; @@ -6733,3 +6733,48 @@ TEST(ReadZeInfoInlineSamplers, GivenUnknownEntryThenPrintWarning) { EXPECT_FALSE(warnings.empty()); EXPECT_TRUE(errors.empty()) << errors; } + +TEST(ZeInfoMetadataExtractionFromElf, givenValidElfContainingZeInfoSectionWhenExtractingZeInfoMetadataStringThenProperMetadataIsReturnedForEachElfType) { + ConstStringRef zeInfoData{"mockZeInfoData\n"}; + constexpr auto mockSectionDataSize = 0x10; + uint8_t mockSectionData[mockSectionDataSize]{0}; + + NEO::Elf::ElfEncoder elfEncoder32B; + NEO::Elf::ElfEncoder elfEncoder64B; + + elfEncoder32B.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef::fromAny(zeInfoData.data(), zeInfoData.size())); + elfEncoder32B.appendSection(NEO::Elf::SHT_PROGBITS, "someOtherSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + auto encoded32BElf = elfEncoder32B.encode(); + + elfEncoder64B.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef::fromAny(zeInfoData.data(), zeInfoData.size())); + elfEncoder64B.appendSection(NEO::Elf::SHT_PROGBITS, "someOtherSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + auto encoded64BElf = elfEncoder64B.encode(); + + std::string outErrors{}, outWarnings{}; + auto zeInfoStr32B = extractZeInfoMetadataStringFromZebin(ArrayRef::fromAny(encoded32BElf.data(), encoded32BElf.size()), outErrors, outWarnings); + auto zeInfoStr64B = extractZeInfoMetadataStringFromZebin(ArrayRef::fromAny(encoded64BElf.data(), encoded64BElf.size()), outErrors, outWarnings); + EXPECT_STREQ(zeInfoStr32B.data(), zeInfoData.data()); + EXPECT_STREQ(zeInfoStr64B.data(), zeInfoData.data()); +} + +TEST(ZeInfoMetadataExtractionFromElf, givenValidElfNotContainingZeInfoSectionWhenExtractingZeInfoMetadataStringThenEmptyDataIsReturnedForEachElfType) { + constexpr auto mockSectionDataSize = 0x10; + uint8_t mockSectionData[mockSectionDataSize]{0}; + + NEO::Elf::ElfEncoder elfEncoder32B; + NEO::Elf::ElfEncoder elfEncoder64B; + + elfEncoder32B.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, "notZeInfoSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + elfEncoder32B.appendSection(NEO::Elf::SHT_PROGBITS, "alsoNotZeInfoSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + auto encoded32BElf = elfEncoder32B.encode(); + + elfEncoder64B.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, "notZeInfoSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + elfEncoder64B.appendSection(NEO::Elf::SHT_PROGBITS, "alsoNotZeInfoSection", ArrayRef::fromAny(mockSectionData, mockSectionDataSize)); + auto encoded64BElf = elfEncoder64B.encode(); + + std::string outErrors{}, outWarnings{}; + auto zeInfoStr32B = extractZeInfoMetadataStringFromZebin(ArrayRef::fromAny(encoded32BElf.data(), encoded32BElf.size()), outErrors, outWarnings); + auto zeInfoStr64B = extractZeInfoMetadataStringFromZebin(ArrayRef::fromAny(encoded64BElf.data(), encoded64BElf.size()), outErrors, outWarnings); + EXPECT_EQ(nullptr, zeInfoStr32B.data()); + EXPECT_EQ(nullptr, zeInfoStr64B.data()); +} \ No newline at end of file