blob: dcc9f9bb8584961c77f82f5a9f9b908da9df7a42 [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//-------------------------------------------------------------------------
31// CommandObjectBreakpointCommandAdd::CommandOptions
32//-------------------------------------------------------------------------
33
Greg Claytonf15996e2011-04-07 22:46:35 +000034CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
35 Options (interpreter),
Johnny Chenb81ed0d2010-09-11 00:18:09 +000036 m_use_commands (false),
37 m_use_script_language (false),
38 m_script_language (eScriptLanguageNone),
39 m_use_one_liner (false),
Enrico Granata8ad21a82012-04-04 17:30:31 +000040 m_one_liner(),
41 m_function_name()
Chris Lattner24943d22010-06-08 16:52:24 +000042{
Chris Lattner24943d22010-06-08 16:52:24 +000043}
44
45CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
46{
47}
48
Jim Ingham949d5ac2011-02-18 00:54:25 +000049// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
50// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
51
Greg Claytonb3448432011-03-24 21:19:54 +000052static OptionEnumValueElement
Jim Ingham949d5ac2011-02-18 00:54:25 +000053g_script_option_enumeration[4] =
54{
55 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
56 { eScriptLanguagePython, "python", "Commands are in the Python language."},
57 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
58 { 0, NULL, NULL }
59};
60
Greg Claytonb3448432011-03-24 21:19:54 +000061OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +000062CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
63{
Enrico Granata8ad21a82012-04-04 17:30:31 +000064 { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
Caroline Tice8bb61f02010-09-21 23:25:40 +000065 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
Johnny Chenb81ed0d2010-09-11 00:18:09 +000066
Jim Ingham949d5ac2011-02-18 00:54:25 +000067 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean,
68 "Specify whether breakpoint command execution should terminate on error." },
Chris Lattner24943d22010-06-08 16:52:24 +000069
Jim Ingham949d5ac2011-02-18 00:54:25 +000070 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone,
71 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
Chris Lattner24943d22010-06-08 16:52:24 +000072
Enrico Granata8ad21a82012-04-04 17:30:31 +000073 { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, NULL, eArgTypePythonFunction,
74 "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
75
Caroline Tice4d6675c2010-10-01 19:59:14 +000076 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000077};
78
Greg Claytonb3448432011-03-24 21:19:54 +000079const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +000080CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
81{
82 return g_option_table;
83}
84
85
86Error
87CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
88(
Greg Clayton143fcc32011-04-13 00:18:08 +000089 uint32_t option_idx,
Chris Lattner24943d22010-06-08 16:52:24 +000090 const char *option_arg
91)
92{
93 Error error;
94 char short_option = (char) m_getopt_table[option_idx].val;
95
96 switch (short_option)
Greg Clayton61aca5d2011-10-07 18:58:12 +000097 {
98 case 'o':
99 m_use_one_liner = true;
100 m_one_liner = option_arg;
101 break;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000102
Greg Clayton61aca5d2011-10-07 18:58:12 +0000103 case 's':
104 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
105 g_option_table[option_idx].enum_values,
106 eScriptLanguageNone,
107 error);
108
109 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
110 {
Greg Clayton61aca5d2011-10-07 18:58:12 +0000111 m_use_script_language = true;
112 }
113 else
114 {
Greg Clayton61aca5d2011-10-07 18:58:12 +0000115 m_use_script_language = false;
116 }
117 break;
118
119 case 'e':
120 {
121 bool success = false;
122 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
123 if (!success)
Greg Clayton9c236732011-10-26 00:56:27 +0000124 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
Greg Clayton61aca5d2011-10-07 18:58:12 +0000125 }
126 break;
Enrico Granata8ad21a82012-04-04 17:30:31 +0000127
128 case 'F':
129 {
130 m_use_one_liner = false;
131 m_use_script_language = true;
132 m_function_name.assign(option_arg);
133 }
134 break;
Greg Clayton61aca5d2011-10-07 18:58:12 +0000135
136 default:
137 break;
138 }
Chris Lattner24943d22010-06-08 16:52:24 +0000139 return error;
140}
141
142void
Greg Clayton143fcc32011-04-13 00:18:08 +0000143CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000144{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000145 m_use_commands = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000146 m_use_script_language = false;
147 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000148
149 m_use_one_liner = false;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000150 m_stop_on_error = true;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000151 m_one_liner.clear();
Enrico Granata8ad21a82012-04-04 17:30:31 +0000152 m_function_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000153}
154
155//-------------------------------------------------------------------------
156// CommandObjectBreakpointCommandAdd
157//-------------------------------------------------------------------------
158
159
Greg Clayton238c0a12010-09-18 01:14:36 +0000160CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
161 CommandObject (interpreter,
162 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000163 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000164 NULL),
165 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000166{
167 SetHelpLong (
168"\nGeneral information about entering breakpoint commands \n\
169------------------------------------------------------ \n\
170 \n\
171This command will cause you to be prompted to enter the command or set \n\
172of commands you wish to be executed when the specified breakpoint is \n\
173hit. You will be told to enter your command(s), and will see a '> ' \n\
174prompt. Because you can enter one or many commands to be executed when \n\
175a breakpoint is hit, you will continue to be prompted after each \n\
176new-line that you enter, until you enter the word 'DONE', which will \n\
177cause the commands you have entered to be stored with the breakpoint \n\
178and executed when the breakpoint is hit. \n\
179 \n\
180Syntax checking is not necessarily done when breakpoint commands are \n\
181entered. An improperly written breakpoint command will attempt to get \n\
182executed when the breakpoint gets hit, and usually silently fail. If \n\
183your breakpoint command does not appear to be getting executed, go \n\
184back and check your syntax. \n\
185 \n\
186 \n\
187Special information about PYTHON breakpoint commands \n\
188---------------------------------------------------- \n\
189 \n\
190You may enter either one line of Python or multiple lines of Python \n\
191(including defining whole functions, if desired). If you enter a \n\
192single line of Python, that will be passed to the Python interpreter \n\
193'as is' when the breakpoint gets hit. If you enter function \n\
194definitions, they will be passed to the Python interpreter as soon as \n\
195you finish entering the breakpoint command, and they can be called \n\
196later (don't forget to add calls to them, if you want them called when \n\
197the breakpoint is hit). If you enter multiple lines of Python that \n\
198are not function definitions, they will be collected into a new, \n\
199automatically generated Python function, and a call to the newly \n\
200generated function will be attached to the breakpoint. Important \n\
201Note: Because loose Python code gets collected into functions, if you \n\
202want to access global variables in the 'loose' code, you need to \n\
203specify that they are global, using the 'global' keyword. Be sure to \n\
204use correct Python syntax, including indentation, when entering Python \n\
Enrico Granata8ad21a82012-04-04 17:30:31 +0000205breakpoint commands. \nAs a third option, you can pass the name of an already \
206existing Python function and that function will be attached to the breakpoint. \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000207 \n\
208Example Python one-line breakpoint command: \n\
209 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000210(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000211Enter your Python command(s). Type 'DONE' to end. \n\
212> print \"Hit this breakpoint!\" \n\
213> DONE \n\
214 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000215As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000216(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000217(lldb) run \n\
218Launching '.../a.out' (x86_64) \n\
219(lldb) Fri Sep 10 12:17:45 2010 \n\
220Process 21778 Stopped \n\
221* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
222 36 \n\
223 37 int c(int val)\n\
224 38 {\n\
225 39 -> return val + 3;\n\
226 40 }\n\
227 41 \n\
228 42 int main (int argc, char const *argv[])\n\
229(lldb) \n\
230 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000231Example multiple line Python breakpoint command, using function definition: \n\
232 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000233(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000234Enter your Python command(s). Type 'DONE' to end. \n\
235> def breakpoint_output (bp_no): \n\
236> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
237> print out_string \n\
238> return True \n\
239> breakpoint_output (1) \n\
240> DONE \n\
241 \n\
242 \n\
243Example multiple line Python breakpoint command, using 'loose' Python: \n\
244 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000245(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000246Enter your Python command(s). Type 'DONE' to end. \n\
247> global bp_count \n\
248> bp_count = bp_count + 1 \n\
249> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
250> DONE \n\
251 \n\
252In this case, since there is a reference to a global variable, \n\
253'bp_count', you will also need to make sure 'bp_count' exists and is \n\
254initialized: \n\
255 \n\
256(lldb) script \n\
257>>> bp_count = 0 \n\
258>>> quit() \n\
259 \n\
260(lldb) \n\
261 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000262 \n\
263Final Note: If you get a warning that no breakpoint command was generated, \n\
264but you did not get any syntax errors, you probably forgot to add a call \n\
265to your functions. \n\
266 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000267Special information about debugger command breakpoint commands \n\
268-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000269 \n\
270You may enter any debugger command, exactly as you would at the \n\
271debugger prompt. You may enter as many debugger commands as you like, \n\
272but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000273
274
275 CommandArgumentEntry arg;
276 CommandArgumentData bp_id_arg;
277
278 // Define the first (and only) variant of this arg.
279 bp_id_arg.arg_type = eArgTypeBreakpointID;
280 bp_id_arg.arg_repetition = eArgRepeatPlain;
281
282 // There is only one variant this argument could be; put it into the argument entry.
283 arg.push_back (bp_id_arg);
284
285 // Push the data for the first argument into the m_arguments vector.
286 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000287}
288
289CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
290{
291}
292
293bool
294CommandObjectBreakpointCommandAdd::Execute
295(
296 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000297 CommandReturnObject &result
298)
299{
Greg Clayton238c0a12010-09-18 01:14:36 +0000300 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000301
302 if (target == NULL)
303 {
304 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
305 result.SetStatus (eReturnStatusFailed);
306 return false;
307 }
308
309 const BreakpointList &breakpoints = target->GetBreakpointList();
310 size_t num_breakpoints = breakpoints.GetSize();
311
312 if (num_breakpoints == 0)
313 {
314 result.AppendError ("No breakpoints exist to have commands added");
315 result.SetStatus (eReturnStatusFailed);
316 return false;
317 }
318
Enrico Granata8ad21a82012-04-04 17:30:31 +0000319 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
320 {
321 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
322 result.SetStatus (eReturnStatusFailed);
323 return false;
324 }
325
Chris Lattner24943d22010-06-08 16:52:24 +0000326 BreakpointIDList valid_bp_ids;
327 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
328
329 if (result.Succeeded())
330 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000331 const size_t count = valid_bp_ids.GetSize();
332 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000333 {
334 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
335 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
336 {
337 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000338 BreakpointOptions *bp_options = NULL;
339 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
340 {
341 // This breakpoint does not have an associated location.
342 bp_options = bp->GetOptions();
343 }
344 else
Chris Lattner24943d22010-06-08 16:52:24 +0000345 {
346 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000347 // This breakpoint does have an associated location.
348 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000349 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000350 bp_options = bp_loc_sp->GetLocationOptions();
351 }
352
Jim Ingham949d5ac2011-02-18 00:54:25 +0000353 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000354 if (bp_options == NULL) continue;
355
356 // If we are using script language, get the script interpreter
357 // in order to set or collect command callback. Otherwise, call
358 // the methods associated with this object.
359 if (m_options.m_use_script_language)
360 {
361 // Special handling for one-liner specified inline.
362 if (m_options.m_use_one_liner)
Enrico Granata8ad21a82012-04-04 17:30:31 +0000363 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000364 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
365 m_options.m_one_liner.c_str());
Enrico Granata8ad21a82012-04-04 17:30:31 +0000366 }
367 // Special handling for using a Python function by name
368 // instead of extending the breakpoint callback data structures, we just automatize
369 // what the user would do manually: make their breakpoint command be a function call
370 else if (m_options.m_function_name.size())
371 {
372 std::string oneliner(m_options.m_function_name);
373 oneliner += "(frame, bp_loc, dict)";
374 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
375 oneliner.c_str());
376 }
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000377 else
Enrico Granata8ad21a82012-04-04 17:30:31 +0000378 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000379 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
380 result);
Enrico Granata8ad21a82012-04-04 17:30:31 +0000381 }
Chris Lattner24943d22010-06-08 16:52:24 +0000382 }
383 else
384 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000385 // Special handling for one-liner specified inline.
386 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000387 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000388 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000389 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000390 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000391 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000392 }
393 }
394 }
395 }
396
397 return result.Succeeded();
398}
399
400Options *
401CommandObjectBreakpointCommandAdd::GetOptions ()
402{
403 return &m_options;
404}
405
406const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
407
408void
409CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
410(
411 BreakpointOptions *bp_options,
412 CommandReturnObject &result
413)
414{
Greg Clayton238c0a12010-09-18 01:14:36 +0000415 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000416 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
417 if (reader_sp && data_ap.get())
418 {
419 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
420 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
421
422 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
423 bp_options, // baton
424 eInputReaderGranularityLine, // token size, to pass to callback function
425 "DONE", // end token
426 "> ", // prompt
427 true)); // echo input
428 if (err.Success())
429 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000430 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000431 result.SetStatus (eReturnStatusSuccessFinishNoResult);
432 }
433 else
434 {
435 result.AppendError (err.AsCString());
436 result.SetStatus (eReturnStatusFailed);
437 }
438 }
439 else
440 {
441 result.AppendError("out of memory");
442 result.SetStatus (eReturnStatusFailed);
443 }
444
445}
446
Johnny Chen3e0571b2010-09-11 00:23:59 +0000447// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000448void
Greg Clayton238c0a12010-09-18 01:14:36 +0000449CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000450 const char *oneliner)
451{
452 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
453
454 // It's necessary to set both user_source and script_source to the oneliner.
455 // The former is used to generate callback description (as in breakpoint command list)
456 // while the latter is used for Python to interpret during the actual callback.
457 data_ap->user_source.AppendString (oneliner);
Enrico Granata400105d2012-03-06 23:42:15 +0000458 data_ap->script_source.assign (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000459 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000460
461 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
462 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
463
464 return;
465}
466
Chris Lattner24943d22010-06-08 16:52:24 +0000467size_t
468CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
469(
470 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000471 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000472 lldb::InputReaderAction notification,
473 const char *bytes,
474 size_t bytes_len
475)
476{
Caroline Tice892fadd2011-06-16 16:27:19 +0000477 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
478 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
479
Chris Lattner24943d22010-06-08 16:52:24 +0000480 switch (notification)
481 {
482 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000483 if (!batch_mode)
484 {
485 out_stream->Printf ("%s\n", g_reader_instructions);
486 if (reader.GetPrompt())
487 out_stream->Printf ("%s", reader.GetPrompt());
488 out_stream->Flush();
489 }
Chris Lattner24943d22010-06-08 16:52:24 +0000490 break;
491
492 case eInputReaderDeactivate:
493 break;
494
495 case eInputReaderReactivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000496 if (reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000497 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000498 out_stream->Printf ("%s", reader.GetPrompt());
499 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000500 }
Chris Lattner24943d22010-06-08 16:52:24 +0000501 break;
502
Caroline Tice4a348082011-05-02 20:41:46 +0000503 case eInputReaderAsynchronousOutputWritten:
504 break;
505
Chris Lattner24943d22010-06-08 16:52:24 +0000506 case eInputReaderGotToken:
507 if (bytes && bytes_len && baton)
508 {
509 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
510 if (bp_options)
511 {
512 Baton *bp_options_baton = bp_options->GetBaton();
513 if (bp_options_baton)
514 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
515 }
516 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000517 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000518 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000519 out_stream->Printf ("%s", reader.GetPrompt());
520 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000521 }
Chris Lattner24943d22010-06-08 16:52:24 +0000522 break;
523
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000524 case eInputReaderInterrupt:
525 {
526 // Finish, and cancel the breakpoint command.
527 reader.SetIsDone (true);
528 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
529 if (bp_options)
530 {
531 Baton *bp_options_baton = bp_options->GetBaton ();
532 if (bp_options_baton)
533 {
534 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
Enrico Granata400105d2012-03-06 23:42:15 +0000535 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000536 }
537 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000538 if (!batch_mode)
539 {
540 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
541 out_stream->Flush();
542 }
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000543 }
544 break;
545
546 case eInputReaderEndOfFile:
547 reader.SetIsDone (true);
548 break;
549
Chris Lattner24943d22010-06-08 16:52:24 +0000550 case eInputReaderDone:
551 break;
552 }
553
554 return bytes_len;
555}
556
557
558//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000559// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000560//-------------------------------------------------------------------------
561
Caroline Ticeb2203882011-05-22 07:14:46 +0000562CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000563 CommandObject (interpreter,
Caroline Ticeb2203882011-05-22 07:14:46 +0000564 "delete",
565 "Delete the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000566 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000567{
Caroline Tice43b014a2010-10-04 22:28:36 +0000568 CommandArgumentEntry arg;
569 CommandArgumentData bp_id_arg;
570
571 // Define the first (and only) variant of this arg.
572 bp_id_arg.arg_type = eArgTypeBreakpointID;
573 bp_id_arg.arg_repetition = eArgRepeatPlain;
574
575 // There is only one variant this argument could be; put it into the argument entry.
576 arg.push_back (bp_id_arg);
577
578 // Push the data for the first argument into the m_arguments vector.
579 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000580}
581
Caroline Ticeb2203882011-05-22 07:14:46 +0000582CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete ()
Chris Lattner24943d22010-06-08 16:52:24 +0000583{
584}
585
586bool
Caroline Ticeb2203882011-05-22 07:14:46 +0000587CommandObjectBreakpointCommandDelete::Execute
Greg Clayton63094e02010-06-23 01:19:29 +0000588(
Greg Clayton63094e02010-06-23 01:19:29 +0000589 Args& command,
590 CommandReturnObject &result
591)
Chris Lattner24943d22010-06-08 16:52:24 +0000592{
Greg Clayton238c0a12010-09-18 01:14:36 +0000593 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000594
595 if (target == NULL)
596 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000597 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000598 result.SetStatus (eReturnStatusFailed);
599 return false;
600 }
601
602 const BreakpointList &breakpoints = target->GetBreakpointList();
603 size_t num_breakpoints = breakpoints.GetSize();
604
605 if (num_breakpoints == 0)
606 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000607 result.AppendError ("No breakpoints exist to have commands deleted");
Chris Lattner24943d22010-06-08 16:52:24 +0000608 result.SetStatus (eReturnStatusFailed);
609 return false;
610 }
611
612 if (command.GetArgumentCount() == 0)
613 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000614 result.AppendError ("No breakpoint specified from which to delete the commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000615 result.SetStatus (eReturnStatusFailed);
616 return false;
617 }
618
619 BreakpointIDList valid_bp_ids;
620 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
621
622 if (result.Succeeded())
623 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000624 const size_t count = valid_bp_ids.GetSize();
625 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000626 {
627 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
628 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
629 {
630 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
631 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
632 {
633 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
634 if (bp_loc_sp)
635 bp_loc_sp->ClearCallback();
636 else
637 {
638 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
639 cur_bp_id.GetBreakpointID(),
640 cur_bp_id.GetLocationID());
641 result.SetStatus (eReturnStatusFailed);
642 return false;
643 }
644 }
645 else
646 {
647 bp->ClearCallback();
648 }
649 }
650 }
651 }
652 return result.Succeeded();
653}
654
655
656//-------------------------------------------------------------------------
657// CommandObjectBreakpointCommandList
658//-------------------------------------------------------------------------
659
Greg Clayton238c0a12010-09-18 01:14:36 +0000660CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
661 CommandObject (interpreter,
662 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000663 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000664 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000665{
Caroline Tice43b014a2010-10-04 22:28:36 +0000666 CommandArgumentEntry arg;
667 CommandArgumentData bp_id_arg;
668
669 // Define the first (and only) variant of this arg.
670 bp_id_arg.arg_type = eArgTypeBreakpointID;
671 bp_id_arg.arg_repetition = eArgRepeatPlain;
672
673 // There is only one variant this argument could be; put it into the argument entry.
674 arg.push_back (bp_id_arg);
675
676 // Push the data for the first argument into the m_arguments vector.
677 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000678}
679
680CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
681{
682}
683
684bool
Greg Clayton63094e02010-06-23 01:19:29 +0000685CommandObjectBreakpointCommandList::Execute
686(
Greg Clayton63094e02010-06-23 01:19:29 +0000687 Args& command,
688 CommandReturnObject &result
689)
Chris Lattner24943d22010-06-08 16:52:24 +0000690{
Greg Clayton238c0a12010-09-18 01:14:36 +0000691 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000692
693 if (target == NULL)
694 {
695 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
696 result.SetStatus (eReturnStatusFailed);
697 return false;
698 }
699
700 const BreakpointList &breakpoints = target->GetBreakpointList();
701 size_t num_breakpoints = breakpoints.GetSize();
702
703 if (num_breakpoints == 0)
704 {
705 result.AppendError ("No breakpoints exist for which to list commands");
706 result.SetStatus (eReturnStatusFailed);
707 return false;
708 }
709
710 if (command.GetArgumentCount() == 0)
711 {
712 result.AppendError ("No breakpoint specified for which to list the commands");
713 result.SetStatus (eReturnStatusFailed);
714 return false;
715 }
716
717 BreakpointIDList valid_bp_ids;
718 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
719
720 if (result.Succeeded())
721 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000722 const size_t count = valid_bp_ids.GetSize();
723 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000724 {
725 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
726 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
727 {
728 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
729
730 if (bp)
731 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000732 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000733 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
734 {
735 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
736 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000737 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000738 else
739 {
740 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
741 cur_bp_id.GetBreakpointID(),
742 cur_bp_id.GetLocationID());
743 result.SetStatus (eReturnStatusFailed);
744 return false;
745 }
746 }
747 else
748 {
749 bp_options = bp->GetOptions();
750 }
751
752 if (bp_options)
753 {
754 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000755 BreakpointID::GetCanonicalReference (&id_str,
756 cur_bp_id.GetBreakpointID(),
757 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000758 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000759 if (baton)
760 {
761 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
762 result.GetOutputStream().IndentMore ();
763 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
764 result.GetOutputStream().IndentLess ();
765 }
766 else
767 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000768 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
769 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000770 }
771 }
772 result.SetStatus (eReturnStatusSuccessFinishResult);
773 }
774 else
775 {
776 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
777 result.SetStatus (eReturnStatusFailed);
778 }
779
780 }
781 }
782 }
783
784 return result.Succeeded();
785}
786
787//-------------------------------------------------------------------------
788// CommandObjectBreakpointCommand
789//-------------------------------------------------------------------------
790
Greg Clayton63094e02010-06-23 01:19:29 +0000791CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000792 CommandObjectMultiword (interpreter,
793 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000794 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
795 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
796{
797 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000798 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000799 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000800 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000801
802 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000803 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000804 list_command_object->SetCommandName ("breakpoint command list");
805
Greg Clayton238c0a12010-09-18 01:14:36 +0000806 status = LoadSubCommand ("add", add_command_object);
Caroline Ticeb2203882011-05-22 07:14:46 +0000807 status = LoadSubCommand ("delete", delete_command_object);
Greg Clayton238c0a12010-09-18 01:14:36 +0000808 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000809}
810
811
812CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
813{
814}
815
816bool
817CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
818(
819 void *baton,
820 StoppointCallbackContext *context,
821 lldb::user_id_t break_id,
822 lldb::user_id_t break_loc_id
823)
824{
825 bool ret_value = true;
826 if (baton == NULL)
827 return true;
828
829
830 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
831 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000832
Chris Lattner24943d22010-06-08 16:52:24 +0000833 if (commands.GetSize() > 0)
834 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000835 ExecutionContext exe_ctx (context->exe_ctx_ref);
836 Target *target = exe_ctx.GetTargetPtr();
Greg Clayton567e7f32011-09-22 04:58:26 +0000837 if (target)
Chris Lattner24943d22010-06-08 16:52:24 +0000838 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000839 CommandReturnObject result;
Greg Clayton567e7f32011-09-22 04:58:26 +0000840 Debugger &debugger = target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000841 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
842 // if the debugger is set up that way.
843
Jim Inghame5ed8e92011-06-02 23:58:26 +0000844 StreamSP output_stream (debugger.GetAsyncOutputStream());
845 StreamSP error_stream (debugger.GetAsyncErrorStream());
Caroline Tice845d6da2011-05-16 19:20:50 +0000846 result.SetImmediateOutputStream (output_stream);
847 result.SetImmediateErrorStream (error_stream);
848
Jim Ingham949d5ac2011-02-18 00:54:25 +0000849 bool stop_on_continue = true;
850 bool echo_commands = false;
851 bool print_results = true;
852
853 debugger.GetCommandInterpreter().HandleCommands (commands,
Greg Claytonf4124de2012-02-21 00:09:25 +0000854 &exe_ctx,
Jim Ingham949d5ac2011-02-18 00:54:25 +0000855 stop_on_continue,
856 data->stop_on_error,
857 echo_commands,
858 print_results,
859 result);
Caroline Tice845d6da2011-05-16 19:20:50 +0000860 result.GetImmediateOutputStream()->Flush();
861 result.GetImmediateErrorStream()->Flush();
862 }
Chris Lattner24943d22010-06-08 16:52:24 +0000863 }
864 return ret_value;
865}
866