LLDB  mainline
CommandObjectBreakpointCommand.cpp
Go to the documentation of this file.
1 //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
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 
15 #include "lldb/Core/IOHandler.h"
16 #include "lldb/Host/OptionParser.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Utility/State.h"
23 
24 #include "llvm/ADT/STLExtras.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 // CommandObjectBreakpointCommandAdd
30 
31 // FIXME: "script-type" needs to have its contents determined dynamically, so
32 // somebody can add a new scripting
33 // language to lldb and have it pickable here without having to change this
34 // enumeration by hand and rebuild lldb proper.
35 
36 static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
37  {eScriptLanguageNone, "command",
38  "Commands are in the lldb command interpreter language"},
39  {eScriptLanguagePython, "python", "Commands are in the Python language."},
40  {eSortOrderByName, "default-script",
41  "Commands are in the default scripting language."} };
42 
43 static constexpr OptionEnumValues ScriptOptionEnum() {
44  return OptionEnumValues(g_script_option_enumeration);
45 }
46 
47 static constexpr OptionDefinition g_breakpoint_add_options[] = {
48  // clang-format off
49  { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
50  { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." },
51  { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
52  { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." },
53  { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
54  // clang-format on
55 };
56 
59 public:
61  : CommandObjectParsed(interpreter, "add",
62  "Add LLDB commands to a breakpoint, to be executed "
63  "whenever the breakpoint is hit."
64  " If no breakpoint is specified, adds the "
65  "commands to the last created breakpoint.",
66  nullptr),
68  IOHandlerDelegate::Completion::LLDBCommand),
69  m_options() {
70  SetHelpLong(
71  R"(
72 General information about entering breakpoint commands
73 ------------------------------------------------------
74 
75 )"
76  "This command will prompt for commands to be executed when the specified \
77 breakpoint is hit. Each command is typed on its own line following the '> ' \
78 prompt until 'DONE' is entered."
79  R"(
80 
81 )"
82  "Syntactic errors may not be detected when initially entered, and many \
83 malformed commands can silently fail when executed. If your breakpoint commands \
84 do not appear to be executing, double-check the command syntax."
85  R"(
86 
87 )"
88  "Note: You may enter any debugger command exactly as you would at the debugger \
89 prompt. There is no limit to the number of commands supplied, but do NOT enter \
90 more than one command per line."
91  R"(
92 
93 Special information about PYTHON breakpoint commands
94 ----------------------------------------------------
95 
96 )"
97  "You may enter either one or more lines of Python, including function \
98 definitions or calls to functions that will have been imported by the time \
99 the code executes. Single line breakpoint commands will be interpreted 'as is' \
100 when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
101 generated function, and a call to the function will be attached to the breakpoint."
102  R"(
103 
104 This auto-generated function is passed in three arguments:
105 
106  frame: an lldb.SBFrame object for the frame which hit breakpoint.
107 
108  bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
109 
110  dict: the python session dictionary hit.
111 
112 )"
113  "When specifying a python function with the --python-function option, you need \
114 to supply the function name prepended by the module name:"
115  R"(
116 
117  --python-function myutils.breakpoint_callback
118 
119 The function itself must have the following prototype:
120 
121 def breakpoint_callback(frame, bp_loc, dict):
122  # Your code goes here
123 
124 )"
125  "The arguments are the same as the arguments passed to generated functions as \
126 described above. Note that the global variable 'lldb.frame' will NOT be updated when \
127 this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
128 can get you to the thread via frame.GetThread(), the thread can get you to the \
129 process via thread.GetProcess(), and the process can get you back to the target \
130 via process.GetTarget()."
131  R"(
132 
133 )"
134  "Important Note: As Python code gets collected into functions, access to global \
135 variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
136 Python syntax, including indentation, when entering Python breakpoint commands."
137  R"(
138 
139 Example Python one-line breakpoint command:
140 
141 (lldb) breakpoint command add -s python 1
142 Enter your Python command(s). Type 'DONE' to end.
143 > print "Hit this breakpoint!"
144 > DONE
145 
146 As a convenience, this also works for a short Python one-liner:
147 
148 (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
149 (lldb) run
150 Launching '.../a.out' (x86_64)
151 (lldb) Fri Sep 10 12:17:45 2010
152 Process 21778 Stopped
153 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
154  36
155  37 int c(int val)
156  38 {
157  39 -> return val + 3;
158  40 }
159  41
160  42 int main (int argc, char const *argv[])
161 
162 Example multiple line Python breakpoint command:
163 
164 (lldb) breakpoint command add -s p 1
165 Enter your Python command(s). Type 'DONE' to end.
166 > global bp_count
167 > bp_count = bp_count + 1
168 > print "Hit this breakpoint " + repr(bp_count) + " times!"
169 > DONE
170 
171 Example multiple line Python breakpoint command, using function definition:
172 
173 (lldb) breakpoint command add -s python 1
174 Enter your Python command(s). Type 'DONE' to end.
175 > def breakpoint_output (bp_no):
176 > out_string = "Hit breakpoint number " + repr (bp_no)
177 > print out_string
178 > return True
179 > breakpoint_output (1)
180 > DONE
181 
182 )"
183  "In this case, since there is a reference to a global variable, \
184 'bp_count', you will also need to make sure 'bp_count' exists and is \
185 initialized:"
186  R"(
187 
188 (lldb) script
189 >>> bp_count = 0
190 >>> quit()
191 
192 )"
193  "Your Python code, however organized, can optionally return a value. \
194 If the returned value is False, that tells LLDB not to stop at the breakpoint \
195 to which the code is associated. Returning anything other than False, or even \
196 returning None, or even omitting a return statement entirely, will cause \
197 LLDB to stop."
198  R"(
199 
200 )"
201  "Final Note: A warning that no breakpoint command was generated when there \
202 are no syntax errors may indicate that a function was declared but never called.");
203 
205  CommandArgumentData bp_id_arg;
206 
207  // Define the first (and only) variant of this arg.
208  bp_id_arg.arg_type = eArgTypeBreakpointID;
210 
211  // There is only one variant this argument could be; put it into the
212  // argument entry.
213  arg.push_back(bp_id_arg);
214 
215  // Push the data for the first argument into the m_arguments vector.
216  m_arguments.push_back(arg);
217  }
218 
219  ~CommandObjectBreakpointCommandAdd() override = default;
220 
221  Options *GetOptions() override { return &m_options; }
222 
223  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
224  StreamFileSP output_sp(io_handler.GetOutputStreamFile());
225  if (output_sp && interactive) {
226  output_sp->PutCString(g_reader_instructions);
227  output_sp->Flush();
228  }
229  }
230 
232  std::string &line) override {
233  io_handler.SetIsDone(true);
234 
235  std::vector<BreakpointOptions *> *bp_options_vec =
236  (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
237  for (BreakpointOptions *bp_options : *bp_options_vec) {
238  if (!bp_options)
239  continue;
240 
241  auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
242  cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
243  bp_options->SetCommandDataCallback(cmd_data);
244  }
245  }
246 
248  std::vector<BreakpointOptions *> &bp_options_vec,
249  CommandReturnObject &result) {
250  m_interpreter.GetLLDBCommandsFromIOHandler(
251  "> ", // Prompt
252  *this, // IOHandlerDelegate
253  true, // Run IOHandler in async mode
254  &bp_options_vec); // Baton for the "io_handler" that will be passed back
255  // into our IOHandlerDelegate functions
256  }
257 
258  /// Set a one-liner as the callback for the breakpoint.
259  void
260  SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
261  const char *oneliner) {
262  for (auto bp_options : bp_options_vec) {
263  auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
264 
265  cmd_data->user_source.AppendString(oneliner);
266  cmd_data->stop_on_error = m_options.m_stop_on_error;
267 
268  bp_options->SetCommandDataCallback(cmd_data);
269  }
270  }
271 
272  class CommandOptions : public Options {
273  public:
275  : Options(), m_use_commands(false), m_use_script_language(false),
276  m_script_language(eScriptLanguageNone), m_use_one_liner(false),
277  m_one_liner(), m_function_name() {}
278 
279  ~CommandOptions() override = default;
280 
281  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
282  ExecutionContext *execution_context) override {
283  Status error;
284  const int short_option = m_getopt_table[option_idx].val;
285 
286  switch (short_option) {
287  case 'o':
288  m_use_one_liner = true;
289  m_one_liner = option_arg;
290  break;
291 
292  case 's':
293  m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
294  option_arg, g_breakpoint_add_options[option_idx].enum_values,
295  eScriptLanguageNone, error);
296 
297  if (m_script_language == eScriptLanguagePython ||
298  m_script_language == eScriptLanguageDefault) {
299  m_use_script_language = true;
300  } else {
301  m_use_script_language = false;
302  }
303  break;
304 
305  case 'e': {
306  bool success = false;
307  m_stop_on_error =
308  OptionArgParser::ToBoolean(option_arg, false, &success);
309  if (!success)
311  "invalid value for stop-on-error: \"%s\"",
312  option_arg.str().c_str());
313  } break;
314 
315  case 'F':
316  m_use_one_liner = false;
317  m_use_script_language = true;
318  m_function_name.assign(option_arg);
319  break;
320 
321  case 'D':
322  m_use_dummy = true;
323  break;
324 
325  default:
326  break;
327  }
328  return error;
329  }
330 
331  void OptionParsingStarting(ExecutionContext *execution_context) override {
332  m_use_commands = true;
333  m_use_script_language = false;
334  m_script_language = eScriptLanguageNone;
335 
336  m_use_one_liner = false;
337  m_stop_on_error = true;
338  m_one_liner.clear();
339  m_function_name.clear();
340  m_use_dummy = false;
341  }
342 
343  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
344  return llvm::makeArrayRef(g_breakpoint_add_options);
345  }
346 
347  // Instance variables to hold the values for command options.
348 
352 
353  // Instance variables to hold the values for one_liner options.
355  std::string m_one_liner;
357  std::string m_function_name;
359  };
360 
361 protected:
362  bool DoExecute(Args &command, CommandReturnObject &result) override {
363  Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
364 
365  if (target == nullptr) {
366  result.AppendError("There is not a current executable; there are no "
367  "breakpoints to which to add commands");
369  return false;
370  }
371 
372  const BreakpointList &breakpoints = target->GetBreakpointList();
373  size_t num_breakpoints = breakpoints.GetSize();
374 
375  if (num_breakpoints == 0) {
376  result.AppendError("No breakpoints exist to have commands added");
378  return false;
379  }
380 
381  if (!m_options.m_use_script_language &&
382  !m_options.m_function_name.empty()) {
383  result.AppendError("need to enable scripting to have a function run as a "
384  "breakpoint command");
386  return false;
387  }
388 
389  BreakpointIDList valid_bp_ids;
390  CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
391  command, target, result, &valid_bp_ids,
392  BreakpointName::Permissions::PermissionKinds::listPerm);
393 
394  m_bp_options_vec.clear();
395 
396  if (result.Succeeded()) {
397  const size_t count = valid_bp_ids.GetSize();
398 
399  for (size_t i = 0; i < count; ++i) {
400  BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
401  if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
402  Breakpoint *bp =
403  target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
404  BreakpointOptions *bp_options = nullptr;
405  if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) {
406  // This breakpoint does not have an associated location.
407  bp_options = bp->GetOptions();
408  } else {
409  BreakpointLocationSP bp_loc_sp(
410  bp->FindLocationByID(cur_bp_id.GetLocationID()));
411  // This breakpoint does have an associated location. Get its
412  // breakpoint options.
413  if (bp_loc_sp)
414  bp_options = bp_loc_sp->GetLocationOptions();
415  }
416  if (bp_options)
417  m_bp_options_vec.push_back(bp_options);
418  }
419  }
420 
421  // If we are using script language, get the script interpreter in order
422  // to set or collect command callback. Otherwise, call the methods
423  // associated with this object.
424  if (m_options.m_use_script_language) {
425  ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter();
426  // Special handling for one-liner specified inline.
427  if (m_options.m_use_one_liner) {
428  script_interp->SetBreakpointCommandCallback(
429  m_bp_options_vec, m_options.m_one_liner.c_str());
430  } else if (!m_options.m_function_name.empty()) {
432  m_bp_options_vec, m_options.m_function_name.c_str());
433  } else {
435  m_bp_options_vec, result);
436  }
437  } else {
438  // Special handling for one-liner specified inline.
439  if (m_options.m_use_one_liner)
440  SetBreakpointCommandCallback(m_bp_options_vec,
441  m_options.m_one_liner.c_str());
442  else
443  CollectDataForBreakpointCommandCallback(m_bp_options_vec, result);
444  }
445  }
446 
447  return result.Succeeded();
448  }
449 
450 private:
451  CommandOptions m_options;
452  std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
453  // breakpoint options that
454  // we are currently
455  // collecting commands for. In the CollectData... calls we need to hand this
456  // off to the IOHandler, which may run asynchronously. So we have to have
457  // some way to keep it alive, and not leak it. Making it an ivar of the
458  // command object, which never goes away achieves this. Note that if we were
459  // able to run the same command concurrently in one interpreter we'd have to
460  // make this "per invocation". But there are many more reasons why it is not
461  // in general safe to do that in lldb at present, so it isn't worthwhile to
462  // come up with a more complex mechanism to address this particular weakness
463  // right now.
464  static const char *g_reader_instructions;
465 };
466 
467 const char *CommandObjectBreakpointCommandAdd::g_reader_instructions =
468  "Enter your debugger command(s). Type 'DONE' to end.\n";
469 
470 // CommandObjectBreakpointCommandDelete
471 
472 static constexpr OptionDefinition g_breakpoint_delete_options[] = {
473  // clang-format off
474  { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
475  // clang-format on
476 };
477 
479 public:
481  : CommandObjectParsed(interpreter, "delete",
482  "Delete the set of commands from a breakpoint.",
483  nullptr),
484  m_options() {
486  CommandArgumentData bp_id_arg;
487 
488  // Define the first (and only) variant of this arg.
489  bp_id_arg.arg_type = eArgTypeBreakpointID;
490  bp_id_arg.arg_repetition = eArgRepeatPlain;
491 
492  // There is only one variant this argument could be; put it into the
493  // argument entry.
494  arg.push_back(bp_id_arg);
495 
496  // Push the data for the first argument into the m_arguments vector.
497  m_arguments.push_back(arg);
498  }
499 
500  ~CommandObjectBreakpointCommandDelete() override = default;
501 
502  Options *GetOptions() override { return &m_options; }
503 
504  class CommandOptions : public Options {
505  public:
506  CommandOptions() : Options(), m_use_dummy(false) {}
507 
508  ~CommandOptions() override = default;
509 
510  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
511  ExecutionContext *execution_context) override {
512  Status error;
513  const int short_option = m_getopt_table[option_idx].val;
514 
515  switch (short_option) {
516  case 'D':
517  m_use_dummy = true;
518  break;
519 
520  default:
521  error.SetErrorStringWithFormat("unrecognized option '%c'",
522  short_option);
523  break;
524  }
525 
526  return error;
527  }
528 
529  void OptionParsingStarting(ExecutionContext *execution_context) override {
530  m_use_dummy = false;
531  }
532 
533  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
534  return llvm::makeArrayRef(g_breakpoint_delete_options);
535  }
536 
537  // Instance variables to hold the values for command options.
539  };
540 
541 protected:
542  bool DoExecute(Args &command, CommandReturnObject &result) override {
543  Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
544 
545  if (target == nullptr) {
546  result.AppendError("There is not a current executable; there are no "
547  "breakpoints from which to delete commands");
549  return false;
550  }
551 
552  const BreakpointList &breakpoints = target->GetBreakpointList();
553  size_t num_breakpoints = breakpoints.GetSize();
554 
555  if (num_breakpoints == 0) {
556  result.AppendError("No breakpoints exist to have commands deleted");
558  return false;
559  }
560 
561  if (command.empty()) {
562  result.AppendError(
563  "No breakpoint specified from which to delete the commands");
565  return false;
566  }
567 
568  BreakpointIDList valid_bp_ids;
569  CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
570  command, target, result, &valid_bp_ids,
571  BreakpointName::Permissions::PermissionKinds::listPerm);
572 
573  if (result.Succeeded()) {
574  const size_t count = valid_bp_ids.GetSize();
575  for (size_t i = 0; i < count; ++i) {
576  BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
577  if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
578  Breakpoint *bp =
579  target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
580  if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
581  BreakpointLocationSP bp_loc_sp(
582  bp->FindLocationByID(cur_bp_id.GetLocationID()));
583  if (bp_loc_sp)
584  bp_loc_sp->ClearCallback();
585  else {
586  result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
587  cur_bp_id.GetBreakpointID(),
588  cur_bp_id.GetLocationID());
590  return false;
591  }
592  } else {
593  bp->ClearCallback();
594  }
595  }
596  }
597  }
598  return result.Succeeded();
599  }
600 
601 private:
602  CommandOptions m_options;
603 };
604 
605 // CommandObjectBreakpointCommandList
606 
608 public:
610  : CommandObjectParsed(interpreter, "list", "List the script or set of "
611  "commands to be executed when "
612  "the breakpoint is hit.",
613  nullptr) {
615  CommandArgumentData bp_id_arg;
616 
617  // Define the first (and only) variant of this arg.
618  bp_id_arg.arg_type = eArgTypeBreakpointID;
619  bp_id_arg.arg_repetition = eArgRepeatPlain;
620 
621  // There is only one variant this argument could be; put it into the
622  // argument entry.
623  arg.push_back(bp_id_arg);
624 
625  // Push the data for the first argument into the m_arguments vector.
626  m_arguments.push_back(arg);
627  }
628 
629  ~CommandObjectBreakpointCommandList() override = default;
630 
631 protected:
632  bool DoExecute(Args &command, CommandReturnObject &result) override {
633  Target *target = GetDebugger().GetSelectedTarget().get();
634 
635  if (target == nullptr) {
636  result.AppendError("There is not a current executable; there are no "
637  "breakpoints for which to list commands");
639  return false;
640  }
641 
642  const BreakpointList &breakpoints = target->GetBreakpointList();
643  size_t num_breakpoints = breakpoints.GetSize();
644 
645  if (num_breakpoints == 0) {
646  result.AppendError("No breakpoints exist for which to list commands");
648  return false;
649  }
650 
651  if (command.empty()) {
652  result.AppendError(
653  "No breakpoint specified for which to list the commands");
655  return false;
656  }
657 
658  BreakpointIDList valid_bp_ids;
659  CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
660  command, target, result, &valid_bp_ids,
661  BreakpointName::Permissions::PermissionKinds::listPerm);
662 
663  if (result.Succeeded()) {
664  const size_t count = valid_bp_ids.GetSize();
665  for (size_t i = 0; i < count; ++i) {
666  BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
667  if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
668  Breakpoint *bp =
669  target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
670 
671  if (bp) {
672  BreakpointLocationSP bp_loc_sp;
673  if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
674  bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID());
675  if (!bp_loc_sp)
676  {
677  result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
678  cur_bp_id.GetBreakpointID(),
679  cur_bp_id.GetLocationID());
681  return false;
682  }
683  }
684 
685  StreamString id_str;
686  BreakpointID::GetCanonicalReference(&id_str,
687  cur_bp_id.GetBreakpointID(),
688  cur_bp_id.GetLocationID());
689  const Baton *baton = nullptr;
690  if (bp_loc_sp)
691  baton = bp_loc_sp
692  ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
693  ->GetBaton();
694  else
695  baton = bp->GetOptions()->GetBaton();
696 
697  if (baton) {
698  result.GetOutputStream().Printf("Breakpoint %s:\n",
699  id_str.GetData());
700  result.GetOutputStream().IndentMore();
701  baton->GetDescription(&result.GetOutputStream(),
703  result.GetOutputStream().IndentLess();
704  } else {
706  "Breakpoint %s does not have an associated command.\n",
707  id_str.GetData());
708  }
709  }
711  } else {
712  result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n",
713  cur_bp_id.GetBreakpointID());
715  }
716  }
717  }
718 
719  return result.Succeeded();
720  }
721 };
722 
723 // CommandObjectBreakpointCommand
724 
725 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(
726  CommandInterpreter &interpreter)
728  interpreter, "command", "Commands for adding, removing and listing "
729  "LLDB commands executed when a breakpoint is "
730  "hit.",
731  "command <sub-command> [<sub-command-options>] <breakpoint-id>") {
732  CommandObjectSP add_command_object(
733  new CommandObjectBreakpointCommandAdd(interpreter));
734  CommandObjectSP delete_command_object(
735  new CommandObjectBreakpointCommandDelete(interpreter));
736  CommandObjectSP list_command_object(
737  new CommandObjectBreakpointCommandList(interpreter));
738 
739  add_command_object->SetCommandName("breakpoint command add");
740  delete_command_object->SetCommandName("breakpoint command delete");
741  list_command_object->SetCommandName("breakpoint command list");
742 
743  LoadSubCommand("add", add_command_object);
744  LoadSubCommand("delete", delete_command_object);
745  LoadSubCommand("list", list_command_object);
746 }
747 
BreakpointOptions * GetOptions()
Returns the BreakpointOptions structure set at the breakpoint level.
Definition: Breakpoint.cpp:446
static constexpr OptionDefinition g_breakpoint_delete_options[]
std::vector< CommandArgumentData > CommandArgumentEntry
A command line argument class.
Definition: Args.h:32
static constexpr OptionDefinition g_breakpoint_add_options[]
bool empty() const
Definition: Args.h:113
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
BreakpointList & GetBreakpointList(bool internal=false)
Definition: Target.cpp:283
void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override
Called when a line or lines have been retrieved.
static constexpr OptionEnumValueElement g_script_option_enumeration[]
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
size_t GetSize() const
Returns the number of elements in this breakpoint list.
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void SetBreakpointCommandCallback(std::vector< BreakpointOptions *> &bp_options_vec, const char *oneliner)
Set a one-liner as the callback for the breakpoint.
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:78
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
lldb::break_id_t GetBreakpointID() const
Definition: BreakpointID.h:30
bool DoExecute(Args &command, CommandReturnObject &result) override
Baton * GetBaton()
Fetch the baton from the callback.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
lldb::BreakpointLocationSP FindLocationByID(lldb::break_id_t bp_loc_id)
Find a breakpoint location for a given breakpoint location ID.
Definition: Breakpoint.cpp:267
void OptionParsingStarting(ExecutionContext *execution_context) override
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
const char * GetData() const
Definition: StreamString.h:43
A delegate class for use with IOHandler subclasses.
Definition: IOHandler.h:188
const BreakpointID & GetBreakpointIDAtIndex(size_t index) const
static constexpr OptionEnumValues ScriptOptionEnum()
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
lldb::BreakpointSP GetBreakpointByID(lldb::break_id_t break_id)
Definition: Target.cpp:297
CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
CommandObjectBreakpointCommandList(CommandInterpreter &interpreter)
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
void IndentLess(int amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:221
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
virtual void CollectDataForBreakpointCommandCallback(std::vector< BreakpointOptions *> &options, CommandReturnObject &result)
void OptionParsingStarting(ExecutionContext *execution_context) override
General Outline: Allows adding and removing breakpoints and find by ID and index. ...
lldb::break_id_t GetLocationID() const
Definition: BreakpointID.h:32
#define LLDB_OPT_SET_2
Definition: lldb-defines.h:112
Status SetBreakpointCommandCallback(std::vector< BreakpointOptions *> &bp_options_vec, const char *callback_text)
Set the specified text as the callback for the breakpoint.
A command line option parsing protocol class.
Definition: Options.h:62
void void AppendError(llvm::StringRef in_string)
CommandObjectBreakpointCommandDelete(CommandInterpreter &interpreter)
"lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a breakpoint or breakpoint lo...
Definition: SBAddress.h:15
virtual void SetIsDone(bool b)
Definition: IOHandler.h:86
void SetBreakpointCommandCallbackFunction(std::vector< BreakpointOptions *> &bp_options_vec, const char *function_name)
bool DoExecute(Args &command, CommandReturnObject &result) override
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:110
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:49
A class designed to wrap callback batons so they can cleanup any acquired resources.
Definition: Baton.h:33
lldb::StreamFileSP & GetOutputStreamFile()
Definition: IOHandler.cpp:126
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void IndentMore(int amount=2)
Increment the current indentation level.
Definition: Stream.cpp:218
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:111
bool DoExecute(Args &command, CommandReturnObject &result) override
void CollectDataForBreakpointCommandCallback(std::vector< BreakpointOptions *> &bp_options_vec, CommandReturnObject &result)
void SetStatus(lldb::ReturnStatus status)
An error handling class.
Definition: Status.h:44