1 //===-- CommandObjectBreakpointCommand.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
13
14 #include "CommandObjectBreakpointCommand.h"
15 #include "CommandObjectBreakpoint.h"
16
17 #include "lldb/Core/IOHandler.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Interpreter/CommandReturnObject.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Breakpoint/BreakpointIDList.h"
23 #include "lldb/Breakpoint/Breakpoint.h"
24 #include "lldb/Breakpoint/BreakpointLocation.h"
25 #include "lldb/Breakpoint/StoppointCallbackContext.h"
26 #include "lldb/Core/State.h"
27
28 using namespace lldb;
29 using namespace lldb_private;
30
31 //-------------------------------------------------------------------------
32 // CommandObjectBreakpointCommandAdd
33 //-------------------------------------------------------------------------
34
35
36 class CommandObjectBreakpointCommandAdd :
37 public CommandObjectParsed,
38 public IOHandlerDelegateMultiline
39 {
40 public:
41
CommandObjectBreakpointCommandAdd(CommandInterpreter & interpreter)42 CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
43 CommandObjectParsed (interpreter,
44 "add",
45 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
46 " If no breakpoint is specified, adds the commands to the last created breakpoint.",
47 NULL),
48 IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
49 m_options (interpreter)
50 {
51 SetHelpLong (
52 R"(
53 General information about entering breakpoint commands
54 ------------------------------------------------------
55
56 )" "This command will prompt for commands to be executed when the specified \
57 breakpoint is hit. Each command is typed on its own line following the '> ' \
58 prompt until 'DONE' is entered." R"(
59
60 )" "Syntactic errors may not be detected when initially entered, and many \
61 malformed commands can silently fail when executed. If your breakpoint commands \
62 do not appear to be executing, double-check the command syntax." R"(
63
64 )" "Note: You may enter any debugger command exactly as you would at the debugger \
65 prompt. There is no limit to the number of commands supplied, but do NOT enter \
66 more than one command per line." R"(
67
68 Special information about PYTHON breakpoint commands
69 ----------------------------------------------------
70
71 )" "You may enter either one or more lines of Python, including function \
72 definitions or calls to functions that will have been imported by the time \
73 the code executes. Single line breakpoint commands will be interpreted 'as is' \
74 when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
75 generated function, and a call to the function will be attached to the breakpoint." R"(
76
77 This auto-generated function is passed in three arguments:
78
79 frame: an lldb.SBFrame object for the frame which hit breakpoint.
80
81 bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
82
83 dict: the python session dictionary hit.
84
85 )" "When specifying a python function with the --python-function option, you need \
86 to supply the function name prepended by the module name:" R"(
87
88 --python-function myutils.breakpoint_callback
89
90 The function itself must have the following prototype:
91
92 def breakpoint_callback(frame, bp_loc, dict):
93 # Your code goes here
94
95 )" "The arguments are the same as the arguments passed to generated functions as \
96 described above. Note that the global variable 'lldb.frame' will NOT be updated when \
97 this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
98 can get you to the thread via frame.GetThread(), the thread can get you to the \
99 process via thread.GetProcess(), and the process can get you back to the target \
100 via process.GetTarget()." R"(
101
102 )" "Important Note: As Python code gets collected into functions, access to global \
103 variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
104 Python syntax, including indentation, when entering Python breakpoint commands." R"(
105
106 Example Python one-line breakpoint command:
107
108 (lldb) breakpoint command add -s python 1
109 Enter your Python command(s). Type 'DONE' to end.
110 > print "Hit this breakpoint!"
111 > DONE
112
113 As a convenience, this also works for a short Python one-liner:
114
115 (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
116 (lldb) run
117 Launching '.../a.out' (x86_64)
118 (lldb) Fri Sep 10 12:17:45 2010
119 Process 21778 Stopped
120 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
121 36
122 37 int c(int val)
123 38 {
124 39 -> return val + 3;
125 40 }
126 41
127 42 int main (int argc, char const *argv[])
128
129 Example multiple line Python breakpoint command:
130
131 (lldb) breakpoint command add -s p 1
132 Enter your Python command(s). Type 'DONE' to end.
133 > global bp_count
134 > bp_count = bp_count + 1
135 > print "Hit this breakpoint " + repr(bp_count) + " times!"
136 > DONE
137
138 Example multiple line Python breakpoint command, using function definition:
139
140 (lldb) breakpoint command add -s python 1
141 Enter your Python command(s). Type 'DONE' to end.
142 > def breakpoint_output (bp_no):
143 > out_string = "Hit breakpoint number " + repr (bp_no)
144 > print out_string
145 > return True
146 > breakpoint_output (1)
147 > DONE
148
149 )" "In this case, since there is a reference to a global variable, \
150 'bp_count', you will also need to make sure 'bp_count' exists and is \
151 initialized:" R"(
152
153 (lldb) script
154 >>> bp_count = 0
155 >>> quit()
156
157 )" "Your Python code, however organized, can optionally return a value. \
158 If the returned value is False, that tells LLDB not to stop at the breakpoint \
159 to which the code is associated. Returning anything other than False, or even \
160 returning None, or even omitting a return statement entirely, will cause \
161 LLDB to stop." R"(
162
163 )" "Final Note: A warning that no breakpoint command was generated when there \
164 are no syntax errors may indicate that a function was declared but never called."
165 );
166
167 CommandArgumentEntry arg;
168 CommandArgumentData bp_id_arg;
169
170 // Define the first (and only) variant of this arg.
171 bp_id_arg.arg_type = eArgTypeBreakpointID;
172 bp_id_arg.arg_repetition = eArgRepeatOptional;
173
174 // There is only one variant this argument could be; put it into the argument entry.
175 arg.push_back (bp_id_arg);
176
177 // Push the data for the first argument into the m_arguments vector.
178 m_arguments.push_back (arg);
179 }
180
181 virtual
~CommandObjectBreakpointCommandAdd()182 ~CommandObjectBreakpointCommandAdd () {}
183
184 virtual Options *
GetOptions()185 GetOptions ()
186 {
187 return &m_options;
188 }
189
190 virtual void
IOHandlerActivated(IOHandler & io_handler)191 IOHandlerActivated (IOHandler &io_handler)
192 {
193 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
194 if (output_sp)
195 {
196 output_sp->PutCString(g_reader_instructions);
197 output_sp->Flush();
198 }
199 }
200
201
202 virtual void
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)203 IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
204 {
205 io_handler.SetIsDone(true);
206
207 std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
208 for (BreakpointOptions *bp_options : *bp_options_vec)
209 {
210 if (!bp_options)
211 continue;
212
213 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
214 if (data_ap.get())
215 {
216 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
217 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
218 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
219 }
220 }
221 }
222
223 void
CollectDataForBreakpointCommandCallback(std::vector<BreakpointOptions * > & bp_options_vec,CommandReturnObject & result)224 CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
225 CommandReturnObject &result)
226 {
227 m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
228 *this, // IOHandlerDelegate
229 true, // Run IOHandler in async mode
230 &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
231 }
232
233 /// Set a one-liner as the callback for the breakpoint.
234 void
SetBreakpointCommandCallback(std::vector<BreakpointOptions * > & bp_options_vec,const char * oneliner)235 SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
236 const char *oneliner)
237 {
238 for (auto bp_options : bp_options_vec)
239 {
240 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
241
242 // It's necessary to set both user_source and script_source to the oneliner.
243 // The former is used to generate callback description (as in breakpoint command list)
244 // while the latter is used for Python to interpret during the actual callback.
245 data_ap->user_source.AppendString (oneliner);
246 data_ap->script_source.assign (oneliner);
247 data_ap->stop_on_error = m_options.m_stop_on_error;
248
249 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
250 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
251 }
252 return;
253 }
254
255 static bool
BreakpointOptionsCallbackFunction(void * baton,StoppointCallbackContext * context,lldb::user_id_t break_id,lldb::user_id_t break_loc_id)256 BreakpointOptionsCallbackFunction (void *baton,
257 StoppointCallbackContext *context,
258 lldb::user_id_t break_id,
259 lldb::user_id_t break_loc_id)
260 {
261 bool ret_value = true;
262 if (baton == NULL)
263 return true;
264
265
266 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
267 StringList &commands = data->user_source;
268
269 if (commands.GetSize() > 0)
270 {
271 ExecutionContext exe_ctx (context->exe_ctx_ref);
272 Target *target = exe_ctx.GetTargetPtr();
273 if (target)
274 {
275 CommandReturnObject result;
276 Debugger &debugger = target->GetDebugger();
277 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
278 // if the debugger is set up that way.
279
280 StreamSP output_stream (debugger.GetAsyncOutputStream());
281 StreamSP error_stream (debugger.GetAsyncErrorStream());
282 result.SetImmediateOutputStream (output_stream);
283 result.SetImmediateErrorStream (error_stream);
284
285 CommandInterpreterRunOptions options;
286 options.SetStopOnContinue(true);
287 options.SetStopOnError (data->stop_on_error);
288 options.SetEchoCommands (true);
289 options.SetPrintResults (true);
290 options.SetAddToHistory (false);
291
292 debugger.GetCommandInterpreter().HandleCommands (commands,
293 &exe_ctx,
294 options,
295 result);
296 result.GetImmediateOutputStream()->Flush();
297 result.GetImmediateErrorStream()->Flush();
298 }
299 }
300 return ret_value;
301 }
302
303 class CommandOptions : public Options
304 {
305 public:
306
CommandOptions(CommandInterpreter & interpreter)307 CommandOptions (CommandInterpreter &interpreter) :
308 Options (interpreter),
309 m_use_commands (false),
310 m_use_script_language (false),
311 m_script_language (eScriptLanguageNone),
312 m_use_one_liner (false),
313 m_one_liner(),
314 m_function_name()
315 {
316 }
317
318 virtual
~CommandOptions()319 ~CommandOptions () {}
320
321 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)322 SetOptionValue (uint32_t option_idx, const char *option_arg)
323 {
324 Error error;
325 const int short_option = m_getopt_table[option_idx].val;
326
327 switch (short_option)
328 {
329 case 'o':
330 m_use_one_liner = true;
331 m_one_liner = option_arg;
332 break;
333
334 case 's':
335 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
336 g_option_table[option_idx].enum_values,
337 eScriptLanguageNone,
338 error);
339
340 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
341 {
342 m_use_script_language = true;
343 }
344 else
345 {
346 m_use_script_language = false;
347 }
348 break;
349
350 case 'e':
351 {
352 bool success = false;
353 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
354 if (!success)
355 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
356 }
357 break;
358
359 case 'F':
360 {
361 m_use_one_liner = false;
362 m_use_script_language = true;
363 m_function_name.assign(option_arg);
364 }
365 break;
366
367 case 'D':
368 m_use_dummy = true;
369 break;
370
371 default:
372 break;
373 }
374 return error;
375 }
376 void
OptionParsingStarting()377 OptionParsingStarting ()
378 {
379 m_use_commands = true;
380 m_use_script_language = false;
381 m_script_language = eScriptLanguageNone;
382
383 m_use_one_liner = false;
384 m_stop_on_error = true;
385 m_one_liner.clear();
386 m_function_name.clear();
387 m_use_dummy = false;
388 }
389
390 const OptionDefinition*
GetDefinitions()391 GetDefinitions ()
392 {
393 return g_option_table;
394 }
395
396 // Options table: Required for subclasses of Options.
397
398 static OptionDefinition g_option_table[];
399
400 // Instance variables to hold the values for command options.
401
402 bool m_use_commands;
403 bool m_use_script_language;
404 lldb::ScriptLanguage m_script_language;
405
406 // Instance variables to hold the values for one_liner options.
407 bool m_use_one_liner;
408 std::string m_one_liner;
409 bool m_stop_on_error;
410 std::string m_function_name;
411 bool m_use_dummy;
412 };
413
414 protected:
415 virtual bool
DoExecute(Args & command,CommandReturnObject & result)416 DoExecute (Args& command, CommandReturnObject &result)
417 {
418 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
419
420 if (target == NULL)
421 {
422 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
423 result.SetStatus (eReturnStatusFailed);
424 return false;
425 }
426
427 const BreakpointList &breakpoints = target->GetBreakpointList();
428 size_t num_breakpoints = breakpoints.GetSize();
429
430 if (num_breakpoints == 0)
431 {
432 result.AppendError ("No breakpoints exist to have commands added");
433 result.SetStatus (eReturnStatusFailed);
434 return false;
435 }
436
437 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
438 {
439 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
440 result.SetStatus (eReturnStatusFailed);
441 return false;
442 }
443
444 BreakpointIDList valid_bp_ids;
445 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
446
447 m_bp_options_vec.clear();
448
449 if (result.Succeeded())
450 {
451 const size_t count = valid_bp_ids.GetSize();
452
453 for (size_t i = 0; i < count; ++i)
454 {
455 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
456 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
457 {
458 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
459 BreakpointOptions *bp_options = NULL;
460 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
461 {
462 // This breakpoint does not have an associated location.
463 bp_options = bp->GetOptions();
464 }
465 else
466 {
467 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
468 // This breakpoint does have an associated location.
469 // Get its breakpoint options.
470 if (bp_loc_sp)
471 bp_options = bp_loc_sp->GetLocationOptions();
472 }
473 if (bp_options)
474 m_bp_options_vec.push_back (bp_options);
475 }
476 }
477
478 // If we are using script language, get the script interpreter
479 // in order to set or collect command callback. Otherwise, call
480 // the methods associated with this object.
481 if (m_options.m_use_script_language)
482 {
483 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
484 // Special handling for one-liner specified inline.
485 if (m_options.m_use_one_liner)
486 {
487 script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
488 m_options.m_one_liner.c_str());
489 }
490 else if (m_options.m_function_name.size())
491 {
492 script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
493 m_options.m_function_name.c_str());
494 }
495 else
496 {
497 script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
498 result);
499 }
500 }
501 else
502 {
503 // Special handling for one-liner specified inline.
504 if (m_options.m_use_one_liner)
505 SetBreakpointCommandCallback (m_bp_options_vec,
506 m_options.m_one_liner.c_str());
507 else
508 CollectDataForBreakpointCommandCallback (m_bp_options_vec,
509 result);
510 }
511
512 }
513
514 return result.Succeeded();
515 }
516
517 private:
518 CommandOptions m_options;
519 std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently
520 // collecting commands for. In the CollectData... calls we need
521 // to hand this off to the IOHandler, which may run asynchronously.
522 // So we have to have some way to keep it alive, and not leak it.
523 // Making it an ivar of the command object, which never goes away
524 // achieves this. Note that if we were able to run
525 // the same command concurrently in one interpreter we'd have to
526 // make this "per invocation". But there are many more reasons
527 // why it is not in general safe to do that in lldb at present,
528 // so it isn't worthwhile to come up with a more complex mechanism
529 // to address this particular weakness right now.
530 static const char *g_reader_instructions;
531
532 };
533
534 const char *
535 CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n";
536
537 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
538 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
539
540 static OptionEnumValueElement
541 g_script_option_enumeration[4] =
542 {
543 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
544 { eScriptLanguagePython, "python", "Commands are in the Python language."},
545 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
546 { 0, NULL, NULL }
547 };
548
549 OptionDefinition
550 CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
551 {
552 { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
553 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
554
555 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
556 "Specify whether breakpoint command execution should terminate on error." },
557
558 { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
559 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
560
561 { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
562 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
563
564 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
565 "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
566
567 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
568 };
569
570 //-------------------------------------------------------------------------
571 // CommandObjectBreakpointCommandDelete
572 //-------------------------------------------------------------------------
573
574 class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
575 {
576 public:
CommandObjectBreakpointCommandDelete(CommandInterpreter & interpreter)577 CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
578 CommandObjectParsed (interpreter,
579 "delete",
580 "Delete the set of commands from a breakpoint.",
581 NULL),
582 m_options (interpreter)
583 {
584 CommandArgumentEntry arg;
585 CommandArgumentData bp_id_arg;
586
587 // Define the first (and only) variant of this arg.
588 bp_id_arg.arg_type = eArgTypeBreakpointID;
589 bp_id_arg.arg_repetition = eArgRepeatPlain;
590
591 // There is only one variant this argument could be; put it into the argument entry.
592 arg.push_back (bp_id_arg);
593
594 // Push the data for the first argument into the m_arguments vector.
595 m_arguments.push_back (arg);
596 }
597
598
599 virtual
~CommandObjectBreakpointCommandDelete()600 ~CommandObjectBreakpointCommandDelete () {}
601
602 virtual Options *
GetOptions()603 GetOptions ()
604 {
605 return &m_options;
606 }
607
608 class CommandOptions : public Options
609 {
610 public:
611
CommandOptions(CommandInterpreter & interpreter)612 CommandOptions (CommandInterpreter &interpreter) :
613 Options (interpreter),
614 m_use_dummy (false)
615 {
616 }
617
618 virtual
~CommandOptions()619 ~CommandOptions () {}
620
621 virtual Error
SetOptionValue(uint32_t option_idx,const char * option_arg)622 SetOptionValue (uint32_t option_idx, const char *option_arg)
623 {
624 Error error;
625 const int short_option = m_getopt_table[option_idx].val;
626
627 switch (short_option)
628 {
629 case 'D':
630 m_use_dummy = true;
631 break;
632
633 default:
634 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
635 break;
636 }
637
638 return error;
639 }
640
641 void
OptionParsingStarting()642 OptionParsingStarting ()
643 {
644 m_use_dummy = false;
645 }
646
647 const OptionDefinition*
GetDefinitions()648 GetDefinitions ()
649 {
650 return g_option_table;
651 }
652
653 // Options table: Required for subclasses of Options.
654
655 static OptionDefinition g_option_table[];
656
657 // Instance variables to hold the values for command options.
658 bool m_use_dummy;
659 };
660
661 protected:
662 virtual bool
DoExecute(Args & command,CommandReturnObject & result)663 DoExecute (Args& command, CommandReturnObject &result)
664 {
665 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
666
667 if (target == NULL)
668 {
669 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
670 result.SetStatus (eReturnStatusFailed);
671 return false;
672 }
673
674 const BreakpointList &breakpoints = target->GetBreakpointList();
675 size_t num_breakpoints = breakpoints.GetSize();
676
677 if (num_breakpoints == 0)
678 {
679 result.AppendError ("No breakpoints exist to have commands deleted");
680 result.SetStatus (eReturnStatusFailed);
681 return false;
682 }
683
684 if (command.GetArgumentCount() == 0)
685 {
686 result.AppendError ("No breakpoint specified from which to delete the commands");
687 result.SetStatus (eReturnStatusFailed);
688 return false;
689 }
690
691 BreakpointIDList valid_bp_ids;
692 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
693
694 if (result.Succeeded())
695 {
696 const size_t count = valid_bp_ids.GetSize();
697 for (size_t i = 0; i < count; ++i)
698 {
699 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
700 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
701 {
702 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
703 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
704 {
705 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
706 if (bp_loc_sp)
707 bp_loc_sp->ClearCallback();
708 else
709 {
710 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
711 cur_bp_id.GetBreakpointID(),
712 cur_bp_id.GetLocationID());
713 result.SetStatus (eReturnStatusFailed);
714 return false;
715 }
716 }
717 else
718 {
719 bp->ClearCallback();
720 }
721 }
722 }
723 }
724 return result.Succeeded();
725 }
726 private:
727 CommandOptions m_options;
728 };
729
730 OptionDefinition
731 CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
732 {
733 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
734 "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
735
736 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
737 };
738
739
740 //-------------------------------------------------------------------------
741 // CommandObjectBreakpointCommandList
742 //-------------------------------------------------------------------------
743
744 class CommandObjectBreakpointCommandList : public CommandObjectParsed
745 {
746 public:
CommandObjectBreakpointCommandList(CommandInterpreter & interpreter)747 CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
748 CommandObjectParsed (interpreter,
749 "list",
750 "List the script or set of commands to be executed when the breakpoint is hit.",
751 NULL)
752 {
753 CommandArgumentEntry arg;
754 CommandArgumentData bp_id_arg;
755
756 // Define the first (and only) variant of this arg.
757 bp_id_arg.arg_type = eArgTypeBreakpointID;
758 bp_id_arg.arg_repetition = eArgRepeatPlain;
759
760 // There is only one variant this argument could be; put it into the argument entry.
761 arg.push_back (bp_id_arg);
762
763 // Push the data for the first argument into the m_arguments vector.
764 m_arguments.push_back (arg);
765 }
766
767 virtual
~CommandObjectBreakpointCommandList()768 ~CommandObjectBreakpointCommandList () {}
769
770 protected:
771 virtual bool
DoExecute(Args & command,CommandReturnObject & result)772 DoExecute (Args& command,
773 CommandReturnObject &result)
774 {
775 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
776
777 if (target == NULL)
778 {
779 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
780 result.SetStatus (eReturnStatusFailed);
781 return false;
782 }
783
784 const BreakpointList &breakpoints = target->GetBreakpointList();
785 size_t num_breakpoints = breakpoints.GetSize();
786
787 if (num_breakpoints == 0)
788 {
789 result.AppendError ("No breakpoints exist for which to list commands");
790 result.SetStatus (eReturnStatusFailed);
791 return false;
792 }
793
794 if (command.GetArgumentCount() == 0)
795 {
796 result.AppendError ("No breakpoint specified for which to list the commands");
797 result.SetStatus (eReturnStatusFailed);
798 return false;
799 }
800
801 BreakpointIDList valid_bp_ids;
802 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
803
804 if (result.Succeeded())
805 {
806 const size_t count = valid_bp_ids.GetSize();
807 for (size_t i = 0; i < count; ++i)
808 {
809 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
810 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
811 {
812 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
813
814 if (bp)
815 {
816 const BreakpointOptions *bp_options = NULL;
817 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
818 {
819 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
820 if (bp_loc_sp)
821 bp_options = bp_loc_sp->GetOptionsNoCreate();
822 else
823 {
824 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
825 cur_bp_id.GetBreakpointID(),
826 cur_bp_id.GetLocationID());
827 result.SetStatus (eReturnStatusFailed);
828 return false;
829 }
830 }
831 else
832 {
833 bp_options = bp->GetOptions();
834 }
835
836 if (bp_options)
837 {
838 StreamString id_str;
839 BreakpointID::GetCanonicalReference (&id_str,
840 cur_bp_id.GetBreakpointID(),
841 cur_bp_id.GetLocationID());
842 const Baton *baton = bp_options->GetBaton();
843 if (baton)
844 {
845 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
846 result.GetOutputStream().IndentMore ();
847 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
848 result.GetOutputStream().IndentLess ();
849 }
850 else
851 {
852 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
853 id_str.GetData());
854 }
855 }
856 result.SetStatus (eReturnStatusSuccessFinishResult);
857 }
858 else
859 {
860 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
861 result.SetStatus (eReturnStatusFailed);
862 }
863
864 }
865 }
866 }
867
868 return result.Succeeded();
869 }
870 };
871
872 //-------------------------------------------------------------------------
873 // CommandObjectBreakpointCommand
874 //-------------------------------------------------------------------------
875
CommandObjectBreakpointCommand(CommandInterpreter & interpreter)876 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
877 CommandObjectMultiword (interpreter,
878 "command",
879 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
880 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
881 {
882 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
883 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
884 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
885
886 add_command_object->SetCommandName ("breakpoint command add");
887 delete_command_object->SetCommandName ("breakpoint command delete");
888 list_command_object->SetCommandName ("breakpoint command list");
889
890 LoadSubCommand ("add", add_command_object);
891 LoadSubCommand ("delete", delete_command_object);
892 LoadSubCommand ("list", list_command_object);
893 }
894
~CommandObjectBreakpointCommand()895 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
896 {
897 }
898
899
900