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

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", "EnabledState", "OneShotState"};
118
119bool BreakpointOptions::NullCallback(void *baton,
120 StoppointCallbackContext *context,
121 lldb::user_id_t break_id,
122 lldb::user_id_t break_loc_id) {
123 return true;
124}
125
126//----------------------------------------------------------------------
127// BreakpointOptions constructor
128//----------------------------------------------------------------------
129BreakpointOptions::BreakpointOptions()
130 : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
131 m_baton_is_command_baton(false), m_callback_is_synchronous(false),
132 m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(),
133 m_condition_text(), m_condition_text_hash(0) {}
134
135BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
136 int32_t ignore, bool one_shot)
137 : m_callback(nullptr), m_baton_is_command_baton(false),
138 m_callback_is_synchronous(false), m_enabled(enabled),
139 m_one_shot(one_shot), m_ignore_count(ignore), m_condition_text(condition),
140 m_condition_text_hash(0)
141
142{}
143
144//----------------------------------------------------------------------
145// BreakpointOptions copy constructor
146//----------------------------------------------------------------------
147BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
148 : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
149 m_baton_is_command_baton(rhs.m_baton_is_command_baton),
150 m_callback_is_synchronous(rhs.m_callback_is_synchronous),
151 m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
152 m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap() {
153 if (rhs.m_thread_spec_ap.get() != nullptr)
154 m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
155 m_condition_text = rhs.m_condition_text;
156 m_condition_text_hash = rhs.m_condition_text_hash;
157}
158
159//----------------------------------------------------------------------
160// BreakpointOptions assignment operator
161//----------------------------------------------------------------------
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_ap.get() != nullptr)
172 m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
173 m_condition_text = rhs.m_condition_text;
174 m_condition_text_hash = rhs.m_condition_text_hash;
175 return *this;
176}
177
178BreakpointOptions *
179BreakpointOptions::CopyOptionsNoCallback(BreakpointOptions &orig) {
180 BreakpointHitCallback orig_callback = orig.m_callback;
181 lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
182 bool orig_is_sync = orig.m_callback_is_synchronous;
183
184 orig.ClearCallback();
185 BreakpointOptions *ret_val = new BreakpointOptions(orig);
186
187 orig.SetCallback(orig_callback, orig_callback_baton_sp, orig_is_sync);
188
189 return ret_val;
190}
191
192//----------------------------------------------------------------------
193// Destructor
194//----------------------------------------------------------------------
195BreakpointOptions::~BreakpointOptions() = default;
196
197std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
198 Target &target, const StructuredData::Dictionary &options_dict,
199 Status &error) {
200 bool enabled = true;
201 bool one_shot = false;
202 int32_t ignore_count = 0;
203 std::string condition_text;
204
205 bool success = options_dict.GetValueForKeyAsBoolean(
206 GetKey(OptionNames::EnabledState), enabled);
207 if (!success) {
208 error.SetErrorStringWithFormat("%s key is not a boolean.",
209 GetKey(OptionNames::EnabledState));
210 return nullptr;
211 }
212
213 success = options_dict.GetValueForKeyAsBoolean(
214 GetKey(OptionNames::OneShotState), one_shot);
215 if (!success) {
216 error.SetErrorStringWithFormat("%s key is not a boolean.",
217 GetKey(OptionNames::OneShotState));
218 return nullptr;
219 }
220 success = options_dict.GetValueForKeyAsInteger(
221 GetKey(OptionNames::IgnoreCount), ignore_count);
222 if (!success) {
223 error.SetErrorStringWithFormat("%s key is not an integer.",
224 GetKey(OptionNames::IgnoreCount));
225 return nullptr;
226 }
227
228 std::unique_ptr<CommandData> cmd_data_up;
229 StructuredData::Dictionary *cmds_dict;
230 success = options_dict.GetValueForKeyAsDictionary(
231 CommandData::GetSerializationKey(), cmds_dict);
232 if (success && cmds_dict) {
233 Status cmds_error;
234 cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
235 if (cmds_error.Fail()) {
236 error.SetErrorStringWithFormat(
237 "Failed to deserialize breakpoint command options: %s.",
238 cmds_error.AsCString());
239 return nullptr;
240 }
241 }
242
243 auto bp_options = llvm::make_unique<BreakpointOptions>(
244 condition_text.c_str(), enabled, ignore_count, one_shot);
245 if (cmd_data_up.get()) {
246 if (cmd_data_up->interpreter == eScriptLanguageNone)
247 bp_options->SetCommandDataCallback(cmd_data_up);
248 else {
249 ScriptInterpreter *interp =
250 target.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
251 if (!interp) {
252 error.SetErrorStringWithFormat(
253 "Can't set script commands - no script interpreter");
254 return nullptr;
255 }
256 if (interp->GetLanguage() != cmd_data_up->interpreter) {
257 error.SetErrorStringWithFormat(
258 "Current script language doesn't match breakpoint's language: %s",
259 ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
260 .c_str());
261 return nullptr;
262 }
263 Status script_error;
264 script_error =
265 interp->SetBreakpointCommandCallback(bp_options.get(), cmd_data_up);
266 if (script_error.Fail()) {
267 error.SetErrorStringWithFormat("Error generating script callback: %s.",
268 error.AsCString());
269 return nullptr;
270 }
271 }
272 }
273
274 StructuredData::Dictionary *thread_spec_dict;
275 success = options_dict.GetValueForKeyAsDictionary(
276 ThreadSpec::GetSerializationKey(), thread_spec_dict);
277 if (success) {
278 Status thread_spec_error;
279 std::unique_ptr<ThreadSpec> thread_spec_up =
280 ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
281 thread_spec_error);
282 if (thread_spec_error.Fail()) {
283 error.SetErrorStringWithFormat(
284 "Failed to deserialize breakpoint thread spec options: %s.",
285 thread_spec_error.AsCString());
286 return nullptr;
287 }
288 bp_options->SetThreadSpec(thread_spec_up);
289 }
290 return bp_options;
291}
292
293StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
294 StructuredData::DictionarySP options_dict_sp(
295 new StructuredData::Dictionary());
296 options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState), m_enabled);
297 options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
298 m_one_shot);
299 options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
300 m_ignore_count);
301 options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
302 m_condition_text);
303 if (m_baton_is_command_baton) {
304 auto cmd_baton =
305 std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
306 StructuredData::ObjectSP commands_sp =
307 cmd_baton->getItem()->SerializeToStructuredData();
308 if (commands_sp) {
309 options_dict_sp->AddItem(
310 BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
311 }
312 }
313 if (m_thread_spec_ap) {
314 StructuredData::ObjectSP thread_spec_sp =
315 m_thread_spec_ap->SerializeToStructuredData();
316 options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
317 }
318
319 return options_dict_sp;
320}
321
322//------------------------------------------------------------------
323// Callbacks
324//------------------------------------------------------------------
325void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
326 const lldb::BatonSP &callback_baton_sp,
327 bool callback_is_synchronous) {
328 // FIXME: This seems unsafe. If BatonSP actually *is* a CommandBaton, but
329 // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we
330 // will set m_baton_is_command_baton to false, which is incorrect.
331 // One possible solution is to make the base Baton class provide a method
332 // such as:
333 // virtual StringRef getBatonId() const { return ""; }
334 // and have CommandBaton override this to return something unique, and then
335 // check for it here. Another option might be to make Baton using the llvm
336 // casting infrastructure, so that we could write something like:
337 // if (llvm::isa<CommandBaton>(callback_baton_sp))
338 // at relevant callsites instead of storing a boolean.
339 m_callback_is_synchronous = callback_is_synchronous;
340 m_callback = callback;
341 m_callback_baton_sp = callback_baton_sp;
342 m_baton_is_command_baton = false;
343}
344
345void BreakpointOptions::SetCallback(
346 BreakpointHitCallback callback,
347 const BreakpointOptions::CommandBatonSP &callback_baton_sp,
348 bool callback_is_synchronous) {
349 m_callback_is_synchronous = callback_is_synchronous;
350 m_callback = callback;
351 m_callback_baton_sp = callback_baton_sp;
352 m_baton_is_command_baton = true;
353}
354
355void BreakpointOptions::ClearCallback() {
356 m_callback = BreakpointOptions::NullCallback;
357 m_callback_is_synchronous = false;
358 m_callback_baton_sp.reset();
359 m_baton_is_command_baton = false;
360}
361
362Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }
363
364const Baton *BreakpointOptions::GetBaton() const {
365 return m_callback_baton_sp.get();
366}
367
368bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
369 lldb::user_id_t break_id,
370 lldb::user_id_t break_loc_id) {
371 if (m_callback && context->is_synchronous == IsCallbackSynchronous()) {
372 return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
373 : nullptr,
374 context, break_id, break_loc_id);
375 } else
376 return true;
377}
378
379bool BreakpointOptions::HasCallback() const {
380 return m_callback != BreakpointOptions::NullCallback;
381}
382
383bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
384 if (!HasCallback())
385 return false;
386 if (!m_baton_is_command_baton)
387 return false;
388
389 auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
390 CommandData *data = cmd_baton->getItem();
391 if (!data)
392 return false;
393 command_list = data->user_source;
394 return true;
395}
396
397void BreakpointOptions::SetCondition(const char *condition) {
398 if (!condition)
399 condition = "";
400
401 m_condition_text.assign(condition);
402 std::hash<std::string> hasher;
403 m_condition_text_hash = hasher(m_condition_text);
404}
405
406const char *BreakpointOptions::GetConditionText(size_t *hash) const {
407 if (!m_condition_text.empty()) {
408 if (hash)
409 *hash = m_condition_text_hash;
410
411 return m_condition_text.c_str();
412 } else {
413 return nullptr;
414 }
415}
416
417const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
418 return m_thread_spec_ap.get();
419}
420
421ThreadSpec *BreakpointOptions::GetThreadSpec() {
422 if (m_thread_spec_ap.get() == nullptr)
423 m_thread_spec_ap.reset(new ThreadSpec());
424
425 return m_thread_spec_ap.get();
426}
427
428void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
429 GetThreadSpec()->SetTID(thread_id);
430}
431
432void BreakpointOptions::SetThreadSpec(
433 std::unique_ptr<ThreadSpec> &thread_spec_up) {
434 m_thread_spec_ap = std::move(thread_spec_up);
435}
436
437void BreakpointOptions::GetDescription(Stream *s,
438 lldb::DescriptionLevel level) const {
439 // Figure out if there are any options not at their default value, and only
440 // print
441 // anything if there are:
442
443 if (m_ignore_count != 0 || !m_enabled || m_one_shot ||
444 (GetThreadSpecNoCreate() != nullptr &&
445 GetThreadSpecNoCreate()->HasSpecification())) {
446 if (level == lldb::eDescriptionLevelVerbose) {
447 s->EOL();
448 s->IndentMore();
449 s->Indent();
450 s->PutCString("Breakpoint Options:\n");
451 s->IndentMore();
452 s->Indent();
453 } else
454 s->PutCString(" Options: ");
455
456 if (m_ignore_count > 0)
457 s->Printf("ignore: %d ", m_ignore_count);
458 s->Printf("%sabled ", m_enabled ? "en" : "dis");
459
460 if (m_one_shot)
461 s->Printf("one-shot ");
462
463 if (m_thread_spec_ap.get())
464 m_thread_spec_ap->GetDescription(s, level);
465
466 if (level == lldb::eDescriptionLevelFull) {
467 s->IndentLess();
468 s->IndentMore();
469 }
470 }
471
472 if (m_callback_baton_sp.get()) {
473 if (level != eDescriptionLevelBrief) {
474 s->EOL();
475 m_callback_baton_sp->GetDescription(s, level);
476 }
477 }
478 if (!m_condition_text.empty()) {
479 if (level != eDescriptionLevelBrief) {
480 s->EOL();
481 s->Printf("Condition: %s\n", m_condition_text.c_str());
482 }
483 }
484}
485
486void BreakpointOptions::CommandBaton::GetDescription(
487 Stream *s, lldb::DescriptionLevel level) const {
488 const CommandData *data = getItem();
489
490 if (level == eDescriptionLevelBrief) {
491 s->Printf(", commands = %s",
492 (data && data->user_source.GetSize() > 0) ? "yes" : "no");
493 return;
494 }
495
496 s->IndentMore();
497 s->Indent("Breakpoint commands");
498 if (data->interpreter != eScriptLanguageNone)
499 s->Printf(" (%s):\n",
500 ScriptInterpreter::LanguageToString(data->interpreter).c_str());
501 else
502 s->PutCString(":\n");
503
504 s->IndentMore();
505 if (data && data->user_source.GetSize() > 0) {
506 const size_t num_strings = data->user_source.GetSize();
507 for (size_t i = 0; i < num_strings; ++i) {
508 s->Indent(data->user_source.GetStringAtIndex(i));
509 s->EOL();
510 }
511 } else {
512 s->PutCString("No commands.\n");
513 }
514 s->IndentLess();
515 s->IndentLess();
516}
517
518void BreakpointOptions::SetCommandDataCallback(
519 std::unique_ptr<CommandData> &cmd_data) {
520 cmd_data->interpreter = eScriptLanguageNone;
521 auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
522 SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
523}
524
525bool BreakpointOptions::BreakpointOptionsCallbackFunction(
526 void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
527 lldb::user_id_t break_loc_id) {
528 bool ret_value = true;
529 if (baton == nullptr)
530 return true;
531
532 CommandData *data = (CommandData *)baton;
533 StringList &commands = data->user_source;
534
535 if (commands.GetSize() > 0) {
536 ExecutionContext exe_ctx(context->exe_ctx_ref);
537 Target *target = exe_ctx.GetTargetPtr();
538 if (target) {
539 CommandReturnObject result;
540 Debugger &debugger = target->GetDebugger();
541 // Rig up the results secondary output stream to the debugger's, so the
542 // output will come out synchronously
543 // if the debugger is set up that way.
544
545 StreamSP output_stream(debugger.GetAsyncOutputStream());
546 StreamSP error_stream(debugger.GetAsyncErrorStream());
547 result.SetImmediateOutputStream(output_stream);
548 result.SetImmediateErrorStream(error_stream);
549
550 CommandInterpreterRunOptions options;
551 options.SetStopOnContinue(true);
552 options.SetStopOnError(data->stop_on_error);
553 options.SetEchoCommands(true);
554 options.SetPrintResults(true);
555 options.SetAddToHistory(false);
556
557 debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
558 options, result);
559 result.GetImmediateOutputStream()->Flush();
560 result.GetImmediateErrorStream()->Flush();
561 }
562 }
563 return ret_value;
564}