Bug Summary

File:build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/lldb/source/Breakpoint/BreakpointOptions.cpp
Warning:line 69, column 5
Value stored to 'found_something' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name BreakpointOptions.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-15/lib/clang/15.0.0 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Breakpoint -I /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/lldb/source/Breakpoint -I /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-15/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-02-24-233250-107839-1 -x c++ /build/llvm-toolchain-snapshot-15~++20220224100907+19e37a7415b3/lldb/source/Breakpoint/BreakpointOptions.cpp
1//===-- BreakpointOptions.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Breakpoint/BreakpointOptions.h"
10
11#include "lldb/Breakpoint/StoppointCallbackContext.h"
12#include "lldb/Core/Value.h"
13#include "lldb/Interpreter/CommandInterpreter.h"
14#include "lldb/Interpreter/CommandReturnObject.h"
15#include "lldb/Target/Process.h"
16#include "lldb/Target/Target.h"
17#include "lldb/Target/ThreadSpec.h"
18#include "lldb/Utility/Stream.h"
19#include "lldb/Utility/StringList.h"
20
21#include "llvm/ADT/STLExtras.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26const char
27 *BreakpointOptions::CommandData::g_option_names[static_cast<uint32_t>(
28 BreakpointOptions::CommandData::OptionNames::LastOptionName)]{
29 "UserSource", "ScriptSource", "StopOnError"};
30
31StructuredData::ObjectSP
32BreakpointOptions::CommandData::SerializeToStructuredData() {
33 size_t num_strings = user_source.GetSize();
34 if (num_strings == 0 && script_source.empty()) {
35 // We shouldn't serialize commands if there aren't any, return an empty sp
36 // to indicate this.
37 return StructuredData::ObjectSP();
38 }
39
40 StructuredData::DictionarySP options_dict_sp(
41 new StructuredData::Dictionary());
42 options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
43 stop_on_error);
44
45 StructuredData::ArraySP user_source_sp(new StructuredData::Array());
46 for (size_t i = 0; i < num_strings; i++) {
47 StructuredData::StringSP item_sp(
48 new StructuredData::String(user_source[i]));
49 user_source_sp->AddItem(item_sp);
50 options_dict_sp->AddItem(GetKey(OptionNames::UserSource), user_source_sp);
51 }
52
53 options_dict_sp->AddStringItem(
54 GetKey(OptionNames::Interpreter),
55 ScriptInterpreter::LanguageToString(interpreter));
56 return options_dict_sp;
57}
58
59std::unique_ptr<BreakpointOptions::CommandData>
60BreakpointOptions::CommandData::CreateFromStructuredData(
61 const StructuredData::Dictionary &options_dict, Status &error) {
62 std::unique_ptr<CommandData> data_up(new CommandData());
63 bool found_something = false;
64
65 bool success = options_dict.GetValueForKeyAsBoolean(
66 GetKey(OptionNames::StopOnError), data_up->stop_on_error);
67
68 if (success)
69 found_something = true;
Value stored to 'found_something' is never read
70
71 llvm::StringRef interpreter_str;
72 ScriptLanguage interp_language;
73 success = options_dict.GetValueForKeyAsString(
74 GetKey(OptionNames::Interpreter), interpreter_str);
75
76 if (!success) {
77 error.SetErrorString("Missing command language value.");
78 return data_up;
79 }
80
81 found_something = true;
82 interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
83 if (interp_language == eScriptLanguageUnknown) {
84 error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
85 interpreter_str);
86 return data_up;
87 }
88 data_up->interpreter = interp_language;
89
90 StructuredData::Array *user_source;
91 success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
92 user_source);
93 if (success) {
94 found_something = true;
95 size_t num_elems = user_source->GetSize();
96 for (size_t i = 0; i < num_elems; i++) {
97 llvm::StringRef elem_string;
98 success = user_source->GetItemAtIndexAsString(i, elem_string);
99 if (success)
100 data_up->user_source.AppendString(elem_string);
101 }
102 }
103
104 if (found_something)
105 return data_up;
106 else
107 return std::unique_ptr<BreakpointOptions::CommandData>();
108}
109
110const char *BreakpointOptions::g_option_names[(
111 size_t)BreakpointOptions::OptionNames::LastOptionName]{
112 "ConditionText", "IgnoreCount",
113 "EnabledState", "OneShotState", "AutoContinue"};
114
115bool BreakpointOptions::NullCallback(void *baton,
116 StoppointCallbackContext *context,
117 lldb::user_id_t break_id,
118 lldb::user_id_t break_loc_id) {
119 return true;
120}
121
122// BreakpointOptions constructor
123BreakpointOptions::BreakpointOptions(bool all_flags_set)
124 : m_callback(BreakpointOptions::NullCallback),
125 m_baton_is_command_baton(false), m_callback_is_synchronous(false),
126 m_enabled(true), m_one_shot(false), m_ignore_count(0),
127 m_condition_text_hash(0), m_auto_continue(false), m_set_flags(0) {
128 if (all_flags_set)
129 m_set_flags.Set(~((Flags::ValueType)0));
130}
131
132BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
133 int32_t ignore, bool one_shot,
134 bool auto_continue)
135 : m_callback(nullptr), m_baton_is_command_baton(false),
136 m_callback_is_synchronous(false), m_enabled(enabled),
137 m_one_shot(one_shot), m_ignore_count(ignore),
138 m_condition_text_hash(0), m_auto_continue(auto_continue)
139{
140 m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot
141 | eAutoContinue);
142 if (condition && *condition != '\0') {
143 SetCondition(condition);
144 }
145}
146
147// BreakpointOptions copy constructor
148BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
149 : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
150 m_baton_is_command_baton(rhs.m_baton_is_command_baton),
151 m_callback_is_synchronous(rhs.m_callback_is_synchronous),
152 m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
153 m_ignore_count(rhs.m_ignore_count), m_auto_continue(rhs.m_auto_continue),
154 m_set_flags(rhs.m_set_flags) {
155 if (rhs.m_thread_spec_up != nullptr)
156 m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
157 m_condition_text = rhs.m_condition_text;
158 m_condition_text_hash = rhs.m_condition_text_hash;
159}
160
161// BreakpointOptions assignment operator
162const BreakpointOptions &BreakpointOptions::
163operator=(const BreakpointOptions &rhs) {
164 m_callback = rhs.m_callback;
165 m_callback_baton_sp = rhs.m_callback_baton_sp;
166 m_baton_is_command_baton = rhs.m_baton_is_command_baton;
167 m_callback_is_synchronous = rhs.m_callback_is_synchronous;
168 m_enabled = rhs.m_enabled;
169 m_one_shot = rhs.m_one_shot;
170 m_ignore_count = rhs.m_ignore_count;
171 if (rhs.m_thread_spec_up != nullptr)
172 m_thread_spec_up = std::make_unique<ThreadSpec>(*rhs.m_thread_spec_up);
173 m_condition_text = rhs.m_condition_text;
174 m_condition_text_hash = rhs.m_condition_text_hash;
175 m_auto_continue = rhs.m_auto_continue;
176 m_set_flags = rhs.m_set_flags;
177 return *this;
178}
179
180void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
181{
182 if (incoming.m_set_flags.Test(eEnabled))
183 {
184 m_enabled = incoming.m_enabled;
185 m_set_flags.Set(eEnabled);
186 }
187 if (incoming.m_set_flags.Test(eOneShot))
188 {
189 m_one_shot = incoming.m_one_shot;
190 m_set_flags.Set(eOneShot);
191 }
192 if (incoming.m_set_flags.Test(eCallback))
193 {
194 m_callback = incoming.m_callback;
195 m_callback_baton_sp = incoming.m_callback_baton_sp;
196 m_callback_is_synchronous = incoming.m_callback_is_synchronous;
197 m_baton_is_command_baton = incoming.m_baton_is_command_baton;
198 m_set_flags.Set(eCallback);
199 }
200 if (incoming.m_set_flags.Test(eIgnoreCount))
201 {
202 m_ignore_count = incoming.m_ignore_count;
203 m_set_flags.Set(eIgnoreCount);
204 }
205 if (incoming.m_set_flags.Test(eCondition))
206 {
207 // If we're copying over an empty condition, mark it as unset.
208 if (incoming.m_condition_text.empty()) {
209 m_condition_text.clear();
210 m_condition_text_hash = 0;
211 m_set_flags.Clear(eCondition);
212 } else {
213 m_condition_text = incoming.m_condition_text;
214 m_condition_text_hash = incoming.m_condition_text_hash;
215 m_set_flags.Set(eCondition);
216 }
217 }
218 if (incoming.m_set_flags.Test(eAutoContinue))
219 {
220 m_auto_continue = incoming.m_auto_continue;
221 m_set_flags.Set(eAutoContinue);
222 }
223 if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_up) {
224 if (!m_thread_spec_up)
225 m_thread_spec_up =
226 std::make_unique<ThreadSpec>(*incoming.m_thread_spec_up);
227 else
228 *m_thread_spec_up = *incoming.m_thread_spec_up;
229 m_set_flags.Set(eThreadSpec);
230 }
231}
232
233// Destructor
234BreakpointOptions::~BreakpointOptions() = default;
235
236std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
237 Target &target, const StructuredData::Dictionary &options_dict,
238 Status &error) {
239 bool enabled = true;
240 bool one_shot = false;
241 bool auto_continue = false;
242 int32_t ignore_count = 0;
243 llvm::StringRef condition_ref("");
244 Flags set_options;
245
246 const char *key = GetKey(OptionNames::EnabledState);
247 bool success;
248 if (key && options_dict.HasKey(key)) {
249 success = options_dict.GetValueForKeyAsBoolean(key, enabled);
250 if (!success) {
251 error.SetErrorStringWithFormat("%s key is not a boolean.", key);
252 return nullptr;
253 }
254 set_options.Set(eEnabled);
255 }
256
257 key = GetKey(OptionNames::OneShotState);
258 if (key && options_dict.HasKey(key)) {
259 success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
260 if (!success) {
261 error.SetErrorStringWithFormat("%s key is not a boolean.", key);
262 return nullptr;
263 }
264 set_options.Set(eOneShot);
265 }
266
267 key = GetKey(OptionNames::AutoContinue);
268 if (key && options_dict.HasKey(key)) {
269 success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
270 if (!success) {
271 error.SetErrorStringWithFormat("%s key is not a boolean.", key);
272 return nullptr;
273 }
274 set_options.Set(eAutoContinue);
275 }
276
277 key = GetKey(OptionNames::IgnoreCount);
278 if (key && options_dict.HasKey(key)) {
279 success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
280 if (!success) {
281 error.SetErrorStringWithFormat("%s key is not an integer.", key);
282 return nullptr;
283 }
284 set_options.Set(eIgnoreCount);
285 }
286
287 key = GetKey(OptionNames::ConditionText);
288 if (key && options_dict.HasKey(key)) {
289 success = options_dict.GetValueForKeyAsString(key, condition_ref);
290 if (!success) {
291 error.SetErrorStringWithFormat("%s key is not an string.", key);
292 return nullptr;
293 }
294 set_options.Set(eCondition);
295 }
296
297 std::unique_ptr<CommandData> cmd_data_up;
298 StructuredData::Dictionary *cmds_dict;
299 success = options_dict.GetValueForKeyAsDictionary(
300 CommandData::GetSerializationKey(), cmds_dict);
301 if (success && cmds_dict) {
302 Status cmds_error;
303 cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
304 if (cmds_error.Fail()) {
305 error.SetErrorStringWithFormat(
306 "Failed to deserialize breakpoint command options: %s.",
307 cmds_error.AsCString());
308 return nullptr;
309 }
310 }
311
312 auto bp_options = std::make_unique<BreakpointOptions>(
313 condition_ref.str().c_str(), enabled,
314 ignore_count, one_shot, auto_continue);
315 if (cmd_data_up) {
316 if (cmd_data_up->interpreter == eScriptLanguageNone)
317 bp_options->SetCommandDataCallback(cmd_data_up);
318 else {
319 ScriptInterpreter *interp = target.GetDebugger().GetScriptInterpreter();
320 if (!interp) {
321 error.SetErrorString(
322 "Can't set script commands - no script interpreter");
323 return nullptr;
324 }
325 if (interp->GetLanguage() != cmd_data_up->interpreter) {
326 error.SetErrorStringWithFormat(
327 "Current script language doesn't match breakpoint's language: %s",
328 ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
329 .c_str());
330 return nullptr;
331 }
332 Status script_error;
333 script_error =
334 interp->SetBreakpointCommandCallback(*bp_options, cmd_data_up);
335 if (script_error.Fail()) {
336 error.SetErrorStringWithFormat("Error generating script callback: %s.",
337 error.AsCString());
338 return nullptr;
339 }
340 }
341 }
342
343 StructuredData::Dictionary *thread_spec_dict;
344 success = options_dict.GetValueForKeyAsDictionary(
345 ThreadSpec::GetSerializationKey(), thread_spec_dict);
346 if (success) {
347 Status thread_spec_error;
348 std::unique_ptr<ThreadSpec> thread_spec_up =
349 ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
350 thread_spec_error);
351 if (thread_spec_error.Fail()) {
352 error.SetErrorStringWithFormat(
353 "Failed to deserialize breakpoint thread spec options: %s.",
354 thread_spec_error.AsCString());
355 return nullptr;
356 }
357 bp_options->SetThreadSpec(thread_spec_up);
358 }
359 return bp_options;
360}
361
362StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
363 StructuredData::DictionarySP options_dict_sp(
364 new StructuredData::Dictionary());
365 if (m_set_flags.Test(eEnabled))
366 options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
367 m_enabled);
368 if (m_set_flags.Test(eOneShot))
369 options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
370 m_one_shot);
371 if (m_set_flags.Test(eAutoContinue))
372 options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
373 m_auto_continue);
374 if (m_set_flags.Test(eIgnoreCount))
375 options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
376 m_ignore_count);
377 if (m_set_flags.Test(eCondition))
378 options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
379 m_condition_text);
380
381 if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
382 auto cmd_baton =
383 std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
384 StructuredData::ObjectSP commands_sp =
385 cmd_baton->getItem()->SerializeToStructuredData();
386 if (commands_sp) {
387 options_dict_sp->AddItem(
388 BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
389 }
390 }
391 if (m_set_flags.Test(eThreadSpec) && m_thread_spec_up) {
392 StructuredData::ObjectSP thread_spec_sp =
393 m_thread_spec_up->SerializeToStructuredData();
394 options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
395 }
396
397 return options_dict_sp;
398}
399
400// Callbacks
401void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
402 const lldb::BatonSP &callback_baton_sp,
403 bool callback_is_synchronous) {
404 // FIXME: This seems unsafe. If BatonSP actually *is* a CommandBaton, but
405 // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
406 // set m_baton_is_command_baton to false, which is incorrect. One possible
407 // solution is to make the base Baton class provide a method such as:
408 // virtual StringRef getBatonId() const { return ""; }
409 // and have CommandBaton override this to return something unique, and then
410 // check for it here. Another option might be to make Baton using the llvm
411 // casting infrastructure, so that we could write something like:
412 // if (llvm::isa<CommandBaton>(callback_baton_sp))
413 // at relevant callsites instead of storing a boolean.
414 m_callback_is_synchronous = callback_is_synchronous;
415 m_callback = callback;
416 m_callback_baton_sp = callback_baton_sp;
417 m_baton_is_command_baton = false;
418 m_set_flags.Set(eCallback);
419}
420
421void BreakpointOptions::SetCallback(
422 BreakpointHitCallback callback,
423 const BreakpointOptions::CommandBatonSP &callback_baton_sp,
424 bool callback_is_synchronous) {
425 m_callback_is_synchronous = callback_is_synchronous;
426 m_callback = callback;
427 m_callback_baton_sp = callback_baton_sp;
428 m_baton_is_command_baton = true;
429 m_set_flags.Set(eCallback);
430}
431
432void BreakpointOptions::ClearCallback() {
433 m_callback = BreakpointOptions::NullCallback;
434 m_callback_is_synchronous = false;
435 m_callback_baton_sp.reset();
436 m_baton_is_command_baton = false;
437 m_set_flags.Clear(eCallback);
438}
439
440Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
441
442const Baton *BreakpointOptions::GetBaton() const {
443 return m_callback_baton_sp.get();
444}
445
446bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
447 lldb::user_id_t break_id,
448 lldb::user_id_t break_loc_id) {
449 if (m_callback) {
450 if (context->is_synchronous == IsCallbackSynchronous()) {
451 return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
452 : nullptr,
453 context, break_id, break_loc_id);
454 } else if (IsCallbackSynchronous()) {
455 return false;
456 }
457 }
458 return true;
459}
460
461bool BreakpointOptions::HasCallback() const {
462 return m_callback != BreakpointOptions::NullCallback;
463}
464
465bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
466 if (!HasCallback())
467 return false;
468 if (!m_baton_is_command_baton)
469 return false;
470
471 auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
472 CommandData *data = cmd_baton->getItem();
473 if (!data)
474 return false;
475 command_list = data->user_source;
476 return true;
477}
478
479void BreakpointOptions::SetCondition(const char *condition) {
480 if (!condition || condition[0] == '\0') {
481 condition = "";
482 m_set_flags.Clear(eCondition);
483 }
484 else
485 m_set_flags.Set(eCondition);
486
487 m_condition_text.assign(condition);
488 std::hash<std::string> hasher;
489 m_condition_text_hash = hasher(m_condition_text);
490}
491
492const char *BreakpointOptions::GetConditionText(size_t *hash) const {
493 if (!m_condition_text.empty()) {
494 if (hash)
495 *hash = m_condition_text_hash;
496
497 return m_condition_text.c_str();
498 } else {
499 return nullptr;
500 }
501}
502
503const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
504 return m_thread_spec_up.get();
505}
506
507ThreadSpec *BreakpointOptions::GetThreadSpec() {
508 if (m_thread_spec_up == nullptr) {
509 m_set_flags.Set(eThreadSpec);
510 m_thread_spec_up = std::make_unique<ThreadSpec>();
511 }
512
513 return m_thread_spec_up.get();
514}
515
516void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
517 GetThreadSpec()->SetTID(thread_id);
518 m_set_flags.Set(eThreadSpec);
519}
520
521void BreakpointOptions::SetThreadSpec(
522 std::unique_ptr<ThreadSpec> &thread_spec_up) {
523 m_thread_spec_up = std::move(thread_spec_up);
524 m_set_flags.Set(eThreadSpec);
525}
526
527void BreakpointOptions::GetDescription(Stream *s,
528 lldb::DescriptionLevel level) const {
529 // Figure out if there are any options not at their default value, and only
530 // print anything if there are:
531
532 if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
533 (GetThreadSpecNoCreate() != nullptr &&
534 GetThreadSpecNoCreate()->HasSpecification())) {
535 if (level == lldb::eDescriptionLevelVerbose) {
536 s->EOL();
537 s->IndentMore();
538 s->Indent();
539 s->PutCString("Breakpoint Options:\n");
540 s->IndentMore();
541 s->Indent();
542 } else
543 s->PutCString(" Options: ");
544
545 if (m_ignore_count > 0)
546 s->Printf("ignore: %d ", m_ignore_count);
547 s->Printf("%sabled ", m_enabled ? "en" : "dis");
548
549 if (m_one_shot)
550 s->Printf("one-shot ");
551
552 if (m_auto_continue)
553 s->Printf("auto-continue ");
554
555 if (m_thread_spec_up)
556 m_thread_spec_up->GetDescription(s, level);
557
558 if (level == lldb::eDescriptionLevelFull) {
559 s->IndentLess();
560 s->IndentMore();
561 }
562 }
563
564 if (m_callback_baton_sp.get()) {
565 if (level != eDescriptionLevelBrief) {
566 s->EOL();
567 m_callback_baton_sp->GetDescription(s->AsRawOstream(), level,
568 s->GetIndentLevel());
569 }
570 }
571 if (!m_condition_text.empty()) {
572 if (level != eDescriptionLevelBrief) {
573 s->EOL();
574 s->Printf("Condition: %s\n", m_condition_text.c_str());
575 }
576 }
577}
578
579void BreakpointOptions::CommandBaton::GetDescription(
580 llvm::raw_ostream &s, lldb::DescriptionLevel level,
581 unsigned indentation) const {
582 const CommandData *data = getItem();
583
584 if (level == eDescriptionLevelBrief) {
585 s << ", commands = "
586 << ((data && data->user_source.GetSize() > 0) ? "yes" : "no");
587 return;
588 }
589
590 indentation += 2;
591 s.indent(indentation);
592 s << "Breakpoint commands";
593 if (data->interpreter != eScriptLanguageNone)
594 s << llvm::formatv(" ({0}):\n",
595 ScriptInterpreter::LanguageToString(data->interpreter));
596 else
597 s << ":\n";
598
599 indentation += 2;
600 if (data && data->user_source.GetSize() > 0) {
601 for (llvm::StringRef str : data->user_source) {
602 s.indent(indentation);
603 s << str << "\n";
604 }
605 } else
606 s << "No commands.\n";
607}
608
609void BreakpointOptions::SetCommandDataCallback(
610 std::unique_ptr<CommandData> &cmd_data) {
611 cmd_data->interpreter = eScriptLanguageNone;
612 auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
613 SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
614 m_set_flags.Set(eCallback);
615}
616
617bool BreakpointOptions::BreakpointOptionsCallbackFunction(
618 void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
619 lldb::user_id_t break_loc_id) {
620 bool ret_value = true;
621 if (baton == nullptr)
622 return true;
623
624 CommandData *data = (CommandData *)baton;
625 StringList &commands = data->user_source;
626
627 if (commands.GetSize() > 0) {
628 ExecutionContext exe_ctx(context->exe_ctx_ref);
629 Target *target = exe_ctx.GetTargetPtr();
630 if (target) {
631 Debugger &debugger = target->GetDebugger();
632 CommandReturnObject result(debugger.GetUseColor());
633
634 // Rig up the results secondary output stream to the debugger's, so the
635 // output will come out synchronously if the debugger is set up that way.
636 StreamSP output_stream(debugger.GetAsyncOutputStream());
637 StreamSP error_stream(debugger.GetAsyncErrorStream());
638 result.SetImmediateOutputStream(output_stream);
639 result.SetImmediateErrorStream(error_stream);
640
641 CommandInterpreterRunOptions options;
642 options.SetStopOnContinue(true);
643 options.SetStopOnError(data->stop_on_error);
644 options.SetEchoCommands(true);
645 options.SetPrintResults(true);
646 options.SetPrintErrors(true);
647 options.SetAddToHistory(false);
648
649 debugger.GetCommandInterpreter().HandleCommands(commands, exe_ctx,
650 options, result);
651 result.GetImmediateOutputStream()->Flush();
652 result.GetImmediateErrorStream()->Flush();
653 }
654 }
655 return ret_value;
656}
657
658void BreakpointOptions::Clear()
659{
660 m_set_flags.Clear();
661 m_thread_spec_up.release();
662 m_one_shot = false;
663 m_ignore_count = 0;
664 m_auto_continue = false;
665 m_callback = nullptr;
666 m_callback_baton_sp.reset();
667 m_baton_is_command_baton = false;
668 m_callback_is_synchronous = false;
669 m_enabled = false;
670 m_condition_text.clear();
671}