blob: 0941f38d65e95383ff8afdc749f150203fa10499 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012// C Includes
13// C++ Includes
14
15
16#include "CommandObjectBreakpointCommand.h"
17#include "CommandObjectBreakpoint.h"
18
Greg Clayton44d93782014-01-27 23:43:24 +000019#include "lldb/Core/IOHandler.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Target/Thread.h"
24#include "lldb/Breakpoint/BreakpointIDList.h"
25#include "lldb/Breakpoint/Breakpoint.h"
26#include "lldb/Breakpoint/BreakpointLocation.h"
27#include "lldb/Breakpoint/StoppointCallbackContext.h"
28#include "lldb/Core/State.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034// CommandObjectBreakpointCommandAdd
35//-------------------------------------------------------------------------
36
37
Greg Clayton44d93782014-01-27 23:43:24 +000038class CommandObjectBreakpointCommandAdd :
39 public CommandObjectParsed,
40 public IOHandlerDelegateMultiline
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041{
Jim Ingham5a988412012-06-08 21:56:10 +000042public:
43
44 CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
45 CommandObjectParsed (interpreter,
46 "add",
47 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
48 NULL),
Greg Claytonc3d874a2014-05-08 16:59:00 +000049 IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
Jim Ingham5a988412012-06-08 21:56:10 +000050 m_options (interpreter)
51 {
52 SetHelpLong (
Greg Clayton13b12132012-10-26 17:53:21 +000053"\nGeneral information about entering breakpoint commands\n\
54------------------------------------------------------\n\
55\n\
56This command will cause you to be prompted to enter the command or set of\n\
57commands you wish to be executed when the specified breakpoint is hit. You\n\
58will be told to enter your command(s), and will see a '> 'prompt. Because\n\
59you can enter one or many commands to be executed when a breakpoint is hit,\n\
60you will continue to be prompted after each new-line that you enter, until you\n\
61enter the word 'DONE', which will cause the commands you have entered to be\n\
62stored with the breakpoint and executed when the breakpoint is hit.\n\
63\n\
64Syntax checking is not necessarily done when breakpoint commands are entered.\n\
65An improperly written breakpoint command will attempt to get executed when the\n\
66breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
67not appear to be getting executed, go back and check your syntax.\n\
68\n\
69Special information about PYTHON breakpoint commands\n\
70----------------------------------------------------\n\
71\n\
72You may enter either one line of Python, multiple lines of Python (including\n\
73function definitions), or specify a Python function in a module that has already,\n\
74or will be imported. If you enter a single line of Python, that will be passed\n\
75to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
76function definitions, they will be passed to the Python interpreter as soon as\n\
77you finish entering the breakpoint command, and they can be called later (don't\n\
78forget to add calls to them, if you want them called when the breakpoint is\n\
79hit). If you enter multiple lines of Python that are not function definitions,\n\
80they will be collected into a new, automatically generated Python function, and\n\
81a call to the newly generated function will be attached to the breakpoint.\n\
82\n\
83\n\
84This auto-generated function is passed in three arguments:\n\
85\n\
86 frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
87 bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
88 location that was hit.\n\
89 dict: the python session dictionary hit.\n\
90\n\
91When specifying a python function with the --python-function option, you need\n\
92to supply the function name prepended by the module name. So if you import a\n\
93module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
94specify the option as:\n\
95\n\
96 --python-function myutils.breakpoint_callback\n\
97\n\
98The function itself must have the following prototype:\n\
99\n\
100def breakpoint_callback(frame, bp_loc, dict):\n\
101 # Your code goes here\n\
102\n\
103The arguments are the same as the 3 auto generation function arguments listed\n\
104above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
105function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
106can get you to the thread (frame.GetThread()), the thread can get you to the\n\
107process (thread.GetProcess()), and the process can get you back to the target\n\
108(process.GetTarget()).\n\
109\n\
110Important Note: Because loose Python code gets collected into functions, if you\n\
111want to access global variables in the 'loose' code, you need to specify that\n\
112they are global, using the 'global' keyword. Be sure to use correct Python\n\
113syntax, including indentation, when entering Python breakpoint commands.\n\
114\n\
115As a third option, you can pass the name of an already existing Python function\n\
116and that function will be attached to the breakpoint. It will get passed the\n\
117frame and bp_loc arguments mentioned above.\n\
118\n\
119Example Python one-line breakpoint command:\n\
120\n\
121(lldb) breakpoint command add -s python 1\n\
122Enter your Python command(s). Type 'DONE' to end.\n\
123> print \"Hit this breakpoint!\"\n\
124> DONE\n\
125\n\
126As a convenience, this also works for a short Python one-liner:\n\
127(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
128(lldb) run\n\
129Launching '.../a.out' (x86_64)\n\
130(lldb) Fri Sep 10 12:17:45 2010\n\
131Process 21778 Stopped\n\
132* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
Johnny Chen3495f252010-09-10 19:34:12 +0000133 36 \n\
134 37 int c(int val)\n\
135 38 {\n\
136 39 -> return val + 3;\n\
137 40 }\n\
138 41 \n\
139 42 int main (int argc, char const *argv[])\n\
Greg Clayton13b12132012-10-26 17:53:21 +0000140(lldb)\n\
141\n\
142Example multiple line Python breakpoint command, using function definition:\n\
143\n\
144(lldb) breakpoint command add -s python 1\n\
145Enter your Python command(s). Type 'DONE' to end.\n\
146> def breakpoint_output (bp_no):\n\
147> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
148> print out_string\n\
149> return True\n\
150> breakpoint_output (1)\n\
151> DONE\n\
152\n\
153\n\
154Example multiple line Python breakpoint command, using 'loose' Python:\n\
155\n\
156(lldb) breakpoint command add -s p 1\n\
157Enter your Python command(s). Type 'DONE' to end.\n\
158> global bp_count\n\
159> bp_count = bp_count + 1\n\
160> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
161> DONE\n\
162\n\
163In this case, since there is a reference to a global variable,\n\
164'bp_count', you will also need to make sure 'bp_count' exists and is\n\
165initialized:\n\
166\n\
167(lldb) script\n\
168>>> bp_count = 0\n\
169>>> quit()\n\
170\n\
171(lldb)\n\
172\n\
173\n\
Enrico Granataf5f560c2013-05-16 23:09:09 +0000174Your Python code, however organized, can optionally return a value.\n\
175If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
176to which the code is associated. Returning anything other than False, or even\n\
177returning None, or even omitting a return statement entirely, will cause\n\
178LLDB to stop.\n\
179\n\
Greg Clayton13b12132012-10-26 17:53:21 +0000180Final Note: If you get a warning that no breakpoint command was generated, but\n\
181you did not get any syntax errors, you probably forgot to add a call to your\n\
182functions.\n\
183\n\
184Special information about debugger command breakpoint commands\n\
185--------------------------------------------------------------\n\
186\n\
187You may enter any debugger command, exactly as you would at the debugger prompt.\n\
188You may enter as many debugger commands as you like, but do NOT enter more than\n\
189one command per line.\n" );
Caroline Tice405fe672010-10-04 22:28:36 +0000190
Jim Ingham5a988412012-06-08 21:56:10 +0000191 CommandArgumentEntry arg;
192 CommandArgumentData bp_id_arg;
Caroline Tice405fe672010-10-04 22:28:36 +0000193
Jim Ingham5a988412012-06-08 21:56:10 +0000194 // Define the first (and only) variant of this arg.
195 bp_id_arg.arg_type = eArgTypeBreakpointID;
196 bp_id_arg.arg_repetition = eArgRepeatPlain;
Caroline Tice405fe672010-10-04 22:28:36 +0000197
Jim Ingham5a988412012-06-08 21:56:10 +0000198 // There is only one variant this argument could be; put it into the argument entry.
199 arg.push_back (bp_id_arg);
Caroline Tice405fe672010-10-04 22:28:36 +0000200
Jim Ingham5a988412012-06-08 21:56:10 +0000201 // Push the data for the first argument into the m_arguments vector.
202 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 }
204
Jim Ingham5a988412012-06-08 21:56:10 +0000205 virtual
206 ~CommandObjectBreakpointCommandAdd () {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207
Jim Ingham5a988412012-06-08 21:56:10 +0000208 virtual Options *
209 GetOptions ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000210 {
Jim Ingham5a988412012-06-08 21:56:10 +0000211 return &m_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000212 }
213
Greg Clayton44d93782014-01-27 23:43:24 +0000214 virtual void
215 IOHandlerActivated (IOHandler &io_handler)
216 {
217 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
218 if (output_sp)
219 {
220 output_sp->PutCString(g_reader_instructions);
221 output_sp->Flush();
222 }
223 }
224
225
226 virtual void
227 IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
228 {
229 io_handler.SetIsDone(true);
230
231 BreakpointOptions *bp_options = (BreakpointOptions *) io_handler.GetUserData();
232 if (bp_options)
233 {
234 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
235 if (data_ap.get())
236 {
237 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
238 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
239 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
240 }
241 }
242
243 }
244
Jim Ingham5a988412012-06-08 21:56:10 +0000245 void
246 CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
247 CommandReturnObject &result)
Enrico Granata8d4a8012012-04-04 17:30:31 +0000248 {
Greg Clayton44d93782014-01-27 23:43:24 +0000249 m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
250 *this, // IOHandlerDelegate
251 true, // Run IOHandler in async mode
252 bp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253 }
Caroline Ticed61c10b2011-06-16 16:27:19 +0000254
Jim Ingham5a988412012-06-08 21:56:10 +0000255 /// Set a one-liner as the callback for the breakpoint.
256 void
257 SetBreakpointCommandCallback (BreakpointOptions *bp_options,
258 const char *oneliner)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259 {
Greg Clayton7b0992d2013-04-18 22:45:39 +0000260 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261
Jim Ingham5a988412012-06-08 21:56:10 +0000262 // It's necessary to set both user_source and script_source to the oneliner.
263 // The former is used to generate callback description (as in breakpoint command list)
264 // while the latter is used for Python to interpret during the actual callback.
265 data_ap->user_source.AppendString (oneliner);
266 data_ap->script_source.assign (oneliner);
267 data_ap->stop_on_error = m_options.m_stop_on_error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000268
Jim Ingham5a988412012-06-08 21:56:10 +0000269 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
270 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271
Jim Ingham5a988412012-06-08 21:56:10 +0000272 return;
273 }
Jim Ingham5a988412012-06-08 21:56:10 +0000274
275 static bool
276 BreakpointOptionsCallbackFunction (void *baton,
277 StoppointCallbackContext *context,
278 lldb::user_id_t break_id,
279 lldb::user_id_t break_loc_id)
280 {
281 bool ret_value = true;
282 if (baton == NULL)
283 return true;
Caroline Ticeefed6132010-11-19 20:47:54 +0000284
Caroline Ticeefed6132010-11-19 20:47:54 +0000285
Jim Ingham5a988412012-06-08 21:56:10 +0000286 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
287 StringList &commands = data->user_source;
288
289 if (commands.GetSize() > 0)
290 {
291 ExecutionContext exe_ctx (context->exe_ctx_ref);
292 Target *target = exe_ctx.GetTargetPtr();
293 if (target)
294 {
295 CommandReturnObject result;
296 Debugger &debugger = target->GetDebugger();
297 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
298 // if the debugger is set up that way.
299
300 StreamSP output_stream (debugger.GetAsyncOutputStream());
301 StreamSP error_stream (debugger.GetAsyncErrorStream());
302 result.SetImmediateOutputStream (output_stream);
303 result.SetImmediateErrorStream (error_stream);
304
305 bool stop_on_continue = true;
306 bool echo_commands = false;
307 bool print_results = true;
308
309 debugger.GetCommandInterpreter().HandleCommands (commands,
310 &exe_ctx,
311 stop_on_continue,
312 data->stop_on_error,
313 echo_commands,
314 print_results,
315 eLazyBoolNo,
316 result);
317 result.GetImmediateOutputStream()->Flush();
318 result.GetImmediateErrorStream()->Flush();
319 }
320 }
321 return ret_value;
322 }
323
324 class CommandOptions : public Options
325 {
326 public:
327
328 CommandOptions (CommandInterpreter &interpreter) :
329 Options (interpreter),
330 m_use_commands (false),
331 m_use_script_language (false),
332 m_script_language (eScriptLanguageNone),
333 m_use_one_liner (false),
334 m_one_liner(),
335 m_function_name()
336 {
337 }
338
339 virtual
340 ~CommandOptions () {}
341
342 virtual Error
343 SetOptionValue (uint32_t option_idx, const char *option_arg)
344 {
345 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000346 const int short_option = m_getopt_table[option_idx].val;
Jim Ingham5a988412012-06-08 21:56:10 +0000347
348 switch (short_option)
349 {
350 case 'o':
351 m_use_one_liner = true;
352 m_one_liner = option_arg;
353 break;
354
355 case 's':
356 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
357 g_option_table[option_idx].enum_values,
358 eScriptLanguageNone,
359 error);
360
361 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
362 {
363 m_use_script_language = true;
364 }
365 else
366 {
367 m_use_script_language = false;
368 }
369 break;
370
371 case 'e':
372 {
373 bool success = false;
374 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
375 if (!success)
376 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
377 }
378 break;
379
380 case 'F':
381 {
382 m_use_one_liner = false;
383 m_use_script_language = true;
384 m_function_name.assign(option_arg);
385 }
386 break;
387
388 default:
389 break;
390 }
391 return error;
392 }
393 void
394 OptionParsingStarting ()
395 {
396 m_use_commands = true;
397 m_use_script_language = false;
398 m_script_language = eScriptLanguageNone;
399
400 m_use_one_liner = false;
401 m_stop_on_error = true;
402 m_one_liner.clear();
403 m_function_name.clear();
404 }
405
406 const OptionDefinition*
407 GetDefinitions ()
408 {
409 return g_option_table;
410 }
411
412 // Options table: Required for subclasses of Options.
413
414 static OptionDefinition g_option_table[];
415
416 // Instance variables to hold the values for command options.
417
418 bool m_use_commands;
419 bool m_use_script_language;
420 lldb::ScriptLanguage m_script_language;
421
422 // Instance variables to hold the values for one_liner options.
423 bool m_use_one_liner;
424 std::string m_one_liner;
425 bool m_stop_on_error;
426 std::string m_function_name;
427 };
428
429protected:
430 virtual bool
431 DoExecute (Args& command, CommandReturnObject &result)
432 {
433 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
434
435 if (target == NULL)
436 {
437 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
438 result.SetStatus (eReturnStatusFailed);
439 return false;
440 }
441
442 const BreakpointList &breakpoints = target->GetBreakpointList();
443 size_t num_breakpoints = breakpoints.GetSize();
444
445 if (num_breakpoints == 0)
446 {
447 result.AppendError ("No breakpoints exist to have commands added");
448 result.SetStatus (eReturnStatusFailed);
449 return false;
450 }
451
452 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
453 {
454 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
455 result.SetStatus (eReturnStatusFailed);
456 return false;
457 }
458
459 BreakpointIDList valid_bp_ids;
460 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
461
462 if (result.Succeeded())
463 {
464 const size_t count = valid_bp_ids.GetSize();
Jim Inghamd9916ea2013-02-28 19:30:07 +0000465 if (count > 1)
466 {
467 result.AppendError ("can only add commands to one breakpoint at a time.");
468 result.SetStatus (eReturnStatusFailed);
469 return false;
470 }
471
Jim Ingham5a988412012-06-08 21:56:10 +0000472 for (size_t i = 0; i < count; ++i)
473 {
474 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
475 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
476 {
477 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
478 BreakpointOptions *bp_options = NULL;
479 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
480 {
481 // This breakpoint does not have an associated location.
482 bp_options = bp->GetOptions();
483 }
484 else
485 {
486 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
487 // This breakpoint does have an associated location.
488 // Get its breakpoint options.
489 if (bp_loc_sp)
490 bp_options = bp_loc_sp->GetLocationOptions();
491 }
492
493 // Skip this breakpoint if bp_options is not good.
494 if (bp_options == NULL) continue;
495
496 // If we are using script language, get the script interpreter
497 // in order to set or collect command callback. Otherwise, call
498 // the methods associated with this object.
499 if (m_options.m_use_script_language)
500 {
501 // Special handling for one-liner specified inline.
502 if (m_options.m_use_one_liner)
503 {
504 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
505 m_options.m_one_liner.c_str());
506 }
Jim Ingham5a988412012-06-08 21:56:10 +0000507 else if (m_options.m_function_name.size())
508 {
Jim Inghamd80102e2014-04-02 01:04:55 +0000509 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallbackFunction (bp_options,
510 m_options.m_function_name.c_str());
Jim Ingham5a988412012-06-08 21:56:10 +0000511 }
512 else
513 {
514 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
515 result);
516 }
517 }
518 else
519 {
520 // Special handling for one-liner specified inline.
521 if (m_options.m_use_one_liner)
522 SetBreakpointCommandCallback (bp_options,
523 m_options.m_one_liner.c_str());
524 else
525 CollectDataForBreakpointCommandCallback (bp_options,
526 result);
527 }
528 }
529 }
530 }
531
532 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000533 }
534
Jim Ingham5a988412012-06-08 21:56:10 +0000535private:
536 CommandOptions m_options;
537 static const char *g_reader_instructions;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538
Jim Ingham5a988412012-06-08 21:56:10 +0000539};
540
541const char *
Greg Clayton44d93782014-01-27 23:43:24 +0000542CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n";
Jim Ingham5a988412012-06-08 21:56:10 +0000543
544// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
545// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
546
547static OptionEnumValueElement
548g_script_option_enumeration[4] =
549{
550 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
551 { eScriptLanguagePython, "python", "Commands are in the Python language."},
552 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
553 { 0, NULL, NULL }
554};
555
556OptionDefinition
557CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
558{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000559 { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
Jim Ingham5a988412012-06-08 21:56:10 +0000560 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
561
Zachary Turnerd37221d2014-07-09 16:31:49 +0000562 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
Jim Ingham5a988412012-06-08 21:56:10 +0000563 "Specify whether breakpoint command execution should terminate on error." },
564
Zachary Turnerd37221d2014-07-09 16:31:49 +0000565 { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
Jim Ingham5a988412012-06-08 21:56:10 +0000566 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
567
Zachary Turnerd37221d2014-07-09 16:31:49 +0000568 { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
Jim Ingham5a988412012-06-08 21:56:10 +0000569 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
570
Zachary Turnerd37221d2014-07-09 16:31:49 +0000571 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
Jim Ingham5a988412012-06-08 21:56:10 +0000572};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000573
574//-------------------------------------------------------------------------
Caroline Tice93e0f192011-05-22 07:14:46 +0000575// CommandObjectBreakpointCommandDelete
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000576//-------------------------------------------------------------------------
577
Jim Ingham5a988412012-06-08 21:56:10 +0000578class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000579{
Jim Ingham5a988412012-06-08 21:56:10 +0000580public:
581 CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
582 CommandObjectParsed (interpreter,
583 "delete",
584 "Delete the set of commands from a breakpoint.",
585 NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586 {
Jim Ingham5a988412012-06-08 21:56:10 +0000587 CommandArgumentEntry arg;
588 CommandArgumentData bp_id_arg;
589
590 // Define the first (and only) variant of this arg.
591 bp_id_arg.arg_type = eArgTypeBreakpointID;
592 bp_id_arg.arg_repetition = eArgRepeatPlain;
593
594 // There is only one variant this argument could be; put it into the argument entry.
595 arg.push_back (bp_id_arg);
596
597 // Push the data for the first argument into the m_arguments vector.
598 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000599 }
600
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601
Jim Ingham5a988412012-06-08 21:56:10 +0000602 virtual
603 ~CommandObjectBreakpointCommandDelete () {}
604
605protected:
606 virtual bool
607 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000608 {
Jim Ingham5a988412012-06-08 21:56:10 +0000609 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000610
Jim Ingham5a988412012-06-08 21:56:10 +0000611 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000612 {
Jim Ingham5a988412012-06-08 21:56:10 +0000613 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
614 result.SetStatus (eReturnStatusFailed);
615 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000616 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617
Jim Ingham5a988412012-06-08 21:56:10 +0000618 const BreakpointList &breakpoints = target->GetBreakpointList();
619 size_t num_breakpoints = breakpoints.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000620
Jim Ingham5a988412012-06-08 21:56:10 +0000621 if (num_breakpoints == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000622 {
Jim Ingham5a988412012-06-08 21:56:10 +0000623 result.AppendError ("No breakpoints exist to have commands deleted");
624 result.SetStatus (eReturnStatusFailed);
625 return false;
626 }
627
628 if (command.GetArgumentCount() == 0)
629 {
630 result.AppendError ("No breakpoint specified from which to delete the commands");
631 result.SetStatus (eReturnStatusFailed);
632 return false;
633 }
634
635 BreakpointIDList valid_bp_ids;
636 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
637
638 if (result.Succeeded())
639 {
640 const size_t count = valid_bp_ids.GetSize();
641 for (size_t i = 0; i < count; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642 {
Jim Ingham5a988412012-06-08 21:56:10 +0000643 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
644 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 {
Jim Ingham5a988412012-06-08 21:56:10 +0000646 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000647 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
648 {
Jim Ingham5a988412012-06-08 21:56:10 +0000649 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000650 if (bp_loc_sp)
Jim Ingham5a988412012-06-08 21:56:10 +0000651 bp_loc_sp->ClearCallback();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 else
653 {
654 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
655 cur_bp_id.GetBreakpointID(),
656 cur_bp_id.GetLocationID());
657 result.SetStatus (eReturnStatusFailed);
658 return false;
659 }
660 }
661 else
662 {
Jim Ingham5a988412012-06-08 21:56:10 +0000663 bp->ClearCallback();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000664 }
Jim Ingham5a988412012-06-08 21:56:10 +0000665 }
666 }
667 }
668 return result.Succeeded();
669 }
670};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000671
Jim Ingham5a988412012-06-08 21:56:10 +0000672//-------------------------------------------------------------------------
673// CommandObjectBreakpointCommandList
674//-------------------------------------------------------------------------
675
676class CommandObjectBreakpointCommandList : public CommandObjectParsed
677{
678public:
679 CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
680 CommandObjectParsed (interpreter,
681 "list",
682 "List the script or set of commands to be executed when the breakpoint is hit.",
683 NULL)
684 {
685 CommandArgumentEntry arg;
686 CommandArgumentData bp_id_arg;
687
688 // Define the first (and only) variant of this arg.
689 bp_id_arg.arg_type = eArgTypeBreakpointID;
690 bp_id_arg.arg_repetition = eArgRepeatPlain;
691
692 // There is only one variant this argument could be; put it into the argument entry.
693 arg.push_back (bp_id_arg);
694
695 // Push the data for the first argument into the m_arguments vector.
696 m_arguments.push_back (arg);
697 }
698
699 virtual
700 ~CommandObjectBreakpointCommandList () {}
701
702protected:
703 virtual bool
704 DoExecute (Args& command,
705 CommandReturnObject &result)
706 {
707 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
708
709 if (target == NULL)
710 {
711 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
712 result.SetStatus (eReturnStatusFailed);
713 return false;
714 }
715
716 const BreakpointList &breakpoints = target->GetBreakpointList();
717 size_t num_breakpoints = breakpoints.GetSize();
718
719 if (num_breakpoints == 0)
720 {
721 result.AppendError ("No breakpoints exist for which to list commands");
722 result.SetStatus (eReturnStatusFailed);
723 return false;
724 }
725
726 if (command.GetArgumentCount() == 0)
727 {
728 result.AppendError ("No breakpoint specified for which to list the commands");
729 result.SetStatus (eReturnStatusFailed);
730 return false;
731 }
732
733 BreakpointIDList valid_bp_ids;
734 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
735
736 if (result.Succeeded())
737 {
738 const size_t count = valid_bp_ids.GetSize();
739 for (size_t i = 0; i < count; ++i)
740 {
741 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
742 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
743 {
744 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
745
746 if (bp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000747 {
Jim Ingham5a988412012-06-08 21:56:10 +0000748 const BreakpointOptions *bp_options = NULL;
749 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000750 {
Jim Ingham5a988412012-06-08 21:56:10 +0000751 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
752 if (bp_loc_sp)
753 bp_options = bp_loc_sp->GetOptionsNoCreate();
754 else
755 {
756 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
757 cur_bp_id.GetBreakpointID(),
758 cur_bp_id.GetLocationID());
759 result.SetStatus (eReturnStatusFailed);
760 return false;
761 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000762 }
763 else
764 {
Jim Ingham5a988412012-06-08 21:56:10 +0000765 bp_options = bp->GetOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000766 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000767
Jim Ingham5a988412012-06-08 21:56:10 +0000768 if (bp_options)
769 {
770 StreamString id_str;
771 BreakpointID::GetCanonicalReference (&id_str,
772 cur_bp_id.GetBreakpointID(),
773 cur_bp_id.GetLocationID());
774 const Baton *baton = bp_options->GetBaton();
775 if (baton)
776 {
777 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
778 result.GetOutputStream().IndentMore ();
779 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
780 result.GetOutputStream().IndentLess ();
781 }
782 else
783 {
784 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
785 id_str.GetData());
786 }
787 }
788 result.SetStatus (eReturnStatusSuccessFinishResult);
789 }
790 else
791 {
792 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
793 result.SetStatus (eReturnStatusFailed);
794 }
795
796 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797 }
798 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000799
Jim Ingham5a988412012-06-08 21:56:10 +0000800 return result.Succeeded();
801 }
802};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000803
804//-------------------------------------------------------------------------
805// CommandObjectBreakpointCommand
806//-------------------------------------------------------------------------
807
Greg Clayton66111032010-06-23 01:19:29 +0000808CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +0000809 CommandObjectMultiword (interpreter,
810 "command",
Sean Callanan7050e0b2014-08-21 16:47:01 +0000811 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000812 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
813{
Greg Claytona7015092010-09-18 01:14:36 +0000814 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Tice93e0f192011-05-22 07:14:46 +0000815 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Claytona7015092010-09-18 01:14:36 +0000816 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000817
818 add_command_object->SetCommandName ("breakpoint command add");
Caroline Tice93e0f192011-05-22 07:14:46 +0000819 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000820 list_command_object->SetCommandName ("breakpoint command list");
821
Greg Clayton23f59502012-07-17 03:23:13 +0000822 LoadSubCommand ("add", add_command_object);
823 LoadSubCommand ("delete", delete_command_object);
824 LoadSubCommand ("list", list_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000825}
826
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000827CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
828{
829}
830
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000831