/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 |