summaryrefslogtreecommitdiffstats
path: root/Source/cmDebuggerExceptionManager.cxx
diff options
context:
space:
mode:
authorGlen Chung <kuchung@microsoft.com>2023-03-16 00:50:08 (GMT)
committerBrad King <brad.king@kitware.com>2023-05-30 13:46:12 (GMT)
commita9a592f96e6498da302f8e968be1db0ad3c32123 (patch)
tree0d75f16ee2eae99b1a3f063e575b3f5f8f2ee931 /Source/cmDebuggerExceptionManager.cxx
parentb0d1ddb7234950374977b83f8dbded806c15b356 (diff)
downloadCMake-a9a592f96e6498da302f8e968be1db0ad3c32123.zip
CMake-a9a592f96e6498da302f8e968be1db0ad3c32123.tar.gz
CMake-a9a592f96e6498da302f8e968be1db0ad3c32123.tar.bz2
cmake: Add debugger
- Depends on cppdap and jsoncpp. - Add --debugger argument to enable the Debugger. - Add --debugger-pipe argument for DAP traffics over named pipes. - Support breakpoints by filenames and line numbers. - Support exception breakpoints. - Call stack shows filenames and line numbers. - Show Cache Variables. - Show the state of currently defined targets, tests and directories with their properties. - Add cmakeVersion to DAP initialize response. - Include unit tests. Co-authored-by: Ben McMorran <bemcmorr@microsoft.com>
Diffstat (limited to 'Source/cmDebuggerExceptionManager.cxx')
-rw-r--r--Source/cmDebuggerExceptionManager.cxx129
1 files changed, 129 insertions, 0 deletions
diff --git a/Source/cmDebuggerExceptionManager.cxx b/Source/cmDebuggerExceptionManager.cxx
new file mode 100644
index 0000000..a27426c
--- /dev/null
+++ b/Source/cmDebuggerExceptionManager.cxx
@@ -0,0 +1,129 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmDebuggerExceptionManager.h"
+
+#include <utility>
+#include <vector>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/session.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerProtocol.h"
+#include "cmMessageType.h"
+
+namespace cmDebugger {
+
+cmDebuggerExceptionManager::cmDebuggerExceptionManager(
+ dap::Session* dapSession)
+ : DapSession(dapSession)
+{
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetExceptionBreakpoints
+ DapSession->registerHandler(
+ [&](const dap::SetExceptionBreakpointsRequest& request) {
+ return HandleSetExceptionBreakpointsRequest(request);
+ });
+
+ // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo
+ DapSession->registerHandler([&](const dap::ExceptionInfoRequest& request) {
+ (void)request;
+ return HandleExceptionInfoRequest();
+ });
+
+ ExceptionMap[MessageType::AUTHOR_WARNING] =
+ cmDebuggerExceptionFilter{ "AUTHOR_WARNING", "Warning (dev)" };
+ ExceptionMap[MessageType::AUTHOR_ERROR] =
+ cmDebuggerExceptionFilter{ "AUTHOR_ERROR", "Error (dev)" };
+ ExceptionMap[MessageType::FATAL_ERROR] =
+ cmDebuggerExceptionFilter{ "FATAL_ERROR", "Fatal error" };
+ ExceptionMap[MessageType::INTERNAL_ERROR] =
+ cmDebuggerExceptionFilter{ "INTERNAL_ERROR", "Internal error" };
+ ExceptionMap[MessageType::MESSAGE] =
+ cmDebuggerExceptionFilter{ "MESSAGE", "Other messages" };
+ ExceptionMap[MessageType::WARNING] =
+ cmDebuggerExceptionFilter{ "WARNING", "Warning" };
+ ExceptionMap[MessageType::LOG] =
+ cmDebuggerExceptionFilter{ "LOG", "Debug log" };
+ ExceptionMap[MessageType::DEPRECATION_ERROR] =
+ cmDebuggerExceptionFilter{ "DEPRECATION_ERROR", "Deprecation error" };
+ ExceptionMap[MessageType::DEPRECATION_WARNING] =
+ cmDebuggerExceptionFilter{ "DEPRECATION_WARNING", "Deprecation warning" };
+ RaiseExceptions["AUTHOR_ERROR"] = true;
+ RaiseExceptions["FATAL_ERROR"] = true;
+ RaiseExceptions["INTERNAL_ERROR"] = true;
+ RaiseExceptions["DEPRECATION_ERROR"] = true;
+}
+
+dap::SetExceptionBreakpointsResponse
+cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest(
+ dap::SetExceptionBreakpointsRequest const& request)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ dap::SetExceptionBreakpointsResponse response;
+ RaiseExceptions.clear();
+ for (const auto& filter : request.filters) {
+ RaiseExceptions[filter] = true;
+ }
+
+ return response;
+}
+
+dap::ExceptionInfoResponse
+cmDebuggerExceptionManager::HandleExceptionInfoRequest()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+
+ dap::ExceptionInfoResponse response;
+ if (TheException.has_value()) {
+ response.exceptionId = TheException->Id;
+ response.breakMode = "always";
+ response.description = TheException->Description;
+ TheException = {};
+ }
+ return response;
+}
+
+void cmDebuggerExceptionManager::HandleInitializeRequest(
+ dap::CMakeInitializeResponse& response)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ response.supportsExceptionInfoRequest = true;
+
+ dap::array<dap::ExceptionBreakpointsFilter> exceptionBreakpointFilters;
+ for (auto& pair : ExceptionMap) {
+ dap::ExceptionBreakpointsFilter filter;
+ filter.filter = pair.second.Filter;
+ filter.label = pair.second.Label;
+ filter.def = RaiseExceptions[filter.filter];
+ exceptionBreakpointFilters.emplace_back(filter);
+ }
+
+ response.exceptionBreakpointFilters = exceptionBreakpointFilters;
+}
+
+cm::optional<dap::StoppedEvent>
+cmDebuggerExceptionManager::RaiseExceptionIfAny(MessageType t,
+ std::string const& text)
+{
+ cm::optional<dap::StoppedEvent> maybeStoppedEvent;
+ std::unique_lock<std::mutex> lock(Mutex);
+ if (RaiseExceptions[ExceptionMap[t].Filter]) {
+ dap::StoppedEvent stoppedEvent;
+ stoppedEvent.allThreadsStopped = true;
+ stoppedEvent.reason = "exception";
+ stoppedEvent.description = "Pause on exception";
+ stoppedEvent.text = text;
+ TheException = cmDebuggerException{ ExceptionMap[t].Filter, text };
+ maybeStoppedEvent = std::move(stoppedEvent);
+ }
+
+ return maybeStoppedEvent;
+}
+
+void cmDebuggerExceptionManager::ClearAll()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ RaiseExceptions.clear();
+}
+
+} // namespace cmDebugger