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