diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 0593cb87f4..5403c3af09 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -26,6 +26,7 @@ #include "shared/source/helpers/api_specific_config.h" #include "shared/source/helpers/compiler_product_helper.h" #include "shared/source/helpers/constants.h" +#include "shared/source/helpers/file_io.h" #include "shared/source/helpers/gfx_core_helper.h" #include "shared/source/helpers/hw_info.h" #include "shared/source/helpers/kernel_helpers.h" @@ -46,10 +47,10 @@ #include "program_debug_data.h" +#include #include #include #include - namespace L0 { namespace BuildOptions { @@ -1315,6 +1316,19 @@ void ModuleImp::registerElfInDebuggerL0() { debugData.vIsaSize = static_cast(translationUnit->debugDataSize); this->debugElfHandle = debuggerL0->registerElf(&debugData); + if (NEO::DebugManager.flags.DebuggerLogBitmask.get() & NEO::DebugVariables::DEBUGGER_LOG_BITMASK::DUMP_ELF) { + std::ofstream elfFile; + std::string name = "dumped_module"; + std::string fileName = name + ".elf"; + + int suffix = 0; + while (fileExists(fileName)) { + fileName = name + "_" + std::to_string(suffix) + ".elf"; + suffix++; + } + writeDataToFile(fileName.c_str(), debugData.vIsa, debugData.vIsaSize); + } + StackVec segmentAllocs; for (auto &kernImmData : kernelImmDatas) { segmentAllocs.push_back(kernImmData->getIsaGraphicsAllocation()); diff --git a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp index 901e728112..5458d2f81f 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp @@ -7,6 +7,7 @@ #include "shared/source/compiler_interface/external_functions.h" #include "shared/source/device_binary_format/patchtokens_decoder.h" +#include "shared/source/helpers/file_io.h" #include "shared/source/kernel/kernel_descriptor_from_patchtokens.h" #include "shared/source/os_interface/os_interface.h" #include "shared/source/program/kernel_info.h" @@ -710,6 +711,51 @@ HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenZebinDebugDataWhenInitializingMo EXPECT_EQ(1u, getMockDebuggerL0Hw()->notifyModuleCreateCount); } +HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenDumpElfFlagAndZebinWhenInitializingModuleThenDebugElfIsDumpedToFile) { + DebugManagerStateRestore stateRestore; + DebugManager.flags.DebuggerLogBitmask.set(NEO::DebugVariables::DEBUGGER_LOG_BITMASK::DUMP_ELF); + + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + + std::unique_ptr moduleMock = std::make_unique(device, nullptr, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = std::make_unique(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + kernelInfo->kernelDescriptor.kernelMetadata.kernelName = ZebinTestData::ValidEmptyProgram<>::kernelName; + + auto kernelImmutableData = ::std::make_unique(device); + kernelImmutableData->initialize(kernelInfo.get(), device, 0, nullptr, nullptr, false); + moduleMock->kernelImmDatas.push_back(std::move(kernelImmutableData)); + + kernelImmutableData = ::std::make_unique(device); + kernelImmutableData->initialize(kernelInfo.get(), device, 0, nullptr, nullptr, false); + moduleMock->kernelImmDatas.push_back(std::move(kernelImmutableData)); + + auto zebin = ZebinTestData::ValidEmptyProgram<>(); + + moduleMock->translationUnit->unpackedDeviceBinarySize = zebin.storage.size(); + moduleMock->translationUnit->unpackedDeviceBinary.reset(new char[zebin.storage.size()]); + memcpy_s(moduleMock->translationUnit->unpackedDeviceBinary.get(), moduleMock->translationUnit->unpackedDeviceBinarySize, + zebin.storage.data(), zebin.storage.size()); + + std::string fileName = "dumped_module.elf"; + EXPECT_FALSE(fileExists(fileName)); + + EXPECT_EQ(moduleMock->initialize(&moduleDesc, neoDevice), ZE_RESULT_SUCCESS); + EXPECT_TRUE(fileExists(fileName)); + std::remove(fileName.c_str()); +} + HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenZebinNoDebugDataWhenInitializingModuleThenDoNotRegisterElfAndDoNotNotifyModuleCreate) { auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();