/* * Copyright (C) 2018 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "igfx_debug_interchange_types.h" #include "runtime/helpers/debug_helpers.h" #include "runtime/program/kernel_info.h" #include "runtime/source_level_debugger/source_level_debugger.h" #include "runtime/os_interface/os_interface.h" #include "lib_names.h" namespace OCLRT { const char *SourceLevelDebugger::notifyNewDeviceSymbol = "notifyNewDevice"; const char *SourceLevelDebugger::notifySourceCodeSymbol = "notifySourceCode"; const char *SourceLevelDebugger::getDebuggerOptionSymbol = "getDebuggerOption"; const char *SourceLevelDebugger::notifyKernelDebugDataSymbol = "notifyKernelDebugData"; const char *SourceLevelDebugger::initSymbol = "init"; const char *SourceLevelDebugger::isDebuggerActiveSymbol = "isDebuggerActive"; const char *SourceLevelDebugger::notifyDeviceDestructionSymbol = "notifyDeviceDestruction"; const char *SourceLevelDebugger::dllName = SLD_LIBRARY_NAME; class SourceLevelDebugger::SourceLevelDebuggerInterface { public: SourceLevelDebuggerInterface() = default; ~SourceLevelDebuggerInterface() = default; typedef int (*NotifyNewDeviceFunction)(GfxDbgNewDeviceData *data); typedef int (*NotifySourceCodeFunction)(GfxDbgSourceCode *data); typedef int (*GetDebuggerOptionFunction)(GfxDbgOption *); typedef int (*NotifyKernelDebugDataFunction)(GfxDbgKernelDebugData *data); typedef int (*InitFunction)(GfxDbgTargetCaps *data); typedef int (*IsDebuggerActiveFunction)(void); typedef int (*NotifyDeviceDestructionFunction)(GfxDbgDeviceDestructionData *data); NotifyNewDeviceFunction notifyNewDeviceFunc = nullptr; NotifySourceCodeFunction notifySourceCodeFunc = nullptr; GetDebuggerOptionFunction getDebuggerOptionFunc = nullptr; NotifyKernelDebugDataFunction notifyKernelDebugDataFunc = nullptr; InitFunction initFunc = nullptr; IsDebuggerActiveFunction isDebuggerActive = nullptr; NotifyDeviceDestructionFunction notifyDeviceDestructionFunc = nullptr; }; SourceLevelDebugger *SourceLevelDebugger::create() { auto library = SourceLevelDebugger::loadDebugger(); if (library) { auto isActiveFunc = reinterpret_cast(library->getProcAddress(isDebuggerActiveSymbol)); int result = isActiveFunc(); if (result == 1) { // pass library ownership to Source Level Debugger return new SourceLevelDebugger(library); } delete library; } return nullptr; } SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) { debuggerLibrary.reset(library); if (debuggerLibrary.get() == nullptr) { return; } sourceLevelDebuggerInterface = new SourceLevelDebuggerInterface; getFunctions(); if (sourceLevelDebuggerInterface->isDebuggerActive == nullptr) { return; } int result = sourceLevelDebuggerInterface->isDebuggerActive(); if (result == 1) { UNRECOVERABLE_IF(sourceLevelDebuggerInterface->getDebuggerOptionFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->initFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyKernelDebugDataFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyNewDeviceFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifySourceCodeFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyDeviceDestructionFunc == nullptr); isActive = true; } } SourceLevelDebugger::~SourceLevelDebugger() { if (sourceLevelDebuggerInterface) { delete sourceLevelDebuggerInterface; } } bool SourceLevelDebugger::isDebuggerActive() { return isActive; } void SourceLevelDebugger::getFunctions() { UNRECOVERABLE_IF(debuggerLibrary.get() == nullptr); sourceLevelDebuggerInterface->notifyNewDeviceFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyNewDeviceSymbol)); sourceLevelDebuggerInterface->notifySourceCodeFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifySourceCodeSymbol)); sourceLevelDebuggerInterface->getDebuggerOptionFunc = reinterpret_cast(debuggerLibrary->getProcAddress(getDebuggerOptionSymbol)); sourceLevelDebuggerInterface->notifyKernelDebugDataFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyKernelDebugDataSymbol)); sourceLevelDebuggerInterface->initFunc = reinterpret_cast(debuggerLibrary->getProcAddress(initSymbol)); sourceLevelDebuggerInterface->isDebuggerActive = reinterpret_cast(debuggerLibrary->getProcAddress(isDebuggerActiveSymbol)); sourceLevelDebuggerInterface->notifyDeviceDestructionFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyDeviceDestructionSymbol)); } bool SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) { if (isActive) { GfxDbgNewDeviceData newDevice; newDevice.version = IGFXDBG_CURRENT_VERSION; newDevice.dh = reinterpret_cast(static_cast(deviceHandle)); newDevice.udh = GfxDeviceHandle(0); int result = sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice); DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); static_cast(result); this->deviceHandle = deviceHandle; } return false; } bool SourceLevelDebugger::notifyDeviceDestruction() { if (isActive) { GfxDbgDeviceDestructionData deviceDestruction; deviceDestruction.version = IGFXDBG_CURRENT_VERSION; deviceDestruction.dh = reinterpret_cast(static_cast(this->deviceHandle)); int result = sourceLevelDebuggerInterface->notifyDeviceDestructionFunc(&deviceDestruction); DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); static_cast(result); this->deviceHandle = 0; return true; } return false; } bool SourceLevelDebugger::notifySourceCode(const char *source, size_t sourceSize, std::string &file) const { if (isActive) { GfxDbgSourceCode sourceCode; char fileName[FILENAME_MAX] = ""; sourceCode.version = IGFXDBG_CURRENT_VERSION; sourceCode.hDevice = reinterpret_cast(static_cast(this->deviceHandle)); sourceCode.sourceCode = source; sourceCode.sourceCodeSize = static_cast(sourceSize); sourceCode.sourceName = &fileName[0]; sourceCode.sourceNameMaxLen = sizeof(fileName); int result = sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode); DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); static_cast(result); file = fileName; } return false; } bool SourceLevelDebugger::isOptimizationDisabled() const { if (isActive) { const size_t optionValueSize = 4; char value[optionValueSize] = {0}; GfxDbgOption option; option.version = IGFXDBG_CURRENT_VERSION; option.optionName = DBG_OPTION_IS_OPTIMIZATION_DISABLED; option.valueLen = sizeof(value); option.value = &value[0]; int result = sourceLevelDebuggerInterface->getDebuggerOptionFunc(&option); if (result == 1) { if (option.value[0] == '1') { return true; } } } return false; } bool SourceLevelDebugger::notifyKernelDebugData(const KernelInfo *kernelInfo) const { if (isActive) { GfxDbgKernelDebugData kernelDebugData; kernelDebugData.hDevice = reinterpret_cast(static_cast(this->deviceHandle)); kernelDebugData.version = IGFXDBG_CURRENT_VERSION; kernelDebugData.hProgram = reinterpret_cast(0); kernelDebugData.kernelName = kernelInfo->name.c_str(); kernelDebugData.kernelBinBuffer = const_cast(kernelInfo->heapInfo.pKernelHeap); kernelDebugData.KernelBinSize = kernelInfo->heapInfo.pKernelHeader->KernelHeapSize; kernelDebugData.dbgVisaBuffer = kernelInfo->debugData.vIsa; kernelDebugData.dbgVisaSize = kernelInfo->debugData.vIsaSize; kernelDebugData.dbgGenIsaBuffer = kernelInfo->debugData.genIsa; kernelDebugData.dbgGenIsaSize = kernelInfo->debugData.genIsaSize; int result = sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData); DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); static_cast(result); } return false; } bool SourceLevelDebugger::initialize(bool useLocalMemory) { if (isActive) { GfxDbgTargetCaps caps = {IGFXDBG_CURRENT_VERSION, useLocalMemory}; int result = sourceLevelDebuggerInterface->initFunc(&caps); if (static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS) { isActive = false; } } return false; } } // namespace OCLRT