blob: 5130a2f86befcb2251976514ae22cb6b4fe73088 [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"
Caroline Tice845d6da2011-05-16 19:20:50 +000026#include "lldb/Core/StreamAsynchronousIO.h"
Chris Lattner24943d22010-06-08 16:52:24 +000027
28using namespace lldb;
29using namespace lldb_private;
30
31//-------------------------------------------------------------------------
32// CommandObjectBreakpointCommandAdd::CommandOptions
33//-------------------------------------------------------------------------
34
Greg Claytonf15996e2011-04-07 22:46:35 +000035CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
36 Options (interpreter),
Johnny Chenb81ed0d2010-09-11 00:18:09 +000037 m_use_commands (false),
38 m_use_script_language (false),
39 m_script_language (eScriptLanguageNone),
40 m_use_one_liner (false),
41 m_one_liner()
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{
Caroline Tice4d6675c2010-10-01 19:59:14 +000064 { LLDB_OPT_SET_ALL, 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
Caroline Tice4d6675c2010-10-01 19:59:14 +000073 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +000074};
75
Greg Claytonb3448432011-03-24 21:19:54 +000076const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +000077CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
78{
79 return g_option_table;
80}
81
82
83Error
84CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
85(
Greg Clayton143fcc32011-04-13 00:18:08 +000086 uint32_t option_idx,
Chris Lattner24943d22010-06-08 16:52:24 +000087 const char *option_arg
88)
89{
90 Error error;
91 char short_option = (char) m_getopt_table[option_idx].val;
92
93 switch (short_option)
94 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +000095 case 'o':
Jim Ingham949d5ac2011-02-18 00:54:25 +000096 m_use_one_liner = true;
97 m_one_liner = option_arg;
98 break;
99 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000100 case 's':
Jim Ingham949d5ac2011-02-18 00:54:25 +0000101 {
102 bool found_one = false;
103 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
104 g_option_table[option_idx].enum_values,
105 eScriptLanguageNone,
106 &found_one);
107 if (!found_one)
108 error.SetErrorStringWithFormat("Invalid enumeration value '%s' for option '%c'.\n",
109 option_arg,
110 short_option);
111
112 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
113 {
114 m_use_commands = false;
115 m_use_script_language = true;
116 }
117 else
118 {
119 m_use_commands = true;
120 m_use_script_language = false;
121 }
122 }
123 break;
124 case 'e':
125 bool success_ptr;
126 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success_ptr);
127 if (!success_ptr)
128 error.SetErrorStringWithFormat("Invalid value for stop-on-error: \"%s\".\n", option_arg);
129 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000130 default:
Jim Ingham949d5ac2011-02-18 00:54:25 +0000131 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000132 }
133 return error;
134}
135
136void
Greg Clayton143fcc32011-04-13 00:18:08 +0000137CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000138{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000139 m_use_commands = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000140 m_use_script_language = false;
141 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000142
143 m_use_one_liner = false;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000144 m_stop_on_error = true;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000145 m_one_liner.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000146}
147
148//-------------------------------------------------------------------------
149// CommandObjectBreakpointCommandAdd
150//-------------------------------------------------------------------------
151
152
Greg Clayton238c0a12010-09-18 01:14:36 +0000153CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
154 CommandObject (interpreter,
155 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000156 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000157 NULL),
158 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000159{
160 SetHelpLong (
161"\nGeneral information about entering breakpoint commands \n\
162------------------------------------------------------ \n\
163 \n\
164This command will cause you to be prompted to enter the command or set \n\
165of commands you wish to be executed when the specified breakpoint is \n\
166hit. You will be told to enter your command(s), and will see a '> ' \n\
167prompt. Because you can enter one or many commands to be executed when \n\
168a breakpoint is hit, you will continue to be prompted after each \n\
169new-line that you enter, until you enter the word 'DONE', which will \n\
170cause the commands you have entered to be stored with the breakpoint \n\
171and executed when the breakpoint is hit. \n\
172 \n\
173Syntax checking is not necessarily done when breakpoint commands are \n\
174entered. An improperly written breakpoint command will attempt to get \n\
175executed when the breakpoint gets hit, and usually silently fail. If \n\
176your breakpoint command does not appear to be getting executed, go \n\
177back and check your syntax. \n\
178 \n\
179 \n\
180Special information about PYTHON breakpoint commands \n\
181---------------------------------------------------- \n\
182 \n\
183You may enter either one line of Python or multiple lines of Python \n\
184(including defining whole functions, if desired). If you enter a \n\
185single line of Python, that will be passed to the Python interpreter \n\
186'as is' when the breakpoint gets hit. If you enter function \n\
187definitions, they will be passed to the Python interpreter as soon as \n\
188you finish entering the breakpoint command, and they can be called \n\
189later (don't forget to add calls to them, if you want them called when \n\
190the breakpoint is hit). If you enter multiple lines of Python that \n\
191are not function definitions, they will be collected into a new, \n\
192automatically generated Python function, and a call to the newly \n\
193generated function will be attached to the breakpoint. Important \n\
194Note: Because loose Python code gets collected into functions, if you \n\
195want to access global variables in the 'loose' code, you need to \n\
196specify that they are global, using the 'global' keyword. Be sure to \n\
197use correct Python syntax, including indentation, when entering Python \n\
198breakpoint commands. \n\
199 \n\
200Example Python one-line breakpoint command: \n\
201 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000202(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000203Enter your Python command(s). Type 'DONE' to end. \n\
204> print \"Hit this breakpoint!\" \n\
205> DONE \n\
206 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000207As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000208(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000209(lldb) run \n\
210Launching '.../a.out' (x86_64) \n\
211(lldb) Fri Sep 10 12:17:45 2010 \n\
212Process 21778 Stopped \n\
213* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
214 36 \n\
215 37 int c(int val)\n\
216 38 {\n\
217 39 -> return val + 3;\n\
218 40 }\n\
219 41 \n\
220 42 int main (int argc, char const *argv[])\n\
221(lldb) \n\
222 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000223Example multiple line Python breakpoint command, using function definition: \n\
224 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000225(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000226Enter your Python command(s). Type 'DONE' to end. \n\
227> def breakpoint_output (bp_no): \n\
228> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
229> print out_string \n\
230> return True \n\
231> breakpoint_output (1) \n\
232> DONE \n\
233 \n\
234 \n\
235Example multiple line Python breakpoint command, using 'loose' Python: \n\
236 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000237(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000238Enter your Python command(s). Type 'DONE' to end. \n\
239> global bp_count \n\
240> bp_count = bp_count + 1 \n\
241> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
242> DONE \n\
243 \n\
244In this case, since there is a reference to a global variable, \n\
245'bp_count', you will also need to make sure 'bp_count' exists and is \n\
246initialized: \n\
247 \n\
248(lldb) script \n\
249>>> bp_count = 0 \n\
250>>> quit() \n\
251 \n\
252(lldb) \n\
253 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000254 \n\
255Final Note: If you get a warning that no breakpoint command was generated, \n\
256but you did not get any syntax errors, you probably forgot to add a call \n\
257to your functions. \n\
258 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000259Special information about debugger command breakpoint commands \n\
260-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000261 \n\
262You may enter any debugger command, exactly as you would at the \n\
263debugger prompt. You may enter as many debugger commands as you like, \n\
264but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000265
266
267 CommandArgumentEntry arg;
268 CommandArgumentData bp_id_arg;
269
270 // Define the first (and only) variant of this arg.
271 bp_id_arg.arg_type = eArgTypeBreakpointID;
272 bp_id_arg.arg_repetition = eArgRepeatPlain;
273
274 // There is only one variant this argument could be; put it into the argument entry.
275 arg.push_back (bp_id_arg);
276
277 // Push the data for the first argument into the m_arguments vector.
278 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000279}
280
281CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
282{
283}
284
285bool
286CommandObjectBreakpointCommandAdd::Execute
287(
288 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000289 CommandReturnObject &result
290)
291{
Greg Clayton238c0a12010-09-18 01:14:36 +0000292 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000293
294 if (target == NULL)
295 {
296 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
297 result.SetStatus (eReturnStatusFailed);
298 return false;
299 }
300
301 const BreakpointList &breakpoints = target->GetBreakpointList();
302 size_t num_breakpoints = breakpoints.GetSize();
303
304 if (num_breakpoints == 0)
305 {
306 result.AppendError ("No breakpoints exist to have commands added");
307 result.SetStatus (eReturnStatusFailed);
308 return false;
309 }
310
Chris Lattner24943d22010-06-08 16:52:24 +0000311 BreakpointIDList valid_bp_ids;
312 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
313
314 if (result.Succeeded())
315 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000316 const size_t count = valid_bp_ids.GetSize();
317 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000318 {
319 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
320 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
321 {
322 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000323 BreakpointOptions *bp_options = NULL;
324 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
325 {
326 // This breakpoint does not have an associated location.
327 bp_options = bp->GetOptions();
328 }
329 else
Chris Lattner24943d22010-06-08 16:52:24 +0000330 {
331 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000332 // This breakpoint does have an associated location.
333 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000334 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000335 bp_options = bp_loc_sp->GetLocationOptions();
336 }
337
Jim Ingham949d5ac2011-02-18 00:54:25 +0000338 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000339 if (bp_options == NULL) continue;
340
341 // If we are using script language, get the script interpreter
342 // in order to set or collect command callback. Otherwise, call
343 // the methods associated with this object.
344 if (m_options.m_use_script_language)
345 {
346 // Special handling for one-liner specified inline.
347 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000348 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
349 m_options.m_one_liner.c_str());
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000350 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000351 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
352 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000353 }
354 else
355 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000356 // Special handling for one-liner specified inline.
357 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000358 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000359 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000360 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000361 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000362 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000363 }
364 }
365 }
366 }
367
368 return result.Succeeded();
369}
370
371Options *
372CommandObjectBreakpointCommandAdd::GetOptions ()
373{
374 return &m_options;
375}
376
377const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
378
379void
380CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
381(
382 BreakpointOptions *bp_options,
383 CommandReturnObject &result
384)
385{
Greg Clayton238c0a12010-09-18 01:14:36 +0000386 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000387 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
388 if (reader_sp && data_ap.get())
389 {
390 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
391 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
392
393 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
394 bp_options, // baton
395 eInputReaderGranularityLine, // token size, to pass to callback function
396 "DONE", // end token
397 "> ", // prompt
398 true)); // echo input
399 if (err.Success())
400 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000401 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000402 result.SetStatus (eReturnStatusSuccessFinishNoResult);
403 }
404 else
405 {
406 result.AppendError (err.AsCString());
407 result.SetStatus (eReturnStatusFailed);
408 }
409 }
410 else
411 {
412 result.AppendError("out of memory");
413 result.SetStatus (eReturnStatusFailed);
414 }
415
416}
417
Johnny Chen3e0571b2010-09-11 00:23:59 +0000418// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000419void
Greg Clayton238c0a12010-09-18 01:14:36 +0000420CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000421 const char *oneliner)
422{
423 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
424
425 // It's necessary to set both user_source and script_source to the oneliner.
426 // The former is used to generate callback description (as in breakpoint command list)
427 // while the latter is used for Python to interpret during the actual callback.
428 data_ap->user_source.AppendString (oneliner);
429 data_ap->script_source.AppendString (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000430 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000431
432 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
433 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
434
435 return;
436}
437
Chris Lattner24943d22010-06-08 16:52:24 +0000438size_t
439CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
440(
441 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000442 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000443 lldb::InputReaderAction notification,
444 const char *bytes,
445 size_t bytes_len
446)
447{
Caroline Tice892fadd2011-06-16 16:27:19 +0000448 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
449 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
450
Chris Lattner24943d22010-06-08 16:52:24 +0000451 switch (notification)
452 {
453 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000454 if (!batch_mode)
455 {
456 out_stream->Printf ("%s\n", g_reader_instructions);
457 if (reader.GetPrompt())
458 out_stream->Printf ("%s", reader.GetPrompt());
459 out_stream->Flush();
460 }
Chris Lattner24943d22010-06-08 16:52:24 +0000461 break;
462
463 case eInputReaderDeactivate:
464 break;
465
466 case eInputReaderReactivate:
Caroline Tice892fadd2011-06-16 16:27:19 +0000467 if (reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000468 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000469 out_stream->Printf ("%s", reader.GetPrompt());
470 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000471 }
Chris Lattner24943d22010-06-08 16:52:24 +0000472 break;
473
Caroline Tice4a348082011-05-02 20:41:46 +0000474 case eInputReaderAsynchronousOutputWritten:
475 break;
476
Chris Lattner24943d22010-06-08 16:52:24 +0000477 case eInputReaderGotToken:
478 if (bytes && bytes_len && baton)
479 {
480 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
481 if (bp_options)
482 {
483 Baton *bp_options_baton = bp_options->GetBaton();
484 if (bp_options_baton)
485 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
486 }
487 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000488 if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
Caroline Ticef81b4c52010-10-27 18:34:42 +0000489 {
Caroline Tice892fadd2011-06-16 16:27:19 +0000490 out_stream->Printf ("%s", reader.GetPrompt());
491 out_stream->Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000492 }
Chris Lattner24943d22010-06-08 16:52:24 +0000493 break;
494
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000495 case eInputReaderInterrupt:
496 {
497 // Finish, and cancel the breakpoint command.
498 reader.SetIsDone (true);
499 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
500 if (bp_options)
501 {
502 Baton *bp_options_baton = bp_options->GetBaton ();
503 if (bp_options_baton)
504 {
505 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
506 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
507 }
508 }
Caroline Tice892fadd2011-06-16 16:27:19 +0000509 if (!batch_mode)
510 {
511 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
512 out_stream->Flush();
513 }
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000514 }
515 break;
516
517 case eInputReaderEndOfFile:
518 reader.SetIsDone (true);
519 break;
520
Chris Lattner24943d22010-06-08 16:52:24 +0000521 case eInputReaderDone:
522 break;
523 }
524
525 return bytes_len;
526}
527
528
529//-------------------------------------------------------------------------
Caroline Ticeb2203882011-05-22 07:14:46 +0000530// CommandObjectBreakpointCommandDelete
Chris Lattner24943d22010-06-08 16:52:24 +0000531//-------------------------------------------------------------------------
532
Caroline Ticeb2203882011-05-22 07:14:46 +0000533CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000534 CommandObject (interpreter,
Caroline Ticeb2203882011-05-22 07:14:46 +0000535 "delete",
536 "Delete the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000537 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000538{
Caroline Tice43b014a2010-10-04 22:28:36 +0000539 CommandArgumentEntry arg;
540 CommandArgumentData bp_id_arg;
541
542 // Define the first (and only) variant of this arg.
543 bp_id_arg.arg_type = eArgTypeBreakpointID;
544 bp_id_arg.arg_repetition = eArgRepeatPlain;
545
546 // There is only one variant this argument could be; put it into the argument entry.
547 arg.push_back (bp_id_arg);
548
549 // Push the data for the first argument into the m_arguments vector.
550 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000551}
552
Caroline Ticeb2203882011-05-22 07:14:46 +0000553CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete ()
Chris Lattner24943d22010-06-08 16:52:24 +0000554{
555}
556
557bool
Caroline Ticeb2203882011-05-22 07:14:46 +0000558CommandObjectBreakpointCommandDelete::Execute
Greg Clayton63094e02010-06-23 01:19:29 +0000559(
Greg Clayton63094e02010-06-23 01:19:29 +0000560 Args& command,
561 CommandReturnObject &result
562)
Chris Lattner24943d22010-06-08 16:52:24 +0000563{
Greg Clayton238c0a12010-09-18 01:14:36 +0000564 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000565
566 if (target == NULL)
567 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000568 result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000569 result.SetStatus (eReturnStatusFailed);
570 return false;
571 }
572
573 const BreakpointList &breakpoints = target->GetBreakpointList();
574 size_t num_breakpoints = breakpoints.GetSize();
575
576 if (num_breakpoints == 0)
577 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000578 result.AppendError ("No breakpoints exist to have commands deleted");
Chris Lattner24943d22010-06-08 16:52:24 +0000579 result.SetStatus (eReturnStatusFailed);
580 return false;
581 }
582
583 if (command.GetArgumentCount() == 0)
584 {
Caroline Ticeb2203882011-05-22 07:14:46 +0000585 result.AppendError ("No breakpoint specified from which to delete the commands");
Chris Lattner24943d22010-06-08 16:52:24 +0000586 result.SetStatus (eReturnStatusFailed);
587 return false;
588 }
589
590 BreakpointIDList valid_bp_ids;
591 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
592
593 if (result.Succeeded())
594 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000595 const size_t count = valid_bp_ids.GetSize();
596 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000597 {
598 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
599 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
600 {
601 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
602 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
603 {
604 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
605 if (bp_loc_sp)
606 bp_loc_sp->ClearCallback();
607 else
608 {
609 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
610 cur_bp_id.GetBreakpointID(),
611 cur_bp_id.GetLocationID());
612 result.SetStatus (eReturnStatusFailed);
613 return false;
614 }
615 }
616 else
617 {
618 bp->ClearCallback();
619 }
620 }
621 }
622 }
623 return result.Succeeded();
624}
625
626
627//-------------------------------------------------------------------------
628// CommandObjectBreakpointCommandList
629//-------------------------------------------------------------------------
630
Greg Clayton238c0a12010-09-18 01:14:36 +0000631CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
632 CommandObject (interpreter,
633 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000634 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000635 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000636{
Caroline Tice43b014a2010-10-04 22:28:36 +0000637 CommandArgumentEntry arg;
638 CommandArgumentData bp_id_arg;
639
640 // Define the first (and only) variant of this arg.
641 bp_id_arg.arg_type = eArgTypeBreakpointID;
642 bp_id_arg.arg_repetition = eArgRepeatPlain;
643
644 // There is only one variant this argument could be; put it into the argument entry.
645 arg.push_back (bp_id_arg);
646
647 // Push the data for the first argument into the m_arguments vector.
648 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000649}
650
651CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
652{
653}
654
655bool
Greg Clayton63094e02010-06-23 01:19:29 +0000656CommandObjectBreakpointCommandList::Execute
657(
Greg Clayton63094e02010-06-23 01:19:29 +0000658 Args& command,
659 CommandReturnObject &result
660)
Chris Lattner24943d22010-06-08 16:52:24 +0000661{
Greg Clayton238c0a12010-09-18 01:14:36 +0000662 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000663
664 if (target == NULL)
665 {
666 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
667 result.SetStatus (eReturnStatusFailed);
668 return false;
669 }
670
671 const BreakpointList &breakpoints = target->GetBreakpointList();
672 size_t num_breakpoints = breakpoints.GetSize();
673
674 if (num_breakpoints == 0)
675 {
676 result.AppendError ("No breakpoints exist for which to list commands");
677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680
681 if (command.GetArgumentCount() == 0)
682 {
683 result.AppendError ("No breakpoint specified for which to list the commands");
684 result.SetStatus (eReturnStatusFailed);
685 return false;
686 }
687
688 BreakpointIDList valid_bp_ids;
689 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
690
691 if (result.Succeeded())
692 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000693 const size_t count = valid_bp_ids.GetSize();
694 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000695 {
696 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
697 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
698 {
699 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
700
701 if (bp)
702 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000703 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000704 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
705 {
706 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
707 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000708 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000709 else
710 {
711 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
712 cur_bp_id.GetBreakpointID(),
713 cur_bp_id.GetLocationID());
714 result.SetStatus (eReturnStatusFailed);
715 return false;
716 }
717 }
718 else
719 {
720 bp_options = bp->GetOptions();
721 }
722
723 if (bp_options)
724 {
725 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000726 BreakpointID::GetCanonicalReference (&id_str,
727 cur_bp_id.GetBreakpointID(),
728 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000729 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000730 if (baton)
731 {
732 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
733 result.GetOutputStream().IndentMore ();
734 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
735 result.GetOutputStream().IndentLess ();
736 }
737 else
738 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000739 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
740 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000741 }
742 }
743 result.SetStatus (eReturnStatusSuccessFinishResult);
744 }
745 else
746 {
747 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
748 result.SetStatus (eReturnStatusFailed);
749 }
750
751 }
752 }
753 }
754
755 return result.Succeeded();
756}
757
758//-------------------------------------------------------------------------
759// CommandObjectBreakpointCommand
760//-------------------------------------------------------------------------
761
Greg Clayton63094e02010-06-23 01:19:29 +0000762CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000763 CommandObjectMultiword (interpreter,
764 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000765 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
766 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
767{
768 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000769 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
Caroline Ticeb2203882011-05-22 07:14:46 +0000770 CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
Greg Clayton238c0a12010-09-18 01:14:36 +0000771 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000772
773 add_command_object->SetCommandName ("breakpoint command add");
Caroline Ticeb2203882011-05-22 07:14:46 +0000774 delete_command_object->SetCommandName ("breakpoint command delete");
Chris Lattner24943d22010-06-08 16:52:24 +0000775 list_command_object->SetCommandName ("breakpoint command list");
776
Greg Clayton238c0a12010-09-18 01:14:36 +0000777 status = LoadSubCommand ("add", add_command_object);
Caroline Ticeb2203882011-05-22 07:14:46 +0000778 status = LoadSubCommand ("delete", delete_command_object);
Greg Clayton238c0a12010-09-18 01:14:36 +0000779 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000780}
781
782
783CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
784{
785}
786
787bool
788CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
789(
790 void *baton,
791 StoppointCallbackContext *context,
792 lldb::user_id_t break_id,
793 lldb::user_id_t break_loc_id
794)
795{
796 bool ret_value = true;
797 if (baton == NULL)
798 return true;
799
800
801 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
802 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000803
Chris Lattner24943d22010-06-08 16:52:24 +0000804 if (commands.GetSize() > 0)
805 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000806 Target *target = context->exe_ctx.GetTargetPtr();
807 if (target)
Chris Lattner24943d22010-06-08 16:52:24 +0000808 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000809 CommandReturnObject result;
Greg Clayton567e7f32011-09-22 04:58:26 +0000810 Debugger &debugger = target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000811 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
812 // if the debugger is set up that way.
813
Jim Inghame5ed8e92011-06-02 23:58:26 +0000814 StreamSP output_stream (debugger.GetAsyncOutputStream());
815 StreamSP error_stream (debugger.GetAsyncErrorStream());
Caroline Tice845d6da2011-05-16 19:20:50 +0000816 result.SetImmediateOutputStream (output_stream);
817 result.SetImmediateErrorStream (error_stream);
818
Jim Ingham949d5ac2011-02-18 00:54:25 +0000819 bool stop_on_continue = true;
820 bool echo_commands = false;
821 bool print_results = true;
822
823 debugger.GetCommandInterpreter().HandleCommands (commands,
824 &(context->exe_ctx),
825 stop_on_continue,
826 data->stop_on_error,
827 echo_commands,
828 print_results,
829 result);
Caroline Tice845d6da2011-05-16 19:20:50 +0000830 result.GetImmediateOutputStream()->Flush();
831 result.GetImmediateErrorStream()->Flush();
832 }
Chris Lattner24943d22010-06-08 16:52:24 +0000833 }
834 return ret_value;
835}
836