blob: a7e98eaf06bc664a96e40a03e859242089ae3d5d [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),
40 m_one_liner()
Chris Lattner24943d22010-06-08 16:52:24 +000041{
Chris Lattner24943d22010-06-08 16:52:24 +000042}
43
44CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
45{
46}
47
Jim Ingham949d5ac2011-02-18 00:54:25 +000048// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
49// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
50
Greg Claytonb3448432011-03-24 21:19:54 +000051static OptionEnumValueElement
Jim Ingham949d5ac2011-02-18 00:54:25 +000052g_script_option_enumeration[4] =
53{
54 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
55 { eScriptLanguagePython, "python", "Commands are in the Python language."},
56 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
57 { 0, NULL, NULL }
58};
59
Greg Claytonb3448432011-03-24 21:19:54 +000060OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +000061CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
62{
Caroline Tice4d6675c2010-10-01 19:59:14 +000063 { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
Caroline Tice8bb61f02010-09-21 23:25:40 +000064 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
Johnny Chenb81ed0d2010-09-11 00:18:09 +000065
Jim Ingham949d5ac2011-02-18 00:54:25 +000066 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean,
67 "Specify whether breakpoint command execution should terminate on error." },
Chris Lattner24943d22010-06-08 16:52:24 +000068
Jim Ingham949d5ac2011-02-18 00:54:25 +000069 { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone,
70 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
Chris Lattner24943d22010-06-08 16:52:24 +000071
Caroline Tice4d6675c2010-10-01 19:59:14 +000072 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000073};
74
Greg Claytonb3448432011-03-24 21:19:54 +000075const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +000076CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
77{
78 return g_option_table;
79}
80
81
82Error
83CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
84(
Greg Clayton143fcc32011-04-13 00:18:08 +000085 uint32_t option_idx,
Chris Lattner24943d22010-06-08 16:52:24 +000086 const char *option_arg
87)
88{
89 Error error;
90 char short_option = (char) m_getopt_table[option_idx].val;
91
92 switch (short_option)
Greg Clayton61aca5d2011-10-07 18:58:12 +000093 {
94 case 'o':
95 m_use_one_liner = true;
96 m_one_liner = option_arg;
97 break;
Jim Ingham949d5ac2011-02-18 00:54:25 +000098
Greg Clayton61aca5d2011-10-07 18:58:12 +000099 case 's':
100 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
101 g_option_table[option_idx].enum_values,
102 eScriptLanguageNone,
103 error);
104
105 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
106 {
107 m_use_commands = false;
108 m_use_script_language = true;
109 }
110 else
111 {
112 m_use_commands = true;
113 m_use_script_language = false;
114 }
115 break;
116
117 case 'e':
118 {
119 bool success = false;
120 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
121 if (!success)
Greg Clayton9c236732011-10-26 00:56:27 +0000122 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
Greg Clayton61aca5d2011-10-07 18:58:12 +0000123 }
124 break;
125
126 default:
127 break;
128 }
Chris Lattner24943d22010-06-08 16:52:24 +0000129 return error;
130}
131
132void
Greg Clayton143fcc32011-04-13 00:18:08 +0000133CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000134{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000135 m_use_commands = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000136 m_use_script_language = false;
137 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000138
139 m_use_one_liner = false;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000140 m_stop_on_error = true;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000141 m_one_liner.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000142}
143
144//-------------------------------------------------------------------------
145// CommandObjectBreakpointCommandAdd
146//-------------------------------------------------------------------------
147
148
Greg Clayton238c0a12010-09-18 01:14:36 +0000149CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
150 CommandObject (interpreter,
151 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000152 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000153 NULL),
154 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000155{
156 SetHelpLong (
157"\nGeneral information about entering breakpoint commands \n\
158------------------------------------------------------ \n\
159 \n\
160This command will cause you to be prompted to enter the command or set \n\
161of commands you wish to be executed when the specified breakpoint is \n\
162hit. You will be told to enter your command(s), and will see a '> ' \n\
163prompt. Because you can enter one or many commands to be executed when \n\
164a breakpoint is hit, you will continue to be prompted after each \n\
165new-line that you enter, until you enter the word 'DONE', which will \n\
166cause the commands you have entered to be stored with the breakpoint \n\
167and executed when the breakpoint is hit. \n\
168 \n\
169Syntax checking is not necessarily done when breakpoint commands are \n\
170entered. An improperly written breakpoint command will attempt to get \n\
171executed when the breakpoint gets hit, and usually silently fail. If \n\
172your breakpoint command does not appear to be getting executed, go \n\
173back and check your syntax. \n\
174 \n\
175 \n\
176Special information about PYTHON breakpoint commands \n\
177---------------------------------------------------- \n\
178 \n\
179You may enter either one line of Python or multiple lines of Python \n\
180(including defining whole functions, if desired). If you enter a \n\
181single line of Python, that will be passed to the Python interpreter \n\
182'as is' when the breakpoint gets hit. If you enter function \n\
183definitions, they will be passed to the Python interpreter as soon as \n\
184you finish entering the breakpoint command, and they can be called \n\
185later (don't forget to add calls to them, if you want them called when \n\
186the breakpoint is hit). If you enter multiple lines of Python that \n\
187are not function definitions, they will be collected into a new, \n\
188automatically generated Python function, and a call to the newly \n\
189generated function will be attached to the breakpoint. Important \n\
190Note: Because loose Python code gets collected into functions, if you \n\
191want to access global variables in the 'loose' code, you need to \n\
192specify that they are global, using the 'global' keyword. Be sure to \n\
193use correct Python syntax, including indentation, when entering Python \n\
194breakpoint commands. \n\
195 \n\
196Example Python one-line breakpoint command: \n\
197 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000198(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000199Enter your Python command(s). Type 'DONE' to end. \n\
200> print \"Hit this breakpoint!\" \n\
201> DONE \n\
202 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000203As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000204(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000205(lldb) run \n\
206Launching '.../a.out' (x86_64) \n\
207(lldb) Fri Sep 10 12:17:45 2010 \n\
208Process 21778 Stopped \n\
209* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
210 36 \n\
211 37 int c(int val)\n\
212 38 {\n\
213 39 -> return val + 3;\n\
214 40 }\n\
215 41 \n\
216 42 int main (int argc, char const *argv[])\n\
217(lldb) \n\
218 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000219Example multiple line Python breakpoint command, using function definition: \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> def breakpoint_output (bp_no): \n\
224> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
225> print out_string \n\
226> return True \n\
227> breakpoint_output (1) \n\
228> DONE \n\
229 \n\
230 \n\
231Example multiple line Python breakpoint command, using 'loose' Python: \n\
232 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000233(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000234Enter your Python command(s). Type 'DONE' to end. \n\
235> global bp_count \n\
236> bp_count = bp_count + 1 \n\
237> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
238> DONE \n\
239 \n\
240In this case, since there is a reference to a global variable, \n\
241'bp_count', you will also need to make sure 'bp_count' exists and is \n\
242initialized: \n\
243 \n\
244(lldb) script \n\
245>>> bp_count = 0 \n\
246>>> quit() \n\
247 \n\
248(lldb) \n\
249 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000250 \n\
251Final Note: If you get a warning that no breakpoint command was generated, \n\
252but you did not get any syntax errors, you probably forgot to add a call \n\
253to your functions. \n\
254 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000255Special information about debugger command breakpoint commands \n\
256-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000257 \n\
258You may enter any debugger command, exactly as you would at the \n\
259debugger prompt. You may enter as many debugger commands as you like, \n\
260but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000261
262
263 CommandArgumentEntry arg;
264 CommandArgumentData bp_id_arg;
265
266 // Define the first (and only) variant of this arg.
267 bp_id_arg.arg_type = eArgTypeBreakpointID;
268 bp_id_arg.arg_repetition = eArgRepeatPlain;
269
270 // There is only one variant this argument could be; put it into the argument entry.
271 arg.push_back (bp_id_arg);
272
273 // Push the data for the first argument into the m_arguments vector.
274 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000275}
276
277CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
278{
279}
280
281bool
282CommandObjectBreakpointCommandAdd::Execute
283(
284 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000285 CommandReturnObject &result
286)
287{
Greg Clayton238c0a12010-09-18 01:14:36 +0000288 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000289
290 if (target == NULL)
291 {
292 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
293 result.SetStatus (eReturnStatusFailed);
294 return false;
295 }
296
297 const BreakpointList &breakpoints = target->GetBreakpointList();
298 size_t num_breakpoints = breakpoints.GetSize();
299
300 if (num_breakpoints == 0)
301 {
302 result.AppendError ("No breakpoints exist to have commands added");
303 result.SetStatus (eReturnStatusFailed);
304 return false;
305 }
306
Chris Lattner24943d22010-06-08 16:52:24 +0000307 BreakpointIDList valid_bp_ids;
308 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
309
310 if (result.Succeeded())
311 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000312 const size_t count = valid_bp_ids.GetSize();
313 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000314 {
315 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
316 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
317 {
318 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000319 BreakpointOptions *bp_options = NULL;
320 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
321 {
322 // This breakpoint does not have an associated location.
323 bp_options = bp->GetOptions();
324 }
325 else
Chris Lattner24943d22010-06-08 16:52:24 +0000326 {
327 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000328 // This breakpoint does have an associated location.
329 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000330 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000331 bp_options = bp_loc_sp->GetLocationOptions();
332 }
333
Jim Ingham949d5ac2011-02-18 00:54:25 +0000334 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000335 if (bp_options == NULL) continue;
336
337 // If we are using script language, get the script interpreter
338 // in order to set or collect command callback. Otherwise, call
339 // the methods associated with this object.
340 if (m_options.m_use_script_language)
341 {
342 // Special handling for one-liner specified inline.
343 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000344 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
345 m_options.m_one_liner.c_str());
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000346 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000347 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
348 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000349 }
350 else
351 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000352 // Special handling for one-liner specified inline.
353 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000354 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000355 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000356 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000357 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000358 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000359 }
360 }
361 }
362 }
363
364 return result.Succeeded();
365}
366
367Options *
368CommandObjectBreakpointCommandAdd::GetOptions ()
369{
370 return &m_options;
371}
372
373const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
374
375void
376CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
377(
378 BreakpointOptions *bp_options,
379 CommandReturnObject &result
380)
381{
Greg Clayton238c0a12010-09-18 01:14:36 +0000382 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000383 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
384 if (reader_sp && data_ap.get())
385 {
386 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
387 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
388
389 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
390 bp_options, // baton
391 eInputReaderGranularityLine, // token size, to pass to callback function
392 "DONE", // end token
393 "> ", // prompt
394 true)); // echo input
395 if (err.Success())
396 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000397 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000398 result.SetStatus (eReturnStatusSuccessFinishNoResult);
399 }
400 else
401 {
402 result.AppendError (err.AsCString());
403 result.SetStatus (eReturnStatusFailed);
404 }
405 }
406 else
407 {
408 result.AppendError("out of memory");
409 result.SetStatus (eReturnStatusFailed);
410 }
411
412}
413
Johnny Chen3e0571b2010-09-11 00:23:59 +0000414// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000415void
Greg Clayton238c0a12010-09-18 01:14:36 +0000416CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000417 const char *oneliner)
418{
419 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
420
421 // It's necessary to set both user_source and script_source to the oneliner.
422 // The former is used to generate callback description (as in breakpoint command list)
423 // while the latter is used for Python to interpret during the actual callback.
424 data_ap->user_source.AppendString (oneliner);
425 data_ap->script_source.AppendString (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000426 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000427
428 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
429 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
430
431 return;
432}
433
Chris Lattner24943d22010-06-08 16:52:24 +0000434size_t
435CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
436(
437 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000438 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000439 lldb::InputReaderAction notification,
440 const char *bytes,
441 size_t bytes_len
442)
443{
Caroline Tice892fadd2011-06-16 16:27:19 +0000444 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
445 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
446
Chris Lattner24943d22010-06-08 16:52:24 +0000447 switch (notification)
448 {
449 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000450 if (!batch_mode)
451 {
452 out_stream->Printf ("%s\n", g_reader_instructions);
453 if (reader.GetPrompt())
454 out_stream->Printf ("%s", reader.GetPrompt());
455 out_stream->Flush();
456 }
Chris Lattner24943d22010-06-08 16:52:24 +0000457 break;
458
459 case eInputReaderDeactivate:
460 break;
461
462 case eInputReaderReactivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000463 if (reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000464 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000465 out_stream->Printf ("%s", reader.GetPrompt());
466 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000467 }
Chris Lattner24943d22010-06-08 16:52:24 +0000468 break;
469
Caroline Tice4a348082011-05-02 20:41:46 +0000470 case eInputReaderAsynchronousOutputWritten:
471 break;
472
Chris Lattner24943d22010-06-08 16:52:24 +0000473 case eInputReaderGotToken:
474 if (bytes && bytes_len && baton)
475 {
476 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
477 if (bp_options)
478 {
479 Baton *bp_options_baton = bp_options->GetBaton();
480 if (bp_options_baton)
481 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
482 }
483 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000484 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000485 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000486 out_stream->Printf ("%s", reader.GetPrompt());
487 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000488 }
Chris Lattner24943d22010-06-08 16:52:24 +0000489 break;
490
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000491 case eInputReaderInterrupt:
492 {
493 // Finish, and cancel the breakpoint command.
494 reader.SetIsDone (true);
495 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
496 if (bp_options)
497 {
498 Baton *bp_options_baton = bp_options->GetBaton ();
499 if (bp_options_baton)
500 {
501 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
502 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
503 }
504 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000505 if (!batch_mode)
506 {
507 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
508 out_stream->Flush();
509 }
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000510 }
511 break;
512
513 case eInputReaderEndOfFile:
514 reader.SetIsDone (true);
515 break;
516
Chris Lattner24943d22010-06-08 16:52:24 +0000517 case eInputReaderDone:
518 break;
519 }
520
521 return bytes_len;
522}
523
524
525//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000526// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000527//-------------------------------------------------------------------------
528
Caroline Ticeb2203882011-05-22 07:14:46 +0000529CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000530 CommandObject (interpreter,
Caroline Ticeb2203882011-05-22 07:14:46 +0000531 "delete",
532 "Delete the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000533 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000534{
Caroline Tice43b014a2010-10-04 22:28:36 +0000535 CommandArgumentEntry arg;
536 CommandArgumentData bp_id_arg;
537
538 // Define the first (and only) variant of this arg.
539 bp_id_arg.arg_type = eArgTypeBreakpointID;
540 bp_id_arg.arg_repetition = eArgRepeatPlain;
541
542 // There is only one variant this argument could be; put it into the argument entry.
543 arg.push_back (bp_id_arg);
544
545 // Push the data for the first argument into the m_arguments vector.
546 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000547}
548
Caroline Ticeb2203882011-05-22 07:14:46 +0000549CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete ()
Chris Lattner24943d22010-06-08 16:52:24 +0000550{
551}
552
553bool
Caroline Ticeb2203882011-05-22 07:14:46 +0000554CommandObjectBreakpointCommandDelete::Execute
Greg Clayton63094e02010-06-23 01:19:29 +0000555(
Greg Clayton63094e02010-06-23 01:19:29 +0000556 Args& command,
557 CommandReturnObject &result
558)
Chris Lattner24943d22010-06-08 16:52:24 +0000559{
Greg Clayton238c0a12010-09-18 01:14:36 +0000560 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000561
562 if (target == NULL)
563 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000564 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000565 result.SetStatus (eReturnStatusFailed);
566 return false;
567 }
568
569 const BreakpointList &breakpoints = target->GetBreakpointList();
570 size_t num_breakpoints = breakpoints.GetSize();
571
572 if (num_breakpoints == 0)
573 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000574 result.AppendError ("No breakpoints exist to have commands deleted");
Chris Lattner24943d22010-06-08 16:52:24 +0000575 result.SetStatus (eReturnStatusFailed);
576 return false;
577 }
578
579 if (command.GetArgumentCount() == 0)
580 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000581 result.AppendError ("No breakpoint specified from which to delete the commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000582 result.SetStatus (eReturnStatusFailed);
583 return false;
584 }
585
586 BreakpointIDList valid_bp_ids;
587 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
588
589 if (result.Succeeded())
590 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000591 const size_t count = valid_bp_ids.GetSize();
592 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000593 {
594 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
595 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
596 {
597 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
598 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
599 {
600 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
601 if (bp_loc_sp)
602 bp_loc_sp->ClearCallback();
603 else
604 {
605 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
606 cur_bp_id.GetBreakpointID(),
607 cur_bp_id.GetLocationID());
608 result.SetStatus (eReturnStatusFailed);
609 return false;
610 }
611 }
612 else
613 {
614 bp->ClearCallback();
615 }
616 }
617 }
618 }
619 return result.Succeeded();
620}
621
622
623//-------------------------------------------------------------------------
624// CommandObjectBreakpointCommandList
625//-------------------------------------------------------------------------
626
Greg Clayton238c0a12010-09-18 01:14:36 +0000627CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
628 CommandObject (interpreter,
629 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000630 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000631 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000632{
Caroline Tice43b014a2010-10-04 22:28:36 +0000633 CommandArgumentEntry arg;
634 CommandArgumentData bp_id_arg;
635
636 // Define the first (and only) variant of this arg.
637 bp_id_arg.arg_type = eArgTypeBreakpointID;
638 bp_id_arg.arg_repetition = eArgRepeatPlain;
639
640 // There is only one variant this argument could be; put it into the argument entry.
641 arg.push_back (bp_id_arg);
642
643 // Push the data for the first argument into the m_arguments vector.
644 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000645}
646
647CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
648{
649}
650
651bool
Greg Clayton63094e02010-06-23 01:19:29 +0000652CommandObjectBreakpointCommandList::Execute
653(
Greg Clayton63094e02010-06-23 01:19:29 +0000654 Args& command,
655 CommandReturnObject &result
656)
Chris Lattner24943d22010-06-08 16:52:24 +0000657{
Greg Clayton238c0a12010-09-18 01:14:36 +0000658 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000659
660 if (target == NULL)
661 {
662 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
663 result.SetStatus (eReturnStatusFailed);
664 return false;
665 }
666
667 const BreakpointList &breakpoints = target->GetBreakpointList();
668 size_t num_breakpoints = breakpoints.GetSize();
669
670 if (num_breakpoints == 0)
671 {
672 result.AppendError ("No breakpoints exist for which to list commands");
673 result.SetStatus (eReturnStatusFailed);
674 return false;
675 }
676
677 if (command.GetArgumentCount() == 0)
678 {
679 result.AppendError ("No breakpoint specified for which to list the commands");
680 result.SetStatus (eReturnStatusFailed);
681 return false;
682 }
683
684 BreakpointIDList valid_bp_ids;
685 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
686
687 if (result.Succeeded())
688 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000689 const size_t count = valid_bp_ids.GetSize();
690 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000691 {
692 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
693 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
694 {
695 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
696
697 if (bp)
698 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000699 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000700 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
701 {
702 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
703 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000704 bp_options = bp_loc_sp->GetOptionsNoCreate();
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 {
716 bp_options = bp->GetOptions();
717 }
718
719 if (bp_options)
720 {
721 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000722 BreakpointID::GetCanonicalReference (&id_str,
723 cur_bp_id.GetBreakpointID(),
724 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000725 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000726 if (baton)
727 {
728 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
729 result.GetOutputStream().IndentMore ();
730 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
731 result.GetOutputStream().IndentLess ();
732 }
733 else
734 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000735 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
736 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000737 }
738 }
739 result.SetStatus (eReturnStatusSuccessFinishResult);
740 }
741 else
742 {
743 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
744 result.SetStatus (eReturnStatusFailed);
745 }
746
747 }
748 }
749 }
750
751 return result.Succeeded();
752}
753
754//-------------------------------------------------------------------------
755// CommandObjectBreakpointCommand
756//-------------------------------------------------------------------------
757
Greg Clayton63094e02010-06-23 01:19:29 +0000758CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000759 CommandObjectMultiword (interpreter,
760 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000761 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
762 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
763{
764 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000765 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000766 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000767 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000768
769 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000770 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000771 list_command_object->SetCommandName ("breakpoint command list");
772
Greg Clayton238c0a12010-09-18 01:14:36 +0000773 status = LoadSubCommand ("add", add_command_object);
Caroline Ticeb2203882011-05-22 07:14:46 +0000774 status = LoadSubCommand ("delete", delete_command_object);
Greg Clayton238c0a12010-09-18 01:14:36 +0000775 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000776}
777
778
779CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
780{
781}
782
783bool
784CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
785(
786 void *baton,
787 StoppointCallbackContext *context,
788 lldb::user_id_t break_id,
789 lldb::user_id_t break_loc_id
790)
791{
792 bool ret_value = true;
793 if (baton == NULL)
794 return true;
795
796
797 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
798 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000799
Chris Lattner24943d22010-06-08 16:52:24 +0000800 if (commands.GetSize() > 0)
801 {
Greg Claytonf4124de2012-02-21 00:09:25 +0000802 ExecutionContext exe_ctx (context->exe_ctx_ref);
803 Target *target = exe_ctx.GetTargetPtr();
Greg Clayton567e7f32011-09-22 04:58:26 +0000804 if (target)
Chris Lattner24943d22010-06-08 16:52:24 +0000805 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000806 CommandReturnObject result;
Greg Clayton567e7f32011-09-22 04:58:26 +0000807 Debugger &debugger = target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000808 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
809 // if the debugger is set up that way.
810
Jim Inghame5ed8e92011-06-02 23:58:26 +0000811 StreamSP output_stream (debugger.GetAsyncOutputStream());
812 StreamSP error_stream (debugger.GetAsyncErrorStream());
Caroline Tice845d6da2011-05-16 19:20:50 +0000813 result.SetImmediateOutputStream (output_stream);
814 result.SetImmediateErrorStream (error_stream);
815
Jim Ingham949d5ac2011-02-18 00:54:25 +0000816 bool stop_on_continue = true;
817 bool echo_commands = false;
818 bool print_results = true;
819
820 debugger.GetCommandInterpreter().HandleCommands (commands,
Greg Claytonf4124de2012-02-21 00:09:25 +0000821 &exe_ctx,
Jim Ingham949d5ac2011-02-18 00:54:25 +0000822 stop_on_continue,
823 data->stop_on_error,
824 echo_commands,
825 print_results,
826 result);
Caroline Tice845d6da2011-05-16 19:20:50 +0000827 result.GetImmediateOutputStream()->Flush();
828 result.GetImmediateErrorStream()->Flush();
829 }
Chris Lattner24943d22010-06-08 16:52:24 +0000830 }
831 return ret_value;
832}
833