blob: 3dbb6e052d5ac6a6cdaa36ca30d3224d25e66434 [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
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/Thread.h"
23#include "lldb/Breakpoint/BreakpointIDList.h"
24#include "lldb/Breakpoint/Breakpoint.h"
25#include "lldb/Breakpoint/BreakpointLocation.h"
26#include "lldb/Breakpoint/StoppointCallbackContext.h"
27#include "lldb/Core/State.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033// CommandObjectBreakpointCommandAdd
34//-------------------------------------------------------------------------
35
36
Jim Ingham5a988412012-06-08 21:56:10 +000037class CommandObjectBreakpointCommandAdd : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038{
Jim Ingham5a988412012-06-08 21:56:10 +000039public:
40
41 CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
42 CommandObjectParsed (interpreter,
43 "add",
44 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
45 NULL),
46 m_options (interpreter)
47 {
48 SetHelpLong (
Greg Clayton13b12132012-10-26 17:53:21 +000049"\nGeneral information about entering breakpoint commands\n\
50------------------------------------------------------\n\
51\n\
52This command will cause you to be prompted to enter the command or set of\n\
53commands you wish to be executed when the specified breakpoint is hit. You\n\
54will be told to enter your command(s), and will see a '> 'prompt. Because\n\
55you can enter one or many commands to be executed when a breakpoint is hit,\n\
56you will continue to be prompted after each new-line that you enter, until you\n\
57enter the word 'DONE', which will cause the commands you have entered to be\n\
58stored with the breakpoint and executed when the breakpoint is hit.\n\
59\n\
60Syntax checking is not necessarily done when breakpoint commands are entered.\n\
61An improperly written breakpoint command will attempt to get executed when the\n\
62breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
63not appear to be getting executed, go back and check your syntax.\n\
64\n\
65Special information about PYTHON breakpoint commands\n\
66----------------------------------------------------\n\
67\n\
68You may enter either one line of Python, multiple lines of Python (including\n\
69function definitions), or specify a Python function in a module that has already,\n\
70or will be imported. If you enter a single line of Python, that will be passed\n\
71to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
72function definitions, they will be passed to the Python interpreter as soon as\n\
73you finish entering the breakpoint command, and they can be called later (don't\n\
74forget to add calls to them, if you want them called when the breakpoint is\n\
75hit). If you enter multiple lines of Python that are not function definitions,\n\
76they will be collected into a new, automatically generated Python function, and\n\
77a call to the newly generated function will be attached to the breakpoint.\n\
78\n\
79\n\
80This auto-generated function is passed in three arguments:\n\
81\n\
82 frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
83 bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
84 location that was hit.\n\
85 dict: the python session dictionary hit.\n\
86\n\
87When specifying a python function with the --python-function option, you need\n\
88to supply the function name prepended by the module name. So if you import a\n\
89module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
90specify the option as:\n\
91\n\
92 --python-function myutils.breakpoint_callback\n\
93\n\
94The function itself must have the following prototype:\n\
95\n\
96def breakpoint_callback(frame, bp_loc, dict):\n\
97 # Your code goes here\n\
98\n\
99The arguments are the same as the 3 auto generation function arguments listed\n\
100above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
101function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
102can get you to the thread (frame.GetThread()), the thread can get you to the\n\
103process (thread.GetProcess()), and the process can get you back to the target\n\
104(process.GetTarget()).\n\
105\n\
106Important Note: Because loose Python code gets collected into functions, if you\n\
107want to access global variables in the 'loose' code, you need to specify that\n\
108they are global, using the 'global' keyword. Be sure to use correct Python\n\
109syntax, including indentation, when entering Python breakpoint commands.\n\
110\n\
111As a third option, you can pass the name of an already existing Python function\n\
112and that function will be attached to the breakpoint. It will get passed the\n\
113frame and bp_loc arguments mentioned above.\n\
114\n\
115Example Python one-line breakpoint command:\n\
116\n\
117(lldb) breakpoint command add -s python 1\n\
118Enter your Python command(s). Type 'DONE' to end.\n\
119> print \"Hit this breakpoint!\"\n\
120> DONE\n\
121\n\
122As a convenience, this also works for a short Python one-liner:\n\
123(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
124(lldb) run\n\
125Launching '.../a.out' (x86_64)\n\
126(lldb) Fri Sep 10 12:17:45 2010\n\
127Process 21778 Stopped\n\
128* 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 +0000129 36 \n\
130 37 int c(int val)\n\
131 38 {\n\
132 39 -> return val + 3;\n\
133 40 }\n\
134 41 \n\
135 42 int main (int argc, char const *argv[])\n\
Greg Clayton13b12132012-10-26 17:53:21 +0000136(lldb)\n\
137\n\
138Example multiple line Python breakpoint command, using function definition:\n\
139\n\
140(lldb) breakpoint command add -s python 1\n\
141Enter your Python command(s). Type 'DONE' to end.\n\
142> def breakpoint_output (bp_no):\n\
143> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
144> print out_string\n\
145> return True\n\
146> breakpoint_output (1)\n\
147> DONE\n\
148\n\
149\n\
150Example multiple line Python breakpoint command, using 'loose' Python:\n\
151\n\
152(lldb) breakpoint command add -s p 1\n\
153Enter your Python command(s). Type 'DONE' to end.\n\
154> global bp_count\n\
155> bp_count = bp_count + 1\n\
156> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
157> DONE\n\
158\n\
159In this case, since there is a reference to a global variable,\n\
160'bp_count', you will also need to make sure 'bp_count' exists and is\n\
161initialized:\n\
162\n\
163(lldb) script\n\
164>>> bp_count = 0\n\
165>>> quit()\n\
166\n\
167(lldb)\n\
168\n\
169\n\
170Final Note: If you get a warning that no breakpoint command was generated, but\n\
171you did not get any syntax errors, you probably forgot to add a call to your\n\
172functions.\n\
173\n\
174Special information about debugger command breakpoint commands\n\
175--------------------------------------------------------------\n\
176\n\
177You may enter any debugger command, exactly as you would at the debugger prompt.\n\
178You may enter as many debugger commands as you like, but do NOT enter more than\n\
179one command per line.\n" );
Caroline Tice405fe672010-10-04 22:28:36 +0000180
Jim Ingham5a988412012-06-08 21:56:10 +0000181 CommandArgumentEntry arg;
182 CommandArgumentData bp_id_arg;
Caroline Tice405fe672010-10-04 22:28:36 +0000183
Jim Ingham5a988412012-06-08 21:56:10 +0000184 // Define the first (and only) variant of this arg.
185 bp_id_arg.arg_type = eArgTypeBreakpointID;
186 bp_id_arg.arg_repetition = eArgRepeatPlain;
Caroline Tice405fe672010-10-04 22:28:36 +0000187
Jim Ingham5a988412012-06-08 21:56:10 +0000188 // There is only one variant this argument could be; put it into the argument entry.
189 arg.push_back (bp_id_arg);
Caroline Tice405fe672010-10-04 22:28:36 +0000190
Jim Ingham5a988412012-06-08 21:56:10 +0000191 // Push the data for the first argument into the m_arguments vector.
192 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193 }
194
Jim Ingham5a988412012-06-08 21:56:10 +0000195 virtual
196 ~CommandObjectBreakpointCommandAdd () {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197
Jim Ingham5a988412012-06-08 21:56:10 +0000198 virtual Options *
199 GetOptions ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 {
Jim Ingham5a988412012-06-08 21:56:10 +0000201 return &m_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 }
203
Jim Ingham5a988412012-06-08 21:56:10 +0000204 void
205 CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
206 CommandReturnObject &result)
Enrico Granata8d4a8012012-04-04 17:30:31 +0000207 {
Jim Ingham5a988412012-06-08 21:56:10 +0000208 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Greg Clayton7b0992d2013-04-18 22:45:39 +0000209 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Jim Ingham5a988412012-06-08 21:56:10 +0000210 if (reader_sp && data_ap.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211 {
Jim Ingham5a988412012-06-08 21:56:10 +0000212 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
213 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
214
215 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
216 bp_options, // baton
217 eInputReaderGranularityLine, // token size, to pass to callback function
218 "DONE", // end token
219 "> ", // prompt
220 true)); // echo input
221 if (err.Success())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 {
Jim Ingham5a988412012-06-08 21:56:10 +0000223 m_interpreter.GetDebugger().PushInputReader (reader_sp);
224 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225 }
Jim Ingham5a988412012-06-08 21:56:10 +0000226 else
227 {
228 result.AppendError (err.AsCString());
229 result.SetStatus (eReturnStatusFailed);
230 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 }
232 else
233 {
Jim Ingham5a988412012-06-08 21:56:10 +0000234 result.AppendError("out of memory");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235 result.SetStatus (eReturnStatusFailed);
236 }
Jim Ingham5a988412012-06-08 21:56:10 +0000237
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238 }
Caroline Ticed61c10b2011-06-16 16:27:19 +0000239
Jim Ingham5a988412012-06-08 21:56:10 +0000240 /// Set a one-liner as the callback for the breakpoint.
241 void
242 SetBreakpointCommandCallback (BreakpointOptions *bp_options,
243 const char *oneliner)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 {
Greg Clayton7b0992d2013-04-18 22:45:39 +0000245 std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246
Jim Ingham5a988412012-06-08 21:56:10 +0000247 // It's necessary to set both user_source and script_source to the oneliner.
248 // The former is used to generate callback description (as in breakpoint command list)
249 // while the latter is used for Python to interpret during the actual callback.
250 data_ap->user_source.AppendString (oneliner);
251 data_ap->script_source.assign (oneliner);
252 data_ap->stop_on_error = m_options.m_stop_on_error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253
Jim Ingham5a988412012-06-08 21:56:10 +0000254 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
255 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256
Jim Ingham5a988412012-06-08 21:56:10 +0000257 return;
258 }
259
260 static size_t
261 GenerateBreakpointCommandCallback (void *baton,
262 InputReader &reader,
263 lldb::InputReaderAction notification,
264 const char *bytes,
265 size_t bytes_len)
266 {
267 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
268 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Caroline Tice969ed3d2011-05-02 20:41:46 +0000269
Jim Ingham5a988412012-06-08 21:56:10 +0000270 switch (notification)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 {
Jim Ingham5a988412012-06-08 21:56:10 +0000272 case eInputReaderActivate:
Caroline Ticed61c10b2011-06-16 16:27:19 +0000273 if (!batch_mode)
274 {
Jim Ingham5a988412012-06-08 21:56:10 +0000275 out_stream->Printf ("%s\n", g_reader_instructions);
276 if (reader.GetPrompt())
277 out_stream->Printf ("%s", reader.GetPrompt());
Caroline Ticed61c10b2011-06-16 16:27:19 +0000278 out_stream->Flush();
279 }
Jim Ingham5a988412012-06-08 21:56:10 +0000280 break;
281
282 case eInputReaderDeactivate:
283 break;
284
285 case eInputReaderReactivate:
286 if (reader.GetPrompt() && !batch_mode)
287 {
288 out_stream->Printf ("%s", reader.GetPrompt());
289 out_stream->Flush();
290 }
291 break;
292
293 case eInputReaderAsynchronousOutputWritten:
294 break;
295
296 case eInputReaderGotToken:
297 if (bytes && bytes_len && baton)
298 {
299 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
300 if (bp_options)
301 {
302 Baton *bp_options_baton = bp_options->GetBaton();
303 if (bp_options_baton)
304 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
305 }
306 }
307 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
308 {
309 out_stream->Printf ("%s", reader.GetPrompt());
310 out_stream->Flush();
311 }
312 break;
313
314 case eInputReaderInterrupt:
315 {
316 // Finish, and cancel the breakpoint command.
317 reader.SetIsDone (true);
318 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
319 if (bp_options)
320 {
321 Baton *bp_options_baton = bp_options->GetBaton ();
322 if (bp_options_baton)
323 {
324 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
325 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
326 }
327 }
328 if (!batch_mode)
329 {
330 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
331 out_stream->Flush();
332 }
333 }
334 break;
335
336 case eInputReaderEndOfFile:
337 reader.SetIsDone (true);
338 break;
339
340 case eInputReaderDone:
341 break;
Caroline Ticeefed6132010-11-19 20:47:54 +0000342 }
Jim Ingham5a988412012-06-08 21:56:10 +0000343
344 return bytes_len;
345 }
346
347 static bool
348 BreakpointOptionsCallbackFunction (void *baton,
349 StoppointCallbackContext *context,
350 lldb::user_id_t break_id,
351 lldb::user_id_t break_loc_id)
352 {
353 bool ret_value = true;
354 if (baton == NULL)
355 return true;
Caroline Ticeefed6132010-11-19 20:47:54 +0000356
Caroline Ticeefed6132010-11-19 20:47:54 +0000357
Jim Ingham5a988412012-06-08 21:56:10 +0000358 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
359 StringList &commands = data->user_source;
360
361 if (commands.GetSize() > 0)
362 {
363 ExecutionContext exe_ctx (context->exe_ctx_ref);
364 Target *target = exe_ctx.GetTargetPtr();
365 if (target)
366 {
367 CommandReturnObject result;
368 Debugger &debugger = target->GetDebugger();
369 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
370 // if the debugger is set up that way.
371
372 StreamSP output_stream (debugger.GetAsyncOutputStream());
373 StreamSP error_stream (debugger.GetAsyncErrorStream());
374 result.SetImmediateOutputStream (output_stream);
375 result.SetImmediateErrorStream (error_stream);
376
377 bool stop_on_continue = true;
378 bool echo_commands = false;
379 bool print_results = true;
380
381 debugger.GetCommandInterpreter().HandleCommands (commands,
382 &exe_ctx,
383 stop_on_continue,
384 data->stop_on_error,
385 echo_commands,
386 print_results,
387 eLazyBoolNo,
388 result);
389 result.GetImmediateOutputStream()->Flush();
390 result.GetImmediateErrorStream()->Flush();
391 }
392 }
393 return ret_value;
394 }
395
396 class CommandOptions : public Options
397 {
398 public:
399
400 CommandOptions (CommandInterpreter &interpreter) :
401 Options (interpreter),
402 m_use_commands (false),
403 m_use_script_language (false),
404 m_script_language (eScriptLanguageNone),
405 m_use_one_liner (false),
406 m_one_liner(),
407 m_function_name()
408 {
409 }
410
411 virtual
412 ~CommandOptions () {}
413
414 virtual Error
415 SetOptionValue (uint32_t option_idx, const char *option_arg)
416 {
417 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000418 const int short_option = m_getopt_table[option_idx].val;
Jim Ingham5a988412012-06-08 21:56:10 +0000419
420 switch (short_option)
421 {
422 case 'o':
423 m_use_one_liner = true;
424 m_one_liner = option_arg;
425 break;
426
427 case 's':
428 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
429 g_option_table[option_idx].enum_values,
430 eScriptLanguageNone,
431 error);
432
433 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
434 {
435 m_use_script_language = true;
436 }
437 else
438 {
439 m_use_script_language = false;
440 }
441 break;
442
443 case 'e':
444 {
445 bool success = false;
446 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
447 if (!success)
448 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
449 }
450 break;
451
452 case 'F':
453 {
454 m_use_one_liner = false;
455 m_use_script_language = true;
456 m_function_name.assign(option_arg);
457 }
458 break;
459
460 default:
461 break;
462 }
463 return error;
464 }
465 void
466 OptionParsingStarting ()
467 {
468 m_use_commands = true;
469 m_use_script_language = false;
470 m_script_language = eScriptLanguageNone;
471
472 m_use_one_liner = false;
473 m_stop_on_error = true;
474 m_one_liner.clear();
475 m_function_name.clear();
476 }
477
478 const OptionDefinition*
479 GetDefinitions ()
480 {
481 return g_option_table;
482 }
483
484 // Options table: Required for subclasses of Options.
485
486 static OptionDefinition g_option_table[];
487
488 // Instance variables to hold the values for command options.
489
490 bool m_use_commands;
491 bool m_use_script_language;
492 lldb::ScriptLanguage m_script_language;
493
494 // Instance variables to hold the values for one_liner options.
495 bool m_use_one_liner;
496 std::string m_one_liner;
497 bool m_stop_on_error;
498 std::string m_function_name;
499 };
500
501protected:
502 virtual bool
503 DoExecute (Args& command, CommandReturnObject &result)
504 {
505 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
506
507 if (target == NULL)
508 {
509 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
510 result.SetStatus (eReturnStatusFailed);
511 return false;
512 }
513
514 const BreakpointList &breakpoints = target->GetBreakpointList();
515 size_t num_breakpoints = breakpoints.GetSize();
516
517 if (num_breakpoints == 0)
518 {
519 result.AppendError ("No breakpoints exist to have commands added");
520 result.SetStatus (eReturnStatusFailed);
521 return false;
522 }
523
524 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
525 {
526 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
527 result.SetStatus (eReturnStatusFailed);
528 return false;
529 }
530
531 BreakpointIDList valid_bp_ids;
532 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
533
534 if (result.Succeeded())
535 {
536 const size_t count = valid_bp_ids.GetSize();
Jim Inghamd9916ea2013-02-28 19:30:07 +0000537 if (count > 1)
538 {
539 result.AppendError ("can only add commands to one breakpoint at a time.");
540 result.SetStatus (eReturnStatusFailed);
541 return false;
542 }
543
Jim Ingham5a988412012-06-08 21:56:10 +0000544 for (size_t i = 0; i < count; ++i)
545 {
546 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
547 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
548 {
549 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
550 BreakpointOptions *bp_options = NULL;
551 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
552 {
553 // This breakpoint does not have an associated location.
554 bp_options = bp->GetOptions();
555 }
556 else
557 {
558 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
559 // This breakpoint does have an associated location.
560 // Get its breakpoint options.
561 if (bp_loc_sp)
562 bp_options = bp_loc_sp->GetLocationOptions();
563 }
564
565 // Skip this breakpoint if bp_options is not good.
566 if (bp_options == NULL) continue;
567
568 // If we are using script language, get the script interpreter
569 // in order to set or collect command callback. Otherwise, call
570 // the methods associated with this object.
571 if (m_options.m_use_script_language)
572 {
573 // Special handling for one-liner specified inline.
574 if (m_options.m_use_one_liner)
575 {
576 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
577 m_options.m_one_liner.c_str());
578 }
579 // Special handling for using a Python function by name
580 // instead of extending the breakpoint callback data structures, we just automatize
581 // what the user would do manually: make their breakpoint command be a function call
582 else if (m_options.m_function_name.size())
583 {
Enrico Granatac8fcaab2013-05-15 02:46:08 +0000584 std::string oneliner("return ");
585 oneliner += m_options.m_function_name;
Enrico Granata40d55712012-08-08 02:06:30 +0000586 oneliner += "(frame, bp_loc, internal_dict)";
Jim Ingham5a988412012-06-08 21:56:10 +0000587 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
588 oneliner.c_str());
589 }
590 else
591 {
592 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
593 result);
594 }
595 }
596 else
597 {
598 // Special handling for one-liner specified inline.
599 if (m_options.m_use_one_liner)
600 SetBreakpointCommandCallback (bp_options,
601 m_options.m_one_liner.c_str());
602 else
603 CollectDataForBreakpointCommandCallback (bp_options,
604 result);
605 }
606 }
607 }
608 }
609
610 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000611 }
612
Jim Ingham5a988412012-06-08 21:56:10 +0000613private:
614 CommandOptions m_options;
615 static const char *g_reader_instructions;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000616
Jim Ingham5a988412012-06-08 21:56:10 +0000617};
618
619const char *
620CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
621
622// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
623// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
624
625static OptionEnumValueElement
626g_script_option_enumeration[4] =
627{
628 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
629 { eScriptLanguagePython, "python", "Commands are in the Python language."},
630 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
631 { 0, NULL, NULL }
632};
633
634OptionDefinition
635CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
636{
Filipe Cabecinhasbc6e85c2012-09-11 16:09:27 +0000637 { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
Jim Ingham5a988412012-06-08 21:56:10 +0000638 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
639
Filipe Cabecinhasbc6e85c2012-09-11 16:09:27 +0000640 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,
Jim Ingham5a988412012-06-08 21:56:10 +0000641 "Specify whether breakpoint command execution should terminate on error." },
642
Filipe Cabecinhasbc6e85c2012-09-11 16:09:27 +0000643 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
Jim Ingham5a988412012-06-08 21:56:10 +0000644 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
645
Filipe Cabecinhasbc6e85c2012-09-11 16:09:27 +0000646 { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction,
Jim Ingham5a988412012-06-08 21:56:10 +0000647 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
648
649 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
650};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000651
652//-------------------------------------------------------------------------
Caroline Tice93e0f192011-05-22 07:14:46 +0000653// CommandObjectBreakpointCommandDelete
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000654//-------------------------------------------------------------------------
655
Jim Ingham5a988412012-06-08 21:56:10 +0000656class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657{
Jim Ingham5a988412012-06-08 21:56:10 +0000658public:
659 CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
660 CommandObjectParsed (interpreter,
661 "delete",
662 "Delete the set of commands from a breakpoint.",
663 NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000664 {
Jim Ingham5a988412012-06-08 21:56:10 +0000665 CommandArgumentEntry arg;
666 CommandArgumentData bp_id_arg;
667
668 // Define the first (and only) variant of this arg.
669 bp_id_arg.arg_type = eArgTypeBreakpointID;
670 bp_id_arg.arg_repetition = eArgRepeatPlain;
671
672 // There is only one variant this argument could be; put it into the argument entry.
673 arg.push_back (bp_id_arg);
674
675 // Push the data for the first argument into the m_arguments vector.
676 m_arguments.push_back (arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000677 }
678
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000679
Jim Ingham5a988412012-06-08 21:56:10 +0000680 virtual
681 ~CommandObjectBreakpointCommandDelete () {}
682
683protected:
684 virtual bool
685 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000686 {
Jim Ingham5a988412012-06-08 21:56:10 +0000687 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000688
Jim Ingham5a988412012-06-08 21:56:10 +0000689 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000690 {
Jim Ingham5a988412012-06-08 21:56:10 +0000691 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
692 result.SetStatus (eReturnStatusFailed);
693 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000694 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000695
Jim Ingham5a988412012-06-08 21:56:10 +0000696 const BreakpointList &breakpoints = target->GetBreakpointList();
697 size_t num_breakpoints = breakpoints.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000698
Jim Ingham5a988412012-06-08 21:56:10 +0000699 if (num_breakpoints == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000700 {
Jim Ingham5a988412012-06-08 21:56:10 +0000701 result.AppendError ("No breakpoints exist to have commands deleted");
702 result.SetStatus (eReturnStatusFailed);
703 return false;
704 }
705
706 if (command.GetArgumentCount() == 0)
707 {
708 result.AppendError ("No breakpoint specified from which to delete the commands");
709 result.SetStatus (eReturnStatusFailed);
710 return false;
711 }
712
713 BreakpointIDList valid_bp_ids;
714 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
715
716 if (result.Succeeded())
717 {
718 const size_t count = valid_bp_ids.GetSize();
719 for (size_t i = 0; i < count; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720 {
Jim Ingham5a988412012-06-08 21:56:10 +0000721 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
722 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000723 {
Jim Ingham5a988412012-06-08 21:56:10 +0000724 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000725 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
726 {
Jim Ingham5a988412012-06-08 21:56:10 +0000727 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000728 if (bp_loc_sp)
Jim Ingham5a988412012-06-08 21:56:10 +0000729 bp_loc_sp->ClearCallback();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000730 else
731 {
732 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
733 cur_bp_id.GetBreakpointID(),
734 cur_bp_id.GetLocationID());
735 result.SetStatus (eReturnStatusFailed);
736 return false;
737 }
738 }
739 else
740 {
Jim Ingham5a988412012-06-08 21:56:10 +0000741 bp->ClearCallback();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000742 }
Jim Ingham5a988412012-06-08 21:56:10 +0000743 }
744 }
745 }
746 return result.Succeeded();
747 }
748};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000749
Jim Ingham5a988412012-06-08 21:56:10 +0000750//-------------------------------------------------------------------------
751// CommandObjectBreakpointCommandList
752//-------------------------------------------------------------------------
753
754class CommandObjectBreakpointCommandList : public CommandObjectParsed
755{
756public:
757 CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
758 CommandObjectParsed (interpreter,
759 "list",
760 "List the script or set of commands to be executed when the breakpoint is hit.",
761 NULL)
762 {
763 CommandArgumentEntry arg;
764 CommandArgumentData bp_id_arg;
765
766 // Define the first (and only) variant of this arg.
767 bp_id_arg.arg_type = eArgTypeBreakpointID;
768 bp_id_arg.arg_repetition = eArgRepeatPlain;
769
770 // There is only one variant this argument could be; put it into the argument entry.
771 arg.push_back (bp_id_arg);
772
773 // Push the data for the first argument into the m_arguments vector.
774 m_arguments.push_back (arg);
775 }
776
777 virtual
778 ~CommandObjectBreakpointCommandList () {}
779
780protected:
781 virtual bool
782 DoExecute (Args& command,
783 CommandReturnObject &result)
784 {
785 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
786
787 if (target == NULL)
788 {
789 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
790 result.SetStatus (eReturnStatusFailed);
791 return false;
792 }
793
794 const BreakpointList &breakpoints = target->GetBreakpointList();
795 size_t num_breakpoints = breakpoints.GetSize();
796
797 if (num_breakpoints == 0)
798 {
799 result.AppendError ("No breakpoints exist for which to list commands");
800 result.SetStatus (eReturnStatusFailed);
801 return false;
802 }
803
804 if (command.GetArgumentCount() == 0)
805 {
806 result.AppendError ("No breakpoint specified for which to list the commands");
807 result.SetStatus (eReturnStatusFailed);
808 return false;
809 }
810
811 BreakpointIDList valid_bp_ids;
812 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
813
814 if (result.Succeeded())
815 {
816 const size_t count = valid_bp_ids.GetSize();
817 for (size_t i = 0; i < count; ++i)
818 {
819 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
820 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
821 {
822 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
823
824 if (bp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000825 {
Jim Ingham5a988412012-06-08 21:56:10 +0000826 const BreakpointOptions *bp_options = NULL;
827 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000828 {
Jim Ingham5a988412012-06-08 21:56:10 +0000829 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
830 if (bp_loc_sp)
831 bp_options = bp_loc_sp->GetOptionsNoCreate();
832 else
833 {
834 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
835 cur_bp_id.GetBreakpointID(),
836 cur_bp_id.GetLocationID());
837 result.SetStatus (eReturnStatusFailed);
838 return false;
839 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000840 }
841 else
842 {
Jim Ingham5a988412012-06-08 21:56:10 +0000843 bp_options = bp->GetOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000844 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000845
Jim Ingham5a988412012-06-08 21:56:10 +0000846 if (bp_options)
847 {
848 StreamString id_str;
849 BreakpointID::GetCanonicalReference (&id_str,
850 cur_bp_id.GetBreakpointID(),
851 cur_bp_id.GetLocationID());
852 const Baton *baton = bp_options->GetBaton();
853 if (baton)
854 {
855 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
856 result.GetOutputStream().IndentMore ();
857 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
858 result.GetOutputStream().IndentLess ();
859 }
860 else
861 {
862 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
863 id_str.GetData());
864 }
865 }
866 result.SetStatus (eReturnStatusSuccessFinishResult);
867 }
868 else
869 {
870 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
871 result.SetStatus (eReturnStatusFailed);
872 }
873
874 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000875 }
876 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000877
Jim Ingham5a988412012-06-08 21:56:10 +0000878 return result.Succeeded();
879 }
880};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000881
882//-------------------------------------------------------------------------
883// CommandObjectBreakpointCommand
884//-------------------------------------------------------------------------
885
Greg Clayton66111032010-06-23 01:19:29 +0000886CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +0000887 CommandObjectMultiword (interpreter,
888 "command",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000889 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
890 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
891{
Greg Claytona7015092010-09-18 01:14:36 +0000892 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Tice93e0f192011-05-22 07:14:46 +0000893 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Claytona7015092010-09-18 01:14:36 +0000894 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000895
896 add_command_object->SetCommandName ("breakpoint command add");
Caroline Tice93e0f192011-05-22 07:14:46 +0000897 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000898 list_command_object->SetCommandName ("breakpoint command list");
899
Greg Clayton23f59502012-07-17 03:23:13 +0000900 LoadSubCommand ("add", add_command_object);
901 LoadSubCommand ("delete", delete_command_object);
902 LoadSubCommand ("list", list_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000903}
904
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000905CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
906{
907}
908
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000909