/* * Copyright (c) 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"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #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" 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"; 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); NotifyNewDeviceFunction notifyNewDeviceFunc = nullptr; NotifySourceCodeFunction notifySourceCodeFunc = nullptr; GetDebuggerOptionFunction getDebuggerOptionFunc = nullptr; NotifyKernelDebugDataFunction notifyKernelDebugDataFunc = nullptr; InitFunction initFunc = nullptr; IsDebuggerActiveFunction isDebuggerActive = 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); 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)); } void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { if (isActive) { GfxDbgNewDeviceData newDevice; newDevice.version = IGFXDBG_CURRENT_VERSION; newDevice.dh = reinterpret_cast(static_cast(deviceHandle)); newDevice.udh = GfxDeviceHandle(0); sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice); } } void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *source, size_t sourceSize) const { if (isActive) { GfxDbgSourceCode sourceCode; char fileName[FILENAME_MAX] = ""; sourceCode.version = IGFXDBG_CURRENT_VERSION; sourceCode.hDevice = reinterpret_cast(static_cast(deviceHandle)); sourceCode.sourceCode = source; sourceCode.sourceCodeSize = static_cast(sourceSize); sourceCode.sourceName = &fileName[0]; sourceCode.sourceNameMaxLen = sizeof(fileName); sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode); } } bool SourceLevelDebugger::isOptimizationDisabled() const { if (isActive) { char value; GfxDbgOption option; option.version = IGFXDBG_CURRENT_VERSION; option.optionName = DBG_OPTION_IS_OPTIMIZATION_DISABLED; option.valueLen = sizeof(value); option.value = &value; int result = sourceLevelDebuggerInterface->getDebuggerOptionFunc(&option); if (result == 1) { if (option.value[0] == '1') { return true; } } } return false; } void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const { if (isActive) { GfxDbgKernelDebugData kernelDebugData; kernelDebugData.hDevice = reinterpret_cast(static_cast(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; sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData); } } void 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; } } } } // namespace OCLRT