blob: 8f19ddea6cb8fcbc8a73a874e68dbd6a910070fe [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 (
Chris Lattner24943d22010-06-08 16:52:24 +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 \n\
51of commands you wish to be executed when the specified breakpoint is \n\
52hit. You will be told to enter your command(s), and will see a '> ' \n\
53prompt. Because you can enter one or many commands to be executed when \n\
54a breakpoint is hit, you will continue to be prompted after each \n\
55new-line that you enter, until you enter the word 'DONE', which will \n\
56cause the commands you have entered to be stored with the breakpoint \n\
57and executed when the breakpoint is hit. \n\
58 \n\
59Syntax checking is not necessarily done when breakpoint commands are \n\
60entered. An improperly written breakpoint command will attempt to get \n\
61executed when the breakpoint gets hit, and usually silently fail. If \n\
62your breakpoint command does not appear to be getting executed, go \n\
63back and check your syntax. \n\
64 \n\
65 \n\
Jim Ingham73260da2012-04-25 01:05:21 +000066Special information about PYTHON breakpoint commands \n\
67---------------------------------------------------- \n\
68 \n\
69You may enter either one line of Python or multiple lines of Python \n\
70(including defining whole functions, if desired). If you enter a \n\
71single line of Python, that will be passed to the Python interpreter \n\
72'as is' when the breakpoint gets hit. If you enter function \n\
73definitions, they will be passed to the Python interpreter as soon as \n\
74you finish entering the breakpoint command, and they can be called \n\
75later (don't forget to add calls to them, if you want them called when \n\
76the breakpoint is hit). If you enter multiple lines of Python that \n\
77are not function definitions, they will be collected into a new, \n\
78automatically generated Python function, and a call to the newly \n\
79generated function will be attached to the breakpoint. \n\
80 \n\
81This auto-generated function is passed in two arguments: \n\
82 \n\
83 frame: an SBFrame object representing the frame which hit the breakpoint. \n\
84 From the frame you can get back to the thread and process. \n\
85 bp_loc: the number of the breakpoint location that was hit. \n\
86 This is useful since one breakpoint can have many locations. \n\
87 \n\
88Important Note: Because loose Python code gets collected into functions, \n\
89if you want to access global variables in the 'loose' code, you need to \n\
90specify that they are global, using the 'global' keyword. Be sure to \n\
91use correct Python syntax, including indentation, when entering Python \n\
92breakpoint commands. \n\
93 \n\
94As a third option, you can pass the name of an already existing Python function \n\
95and that function will be attached to the breakpoint. It will get passed the \n\
96frame and bp_loc arguments mentioned above. \n\
97 \n\
Chris Lattner24943d22010-06-08 16:52:24 +000098Example Python one-line breakpoint command: \n\
99 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000100(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000101Enter your Python command(s). Type 'DONE' to end. \n\
102> print \"Hit this breakpoint!\" \n\
103> DONE \n\
104 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000105As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000106(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000107(lldb) run \n\
108Launching '.../a.out' (x86_64) \n\
109(lldb) Fri Sep 10 12:17:45 2010 \n\
110Process 21778 Stopped \n\
111* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
112 36 \n\
113 37 int c(int val)\n\
114 38 {\n\
115 39 -> return val + 3;\n\
116 40 }\n\
117 41 \n\
118 42 int main (int argc, char const *argv[])\n\
119(lldb) \n\
120 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000121Example multiple line Python breakpoint command, using function definition: \n\
122 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000123(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000124Enter your Python command(s). Type 'DONE' to end. \n\
125> def breakpoint_output (bp_no): \n\
126> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
127> print out_string \n\
128> return True \n\
129> breakpoint_output (1) \n\
130> DONE \n\
131 \n\
132 \n\
133Example multiple line Python breakpoint command, using 'loose' Python: \n\
134 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000135(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000136Enter your Python command(s). Type 'DONE' to end. \n\
137> global bp_count \n\
138> bp_count = bp_count + 1 \n\
139> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
140> DONE \n\
141 \n\
142In this case, since there is a reference to a global variable, \n\
143'bp_count', you will also need to make sure 'bp_count' exists and is \n\
144initialized: \n\
145 \n\
146(lldb) script \n\
147>>> bp_count = 0 \n\
148>>> quit() \n\
149 \n\
150(lldb) \n\
151 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000152 \n\
153Final Note: If you get a warning that no breakpoint command was generated, \n\
154but you did not get any syntax errors, you probably forgot to add a call \n\
155to your functions. \n\
156 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000157Special information about debugger command breakpoint commands \n\
158-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000159 \n\
160You may enter any debugger command, exactly as you would at the \n\
161debugger prompt. You may enter as many debugger commands as you like, \n\
162but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000163
Jim Inghamda26bd22012-06-08 21:56:10 +0000164 CommandArgumentEntry arg;
165 CommandArgumentData bp_id_arg;
Caroline Tice43b014a2010-10-04 22:28:36 +0000166
Jim Inghamda26bd22012-06-08 21:56:10 +0000167 // Define the first (and only) variant of this arg.
168 bp_id_arg.arg_type = eArgTypeBreakpointID;
169 bp_id_arg.arg_repetition = eArgRepeatPlain;
Caroline Tice43b014a2010-10-04 22:28:36 +0000170
Jim Inghamda26bd22012-06-08 21:56:10 +0000171 // There is only one variant this argument could be; put it into the argument entry.
172 arg.push_back (bp_id_arg);
Caroline Tice43b014a2010-10-04 22:28:36 +0000173
Jim Inghamda26bd22012-06-08 21:56:10 +0000174 // Push the data for the first argument into the m_arguments vector.
175 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000176 }
177
Jim Inghamda26bd22012-06-08 21:56:10 +0000178 virtual
179 ~CommandObjectBreakpointCommandAdd () {}
Chris Lattner24943d22010-06-08 16:52:24 +0000180
Jim Inghamda26bd22012-06-08 21:56:10 +0000181 virtual Options *
182 GetOptions ()
Chris Lattner24943d22010-06-08 16:52:24 +0000183 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000184 return &m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000185 }
186
Jim Inghamda26bd22012-06-08 21:56:10 +0000187 void
188 CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
189 CommandReturnObject &result)
Enrico Granata8ad21a82012-04-04 17:30:31 +0000190 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000191 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
192 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
193 if (reader_sp && data_ap.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000194 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000195 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
196 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
197
198 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
199 bp_options, // baton
200 eInputReaderGranularityLine, // token size, to pass to callback function
201 "DONE", // end token
202 "> ", // prompt
203 true)); // echo input
204 if (err.Success())
Chris Lattner24943d22010-06-08 16:52:24 +0000205 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000206 m_interpreter.GetDebugger().PushInputReader (reader_sp);
207 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000208 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000209 else
210 {
211 result.AppendError (err.AsCString());
212 result.SetStatus (eReturnStatusFailed);
213 }
Chris Lattner24943d22010-06-08 16:52:24 +0000214 }
215 else
216 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000217 result.AppendError("out of memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000218 result.SetStatus (eReturnStatusFailed);
219 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000220
Chris Lattner24943d22010-06-08 16:52:24 +0000221 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000222
Jim Inghamda26bd22012-06-08 21:56:10 +0000223 /// Set a one-liner as the callback for the breakpoint.
224 void
225 SetBreakpointCommandCallback (BreakpointOptions *bp_options,
226 const char *oneliner)
Chris Lattner24943d22010-06-08 16:52:24 +0000227 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000228 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Chris Lattner24943d22010-06-08 16:52:24 +0000229
Jim Inghamda26bd22012-06-08 21:56:10 +0000230 // It's necessary to set both user_source and script_source to the oneliner.
231 // The former is used to generate callback description (as in breakpoint command list)
232 // while the latter is used for Python to interpret during the actual callback.
233 data_ap->user_source.AppendString (oneliner);
234 data_ap->script_source.assign (oneliner);
235 data_ap->stop_on_error = m_options.m_stop_on_error;
Chris Lattner24943d22010-06-08 16:52:24 +0000236
Jim Inghamda26bd22012-06-08 21:56:10 +0000237 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
238 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000239
Jim Inghamda26bd22012-06-08 21:56:10 +0000240 return;
241 }
242
243 static size_t
244 GenerateBreakpointCommandCallback (void *baton,
245 InputReader &reader,
246 lldb::InputReaderAction notification,
247 const char *bytes,
248 size_t bytes_len)
249 {
250 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
251 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Caroline Tice4a348082011-05-02 20:41:46 +0000252
Jim Inghamda26bd22012-06-08 21:56:10 +0000253 switch (notification)
Chris Lattner24943d22010-06-08 16:52:24 +0000254 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000255 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000256 if (!batch_mode)
257 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000258 out_stream->Printf ("%s\n", g_reader_instructions);
259 if (reader.GetPrompt())
260 out_stream->Printf ("%s", reader.GetPrompt());
Caroline Tice892fadd2011-06-16 16:27:19 +0000261 out_stream->Flush();
262 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000263 break;
264
265 case eInputReaderDeactivate:
266 break;
267
268 case eInputReaderReactivate:
269 if (reader.GetPrompt() && !batch_mode)
270 {
271 out_stream->Printf ("%s", reader.GetPrompt());
272 out_stream->Flush();
273 }
274 break;
275
276 case eInputReaderAsynchronousOutputWritten:
277 break;
278
279 case eInputReaderGotToken:
280 if (bytes && bytes_len && baton)
281 {
282 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
283 if (bp_options)
284 {
285 Baton *bp_options_baton = bp_options->GetBaton();
286 if (bp_options_baton)
287 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
288 }
289 }
290 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
291 {
292 out_stream->Printf ("%s", reader.GetPrompt());
293 out_stream->Flush();
294 }
295 break;
296
297 case eInputReaderInterrupt:
298 {
299 // Finish, and cancel the breakpoint command.
300 reader.SetIsDone (true);
301 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
302 if (bp_options)
303 {
304 Baton *bp_options_baton = bp_options->GetBaton ();
305 if (bp_options_baton)
306 {
307 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
308 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
309 }
310 }
311 if (!batch_mode)
312 {
313 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
314 out_stream->Flush();
315 }
316 }
317 break;
318
319 case eInputReaderEndOfFile:
320 reader.SetIsDone (true);
321 break;
322
323 case eInputReaderDone:
324 break;
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000325 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000326
327 return bytes_len;
328 }
329
330 static bool
331 BreakpointOptionsCallbackFunction (void *baton,
332 StoppointCallbackContext *context,
333 lldb::user_id_t break_id,
334 lldb::user_id_t break_loc_id)
335 {
336 bool ret_value = true;
337 if (baton == NULL)
338 return true;
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000339
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000340
Jim Inghamda26bd22012-06-08 21:56:10 +0000341 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
342 StringList &commands = data->user_source;
343
344 if (commands.GetSize() > 0)
345 {
346 ExecutionContext exe_ctx (context->exe_ctx_ref);
347 Target *target = exe_ctx.GetTargetPtr();
348 if (target)
349 {
350 CommandReturnObject result;
351 Debugger &debugger = target->GetDebugger();
352 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
353 // if the debugger is set up that way.
354
355 StreamSP output_stream (debugger.GetAsyncOutputStream());
356 StreamSP error_stream (debugger.GetAsyncErrorStream());
357 result.SetImmediateOutputStream (output_stream);
358 result.SetImmediateErrorStream (error_stream);
359
360 bool stop_on_continue = true;
361 bool echo_commands = false;
362 bool print_results = true;
363
364 debugger.GetCommandInterpreter().HandleCommands (commands,
365 &exe_ctx,
366 stop_on_continue,
367 data->stop_on_error,
368 echo_commands,
369 print_results,
370 eLazyBoolNo,
371 result);
372 result.GetImmediateOutputStream()->Flush();
373 result.GetImmediateErrorStream()->Flush();
374 }
375 }
376 return ret_value;
377 }
378
379 class CommandOptions : public Options
380 {
381 public:
382
383 CommandOptions (CommandInterpreter &interpreter) :
384 Options (interpreter),
385 m_use_commands (false),
386 m_use_script_language (false),
387 m_script_language (eScriptLanguageNone),
388 m_use_one_liner (false),
389 m_one_liner(),
390 m_function_name()
391 {
392 }
393
394 virtual
395 ~CommandOptions () {}
396
397 virtual Error
398 SetOptionValue (uint32_t option_idx, const char *option_arg)
399 {
400 Error error;
401 char short_option = (char) m_getopt_table[option_idx].val;
402
403 switch (short_option)
404 {
405 case 'o':
406 m_use_one_liner = true;
407 m_one_liner = option_arg;
408 break;
409
410 case 's':
411 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
412 g_option_table[option_idx].enum_values,
413 eScriptLanguageNone,
414 error);
415
416 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
417 {
418 m_use_script_language = true;
419 }
420 else
421 {
422 m_use_script_language = false;
423 }
424 break;
425
426 case 'e':
427 {
428 bool success = false;
429 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
430 if (!success)
431 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
432 }
433 break;
434
435 case 'F':
436 {
437 m_use_one_liner = false;
438 m_use_script_language = true;
439 m_function_name.assign(option_arg);
440 }
441 break;
442
443 default:
444 break;
445 }
446 return error;
447 }
448 void
449 OptionParsingStarting ()
450 {
451 m_use_commands = true;
452 m_use_script_language = false;
453 m_script_language = eScriptLanguageNone;
454
455 m_use_one_liner = false;
456 m_stop_on_error = true;
457 m_one_liner.clear();
458 m_function_name.clear();
459 }
460
461 const OptionDefinition*
462 GetDefinitions ()
463 {
464 return g_option_table;
465 }
466
467 // Options table: Required for subclasses of Options.
468
469 static OptionDefinition g_option_table[];
470
471 // Instance variables to hold the values for command options.
472
473 bool m_use_commands;
474 bool m_use_script_language;
475 lldb::ScriptLanguage m_script_language;
476
477 // Instance variables to hold the values for one_liner options.
478 bool m_use_one_liner;
479 std::string m_one_liner;
480 bool m_stop_on_error;
481 std::string m_function_name;
482 };
483
484protected:
485 virtual bool
486 DoExecute (Args& command, CommandReturnObject &result)
487 {
488 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
489
490 if (target == NULL)
491 {
492 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
493 result.SetStatus (eReturnStatusFailed);
494 return false;
495 }
496
497 const BreakpointList &breakpoints = target->GetBreakpointList();
498 size_t num_breakpoints = breakpoints.GetSize();
499
500 if (num_breakpoints == 0)
501 {
502 result.AppendError ("No breakpoints exist to have commands added");
503 result.SetStatus (eReturnStatusFailed);
504 return false;
505 }
506
507 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
508 {
509 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
510 result.SetStatus (eReturnStatusFailed);
511 return false;
512 }
513
514 BreakpointIDList valid_bp_ids;
515 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
516
517 if (result.Succeeded())
518 {
519 const size_t count = valid_bp_ids.GetSize();
520 for (size_t i = 0; i < count; ++i)
521 {
522 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
523 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
524 {
525 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
526 BreakpointOptions *bp_options = NULL;
527 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
528 {
529 // This breakpoint does not have an associated location.
530 bp_options = bp->GetOptions();
531 }
532 else
533 {
534 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
535 // This breakpoint does have an associated location.
536 // Get its breakpoint options.
537 if (bp_loc_sp)
538 bp_options = bp_loc_sp->GetLocationOptions();
539 }
540
541 // Skip this breakpoint if bp_options is not good.
542 if (bp_options == NULL) continue;
543
544 // If we are using script language, get the script interpreter
545 // in order to set or collect command callback. Otherwise, call
546 // the methods associated with this object.
547 if (m_options.m_use_script_language)
548 {
549 // Special handling for one-liner specified inline.
550 if (m_options.m_use_one_liner)
551 {
552 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
553 m_options.m_one_liner.c_str());
554 }
555 // Special handling for using a Python function by name
556 // instead of extending the breakpoint callback data structures, we just automatize
557 // what the user would do manually: make their breakpoint command be a function call
558 else if (m_options.m_function_name.size())
559 {
560 std::string oneliner(m_options.m_function_name);
Enrico Granatac1ca9dc2012-08-08 02:06:30 +0000561 oneliner += "(frame, bp_loc, internal_dict)";
Jim Inghamda26bd22012-06-08 21:56:10 +0000562 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
563 oneliner.c_str());
564 }
565 else
566 {
567 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
568 result);
569 }
570 }
571 else
572 {
573 // Special handling for one-liner specified inline.
574 if (m_options.m_use_one_liner)
575 SetBreakpointCommandCallback (bp_options,
576 m_options.m_one_liner.c_str());
577 else
578 CollectDataForBreakpointCommandCallback (bp_options,
579 result);
580 }
581 }
582 }
583 }
584
585 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +0000586 }
587
Jim Inghamda26bd22012-06-08 21:56:10 +0000588private:
589 CommandOptions m_options;
590 static const char *g_reader_instructions;
Chris Lattner24943d22010-06-08 16:52:24 +0000591
Jim Inghamda26bd22012-06-08 21:56:10 +0000592};
593
594const char *
595CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
596
597// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
598// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
599
600static OptionEnumValueElement
601g_script_option_enumeration[4] =
602{
603 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
604 { eScriptLanguagePython, "python", "Commands are in the Python language."},
605 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
606 { 0, NULL, NULL }
607};
608
609OptionDefinition
610CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
611{
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000612 { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
Jim Inghamda26bd22012-06-08 21:56:10 +0000613 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
614
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000615 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,
Jim Inghamda26bd22012-06-08 21:56:10 +0000616 "Specify whether breakpoint command execution should terminate on error." },
617
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000618 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
Jim Inghamda26bd22012-06-08 21:56:10 +0000619 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
620
Filipe Cabecinhas560c5142012-09-11 16:09:27 +0000621 { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction,
Jim Inghamda26bd22012-06-08 21:56:10 +0000622 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
623
624 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
625};
Chris Lattner24943d22010-06-08 16:52:24 +0000626
627//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000628// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000629//-------------------------------------------------------------------------
630
Jim Inghamda26bd22012-06-08 21:56:10 +0000631class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000632{
Jim Inghamda26bd22012-06-08 21:56:10 +0000633public:
634 CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
635 CommandObjectParsed (interpreter,
636 "delete",
637 "Delete the set of commands from a breakpoint.",
638 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000639 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000640 CommandArgumentEntry arg;
641 CommandArgumentData bp_id_arg;
642
643 // Define the first (and only) variant of this arg.
644 bp_id_arg.arg_type = eArgTypeBreakpointID;
645 bp_id_arg.arg_repetition = eArgRepeatPlain;
646
647 // There is only one variant this argument could be; put it into the argument entry.
648 arg.push_back (bp_id_arg);
649
650 // Push the data for the first argument into the m_arguments vector.
651 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000652 }
653
Chris Lattner24943d22010-06-08 16:52:24 +0000654
Jim Inghamda26bd22012-06-08 21:56:10 +0000655 virtual
656 ~CommandObjectBreakpointCommandDelete () {}
657
658protected:
659 virtual bool
660 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000661 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000662 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000663
Jim Inghamda26bd22012-06-08 21:56:10 +0000664 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000665 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000666 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
667 result.SetStatus (eReturnStatusFailed);
668 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000669 }
Chris Lattner24943d22010-06-08 16:52:24 +0000670
Jim Inghamda26bd22012-06-08 21:56:10 +0000671 const BreakpointList &breakpoints = target->GetBreakpointList();
672 size_t num_breakpoints = breakpoints.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000673
Jim Inghamda26bd22012-06-08 21:56:10 +0000674 if (num_breakpoints == 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000675 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000676 result.AppendError ("No breakpoints exist to have commands deleted");
677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680
681 if (command.GetArgumentCount() == 0)
682 {
683 result.AppendError ("No breakpoint specified from which to delete the commands");
684 result.SetStatus (eReturnStatusFailed);
685 return false;
686 }
687
688 BreakpointIDList valid_bp_ids;
689 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
690
691 if (result.Succeeded())
692 {
693 const size_t count = valid_bp_ids.GetSize();
694 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000695 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000696 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
697 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000698 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000699 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000700 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
701 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000702 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
Chris Lattner24943d22010-06-08 16:52:24 +0000703 if (bp_loc_sp)
Jim Inghamda26bd22012-06-08 21:56:10 +0000704 bp_loc_sp->ClearCallback();
Chris Lattner24943d22010-06-08 16:52:24 +0000705 else
706 {
707 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
708 cur_bp_id.GetBreakpointID(),
709 cur_bp_id.GetLocationID());
710 result.SetStatus (eReturnStatusFailed);
711 return false;
712 }
713 }
714 else
715 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000716 bp->ClearCallback();
Chris Lattner24943d22010-06-08 16:52:24 +0000717 }
Jim Inghamda26bd22012-06-08 21:56:10 +0000718 }
719 }
720 }
721 return result.Succeeded();
722 }
723};
Chris Lattner24943d22010-06-08 16:52:24 +0000724
Jim Inghamda26bd22012-06-08 21:56:10 +0000725//-------------------------------------------------------------------------
726// CommandObjectBreakpointCommandList
727//-------------------------------------------------------------------------
728
729class CommandObjectBreakpointCommandList : public CommandObjectParsed
730{
731public:
732 CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
733 CommandObjectParsed (interpreter,
734 "list",
735 "List the script or set of commands to be executed when the breakpoint is hit.",
736 NULL)
737 {
738 CommandArgumentEntry arg;
739 CommandArgumentData bp_id_arg;
740
741 // Define the first (and only) variant of this arg.
742 bp_id_arg.arg_type = eArgTypeBreakpointID;
743 bp_id_arg.arg_repetition = eArgRepeatPlain;
744
745 // There is only one variant this argument could be; put it into the argument entry.
746 arg.push_back (bp_id_arg);
747
748 // Push the data for the first argument into the m_arguments vector.
749 m_arguments.push_back (arg);
750 }
751
752 virtual
753 ~CommandObjectBreakpointCommandList () {}
754
755protected:
756 virtual bool
757 DoExecute (Args& command,
758 CommandReturnObject &result)
759 {
760 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
761
762 if (target == NULL)
763 {
764 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
765 result.SetStatus (eReturnStatusFailed);
766 return false;
767 }
768
769 const BreakpointList &breakpoints = target->GetBreakpointList();
770 size_t num_breakpoints = breakpoints.GetSize();
771
772 if (num_breakpoints == 0)
773 {
774 result.AppendError ("No breakpoints exist for which to list commands");
775 result.SetStatus (eReturnStatusFailed);
776 return false;
777 }
778
779 if (command.GetArgumentCount() == 0)
780 {
781 result.AppendError ("No breakpoint specified for which to list the commands");
782 result.SetStatus (eReturnStatusFailed);
783 return false;
784 }
785
786 BreakpointIDList valid_bp_ids;
787 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
788
789 if (result.Succeeded())
790 {
791 const size_t count = valid_bp_ids.GetSize();
792 for (size_t i = 0; i < count; ++i)
793 {
794 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
795 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
796 {
797 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
798
799 if (bp)
Chris Lattner24943d22010-06-08 16:52:24 +0000800 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000801 const BreakpointOptions *bp_options = NULL;
802 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000803 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000804 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
805 if (bp_loc_sp)
806 bp_options = bp_loc_sp->GetOptionsNoCreate();
807 else
808 {
809 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
810 cur_bp_id.GetBreakpointID(),
811 cur_bp_id.GetLocationID());
812 result.SetStatus (eReturnStatusFailed);
813 return false;
814 }
Chris Lattner24943d22010-06-08 16:52:24 +0000815 }
816 else
817 {
Jim Inghamda26bd22012-06-08 21:56:10 +0000818 bp_options = bp->GetOptions();
Chris Lattner24943d22010-06-08 16:52:24 +0000819 }
Chris Lattner24943d22010-06-08 16:52:24 +0000820
Jim Inghamda26bd22012-06-08 21:56:10 +0000821 if (bp_options)
822 {
823 StreamString id_str;
824 BreakpointID::GetCanonicalReference (&id_str,
825 cur_bp_id.GetBreakpointID(),
826 cur_bp_id.GetLocationID());
827 const Baton *baton = bp_options->GetBaton();
828 if (baton)
829 {
830 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
831 result.GetOutputStream().IndentMore ();
832 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
833 result.GetOutputStream().IndentLess ();
834 }
835 else
836 {
837 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
838 id_str.GetData());
839 }
840 }
841 result.SetStatus (eReturnStatusSuccessFinishResult);
842 }
843 else
844 {
845 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
846 result.SetStatus (eReturnStatusFailed);
847 }
848
849 }
Chris Lattner24943d22010-06-08 16:52:24 +0000850 }
851 }
Chris Lattner24943d22010-06-08 16:52:24 +0000852
Jim Inghamda26bd22012-06-08 21:56:10 +0000853 return result.Succeeded();
854 }
855};
Chris Lattner24943d22010-06-08 16:52:24 +0000856
857//-------------------------------------------------------------------------
858// CommandObjectBreakpointCommand
859//-------------------------------------------------------------------------
860
Greg Clayton63094e02010-06-23 01:19:29 +0000861CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000862 CommandObjectMultiword (interpreter,
863 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000864 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
865 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
866{
Greg Clayton238c0a12010-09-18 01:14:36 +0000867 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000868 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000869 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000870
871 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000872 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000873 list_command_object->SetCommandName ("breakpoint command list");
874
Greg Clayton4a379b12012-07-17 03:23:13 +0000875 LoadSubCommand ("add", add_command_object);
876 LoadSubCommand ("delete", delete_command_object);
877 LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000878}
879
Chris Lattner24943d22010-06-08 16:52:24 +0000880CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
881{
882}
883
Chris Lattner24943d22010-06-08 16:52:24 +0000884