|
9 | 9 | #include "DAP.h"
|
10 | 10 | #include "DAPLog.h"
|
11 | 11 | #include "EventHelper.h"
|
| 12 | +#include "ExceptionBreakpoint.h" |
12 | 13 | #include "Handler/RequestHandler.h"
|
13 | 14 | #include "Handler/ResponseHandler.h"
|
14 | 15 | #include "JSONUtils.h"
|
|
17 | 18 | #include "Protocol/ProtocolBase.h"
|
18 | 19 | #include "Protocol/ProtocolRequests.h"
|
19 | 20 | #include "Protocol/ProtocolTypes.h"
|
| 21 | +#include "ProtocolUtils.h" |
20 | 22 | #include "Transport.h"
|
21 | 23 | #include "lldb/API/SBBreakpoint.h"
|
22 | 24 | #include "lldb/API/SBCommandInterpreter.h"
|
@@ -129,104 +131,89 @@ DAP::DAP(Log *log, const ReplMode default_repl_mode,
|
129 | 131 | DAP::~DAP() = default;
|
130 | 132 |
|
131 | 133 | void DAP::PopulateExceptionBreakpoints() {
|
132 |
| - llvm::call_once(init_exception_breakpoints_flag, [this]() { |
133 |
| - exception_breakpoints = std::vector<ExceptionBreakpoint>{}; |
134 |
| - |
135 |
| - if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeC_plus_plus)) { |
136 |
| - exception_breakpoints->emplace_back(*this, "cpp_catch", "C++ Catch", |
137 |
| - lldb::eLanguageTypeC_plus_plus); |
138 |
| - exception_breakpoints->emplace_back(*this, "cpp_throw", "C++ Throw", |
139 |
| - lldb::eLanguageTypeC_plus_plus); |
140 |
| - } |
141 |
| - if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeObjC)) { |
142 |
| - exception_breakpoints->emplace_back( |
143 |
| - *this, "objc_catch", "Objective-C Catch", lldb::eLanguageTypeObjC); |
144 |
| - exception_breakpoints->emplace_back( |
145 |
| - *this, "objc_throw", "Objective-C Throw", lldb::eLanguageTypeObjC); |
146 |
| - } |
147 |
| - if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeSwift)) { |
148 |
| - exception_breakpoints->emplace_back(*this, "swift_catch", "Swift Catch", |
149 |
| - lldb::eLanguageTypeSwift); |
150 |
| - exception_breakpoints->emplace_back(*this, "swift_throw", "Swift Throw", |
151 |
| - lldb::eLanguageTypeSwift); |
| 134 | + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeC_plus_plus)) { |
| 135 | + exception_breakpoints.emplace_back(*this, "cpp_catch", "C++ Catch", |
| 136 | + lldb::eLanguageTypeC_plus_plus, |
| 137 | + eExceptionKindCatch); |
| 138 | + exception_breakpoints.emplace_back(*this, "cpp_throw", "C++ Throw", |
| 139 | + lldb::eLanguageTypeC_plus_plus, |
| 140 | + eExceptionKindThrow); |
| 141 | + } |
| 142 | + |
| 143 | + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeObjC)) { |
| 144 | + exception_breakpoints.emplace_back(*this, "objc_catch", "Objective-C Catch", |
| 145 | + lldb::eLanguageTypeObjC, |
| 146 | + eExceptionKindCatch); |
| 147 | + exception_breakpoints.emplace_back(*this, "objc_throw", "Objective-C Throw", |
| 148 | + lldb::eLanguageTypeObjC, |
| 149 | + eExceptionKindThrow); |
| 150 | + } |
| 151 | + |
| 152 | + if (lldb::SBDebugger::SupportsLanguage(lldb::eLanguageTypeSwift)) { |
| 153 | + exception_breakpoints.emplace_back(*this, "swift_catch", "Swift Catch", |
| 154 | + lldb::eLanguageTypeSwift, |
| 155 | + eExceptionKindCatch); |
| 156 | + exception_breakpoints.emplace_back(*this, "swift_throw", "Swift Throw", |
| 157 | + lldb::eLanguageTypeSwift, |
| 158 | + eExceptionKindThrow); |
| 159 | + } |
| 160 | + |
| 161 | + // Besides handling the hardcoded list of languages from above, we try to find |
| 162 | + // any other languages that support exception breakpoints using the SB API. |
| 163 | + for (int raw_lang = lldb::eLanguageTypeUnknown; |
| 164 | + raw_lang < lldb::eNumLanguageTypes; ++raw_lang) { |
| 165 | + lldb::LanguageType lang = static_cast<lldb::LanguageType>(raw_lang); |
| 166 | + |
| 167 | + // We first discard any languages already handled above. |
| 168 | + if (lldb::SBLanguageRuntime::LanguageIsCFamily(lang) || |
| 169 | + lang == lldb::eLanguageTypeSwift) |
| 170 | + continue; |
| 171 | + |
| 172 | + if (!lldb::SBDebugger::SupportsLanguage(lang)) |
| 173 | + continue; |
| 174 | + |
| 175 | + const char *name = lldb::SBLanguageRuntime::GetNameForLanguageType(lang); |
| 176 | + if (!name) |
| 177 | + continue; |
| 178 | + std::string raw_lang_name = name; |
| 179 | + std::string capitalized_lang_name = capitalize(name); |
| 180 | + |
| 181 | + if (lldb::SBLanguageRuntime::SupportsExceptionBreakpointsOnThrow(lang)) { |
| 182 | + const char *raw_throw_keyword = |
| 183 | + lldb::SBLanguageRuntime::GetThrowKeywordForLanguage(lang); |
| 184 | + std::string throw_keyword = |
| 185 | + raw_throw_keyword ? raw_throw_keyword : "throw"; |
| 186 | + |
| 187 | + exception_breakpoints.emplace_back( |
| 188 | + *this, raw_lang_name + "_" + throw_keyword, |
| 189 | + capitalized_lang_name + " " + capitalize(throw_keyword), lang, |
| 190 | + eExceptionKindThrow); |
152 | 191 | }
|
153 |
| - // Besides handling the hardcoded list of languages from above, we try to |
154 |
| - // find any other languages that support exception breakpoints using the |
155 |
| - // SB API. |
156 |
| - for (int raw_lang = lldb::eLanguageTypeUnknown; |
157 |
| - raw_lang < lldb::eNumLanguageTypes; ++raw_lang) { |
158 |
| - lldb::LanguageType lang = static_cast<lldb::LanguageType>(raw_lang); |
159 |
| - |
160 |
| - // We first discard any languages already handled above. |
161 |
| - if (lldb::SBLanguageRuntime::LanguageIsCFamily(lang) || |
162 |
| - lang == lldb::eLanguageTypeSwift) |
163 |
| - continue; |
164 |
| - |
165 |
| - if (!lldb::SBDebugger::SupportsLanguage(lang)) |
166 |
| - continue; |
167 |
| - |
168 |
| - const char *name = lldb::SBLanguageRuntime::GetNameForLanguageType(lang); |
169 |
| - if (!name) |
170 |
| - continue; |
171 |
| - std::string raw_lang_name = name; |
172 |
| - std::string capitalized_lang_name = capitalize(name); |
173 |
| - |
174 |
| - if (lldb::SBLanguageRuntime::SupportsExceptionBreakpointsOnThrow(lang)) { |
175 |
| - const char *raw_throw_keyword = |
176 |
| - lldb::SBLanguageRuntime::GetThrowKeywordForLanguage(lang); |
177 |
| - std::string throw_keyword = |
178 |
| - raw_throw_keyword ? raw_throw_keyword : "throw"; |
179 |
| - |
180 |
| - exception_breakpoints->emplace_back( |
181 |
| - *this, raw_lang_name + "_" + throw_keyword, |
182 |
| - capitalized_lang_name + " " + capitalize(throw_keyword), lang); |
183 |
| - } |
184 | 192 |
|
185 |
| - if (lldb::SBLanguageRuntime::SupportsExceptionBreakpointsOnCatch(lang)) { |
186 |
| - const char *raw_catch_keyword = |
187 |
| - lldb::SBLanguageRuntime::GetCatchKeywordForLanguage(lang); |
188 |
| - std::string catch_keyword = |
189 |
| - raw_catch_keyword ? raw_catch_keyword : "catch"; |
| 193 | + if (lldb::SBLanguageRuntime::SupportsExceptionBreakpointsOnCatch(lang)) { |
| 194 | + const char *raw_catch_keyword = |
| 195 | + lldb::SBLanguageRuntime::GetCatchKeywordForLanguage(lang); |
| 196 | + std::string catch_keyword = |
| 197 | + raw_catch_keyword ? raw_catch_keyword : "catch"; |
190 | 198 |
|
191 |
| - exception_breakpoints->emplace_back( |
192 |
| - *this, raw_lang_name + "_" + catch_keyword, |
193 |
| - capitalized_lang_name + " " + capitalize(catch_keyword), lang); |
194 |
| - } |
| 199 | + exception_breakpoints.emplace_back( |
| 200 | + *this, raw_lang_name + "_" + catch_keyword, |
| 201 | + capitalized_lang_name + " " + capitalize(catch_keyword), lang, |
| 202 | + eExceptionKindCatch); |
195 | 203 | }
|
196 |
| - assert(!exception_breakpoints->empty() && "should not be empty"); |
197 |
| - }); |
| 204 | + } |
198 | 205 | }
|
199 | 206 |
|
200 | 207 | ExceptionBreakpoint *DAP::GetExceptionBreakpoint(llvm::StringRef filter) {
|
201 |
| - // PopulateExceptionBreakpoints() is called after g_dap.debugger is created |
202 |
| - // in a request-initialize. |
203 |
| - // |
204 |
| - // But this GetExceptionBreakpoint() method may be called before attaching, in |
205 |
| - // which case, we may not have populated the filter yet. |
206 |
| - // |
207 |
| - // We also cannot call PopulateExceptionBreakpoints() in DAP::DAP() because |
208 |
| - // we need SBDebugger::Initialize() to have been called before this. |
209 |
| - // |
210 |
| - // So just calling PopulateExceptionBreakoints(),which does lazy-populating |
211 |
| - // seems easiest. Two other options include: |
212 |
| - // + call g_dap.PopulateExceptionBreakpoints() in lldb-dap.cpp::main() |
213 |
| - // right after the call to SBDebugger::Initialize() |
214 |
| - // + Just call PopulateExceptionBreakpoints() to get a fresh list everytime |
215 |
| - // we query (a bit overkill since it's not likely to change?) |
216 |
| - PopulateExceptionBreakpoints(); |
217 |
| - |
218 |
| - for (auto &bp : *exception_breakpoints) { |
| 208 | + for (auto &bp : exception_breakpoints) { |
219 | 209 | if (bp.GetFilter() == filter)
|
220 | 210 | return &bp;
|
221 | 211 | }
|
222 | 212 | return nullptr;
|
223 | 213 | }
|
224 | 214 |
|
225 | 215 | ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
|
226 |
| - // See comment in the other GetExceptionBreakpoint(). |
227 |
| - PopulateExceptionBreakpoints(); |
228 |
| - |
229 |
| - for (auto &bp : *exception_breakpoints) { |
| 216 | + for (auto &bp : exception_breakpoints) { |
230 | 217 | if (bp.GetID() == bp_id)
|
231 | 218 | return &bp;
|
232 | 219 | }
|
@@ -1118,8 +1105,9 @@ protocol::Capabilities DAP::GetCapabilities() {
|
1118 | 1105 | }
|
1119 | 1106 |
|
1120 | 1107 | // Available filters or options for the setExceptionBreakpoints request.
|
| 1108 | + PopulateExceptionBreakpoints(); |
1121 | 1109 | std::vector<protocol::ExceptionBreakpointsFilter> filters;
|
1122 |
| - for (const auto &exc_bp : *exception_breakpoints) |
| 1110 | + for (const auto &exc_bp : exception_breakpoints) |
1123 | 1111 | filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
|
1124 | 1112 | capabilities.exceptionBreakpointFilters = std::move(filters);
|
1125 | 1113 |
|
|
0 commit comments