blob: f308ae3713cb9c601ec635df2eca6aade9edbc87 [file] [log] [blame]
Chris Lattner24943d22010-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
10// C Includes
11// C++ Includes
12
13
14#include "CommandObjectBreakpointCommand.h"
15#include "CommandObjectBreakpoint.h"
16
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Interpreter/CommandReturnObject.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/Thread.h"
21#include "lldb/Breakpoint/BreakpointIDList.h"
22#include "lldb/Breakpoint/Breakpoint.h"
23#include "lldb/Breakpoint/BreakpointLocation.h"
24#include "lldb/Breakpoint/StoppointCallbackContext.h"
25#include "lldb/Core/State.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +000031// CommandObjectBreakpointCommandAdd
32//-------------------------------------------------------------------------
33
34
Jim Inghamda26bd22012-06-08 21:56:10 +000035class CommandObjectBreakpointCommandAdd : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +000036{
Jim Inghamda26bd22012-06-08 21:56:10 +000037public:
38
39 CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
40 CommandObjectParsed (interpreter,
41 "add",
42 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
43 NULL),
44 m_options (interpreter)
45 {
46 SetHelpLong (
Greg Claytonb34ca852012-10-26 17:53:21 +000047"\nGeneral information about entering breakpoint commands\n\
48------------------------------------------------------\n\
49\n\
50This command will cause you to be prompted to enter the command or set of\n\
51commands you wish to be executed when the specified breakpoint is hit. You\n\
52will be told to enter your command(s), and will see a '> 'prompt. Because\n\
53you can enter one or many commands to be executed when a breakpoint is hit,\n\
54you will continue to be prompted after each new-line that you enter, until you\n\
55enter the word 'DONE', which will cause the commands you have entered to be\n\
56stored with the breakpoint and executed when the breakpoint is hit.\n\
57\n\
58Syntax checking is not necessarily done when breakpoint commands are entered.\n\
59An improperly written breakpoint command will attempt to get executed when the\n\
60breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
61not appear to be getting executed, go back and check your syntax.\n\
62\n\
63Special information about PYTHON breakpoint commands\n\
64----------------------------------------------------\n\
65\n\
66You may enter either one line of Python, multiple lines of Python (including\n\
67function definitions), or specify a Python function in a module that has already,\n\
68or will be imported. If you enter a single line of Python, that will be passed\n\
69to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
70function definitions, they will be passed to the Python interpreter as soon as\n\
71you finish entering the breakpoint command, and they can be called later (don't\n\
72forget to add calls to them, if you want them called when the breakpoint is\n\
73hit). If you enter multiple lines of Python that are not function definitions,\n\
74they will be collected into a new, automatically generated Python function, and\n\
75a call to the newly generated function will be attached to the breakpoint.\n\
76\n\
77\n\
78This auto-generated function is passed in three arguments:\n\
79\n\
80 frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
81 bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
82 location that was hit.\n\
83 dict: the python session dictionary hit.\n\
84\n\
85When specifying a python function with the --python-function option, you need\n\
86to supply the function name prepended by the module name. So if you import a\n\
87module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
88specify the option as:\n\
89\n\
90 --python-function myutils.breakpoint_callback\n\
91\n\
92The function itself must have the following prototype:\n\
93\n\
94def breakpoint_callback(frame, bp_loc, dict):\n\
95 # Your code goes here\n\
96\n\
97The arguments are the same as the 3 auto generation function arguments listed\n\
98above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
99function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
100can get you to the thread (frame.GetThread()), the thread can get you to the\n\
101process (thread.GetProcess()), and the process can get you back to the target\n\
102(process.GetTarget()).\n\
103\n\
104Important Note: Because loose Python code gets collected into functions, if you\n\
105want to access global variables in the 'loose' code, you need to specify that\n\
106they are global, using the 'global' keyword. Be sure to use correct Python\n\
107syntax, including indentation, when entering Python breakpoint commands.\n\
108\n\
109As a third option, you can pass the name of an already existing Python function\n\
110and that function will be attached to the breakpoint. It will get passed the\n\
111frame and bp_loc arguments mentioned above.\n\
112\n\
113Example Python one-line breakpoint command:\n\
114\n\
115(lldb) breakpoint command add -s python 1\n\
116Enter your Python command(s). Type 'DONE' to end.\n\
117> print \"Hit this breakpoint!\"\n\
118> DONE\n\
119\n\
120As a convenience, this also works for a short Python one-liner:\n\
121(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
122(lldb) run\n\
123Launching '.../a.out' (x86_64)\n\
124(lldb) Fri Sep 10 12:17:45 2010\n\
125Process 21778 Stopped\n\
126* 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 Chen4c1b2182010-09-10 19:34:12 +0000127 36 \n\
128 37 int c(int val)\n\
129 38 {\n\
130 39 -> return val + 3;\n\
131 40 }\n\
132 41 \n\
133 42 int main (int argc, char const *argv[])\n\
Greg Claytonb34ca852012-10-26 17:53:21 +0000134(lldb)\n\
135\n\
136Example multiple line Python breakpoint command, using function definition:\n\
137\n\
138(lldb) breakpoint command add -s python 1\n\
139Enter your Python command(s). Type 'DONE' to end.\n\
140> def breakpoint_output (bp_no):\n\
141> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
142> print out_string\n\
143> return True\n\
144> breakpoint_output (1)\n\
145> DONE\n\
146\n\
147\n\
148Example multiple line Python breakpoint command, using 'loose' Python:\n\
149\n\
150(lldb) breakpoint command add -s p 1\n\
151Enter your Python command(s). Type 'DONE' to end.\n\
152> global bp_count\n\
153> bp_count = bp_count + 1\n\
154> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
155> DONE\n\
156\n\
157In this case, since there is a reference to a global variable,\n\
158'bp_count', you will also need to make sure 'bp_count' exists and is\n\
159initialized:\n\
160\n\
161(lldb) script\n\
162>>> bp_count = 0\n\
163>>> quit()\n\
164\n\
165(lldb)\n\
166\n\
167\n\
168Final Note: If you get a warning that no breakpoint command was generated, but\n\
169you did not get any syntax errors, you probably forgot to add a call to your\n\
170functions.\n\
171\n\
172Special information about debugger command breakpoint commands\n\
173--------------------------------------------------------------\n\
174\n\
175You may enter any debugger command, exactly as you would at the debugger prompt.\n\
176You may enter as many debugger commands as you like, but do NOT enter more than\n\
177one command per line.\n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000178
Jim Inghamda26bd22012-06-08 21:56:10 +0000179 CommandArgumentEntry arg;
180 CommandArgumentData bp_id_arg;
Caroline Tice43b014a2010-10-04 22:28:36 +0000181
Jim Inghamda26bd22012-06-08 21:56:10 +0000182 // Define the first (and only) variant of this arg.
183 bp_id_arg.arg_type = eArgTypeBreakpointID;
184 bp_id_arg.arg_repetition = eArgRepeatPlain;
Caroline Tice43b014a2010-10-04 22:28:36 +0000185
Jim Inghamda26bd22012-06-08 21:56:10 +0000186 // There is only one variant this argument could be; put it into the argument entry.
187 arg.push_back (bp_id_arg);
Caroline Tice43b014a2010-10-04 22:28:36 +0000188
Jim Inghamda26bd22012-06-08 21:56:10 +0000189 // Push the data for the first argument into the m_arguments vector.
190 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000191 }
192
Jim Inghamda26bd22012-06-08 21:56:10 +0000193 virtual
194 ~CommandObjectBreakpointCommandAdd () {}
Chris Lattner24943d22010-06-08 16:52:24 +0000195
Jim Inghamda26bd22012-06-08 21:56:10 +0000196 virtual Options *
197 GetOptions ()
Chris Lattner24943d22010-06-08 16:52:24 +0000198 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000199 return &m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000200 }
201
Jim Inghamda26bd22012-06-08 21:56:10 +0000202 void
203 CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
204 CommandReturnObject &result)
Enrico Granata8ad21a82012-04-04 17:30:31 +0000205 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000206 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
207 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
208 if (reader_sp && data_ap.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000209 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000210 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
211 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
212
213 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
214 bp_options, // baton
215 eInputReaderGranularityLine, // token size, to pass to callback function
216 "DONE", // end token
217 "> ", // prompt
218 true)); // echo input
219 if (err.Success())
Chris Lattner24943d22010-06-08 16:52:24 +0000220 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000221 m_interpreter.GetDebugger().PushInputReader (reader_sp);
222 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000223 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000224 else
225 {
226 result.AppendError (err.AsCString());
227 result.SetStatus (eReturnStatusFailed);
228 }
Chris Lattner24943d22010-06-08 16:52:24 +0000229 }
230 else
231 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000232 result.AppendError("out of memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000233 result.SetStatus (eReturnStatusFailed);
234 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000235
Chris Lattner24943d22010-06-08 16:52:24 +0000236 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000237
Jim Inghamda26bd22012-06-08 21:56:10 +0000238 /// Set a one-liner as the callback for the breakpoint.
239 void
240 SetBreakpointCommandCallback (BreakpointOptions *bp_options,
241 const char *oneliner)
Chris Lattner24943d22010-06-08 16:52:24 +0000242 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000243 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Chris Lattner24943d22010-06-08 16:52:24 +0000244
Jim Inghamda26bd22012-06-08 21:56:10 +0000245 // It's necessary to set both user_source and script_source to the oneliner.
246 // The former is used to generate callback description (as in breakpoint command list)
247 // while the latter is used for Python to interpret during the actual callback.
248 data_ap->user_source.AppendString (oneliner);
249 data_ap->script_source.assign (oneliner);
250 data_ap->stop_on_error = m_options.m_stop_on_error;
Chris Lattner24943d22010-06-08 16:52:24 +0000251
Jim Inghamda26bd22012-06-08 21:56:10 +0000252 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
253 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000254
Jim Inghamda26bd22012-06-08 21:56:10 +0000255 return;
256 }
257
258 static size_t
259 GenerateBreakpointCommandCallback (void *baton,
260 InputReader &reader,
261 lldb::InputReaderAction notification,
262 const char *bytes,
263 size_t bytes_len)
264 {
265 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
266 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Caroline Tice4a348082011-05-02 20:41:46 +0000267
Jim Inghamda26bd22012-06-08 21:56:10 +0000268 switch (notification)
Chris Lattner24943d22010-06-08 16:52:24 +0000269 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000270 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000271 if (!batch_mode)
272 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000273 out_stream->Printf ("%s\n", g_reader_instructions);
274 if (reader.GetPrompt())
275 out_stream->Printf ("%s", reader.GetPrompt());
Caroline Tice892fadd2011-06-16 16:27:19 +0000276 out_stream->Flush();
277 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000278 break;
279
280 case eInputReaderDeactivate:
281 break;
282
283 case eInputReaderReactivate:
284 if (reader.GetPrompt() && !batch_mode)
285 {
286 out_stream->Printf ("%s", reader.GetPrompt());
287 out_stream->Flush();
288 }
289 break;
290
291 case eInputReaderAsynchronousOutputWritten:
292 break;
293
294 case eInputReaderGotToken:
295 if (bytes && bytes_len && baton)
296 {
297 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
298 if (bp_options)
299 {
300 Baton *bp_options_baton = bp_options->GetBaton();
301 if (bp_options_baton)
302 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
303 }
304 }
305 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
306 {
307 out_stream->Printf ("%s", reader.GetPrompt());
308 out_stream->Flush();
309 }
310 break;
311
312 case eInputReaderInterrupt:
313 {
314 // Finish, and cancel the breakpoint command.
315 reader.SetIsDone (true);
316 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
317 if (bp_options)
318 {
319 Baton *bp_options_baton = bp_options->GetBaton ();
320 if (bp_options_baton)
321 {
322 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
323 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
324 }
325 }
326 if (!batch_mode)
327 {
328 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
329 out_stream->Flush();
330 }
331 }
332 break;
333
334 case eInputReaderEndOfFile:
335 reader.SetIsDone (true);
336 break;
337
338 case eInputReaderDone:
339 break;
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000340 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000341
342 return bytes_len;
343 }
344
345 static bool
346 BreakpointOptionsCallbackFunction (void *baton,
347 StoppointCallbackContext *context,
348 lldb::user_id_t break_id,
349 lldb::user_id_t break_loc_id)
350 {
351 bool ret_value = true;
352 if (baton == NULL)
353 return true;
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000354
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000355
Jim Inghamda26bd22012-06-08 21:56:10 +0000356 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
357 StringList &commands = data->user_source;
358
359 if (commands.GetSize() > 0)
360 {
361 ExecutionContext exe_ctx (context->exe_ctx_ref);
362 Target *target = exe_ctx.GetTargetPtr();
363 if (target)
364 {
365 CommandReturnObject result;
366 Debugger &debugger = target->GetDebugger();
367 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
368 // if the debugger is set up that way.
369
370 StreamSP output_stream (debugger.GetAsyncOutputStream());
371 StreamSP error_stream (debugger.GetAsyncErrorStream());
372 result.SetImmediateOutputStream (output_stream);
373 result.SetImmediateErrorStream (error_stream);
374
375 bool stop_on_continue = true;
376 bool echo_commands = false;
377 bool print_results = true;
378
379 debugger.GetCommandInterpreter().HandleCommands (commands,
380 &exe_ctx,
381 stop_on_continue,
382 data->stop_on_error,
383 echo_commands,
384 print_results,
385 eLazyBoolNo,
386 result);
387 result.GetImmediateOutputStream()->Flush();
388 result.GetImmediateErrorStream()->Flush();
389 }
390 }
391 return ret_value;
392 }
393
394 class CommandOptions : public Options
395 {
396 public:
397
398 CommandOptions (CommandInterpreter &interpreter) :
399 Options (interpreter),
400 m_use_commands (false),
401 m_use_script_language (false),
402 m_script_language (eScriptLanguageNone),
403 m_use_one_liner (false),
404 m_one_liner(),
405 m_function_name()
406 {
407 }
408
409 virtual
410 ~CommandOptions () {}
411
412 virtual Error
413 SetOptionValue (uint32_t option_idx, const char *option_arg)
414 {
415 Error error;
416 char short_option = (char) m_getopt_table[option_idx].val;
417
418 switch (short_option)
419 {
420 case 'o':
421 m_use_one_liner = true;
422 m_one_liner = option_arg;
423 break;
424
425 case 's':
426 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
427 g_option_table[option_idx].enum_values,
428 eScriptLanguageNone,
429 error);
430
431 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
432 {
433 m_use_script_language = true;
434 }
435 else
436 {
437 m_use_script_language = false;
438 }
439 break;
440
441 case 'e':
442 {
443 bool success = false;
444 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
445 if (!success)
446 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
447 }
448 break;
449
450 case 'F':
451 {
452 m_use_one_liner = false;
453 m_use_script_language = true;
454 m_function_name.assign(option_arg);
455 }
456 break;
457
458 default:
459 break;
460 }
461 return error;
462 }
463 void
464 OptionParsingStarting ()
465 {
466 m_use_commands = true;
467 m_use_script_language = false;
468 m_script_language = eScriptLanguageNone;
469
470 m_use_one_liner = false;
471 m_stop_on_error = true;
472 m_one_liner.clear();
473 m_function_name.clear();
474 }
475
476 const OptionDefinition*
477 GetDefinitions ()
478 {
479 return g_option_table;
480 }
481
482 // Options table: Required for subclasses of Options.
483
484 static OptionDefinition g_option_table[];
485
486 // Instance variables to hold the values for command options.
487
488 bool m_use_commands;
489 bool m_use_script_language;
490 lldb::ScriptLanguage m_script_language;
491
492 // Instance variables to hold the values for one_liner options.
493 bool m_use_one_liner;
494 std::string m_one_liner;
495 bool m_stop_on_error;
496 std::string m_function_name;
497 };
498
499protected:
500 virtual bool
501 DoExecute (Args& command, CommandReturnObject &result)
502 {
503 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
504
505 if (target == NULL)
506 {
507 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
508 result.SetStatus (eReturnStatusFailed);
509 return false;
510 }
511
512 const BreakpointList &breakpoints = target->GetBreakpointList();
513 size_t num_breakpoints = breakpoints.GetSize();
514
515 if (num_breakpoints == 0)
516 {
517 result.AppendError ("No breakpoints exist to have commands added");
518 result.SetStatus (eReturnStatusFailed);
519 return false;
520 }
521
522 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
523 {
524 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
525 result.SetStatus (eReturnStatusFailed);
526 return false;
527 }
528
529 BreakpointIDList valid_bp_ids;
530 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
531
532 if (result.Succeeded())
533 {
534 const size_t count = valid_bp_ids.GetSize();
535 for (size_t i = 0; i < count; ++i)
536 {
537 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
538 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
539 {
540 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
541 BreakpointOptions *bp_options = NULL;
542 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
543 {
544 // This breakpoint does not have an associated location.
545 bp_options = bp->GetOptions();
546 }
547 else
548 {
549 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
550 // This breakpoint does have an associated location.
551 // Get its breakpoint options.
552 if (bp_loc_sp)
553 bp_options = bp_loc_sp->GetLocationOptions();
554 }
555
556 // Skip this breakpoint if bp_options is not good.
557 if (bp_options == NULL) continue;
558
559 // If we are using script language, get the script interpreter
560 // in order to set or collect command callback. Otherwise, call
561 // the methods associated with this object.
562 if (m_options.m_use_script_language)
563 {
564 // Special handling for one-liner specified inline.
565 if (m_options.m_use_one_liner)
566 {
567 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
568 m_options.m_one_liner.c_str());
569 }
570 // Special handling for using a Python function by name
571 // instead of extending the breakpoint callback data structures, we just automatize
572 // what the user would do manually: make their breakpoint command be a function call
573 else if (m_options.m_function_name.size())
574 {
575 std::string oneliner(m_options.m_function_name);
Enrico Granatac1ca9dc2012-08-08 02:06:30 +0000576 oneliner += "(frame, bp_loc, internal_dict)";
Jim Inghamda26bd22012-06-08 21:56:10 +0000577 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
578 oneliner.c_str());
579 }
580 else
581 {
582 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
583 result);
584 }
585 }
586 else
587 {
588 // Special handling for one-liner specified inline.
589 if (m_options.m_use_one_liner)
590 SetBreakpointCommandCallback (bp_options,
591 m_options.m_one_liner.c_str());
592 else
593 CollectDataForBreakpointCommandCallback (bp_options,
594 result);
595 }
596 }
597 }
598 }
599
600 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +0000601 }
602
Jim Inghamda26bd22012-06-08 21:56:10 +0000603private:
604 CommandOptions m_options;
605 static const char *g_reader_instructions;
Chris Lattner24943d22010-06-08 16:52:24 +0000606
Jim Inghamda26bd22012-06-08 21:56:10 +0000607};
608
609const char *
610CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
611
612// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
613// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
614
615static OptionEnumValueElement
616g_script_option_enumeration[4] =
617{
618 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
619 { eScriptLanguagePython, "python", "Commands are in the Python language."},
620 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
621 { 0, NULL, NULL }
622};
623
624OptionDefinition
625CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
626{
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000627 { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
Jim Inghamda26bd22012-06-08 21:56:10 +0000628 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
629
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000630 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,
Jim Inghamda26bd22012-06-08 21:56:10 +0000631 "Specify whether breakpoint command execution should terminate on error." },
632
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000633 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
Jim Inghamda26bd22012-06-08 21:56:10 +0000634 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
635
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000636 { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction,
Jim Inghamda26bd22012-06-08 21:56:10 +0000637 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
638
639 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
640};
Chris Lattner24943d22010-06-08 16:52:24 +0000641
642//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000643// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000644//-------------------------------------------------------------------------
645
Jim Inghamda26bd22012-06-08 21:56:10 +0000646class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000647{
Jim Inghamda26bd22012-06-08 21:56:10 +0000648public:
649 CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
650 CommandObjectParsed (interpreter,
651 "delete",
652 "Delete the set of commands from a breakpoint.",
653 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000654 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000655 CommandArgumentEntry arg;
656 CommandArgumentData bp_id_arg;
657
658 // Define the first (and only) variant of this arg.
659 bp_id_arg.arg_type = eArgTypeBreakpointID;
660 bp_id_arg.arg_repetition = eArgRepeatPlain;
661
662 // There is only one variant this argument could be; put it into the argument entry.
663 arg.push_back (bp_id_arg);
664
665 // Push the data for the first argument into the m_arguments vector.
666 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000667 }
668
Chris Lattner24943d22010-06-08 16:52:24 +0000669
Jim Inghamda26bd22012-06-08 21:56:10 +0000670 virtual
671 ~CommandObjectBreakpointCommandDelete () {}
672
673protected:
674 virtual bool
675 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000676 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000677 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000678
Jim Inghamda26bd22012-06-08 21:56:10 +0000679 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000680 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000681 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
682 result.SetStatus (eReturnStatusFailed);
683 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000684 }
Chris Lattner24943d22010-06-08 16:52:24 +0000685
Jim Inghamda26bd22012-06-08 21:56:10 +0000686 const BreakpointList &breakpoints = target->GetBreakpointList();
687 size_t num_breakpoints = breakpoints.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000688
Jim Inghamda26bd22012-06-08 21:56:10 +0000689 if (num_breakpoints == 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000690 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000691 result.AppendError ("No breakpoints exist to have commands deleted");
692 result.SetStatus (eReturnStatusFailed);
693 return false;
694 }
695
696 if (command.GetArgumentCount() == 0)
697 {
698 result.AppendError ("No breakpoint specified from which to delete the commands");
699 result.SetStatus (eReturnStatusFailed);
700 return false;
701 }
702
703 BreakpointIDList valid_bp_ids;
704 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
705
706 if (result.Succeeded())
707 {
708 const size_t count = valid_bp_ids.GetSize();
709 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000710 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000711 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
712 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000713 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000714 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000715 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
716 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000717 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
Chris Lattner24943d22010-06-08 16:52:24 +0000718 if (bp_loc_sp)
Jim Inghamda26bd22012-06-08 21:56:10 +0000719 bp_loc_sp->ClearCallback();
Chris Lattner24943d22010-06-08 16:52:24 +0000720 else
721 {
722 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
723 cur_bp_id.GetBreakpointID(),
724 cur_bp_id.GetLocationID());
725 result.SetStatus (eReturnStatusFailed);
726 return false;
727 }
728 }
729 else
730 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000731 bp->ClearCallback();
Chris Lattner24943d22010-06-08 16:52:24 +0000732 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000733 }
734 }
735 }
736 return result.Succeeded();
737 }
738};
Chris Lattner24943d22010-06-08 16:52:24 +0000739
Jim Inghamda26bd22012-06-08 21:56:10 +0000740//-------------------------------------------------------------------------
741// CommandObjectBreakpointCommandList
742//-------------------------------------------------------------------------
743
744class CommandObjectBreakpointCommandList : public CommandObjectParsed
745{
746public:
747 CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
748 CommandObjectParsed (interpreter,
749 "list",
750 "List the script or set of commands to be executed when the breakpoint is hit.",
751 NULL)
752 {
753 CommandArgumentEntry arg;
754 CommandArgumentData bp_id_arg;
755
756 // Define the first (and only) variant of this arg.
757 bp_id_arg.arg_type = eArgTypeBreakpointID;
758 bp_id_arg.arg_repetition = eArgRepeatPlain;
759
760 // There is only one variant this argument could be; put it into the argument entry.
761 arg.push_back (bp_id_arg);
762
763 // Push the data for the first argument into the m_arguments vector.
764 m_arguments.push_back (arg);
765 }
766
767 virtual
768 ~CommandObjectBreakpointCommandList () {}
769
770protected:
771 virtual bool
772 DoExecute (Args& command,
773 CommandReturnObject &result)
774 {
775 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
776
777 if (target == NULL)
778 {
779 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
780 result.SetStatus (eReturnStatusFailed);
781 return false;
782 }
783
784 const BreakpointList &breakpoints = target->GetBreakpointList();
785 size_t num_breakpoints = breakpoints.GetSize();
786
787 if (num_breakpoints == 0)
788 {
789 result.AppendError ("No breakpoints exist for which to list commands");
790 result.SetStatus (eReturnStatusFailed);
791 return false;
792 }
793
794 if (command.GetArgumentCount() == 0)
795 {
796 result.AppendError ("No breakpoint specified for which to list the commands");
797 result.SetStatus (eReturnStatusFailed);
798 return false;
799 }
800
801 BreakpointIDList valid_bp_ids;
802 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
803
804 if (result.Succeeded())
805 {
806 const size_t count = valid_bp_ids.GetSize();
807 for (size_t i = 0; i < count; ++i)
808 {
809 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
810 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
811 {
812 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
813
814 if (bp)
Chris Lattner24943d22010-06-08 16:52:24 +0000815 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000816 const BreakpointOptions *bp_options = NULL;
817 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000818 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000819 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
820 if (bp_loc_sp)
821 bp_options = bp_loc_sp->GetOptionsNoCreate();
822 else
823 {
824 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
825 cur_bp_id.GetBreakpointID(),
826 cur_bp_id.GetLocationID());
827 result.SetStatus (eReturnStatusFailed);
828 return false;
829 }
Chris Lattner24943d22010-06-08 16:52:24 +0000830 }
831 else
832 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000833 bp_options = bp->GetOptions();
Chris Lattner24943d22010-06-08 16:52:24 +0000834 }
Chris Lattner24943d22010-06-08 16:52:24 +0000835
Jim Inghamda26bd22012-06-08 21:56:10 +0000836 if (bp_options)
837 {
838 StreamString id_str;
839 BreakpointID::GetCanonicalReference (&id_str,
840 cur_bp_id.GetBreakpointID(),
841 cur_bp_id.GetLocationID());
842 const Baton *baton = bp_options->GetBaton();
843 if (baton)
844 {
845 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
846 result.GetOutputStream().IndentMore ();
847 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
848 result.GetOutputStream().IndentLess ();
849 }
850 else
851 {
852 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
853 id_str.GetData());
854 }
855 }
856 result.SetStatus (eReturnStatusSuccessFinishResult);
857 }
858 else
859 {
860 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
861 result.SetStatus (eReturnStatusFailed);
862 }
863
864 }
Chris Lattner24943d22010-06-08 16:52:24 +0000865 }
866 }
Chris Lattner24943d22010-06-08 16:52:24 +0000867
Jim Inghamda26bd22012-06-08 21:56:10 +0000868 return result.Succeeded();
869 }
870};
Chris Lattner24943d22010-06-08 16:52:24 +0000871
872//-------------------------------------------------------------------------
873// CommandObjectBreakpointCommand
874//-------------------------------------------------------------------------
875
Greg Clayton63094e02010-06-23 01:19:29 +0000876CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000877 CommandObjectMultiword (interpreter,
878 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000879 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
880 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
881{
Greg Clayton238c0a12010-09-18 01:14:36 +0000882 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000883 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000884 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000885
886 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000887 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000888 list_command_object->SetCommandName ("breakpoint command list");
889
Greg Clayton4a379b12012-07-17 03:23:13 +0000890 LoadSubCommand ("add", add_command_object);
891 LoadSubCommand ("delete", delete_command_object);
892 LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000893}
894
Chris Lattner24943d22010-06-08 16:52:24 +0000895CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
896{
897}
898
Chris Lattner24943d22010-06-08 16:52:24 +0000899