blob: 40e9ee9dbe85e3f153fb12e670e4e879a9946b43 [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\
Jim Ingham73260da2012-04-25 01:05:21 +0000187Special 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. \n\
201 \n\
202This auto-generated function is passed in two arguments: \n\
203 \n\
204 frame: an SBFrame object representing the frame which hit the breakpoint. \n\
205 From the frame you can get back to the thread and process. \n\
206 bp_loc: the number of the breakpoint location that was hit. \n\
207 This is useful since one breakpoint can have many locations. \n\
208 \n\
209Important Note: Because loose Python code gets collected into functions, \n\
210if you want to access global variables in the 'loose' code, you need to \n\
211specify that they are global, using the 'global' keyword. Be sure to \n\
212use correct Python syntax, including indentation, when entering Python \n\
213breakpoint commands. \n\
214 \n\
215As a third option, you can pass the name of an already existing Python function \n\
216and that function will be attached to the breakpoint. It will get passed the \n\
217frame and bp_loc arguments mentioned above. \n\
218 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000219Example Python one-line breakpoint command: \n\
220 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000221(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000222Enter your Python command(s). Type 'DONE' to end. \n\
223> print \"Hit this breakpoint!\" \n\
224> DONE \n\
225 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000226As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000227(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000228(lldb) run \n\
229Launching '.../a.out' (x86_64) \n\
230(lldb) Fri Sep 10 12:17:45 2010 \n\
231Process 21778 Stopped \n\
232* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
233 36 \n\
234 37 int c(int val)\n\
235 38 {\n\
236 39 -> return val + 3;\n\
237 40 }\n\
238 41 \n\
239 42 int main (int argc, char const *argv[])\n\
240(lldb) \n\
241 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000242Example multiple line Python breakpoint command, using function definition: \n\
243 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000244(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000245Enter your Python command(s). Type 'DONE' to end. \n\
246> def breakpoint_output (bp_no): \n\
247> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
248> print out_string \n\
249> return True \n\
250> breakpoint_output (1) \n\
251> DONE \n\
252 \n\
253 \n\
254Example multiple line Python breakpoint command, using 'loose' Python: \n\
255 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000256(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000257Enter your Python command(s). Type 'DONE' to end. \n\
258> global bp_count \n\
259> bp_count = bp_count + 1 \n\
260> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
261> DONE \n\
262 \n\
263In this case, since there is a reference to a global variable, \n\
264'bp_count', you will also need to make sure 'bp_count' exists and is \n\
265initialized: \n\
266 \n\
267(lldb) script \n\
268>>> bp_count = 0 \n\
269>>> quit() \n\
270 \n\
271(lldb) \n\
272 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000273 \n\
274Final Note: If you get a warning that no breakpoint command was generated, \n\
275but you did not get any syntax errors, you probably forgot to add a call \n\
276to your functions. \n\
277 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000278Special information about debugger command breakpoint commands \n\
279-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000280 \n\
281You may enter any debugger command, exactly as you would at the \n\
282debugger prompt. You may enter as many debugger commands as you like, \n\
283but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000284
285
286 CommandArgumentEntry arg;
287 CommandArgumentData bp_id_arg;
288
289 // Define the first (and only) variant of this arg.
290 bp_id_arg.arg_type = eArgTypeBreakpointID;
291 bp_id_arg.arg_repetition = eArgRepeatPlain;
292
293 // There is only one variant this argument could be; put it into the argument entry.
294 arg.push_back (bp_id_arg);
295
296 // Push the data for the first argument into the m_arguments vector.
297 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000298}
299
300CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
301{
302}
303
304bool
305CommandObjectBreakpointCommandAdd::Execute
306(
307 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000308 CommandReturnObject &result
309)
310{
Greg Clayton238c0a12010-09-18 01:14:36 +0000311 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000312
313 if (target == NULL)
314 {
315 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
316 result.SetStatus (eReturnStatusFailed);
317 return false;
318 }
319
320 const BreakpointList &breakpoints = target->GetBreakpointList();
321 size_t num_breakpoints = breakpoints.GetSize();
322
323 if (num_breakpoints == 0)
324 {
325 result.AppendError ("No breakpoints exist to have commands added");
326 result.SetStatus (eReturnStatusFailed);
327 return false;
328 }
329
Enrico Granata8ad21a82012-04-04 17:30:31 +0000330 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
331 {
332 result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
333 result.SetStatus (eReturnStatusFailed);
334 return false;
335 }
336
Chris Lattner24943d22010-06-08 16:52:24 +0000337 BreakpointIDList valid_bp_ids;
338 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
339
340 if (result.Succeeded())
341 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000342 const size_t count = valid_bp_ids.GetSize();
343 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000344 {
345 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
346 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
347 {
348 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000349 BreakpointOptions *bp_options = NULL;
350 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
351 {
352 // This breakpoint does not have an associated location.
353 bp_options = bp->GetOptions();
354 }
355 else
Chris Lattner24943d22010-06-08 16:52:24 +0000356 {
357 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000358 // This breakpoint does have an associated location.
359 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000360 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000361 bp_options = bp_loc_sp->GetLocationOptions();
362 }
363
Jim Ingham949d5ac2011-02-18 00:54:25 +0000364 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000365 if (bp_options == NULL) continue;
366
367 // If we are using script language, get the script interpreter
368 // in order to set or collect command callback. Otherwise, call
369 // the methods associated with this object.
370 if (m_options.m_use_script_language)
371 {
372 // Special handling for one-liner specified inline.
373 if (m_options.m_use_one_liner)
Enrico Granata8ad21a82012-04-04 17:30:31 +0000374 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000375 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
376 m_options.m_one_liner.c_str());
Enrico Granata8ad21a82012-04-04 17:30:31 +0000377 }
378 // Special handling for using a Python function by name
379 // instead of extending the breakpoint callback data structures, we just automatize
380 // what the user would do manually: make their breakpoint command be a function call
381 else if (m_options.m_function_name.size())
382 {
383 std::string oneliner(m_options.m_function_name);
384 oneliner += "(frame, bp_loc, dict)";
385 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
386 oneliner.c_str());
387 }
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000388 else
Enrico Granata8ad21a82012-04-04 17:30:31 +0000389 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000390 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
391 result);
Enrico Granata8ad21a82012-04-04 17:30:31 +0000392 }
Chris Lattner24943d22010-06-08 16:52:24 +0000393 }
394 else
395 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000396 // Special handling for one-liner specified inline.
397 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000398 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000399 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000400 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000401 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000402 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000403 }
404 }
405 }
406 }
407
408 return result.Succeeded();
409}
410
411Options *
412CommandObjectBreakpointCommandAdd::GetOptions ()
413{
414 return &m_options;
415}
416
417const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
418
419void
420CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
421(
422 BreakpointOptions *bp_options,
423 CommandReturnObject &result
424)
425{
Greg Clayton238c0a12010-09-18 01:14:36 +0000426 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000427 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
428 if (reader_sp && data_ap.get())
429 {
430 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
431 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
432
433 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
434 bp_options, // baton
435 eInputReaderGranularityLine, // token size, to pass to callback function
436 "DONE", // end token
437 "> ", // prompt
438 true)); // echo input
439 if (err.Success())
440 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000441 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000442 result.SetStatus (eReturnStatusSuccessFinishNoResult);
443 }
444 else
445 {
446 result.AppendError (err.AsCString());
447 result.SetStatus (eReturnStatusFailed);
448 }
449 }
450 else
451 {
452 result.AppendError("out of memory");
453 result.SetStatus (eReturnStatusFailed);
454 }
455
456}
457
Johnny Chen3e0571b2010-09-11 00:23:59 +0000458// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000459void
Greg Clayton238c0a12010-09-18 01:14:36 +0000460CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000461 const char *oneliner)
462{
463 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
464
465 // It's necessary to set both user_source and script_source to the oneliner.
466 // The former is used to generate callback description (as in breakpoint command list)
467 // while the latter is used for Python to interpret during the actual callback.
468 data_ap->user_source.AppendString (oneliner);
Enrico Granata400105d2012-03-06 23:42:15 +0000469 data_ap->script_source.assign (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000470 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000471
472 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
473 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
474
475 return;
476}
477
Chris Lattner24943d22010-06-08 16:52:24 +0000478size_t
479CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
480(
481 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000482 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000483 lldb::InputReaderAction notification,
484 const char *bytes,
485 size_t bytes_len
486)
487{
Caroline Tice892fadd2011-06-16 16:27:19 +0000488 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
489 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
490
Chris Lattner24943d22010-06-08 16:52:24 +0000491 switch (notification)
492 {
493 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000494 if (!batch_mode)
495 {
496 out_stream->Printf ("%s\n", g_reader_instructions);
497 if (reader.GetPrompt())
498 out_stream->Printf ("%s", reader.GetPrompt());
499 out_stream->Flush();
500 }
Chris Lattner24943d22010-06-08 16:52:24 +0000501 break;
502
503 case eInputReaderDeactivate:
504 break;
505
506 case eInputReaderReactivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000507 if (reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000508 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000509 out_stream->Printf ("%s", reader.GetPrompt());
510 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000511 }
Chris Lattner24943d22010-06-08 16:52:24 +0000512 break;
513
Caroline Tice4a348082011-05-02 20:41:46 +0000514 case eInputReaderAsynchronousOutputWritten:
515 break;
516
Chris Lattner24943d22010-06-08 16:52:24 +0000517 case eInputReaderGotToken:
518 if (bytes && bytes_len && baton)
519 {
520 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
521 if (bp_options)
522 {
523 Baton *bp_options_baton = bp_options->GetBaton();
524 if (bp_options_baton)
525 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
526 }
527 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000528 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000529 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000530 out_stream->Printf ("%s", reader.GetPrompt());
531 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000532 }
Chris Lattner24943d22010-06-08 16:52:24 +0000533 break;
534
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000535 case eInputReaderInterrupt:
536 {
537 // Finish, and cancel the breakpoint command.
538 reader.SetIsDone (true);
539 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
540 if (bp_options)
541 {
542 Baton *bp_options_baton = bp_options->GetBaton ();
543 if (bp_options_baton)
544 {
545 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
Enrico Granata400105d2012-03-06 23:42:15 +0000546 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000547 }
548 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000549 if (!batch_mode)
550 {
551 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
552 out_stream->Flush();
553 }
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000554 }
555 break;
556
557 case eInputReaderEndOfFile:
558 reader.SetIsDone (true);
559 break;
560
Chris Lattner24943d22010-06-08 16:52:24 +0000561 case eInputReaderDone:
562 break;
563 }
564
565 return bytes_len;
566}
567
568
569//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000570// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000571//-------------------------------------------------------------------------
572
Caroline Ticeb2203882011-05-22 07:14:46 +0000573CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000574 CommandObject (interpreter,
Caroline Ticeb2203882011-05-22 07:14:46 +0000575 "delete",
576 "Delete the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000577 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000578{
Caroline Tice43b014a2010-10-04 22:28:36 +0000579 CommandArgumentEntry arg;
580 CommandArgumentData bp_id_arg;
581
582 // Define the first (and only) variant of this arg.
583 bp_id_arg.arg_type = eArgTypeBreakpointID;
584 bp_id_arg.arg_repetition = eArgRepeatPlain;
585
586 // There is only one variant this argument could be; put it into the argument entry.
587 arg.push_back (bp_id_arg);
588
589 // Push the data for the first argument into the m_arguments vector.
590 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000591}
592
Caroline Ticeb2203882011-05-22 07:14:46 +0000593CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete ()
Chris Lattner24943d22010-06-08 16:52:24 +0000594{
595}
596
597bool
Caroline Ticeb2203882011-05-22 07:14:46 +0000598CommandObjectBreakpointCommandDelete::Execute
Greg Clayton63094e02010-06-23 01:19:29 +0000599(
Greg Clayton63094e02010-06-23 01:19:29 +0000600 Args& command,
601 CommandReturnObject &result
602)
Chris Lattner24943d22010-06-08 16:52:24 +0000603{
Greg Clayton238c0a12010-09-18 01:14:36 +0000604 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000605
606 if (target == NULL)
607 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000608 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000609 result.SetStatus (eReturnStatusFailed);
610 return false;
611 }
612
613 const BreakpointList &breakpoints = target->GetBreakpointList();
614 size_t num_breakpoints = breakpoints.GetSize();
615
616 if (num_breakpoints == 0)
617 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000618 result.AppendError ("No breakpoints exist to have commands deleted");
Chris Lattner24943d22010-06-08 16:52:24 +0000619 result.SetStatus (eReturnStatusFailed);
620 return false;
621 }
622
623 if (command.GetArgumentCount() == 0)
624 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000625 result.AppendError ("No breakpoint specified from which to delete the commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000626 result.SetStatus (eReturnStatusFailed);
627 return false;
628 }
629
630 BreakpointIDList valid_bp_ids;
631 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
632
633 if (result.Succeeded())
634 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000635 const size_t count = valid_bp_ids.GetSize();
636 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000637 {
638 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
639 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
640 {
641 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
642 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
643 {
644 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
645 if (bp_loc_sp)
646 bp_loc_sp->ClearCallback();
647 else
648 {
649 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
650 cur_bp_id.GetBreakpointID(),
651 cur_bp_id.GetLocationID());
652 result.SetStatus (eReturnStatusFailed);
653 return false;
654 }
655 }
656 else
657 {
658 bp->ClearCallback();
659 }
660 }
661 }
662 }
663 return result.Succeeded();
664}
665
666
667//-------------------------------------------------------------------------
668// CommandObjectBreakpointCommandList
669//-------------------------------------------------------------------------
670
Greg Clayton238c0a12010-09-18 01:14:36 +0000671CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
672 CommandObject (interpreter,
673 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000674 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000675 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000676{
Caroline Tice43b014a2010-10-04 22:28:36 +0000677 CommandArgumentEntry arg;
678 CommandArgumentData bp_id_arg;
679
680 // Define the first (and only) variant of this arg.
681 bp_id_arg.arg_type = eArgTypeBreakpointID;
682 bp_id_arg.arg_repetition = eArgRepeatPlain;
683
684 // There is only one variant this argument could be; put it into the argument entry.
685 arg.push_back (bp_id_arg);
686
687 // Push the data for the first argument into the m_arguments vector.
688 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000689}
690
691CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
692{
693}
694
695bool
Greg Clayton63094e02010-06-23 01:19:29 +0000696CommandObjectBreakpointCommandList::Execute
697(
Greg Clayton63094e02010-06-23 01:19:29 +0000698 Args& command,
699 CommandReturnObject &result
700)
Chris Lattner24943d22010-06-08 16:52:24 +0000701{
Greg Clayton238c0a12010-09-18 01:14:36 +0000702 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000703
704 if (target == NULL)
705 {
706 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
707 result.SetStatus (eReturnStatusFailed);
708 return false;
709 }
710
711 const BreakpointList &breakpoints = target->GetBreakpointList();
712 size_t num_breakpoints = breakpoints.GetSize();
713
714 if (num_breakpoints == 0)
715 {
716 result.AppendError ("No breakpoints exist for which to list commands");
717 result.SetStatus (eReturnStatusFailed);
718 return false;
719 }
720
721 if (command.GetArgumentCount() == 0)
722 {
723 result.AppendError ("No breakpoint specified for which to list the commands");
724 result.SetStatus (eReturnStatusFailed);
725 return false;
726 }
727
728 BreakpointIDList valid_bp_ids;
729 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
730
731 if (result.Succeeded())
732 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000733 const size_t count = valid_bp_ids.GetSize();
734 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000735 {
736 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
737 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
738 {
739 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
740
741 if (bp)
742 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000743 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000744 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
745 {
746 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
747 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000748 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000749 else
750 {
751 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
752 cur_bp_id.GetBreakpointID(),
753 cur_bp_id.GetLocationID());
754 result.SetStatus (eReturnStatusFailed);
755 return false;
756 }
757 }
758 else
759 {
760 bp_options = bp->GetOptions();
761 }
762
763 if (bp_options)
764 {
765 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000766 BreakpointID::GetCanonicalReference (&id_str,
767 cur_bp_id.GetBreakpointID(),
768 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000769 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000770 if (baton)
771 {
772 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
773 result.GetOutputStream().IndentMore ();
774 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
775 result.GetOutputStream().IndentLess ();
776 }
777 else
778 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000779 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
780 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000781 }
782 }
783 result.SetStatus (eReturnStatusSuccessFinishResult);
784 }
785 else
786 {
787 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
788 result.SetStatus (eReturnStatusFailed);
789 }
790
791 }
792 }
793 }
794
795 return result.Succeeded();
796}
797
798//-------------------------------------------------------------------------
799// CommandObjectBreakpointCommand
800//-------------------------------------------------------------------------
801
Greg Clayton63094e02010-06-23 01:19:29 +0000802CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000803 CommandObjectMultiword (interpreter,
804 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000805 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
806 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
807{
808 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000809 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000810 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000811 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000812
813 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000814 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000815 list_command_object->SetCommandName ("breakpoint command list");
816
Greg Clayton238c0a12010-09-18 01:14:36 +0000817 status = LoadSubCommand ("add", add_command_object);
Caroline Ticeb2203882011-05-22 07:14:46 +0000818 status = LoadSubCommand ("delete", delete_command_object);
Greg Clayton238c0a12010-09-18 01:14:36 +0000819 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000820}
821
822
823CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
824{
825}
826
827bool
828CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
829(
830 void *baton,
831 StoppointCallbackContext *context,
832 lldb::user_id_t break_id,
833 lldb::user_id_t break_loc_id
834)
835{
836 bool ret_value = true;
837 if (baton == NULL)
838 return true;
839
840
841 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
842 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000843
Chris Lattner24943d22010-06-08 16:52:24 +0000844 if (commands.GetSize() > 0)
845 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000846 ExecutionContext exe_ctx (context->exe_ctx_ref);
847 Target *target = exe_ctx.GetTargetPtr();
Greg Clayton567e7f32011-09-22 04:58:26 +0000848 if (target)
Chris Lattner24943d22010-06-08 16:52:24 +0000849 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000850 CommandReturnObject result;
Greg Clayton567e7f32011-09-22 04:58:26 +0000851 Debugger &debugger = target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000852 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
853 // if the debugger is set up that way.
854
Jim Inghame5ed8e92011-06-02 23:58:26 +0000855 StreamSP output_stream (debugger.GetAsyncOutputStream());
856 StreamSP error_stream (debugger.GetAsyncErrorStream());
Caroline Tice845d6da2011-05-16 19:20:50 +0000857 result.SetImmediateOutputStream (output_stream);
858 result.SetImmediateErrorStream (error_stream);
859
Jim Ingham949d5ac2011-02-18 00:54:25 +0000860 bool stop_on_continue = true;
861 bool echo_commands = false;
862 bool print_results = true;
863
864 debugger.GetCommandInterpreter().HandleCommands (commands,
Greg Claytonf4124de2012-02-21 00:09:25 +0000865 &exe_ctx,
Jim Ingham949d5ac2011-02-18 00:54:25 +0000866 stop_on_continue,
867 data->stop_on_error,
868 echo_commands,
Enrico Granata01bc2d42012-05-31 01:09:06 +0000869 print_results,
870 eLazyBoolNo,
Jim Ingham949d5ac2011-02-18 00:54:25 +0000871 result);
Caroline Tice845d6da2011-05-16 19:20:50 +0000872 result.GetImmediateOutputStream()->Flush();
873 result.GetImmediateErrorStream()->Flush();
874 }
Chris Lattner24943d22010-06-08 16:52:24 +0000875 }
876 return ret_value;
877}
878