Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmDebuggerThread.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
4
#include "cmDebuggerThread.h"
5
6
#include <cstdint>
7
#include <utility>
8
9
#include <cm3p/cppdap/optional.h>
10
#include <cm3p/cppdap/types.h>
11
12
#include "cmDebuggerStackFrame.h"
13
#include "cmDebuggerVariables.h"
14
#include "cmDebuggerVariablesHelper.h"
15
#include "cmDebuggerVariablesManager.h"
16
#include "cmListFileCache.h"
17
#include "cmStringAlgorithms.h"
18
19
namespace cmDebugger {
20
21
cmDebuggerThread::cmDebuggerThread(int64_t id, std::string name)
22
0
  : Id(id)
23
0
  , Name(std::move(name))
24
0
  , VariablesManager(std::make_shared<cmDebuggerVariablesManager>())
25
0
{
26
0
}
27
28
void cmDebuggerThread::PushStackFrame(cmMakefile* mf,
29
                                      std::string const& sourcePath,
30
                                      cmListFileFunction const& lff)
31
0
{
32
0
  std::unique_lock<std::mutex> lock(Mutex);
33
0
  Frames.emplace_back(
34
0
    std::make_shared<cmDebuggerStackFrame>(mf, sourcePath, lff));
35
0
  FrameMap.insert({ Frames.back()->GetId(), Frames.back() });
36
0
}
37
38
void cmDebuggerThread::PopStackFrame()
39
0
{
40
0
  std::unique_lock<std::mutex> lock(Mutex);
41
0
  FrameMap.erase(Frames.back()->GetId());
42
0
  FrameScopes.erase(Frames.back()->GetId());
43
0
  FrameVariables.erase(Frames.back()->GetId());
44
0
  Frames.pop_back();
45
0
}
46
47
std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetTopStackFrame()
48
0
{
49
0
  std::unique_lock<std::mutex> lock(Mutex);
50
0
  if (!Frames.empty()) {
51
0
    return Frames.back();
52
0
  }
53
54
0
  return {};
55
0
}
56
57
std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetStackFrame(
58
  int64_t frameId)
59
0
{
60
0
  std::unique_lock<std::mutex> lock(Mutex);
61
0
  auto it = FrameMap.find(frameId);
62
63
0
  if (it == FrameMap.end()) {
64
0
    return {};
65
0
  }
66
67
0
  return it->second;
68
0
}
69
70
dap::ScopesResponse cmDebuggerThread::GetScopesResponse(
71
  int64_t frameId, bool supportsVariableType)
72
0
{
73
0
  std::unique_lock<std::mutex> lock(Mutex);
74
0
  auto it = FrameScopes.find(frameId);
75
76
0
  if (it != FrameScopes.end()) {
77
0
    dap::ScopesResponse response;
78
0
    response.scopes = it->second;
79
0
    return response;
80
0
  }
81
82
0
  auto it2 = FrameMap.find(frameId);
83
0
  if (it2 == FrameMap.end()) {
84
0
    return dap::ScopesResponse();
85
0
  }
86
87
0
  std::shared_ptr<cmDebuggerStackFrame> frame = it2->second;
88
0
  std::shared_ptr<cmDebuggerVariables> localVariables =
89
0
    cmDebuggerVariablesHelper::Create(VariablesManager, "Locals",
90
0
                                      supportsVariableType, frame);
91
92
0
  FrameVariables[frameId].emplace_back(localVariables);
93
94
0
  dap::Scope scope;
95
0
  scope.name = localVariables->GetName();
96
0
  scope.presentationHint = "locals";
97
0
  scope.variablesReference = localVariables->GetId();
98
99
0
  dap::Source source;
100
0
  source.name = frame->GetFileName();
101
0
  source.path = source.name;
102
0
  scope.source = source;
103
104
0
  FrameScopes[frameId].push_back(scope);
105
106
0
  dap::ScopesResponse response;
107
0
  response.scopes.push_back(scope);
108
0
  return response;
109
0
}
110
111
dap::VariablesResponse cmDebuggerThread::GetVariablesResponse(
112
  dap::VariablesRequest const& request)
113
0
{
114
0
  std::unique_lock<std::mutex> lock(Mutex);
115
0
  dap::VariablesResponse response;
116
0
  response.variables = VariablesManager->HandleVariablesRequest(request);
117
0
  return response;
118
0
}
119
120
dap::StackTraceResponse GetStackTraceResponse(
121
  std::shared_ptr<cmDebuggerThread> const& thread,
122
  dap::optional<dap::StackFrameFormat> format)
123
0
{
124
0
  dap::boolean showParameters = false;
125
0
  dap::boolean showParameterValues = false;
126
0
  dap::boolean showLine = false;
127
0
  if (format.has_value()) {
128
0
    auto formatValue = format.value();
129
0
    if (formatValue.parameters.has_value()) {
130
0
      showParameters = formatValue.parameters.value();
131
0
    }
132
133
0
    if (formatValue.parameterValues.has_value()) {
134
0
      showParameterValues = formatValue.parameterValues.value();
135
0
    }
136
137
0
    if (formatValue.line.has_value()) {
138
0
      showLine = formatValue.line.value();
139
0
    }
140
0
  }
141
142
0
  dap::StackTraceResponse response;
143
0
  std::unique_lock<std::mutex> lock(thread->Mutex);
144
0
  for (int i = static_cast<int>(thread->Frames.size()) - 1; i >= 0; --i) {
145
0
    dap::Source source;
146
0
    source.name = thread->Frames[i]->GetFileName();
147
0
    source.path = source.name;
148
149
0
#ifdef __GNUC__
150
0
#  pragma GCC diagnostic push
151
0
#  pragma GCC diagnostic ignored "-Warray-bounds"
152
0
#endif
153
0
    dap::StackFrame stackFrame;
154
0
#ifdef __GNUC__
155
0
#  pragma GCC diagnostic pop
156
0
#endif
157
0
    stackFrame.line = thread->Frames[i]->GetLine();
158
0
    stackFrame.column = 1;
159
0
    stackFrame.id = thread->Frames[i]->GetId();
160
0
    stackFrame.source = source;
161
162
0
    auto stackName = thread->Frames[i]->GetFunction().OriginalName();
163
0
    if (showParameters) {
164
0
      stackName.push_back('(');
165
0
      if (showParameterValues && !thread->Frames[i]->GetArguments().empty()) {
166
0
        for (auto const& arg : thread->Frames[i]->GetArguments()) {
167
0
          stackName = cmStrCat(stackName, arg.Value, ", ");
168
0
        }
169
170
0
        stackName.erase(stackName.end() - 2, stackName.end());
171
0
      }
172
173
0
      stackName.push_back(')');
174
0
    }
175
176
0
    if (showLine) {
177
0
      stackName =
178
0
        cmStrCat(stackName, " Line: ", static_cast<int64_t>(stackFrame.line));
179
0
    }
180
181
0
    stackFrame.name = stackName;
182
0
    response.stackFrames.push_back(stackFrame);
183
0
  }
184
185
0
  response.totalFrames = response.stackFrames.size();
186
0
  return response;
187
0
}
188
189
} // namespace cmDebugger