mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-18 22:08:53 +08:00
Create L0 debugger object
Related-To: NEO-4713 Change-Id: I9d10019bbe6e8514ce10bdd729a64ea233bf91b0 Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
committed by
sys_ocldev
parent
3029db07c3
commit
68847ef942
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -1,5 +1,5 @@
|
||||
#!groovy
|
||||
dependenciesRevision='b32fd8b47e88a0f63acd0064d61dbff86e26af0b-1438'
|
||||
strategy='EQUAL'
|
||||
allowedCD=260
|
||||
allowedCD=261
|
||||
allowedF=27
|
||||
|
||||
@@ -322,6 +322,15 @@ function(generate_l0_lib LIB_NAME MOCKABLE)
|
||||
L0_SRCS_DEBUGGER
|
||||
L0_SRCS_OCLOC_SHARED
|
||||
)
|
||||
if(WIN32)
|
||||
append_sources_from_properties(L0_RUNTIME_SOURCES
|
||||
L0_SRCS_DEBUGGER_WINDOWS
|
||||
)
|
||||
else()
|
||||
append_sources_from_properties(L0_RUNTIME_SOURCES
|
||||
L0_SRCS_DEBUGGER_LINUX
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(${LIB_NAME} PRIVATE ${L0_RUNTIME_SOURCES})
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@ set(L0_SRCS_DEBUGGER
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debugger_l0.h
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY L0_SRCS_DEBUGGER ${L0_SRCS_DEBUGGER})
|
||||
add_subdirectories()
|
||||
set_property(GLOBAL PROPERTY L0_SRCS_DEBUGGER ${L0_SRCS_DEBUGGER})
|
||||
@@ -6,13 +6,27 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/debugger/debugger.h"
|
||||
#include "shared/source/helpers/non_copyable_or_moveable.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace NEO {
|
||||
class Device;
|
||||
}
|
||||
|
||||
namespace L0 {
|
||||
class DebuggerL0 : public NEO::Debugger {
|
||||
class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass {
|
||||
public:
|
||||
static std::unique_ptr<Debugger> create(NEO::Device *device);
|
||||
bool isDebuggerActive() override;
|
||||
|
||||
DebuggerL0(NEO::Device *device) : device(device) {
|
||||
isLegacyMode = false;
|
||||
}
|
||||
~DebuggerL0() override = default;
|
||||
|
||||
protected:
|
||||
NEO::Device *device = nullptr;
|
||||
};
|
||||
} // namespace L0
|
||||
13
level_zero/core/source/debugger/linux/CMakeLists.txt
Normal file
13
level_zero/core/source/debugger/linux/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(L0_SRCS_DEBUGGER_LINUX
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debugger_l0_linux.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debugger_l0_linux.h
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY L0_SRCS_DEBUGGER_LINUX ${L0_SRCS_DEBUGGER_LINUX})
|
||||
15
level_zero/core/source/debugger/linux/debugger_l0_linux.cpp
Normal file
15
level_zero/core/source/debugger/linux/debugger_l0_linux.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/core/source/debugger/linux/debugger_l0_linux.h"
|
||||
|
||||
namespace L0 {
|
||||
std::unique_ptr<NEO::Debugger> DebuggerL0::create(NEO::Device *device) {
|
||||
return std::make_unique<DebuggerL0Linux>(device);
|
||||
}
|
||||
|
||||
} // namespace L0
|
||||
18
level_zero/core/source/debugger/linux/debugger_l0_linux.h
Normal file
18
level_zero/core/source/debugger/linux/debugger_l0_linux.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "level_zero/core/source/debugger/debugger_l0.h"
|
||||
|
||||
namespace L0 {
|
||||
class DebuggerL0Linux : public DebuggerL0 {
|
||||
public:
|
||||
DebuggerL0Linux(NEO::Device *device) : DebuggerL0(device) {
|
||||
}
|
||||
~DebuggerL0Linux() override = default;
|
||||
};
|
||||
} // namespace L0
|
||||
14
level_zero/core/source/debugger/windows/CMakeLists.txt
Normal file
14
level_zero/core/source/debugger/windows/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(L0_SRCS_DEBUGGER_WINDOWS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/debugger_l0_windows.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set_property(GLOBAL PROPERTY L0_SRCS_DEBUGGER_WINDOWS ${L0_SRCS_DEBUGGER_WINDOWS})
|
||||
endif()
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/core/source/debugger/debugger_l0.h"
|
||||
|
||||
namespace L0 {
|
||||
std::unique_ptr<NEO::Debugger> DebuggerL0::create(NEO::Device *device) {
|
||||
return std::unique_ptr<NEO::Debugger>(nullptr);
|
||||
}
|
||||
} // namespace L0
|
||||
@@ -106,10 +106,8 @@ struct Device : _ze_device_handle_t {
|
||||
virtual NEO::PreemptionMode getDevicePreemptionMode() const = 0;
|
||||
virtual const NEO::DeviceInfo &getDeviceInfo() const = 0;
|
||||
virtual NEO::Device *getNEODevice() = 0;
|
||||
NEO::SourceLevelDebugger *getSourceLevelDebugger() { return getNEODevice()->getSourceLevelDebugger(); }
|
||||
|
||||
NEO::SourceLevelDebugger *getSourceLevelDebugger() {
|
||||
return getNEODevice() ? reinterpret_cast<NEO::SourceLevelDebugger *>(getNEODevice()->getDebugger()) : nullptr;
|
||||
}
|
||||
virtual NEO::GraphicsAllocation *getDebugSurface() const = 0;
|
||||
|
||||
virtual NEO::GraphicsAllocation *allocateManagedMemoryFromHostPtr(void *buffer,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "shared/source/os_interface/debug_env_reader.h"
|
||||
#include "shared/source/os_interface/os_library.h"
|
||||
|
||||
#include "level_zero/core/source/debugger/debugger_l0.h"
|
||||
#include "level_zero/core/source/device/device_imp.h"
|
||||
|
||||
#include "driver_version_l0.h"
|
||||
@@ -108,6 +109,10 @@ ze_result_t DriverHandleImp::getMemAllocProperties(const void *ptr,
|
||||
|
||||
DriverHandleImp::~DriverHandleImp() {
|
||||
for (auto &device : this->devices) {
|
||||
if (device->getNEODevice()->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->debugger.get() &&
|
||||
!device->getNEODevice()->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->debugger->isLegacy()) {
|
||||
device->getNEODevice()->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->debugger.reset(nullptr);
|
||||
}
|
||||
delete device;
|
||||
}
|
||||
if (this->svmAllocsManager) {
|
||||
@@ -149,6 +154,11 @@ ze_result_t DriverHandleImp::initialize(std::vector<std::unique_ptr<NEO::Device>
|
||||
}
|
||||
}
|
||||
|
||||
if (enableProgramDebugging) {
|
||||
UNRECOVERABLE_IF(neoDevice->getDebugger() != nullptr && enableProgramDebugging);
|
||||
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->debugger = DebuggerL0::create(neoDevice.get());
|
||||
}
|
||||
|
||||
auto device = Device::create(this, neoDevice.release(), currentDeviceMask, false);
|
||||
this->devices.push_back(device);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ set(L0_MOCKS_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_event.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_gmm_resource_info_l0.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_kernel.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_l0_debugger.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_memory_manager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_memory_manager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_module.cpp
|
||||
|
||||
21
level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h
Normal file
21
level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "level_zero/core/source/debugger/debugger_l0.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace ult {
|
||||
|
||||
class MockDebuggerL0 : public L0::DebuggerL0 {
|
||||
public:
|
||||
using L0::DebuggerL0::DebuggerL0;
|
||||
~MockDebuggerL0() override = default;
|
||||
};
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -7,6 +7,10 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/active_debugger_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_debugger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/l0_debugger_fixture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_source_level_debugger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_l0_debugger.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_module_with_debug.cpp
|
||||
)
|
||||
)
|
||||
|
||||
add_subdirectories()
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared/test/unit_test/helpers/debug_manager_state_restore.h"
|
||||
#include "shared/test/unit_test/mocks/mock_device.h"
|
||||
|
||||
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
|
||||
#include "level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace ult {
|
||||
|
||||
struct L0DebuggerFixture {
|
||||
void SetUp() {
|
||||
neoDevice = NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(NEO::defaultHwInfo.get());
|
||||
NEO::DeviceVector devices;
|
||||
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
|
||||
driverHandle = std::make_unique<Mock<L0::DriverHandleImp>>();
|
||||
driverHandle->enableProgramDebugging = true;
|
||||
|
||||
driverHandle->initialize(std::move(devices));
|
||||
device = driverHandle->devices[0];
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Mock<L0::DriverHandleImp>> driverHandle;
|
||||
NEO::MockDevice *neoDevice = nullptr;
|
||||
L0::Device *device = nullptr;
|
||||
};
|
||||
|
||||
struct MockL0DebuggerFixture : public L0DebuggerFixture {
|
||||
void SetUp() {
|
||||
L0DebuggerFixture::SetUp();
|
||||
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->debugger.reset(new MockDebuggerL0(neoDevice));
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
L0DebuggerFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
if(UNIX)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_l0_debugger_linux.cpp
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "level_zero/core/test/unit_tests/sources/debugger/l0_debugger_fixture.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace ult {
|
||||
|
||||
using L0DebuggerLinuxTest = Test<L0DebuggerFixture>;
|
||||
|
||||
TEST_F(L0DebuggerLinuxTest, givenProgramDebuggingEnabledWhenDriverHandleIsCreatedThenItAllocatesL0Debugger) {
|
||||
EXPECT_NE(nullptr, neoDevice->getDebugger());
|
||||
EXPECT_FALSE(neoDevice->getDebugger()->isLegacy());
|
||||
|
||||
EXPECT_EQ(nullptr, neoDevice->getSourceLevelDebugger());
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include "level_zero/core/test/unit_tests/sources/debugger/l0_debugger_fixture.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace ult {
|
||||
|
||||
using L0DebuggerTest = Test<MockL0DebuggerFixture>;
|
||||
|
||||
TEST_F(L0DebuggerTest, givenL0DebuggerWhenCallingIsLegacyThenFalseIsReturned) {
|
||||
EXPECT_FALSE(neoDevice->getDebugger()->isLegacy());
|
||||
}
|
||||
|
||||
TEST_F(L0DebuggerTest, givenL0DebuggerWhenGettingSourceLevelDebuggerThenNullptrReturned) {
|
||||
EXPECT_EQ(nullptr, neoDevice->getSourceLevelDebugger());
|
||||
}
|
||||
|
||||
TEST_F(L0DebuggerTest, givenL0DebuggerWhenCallingIsDebuggerActiveThenFalseIsReturned) {
|
||||
EXPECT_FALSE(neoDevice->getDebugger()->isDebuggerActive());
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -488,5 +488,9 @@ TEST_F(DeviceTest, givenBlitterSupportAndCopyOnlyFlagWhenCopyOnlyDebugFlagIsSetT
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, res);
|
||||
}
|
||||
|
||||
TEST_F(DeviceTest, givenNoActiveSourceLevelDebuggerWhenGetIsCalledThenNullptrIsReturned) {
|
||||
EXPECT_EQ(nullptr, device->getSourceLevelDebugger());
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -144,7 +144,7 @@ PerformanceCounters *ClDevice::getPerformanceCounters() { return device.getPerfo
|
||||
PreemptionMode ClDevice::getPreemptionMode() const { return device.getPreemptionMode(); }
|
||||
bool ClDevice::isDebuggerActive() const { return device.isDebuggerActive(); }
|
||||
Debugger *ClDevice::getDebugger() { return device.getDebugger(); }
|
||||
SourceLevelDebugger *ClDevice::getSourceLevelDebugger() { return reinterpret_cast<SourceLevelDebugger *>(device.getDebugger()); }
|
||||
SourceLevelDebugger *ClDevice::getSourceLevelDebugger() { return device.getSourceLevelDebugger(); }
|
||||
ExecutionEnvironment *ClDevice::getExecutionEnvironment() const { return device.getExecutionEnvironment(); }
|
||||
const RootDeviceEnvironment &ClDevice::getRootDeviceEnvironment() const { return device.getRootDeviceEnvironment(); }
|
||||
const HardwareCapabilities &ClDevice::getHardwareCapabilities() const { return device.getHardwareCapabilities(); }
|
||||
|
||||
@@ -43,6 +43,14 @@ class DebuggerLibraryRestorer {
|
||||
bool restoreAvailableState = false;
|
||||
};
|
||||
|
||||
TEST(SourceLevelDebugger, whenSourceLevelDebuggerIsCreatedThenLegacyModeIsTrue) {
|
||||
DebuggerLibraryRestorer restorer;
|
||||
DebuggerLibrary::setLibraryAvailable(true);
|
||||
|
||||
MockSourceLevelDebugger debugger;
|
||||
EXPECT_TRUE(debugger.isLegacy());
|
||||
}
|
||||
|
||||
TEST(SourceLevelDebugger, givenPlatformWhenItIsCreatedThenSourceLevelDebuggerIsCreatedInExecutionEnvironment) {
|
||||
DebuggerLibraryRestorer restorer;
|
||||
|
||||
@@ -521,6 +529,19 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenDeviceIsCreated
|
||||
EXPECT_FALSE(interceptor.newDeviceCalled);
|
||||
}
|
||||
|
||||
TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenGettingSourceLevelDebuggerThenNullptrIsReturned) {
|
||||
DebuggerLibraryRestorer restorer;
|
||||
|
||||
DebuggerLibraryInterceptor interceptor;
|
||||
DebuggerLibrary::setLibraryAvailable(true);
|
||||
DebuggerLibrary::setDebuggerActive(false);
|
||||
DebuggerLibrary::injectDebuggerLibraryInterceptor(&interceptor);
|
||||
|
||||
auto device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
|
||||
EXPECT_EQ(nullptr, device->getSourceLevelDebugger());
|
||||
}
|
||||
|
||||
TEST(SourceLevelDebugger, givenTwoRootDevicesWhenSecondIsCreatedThenCreatingNewSourceLevelDebugger) {
|
||||
DebuggerLibraryRestorer restorer;
|
||||
|
||||
|
||||
@@ -14,5 +14,9 @@ class Debugger {
|
||||
static std::unique_ptr<Debugger> create(HardwareInfo *hwInfo);
|
||||
virtual ~Debugger() = default;
|
||||
virtual bool isDebuggerActive() = 0;
|
||||
bool isLegacy() const { return isLegacyMode; }
|
||||
|
||||
protected:
|
||||
bool isLegacyMode = true;
|
||||
};
|
||||
} // namespace NEO
|
||||
@@ -245,4 +245,12 @@ uint64_t Device::getGlobalMemorySize() const {
|
||||
return globalMemorySize;
|
||||
}
|
||||
|
||||
NEO::SourceLevelDebugger *Device::getSourceLevelDebugger() {
|
||||
auto debugger = getDebugger();
|
||||
if (debugger) {
|
||||
return debugger->isLegacy() ? static_cast<NEO::SourceLevelDebugger *>(debugger) : nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "shared/source/debugger/debugger.h"
|
||||
#include "shared/source/device/device_info.h"
|
||||
#include "shared/source/execution_environment/execution_environment.h"
|
||||
#include "shared/source/execution_environment/root_device_environment.h"
|
||||
@@ -17,6 +18,7 @@
|
||||
|
||||
namespace NEO {
|
||||
class OSTime;
|
||||
class SourceLevelDebugger;
|
||||
|
||||
class Device : public ReferenceTrackedObject<Device> {
|
||||
public:
|
||||
@@ -58,6 +60,8 @@ class Device : public ReferenceTrackedObject<Device> {
|
||||
PreemptionMode getPreemptionMode() const { return preemptionMode; }
|
||||
MOCKABLE_VIRTUAL bool isDebuggerActive() const;
|
||||
Debugger *getDebugger() { return getRootDeviceEnvironment().debugger.get(); }
|
||||
NEO::SourceLevelDebugger *getSourceLevelDebugger();
|
||||
|
||||
ExecutionEnvironment *getExecutionEnvironment() const { return executionEnvironment; }
|
||||
const RootDeviceEnvironment &getRootDeviceEnvironment() const { return *executionEnvironment->rootDeviceEnvironments[getRootDeviceIndex()]; }
|
||||
const HardwareCapabilities &getHardwareCapabilities() const { return hardwareCapabilities; }
|
||||
|
||||
@@ -65,6 +65,7 @@ SourceLevelDebugger *SourceLevelDebugger::create() {
|
||||
}
|
||||
SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) {
|
||||
debuggerLibrary.reset(library);
|
||||
isLegacyMode = true;
|
||||
|
||||
if (debuggerLibrary.get() == nullptr) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user