summaryrefslogtreecommitdiffstats
path: root/Source/cmDebuggerThread.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/cmDebuggerThread.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/cmDebuggerThread.cxx')
-rw-r--r--Source/cmDebuggerThread.cxx150
1 files changed, 150 insertions, 0 deletions
diff --git a/Source/cmDebuggerThread.cxx b/Source/cmDebuggerThread.cxx
new file mode 100644
index 0000000..fd52f5a
--- /dev/null
+++ b/Source/cmDebuggerThread.cxx
@@ -0,0 +1,150 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmDebuggerThread.h"
+
+#include <cstdint>
+#include <utility>
+
+#include <cm3p/cppdap/optional.h>
+#include <cm3p/cppdap/types.h>
+
+#include "cmDebuggerStackFrame.h"
+#include "cmDebuggerVariables.h"
+#include "cmDebuggerVariablesHelper.h"
+#include "cmDebuggerVariablesManager.h"
+
+namespace cmDebugger {
+
+cmDebuggerThread::cmDebuggerThread(int64_t id, std::string name)
+ : Id(id)
+ , Name(std::move(name))
+ , VariablesManager(std::make_shared<cmDebuggerVariablesManager>())
+{
+}
+
+void cmDebuggerThread::PushStackFrame(cmMakefile* mf,
+ std::string const& sourcePath,
+ cmListFileFunction const& lff)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ Frames.emplace_back(
+ std::make_shared<cmDebuggerStackFrame>(mf, sourcePath, lff));
+ FrameMap.insert({ Frames.back()->GetId(), Frames.back() });
+}
+
+void cmDebuggerThread::PopStackFrame()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ FrameMap.erase(Frames.back()->GetId());
+ FrameScopes.erase(Frames.back()->GetId());
+ FrameVariables.erase(Frames.back()->GetId());
+ Frames.pop_back();
+}
+
+std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetTopStackFrame()
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ if (!Frames.empty()) {
+ return Frames.back();
+ }
+
+ return {};
+}
+
+std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetStackFrame(
+ int64_t frameId)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ auto it = FrameMap.find(frameId);
+
+ if (it == FrameMap.end()) {
+ return {};
+ }
+
+ return it->second;
+}
+
+dap::ScopesResponse cmDebuggerThread::GetScopesResponse(
+ int64_t frameId, bool supportsVariableType)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ auto it = FrameScopes.find(frameId);
+
+ if (it != FrameScopes.end()) {
+ dap::ScopesResponse response;
+ response.scopes = it->second;
+ return response;
+ }
+
+ auto it2 = FrameMap.find(frameId);
+ if (it2 == FrameMap.end()) {
+ return dap::ScopesResponse();
+ }
+
+ std::shared_ptr<cmDebuggerStackFrame> frame = it2->second;
+ std::shared_ptr<cmDebuggerVariables> localVariables =
+ cmDebuggerVariablesHelper::Create(VariablesManager, "Locals",
+ supportsVariableType, frame);
+
+ FrameVariables[frameId].emplace_back(localVariables);
+
+ dap::Scope scope;
+ scope.name = localVariables->GetName();
+ scope.presentationHint = "locals";
+ scope.variablesReference = localVariables->GetId();
+
+ dap::Source source;
+ source.name = frame->GetFileName();
+ source.path = source.name;
+ scope.source = source;
+
+ FrameScopes[frameId].push_back(scope);
+
+ dap::ScopesResponse response;
+ response.scopes.push_back(scope);
+ return response;
+}
+
+dap::VariablesResponse cmDebuggerThread::GetVariablesResponse(
+ dap::VariablesRequest const& request)
+{
+ std::unique_lock<std::mutex> lock(Mutex);
+ dap::VariablesResponse response;
+ response.variables = VariablesManager->HandleVariablesRequest(request);
+ return response;
+}
+
+dap::StackTraceResponse GetStackTraceResponse(
+ std::shared_ptr<cmDebuggerThread> const& thread)
+{
+ dap::StackTraceResponse response;
+ std::unique_lock<std::mutex> lock(thread->Mutex);
+ for (int i = static_cast<int>(thread->Frames.size()) - 1; i >= 0; --i) {
+ dap::Source source;
+ source.name = thread->Frames[i]->GetFileName();
+ source.path = source.name;
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+ dap::StackFrame stackFrame;
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+ stackFrame.line = thread->Frames[i]->GetLine();
+ stackFrame.column = 1;
+ stackFrame.name = thread->Frames[i]->GetFileName() + " Line " +
+ std::to_string(stackFrame.line);
+ stackFrame.id = thread->Frames[i]->GetId();
+ stackFrame.source = source;
+
+ response.stackFrames.push_back(stackFrame);
+ }
+
+ response.totalFrames = response.stackFrames.size();
+ return response;
+}
+
+} // namespace cmDebugger