Bug Summary

File:tools/lldb/source/Breakpoint/BreakpointOptions.cpp
Warning:line 74, column 5
Value stored to 'found_something' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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