blob: de725a6504683472050f82e65606cc1cb73c8d2f [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{
Greg Clayton58928562011-02-09 01:08:52 +0000448 File &out_file = reader.GetDebugger().GetOutputFile();
Chris Lattner24943d22010-06-08 16:52:24 +0000449
450 switch (notification)
451 {
452 case eInputReaderActivate:
Greg Clayton58928562011-02-09 01:08:52 +0000453 out_file.Printf ("%s\n", g_reader_instructions);
454 if (reader.GetPrompt())
455 out_file.Printf ("%s", reader.GetPrompt());
456 out_file.Flush();
Chris Lattner24943d22010-06-08 16:52:24 +0000457 break;
458
459 case eInputReaderDeactivate:
460 break;
461
462 case eInputReaderReactivate:
Greg Clayton58928562011-02-09 01:08:52 +0000463 if (reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000464 {
Greg Clayton58928562011-02-09 01:08:52 +0000465 out_file.Printf ("%s", reader.GetPrompt());
466 out_file.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 }
Greg Clayton58928562011-02-09 01:08:52 +0000484 if (!reader.IsDone() && reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000485 {
Greg Clayton58928562011-02-09 01:08:52 +0000486 out_file.Printf ("%s", reader.GetPrompt());
487 out_file.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 }
Greg Clayton58928562011-02-09 01:08:52 +0000505 out_file.Printf ("Warning: No command attached to breakpoint.\n");
506 out_file.Flush();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000507 }
508 break;
509
510 case eInputReaderEndOfFile:
511 reader.SetIsDone (true);
512 break;
513
Chris Lattner24943d22010-06-08 16:52:24 +0000514 case eInputReaderDone:
515 break;
516 }
517
518 return bytes_len;
519}
520
521
522//-------------------------------------------------------------------------
523// CommandObjectBreakpointCommandRemove
524//-------------------------------------------------------------------------
525
Greg Clayton238c0a12010-09-18 01:14:36 +0000526CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
527 CommandObject (interpreter,
528 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000529 "Remove the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000530 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000531{
Caroline Tice43b014a2010-10-04 22:28:36 +0000532 CommandArgumentEntry arg;
533 CommandArgumentData bp_id_arg;
534
535 // Define the first (and only) variant of this arg.
536 bp_id_arg.arg_type = eArgTypeBreakpointID;
537 bp_id_arg.arg_repetition = eArgRepeatPlain;
538
539 // There is only one variant this argument could be; put it into the argument entry.
540 arg.push_back (bp_id_arg);
541
542 // Push the data for the first argument into the m_arguments vector.
543 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000544}
545
546CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
547{
548}
549
550bool
Greg Clayton63094e02010-06-23 01:19:29 +0000551CommandObjectBreakpointCommandRemove::Execute
552(
Greg Clayton63094e02010-06-23 01:19:29 +0000553 Args& command,
554 CommandReturnObject &result
555)
Chris Lattner24943d22010-06-08 16:52:24 +0000556{
Greg Clayton238c0a12010-09-18 01:14:36 +0000557 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000558
559 if (target == NULL)
560 {
561 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
562 result.SetStatus (eReturnStatusFailed);
563 return false;
564 }
565
566 const BreakpointList &breakpoints = target->GetBreakpointList();
567 size_t num_breakpoints = breakpoints.GetSize();
568
569 if (num_breakpoints == 0)
570 {
571 result.AppendError ("No breakpoints exist to have commands removed");
572 result.SetStatus (eReturnStatusFailed);
573 return false;
574 }
575
576 if (command.GetArgumentCount() == 0)
577 {
578 result.AppendError ("No breakpoint specified from which to remove the commands");
579 result.SetStatus (eReturnStatusFailed);
580 return false;
581 }
582
583 BreakpointIDList valid_bp_ids;
584 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
585
586 if (result.Succeeded())
587 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000588 const size_t count = valid_bp_ids.GetSize();
589 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000590 {
591 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
592 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
593 {
594 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
595 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
596 {
597 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
598 if (bp_loc_sp)
599 bp_loc_sp->ClearCallback();
600 else
601 {
602 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
603 cur_bp_id.GetBreakpointID(),
604 cur_bp_id.GetLocationID());
605 result.SetStatus (eReturnStatusFailed);
606 return false;
607 }
608 }
609 else
610 {
611 bp->ClearCallback();
612 }
613 }
614 }
615 }
616 return result.Succeeded();
617}
618
619
620//-------------------------------------------------------------------------
621// CommandObjectBreakpointCommandList
622//-------------------------------------------------------------------------
623
Greg Clayton238c0a12010-09-18 01:14:36 +0000624CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
625 CommandObject (interpreter,
626 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000627 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000628 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000629{
Caroline Tice43b014a2010-10-04 22:28:36 +0000630 CommandArgumentEntry arg;
631 CommandArgumentData bp_id_arg;
632
633 // Define the first (and only) variant of this arg.
634 bp_id_arg.arg_type = eArgTypeBreakpointID;
635 bp_id_arg.arg_repetition = eArgRepeatPlain;
636
637 // There is only one variant this argument could be; put it into the argument entry.
638 arg.push_back (bp_id_arg);
639
640 // Push the data for the first argument into the m_arguments vector.
641 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000642}
643
644CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
645{
646}
647
648bool
Greg Clayton63094e02010-06-23 01:19:29 +0000649CommandObjectBreakpointCommandList::Execute
650(
Greg Clayton63094e02010-06-23 01:19:29 +0000651 Args& command,
652 CommandReturnObject &result
653)
Chris Lattner24943d22010-06-08 16:52:24 +0000654{
Greg Clayton238c0a12010-09-18 01:14:36 +0000655 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000656
657 if (target == NULL)
658 {
659 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
660 result.SetStatus (eReturnStatusFailed);
661 return false;
662 }
663
664 const BreakpointList &breakpoints = target->GetBreakpointList();
665 size_t num_breakpoints = breakpoints.GetSize();
666
667 if (num_breakpoints == 0)
668 {
669 result.AppendError ("No breakpoints exist for which to list commands");
670 result.SetStatus (eReturnStatusFailed);
671 return false;
672 }
673
674 if (command.GetArgumentCount() == 0)
675 {
676 result.AppendError ("No breakpoint specified for which to list the commands");
677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680
681 BreakpointIDList valid_bp_ids;
682 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
683
684 if (result.Succeeded())
685 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000686 const size_t count = valid_bp_ids.GetSize();
687 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000688 {
689 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
690 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
691 {
692 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
693
694 if (bp)
695 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000696 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000697 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
698 {
699 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
700 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000701 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000702 else
703 {
704 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
705 cur_bp_id.GetBreakpointID(),
706 cur_bp_id.GetLocationID());
707 result.SetStatus (eReturnStatusFailed);
708 return false;
709 }
710 }
711 else
712 {
713 bp_options = bp->GetOptions();
714 }
715
716 if (bp_options)
717 {
718 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000719 BreakpointID::GetCanonicalReference (&id_str,
720 cur_bp_id.GetBreakpointID(),
721 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000722 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000723 if (baton)
724 {
725 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
726 result.GetOutputStream().IndentMore ();
727 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
728 result.GetOutputStream().IndentLess ();
729 }
730 else
731 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000732 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
733 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000734 }
735 }
736 result.SetStatus (eReturnStatusSuccessFinishResult);
737 }
738 else
739 {
740 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
741 result.SetStatus (eReturnStatusFailed);
742 }
743
744 }
745 }
746 }
747
748 return result.Succeeded();
749}
750
751//-------------------------------------------------------------------------
752// CommandObjectBreakpointCommand
753//-------------------------------------------------------------------------
754
Greg Clayton63094e02010-06-23 01:19:29 +0000755CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000756 CommandObjectMultiword (interpreter,
757 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000758 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
759 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
760{
761 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000762 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
763 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
764 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000765
766 add_command_object->SetCommandName ("breakpoint command add");
767 remove_command_object->SetCommandName ("breakpoint command remove");
768 list_command_object->SetCommandName ("breakpoint command list");
769
Greg Clayton238c0a12010-09-18 01:14:36 +0000770 status = LoadSubCommand ("add", add_command_object);
771 status = LoadSubCommand ("remove", remove_command_object);
772 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000773}
774
775
776CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
777{
778}
779
780bool
781CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
782(
783 void *baton,
784 StoppointCallbackContext *context,
785 lldb::user_id_t break_id,
786 lldb::user_id_t break_loc_id
787)
788{
789 bool ret_value = true;
790 if (baton == NULL)
791 return true;
792
793
794 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
795 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000796
Chris Lattner24943d22010-06-08 16:52:24 +0000797 if (commands.GetSize() > 0)
798 {
Greg Clayton63094e02010-06-23 01:19:29 +0000799 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000800 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000801 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000802 Debugger &debugger = context->exe_ctx.target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000803 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
804 // if the debugger is set up that way.
805
Caroline Tice845d6da2011-05-16 19:20:50 +0000806 StreamSP output_stream (new StreamAsynchronousIO (debugger.GetCommandInterpreter(),
807 CommandInterpreter::eBroadcastBitAsynchronousOutputData));
808 StreamSP error_stream (new StreamAsynchronousIO (debugger.GetCommandInterpreter(),
809 CommandInterpreter::eBroadcastBitAsynchronousErrorData));
810 result.SetImmediateOutputStream (output_stream);
811 result.SetImmediateErrorStream (error_stream);
812
Jim Ingham949d5ac2011-02-18 00:54:25 +0000813 bool stop_on_continue = true;
814 bool echo_commands = false;
815 bool print_results = true;
816
817 debugger.GetCommandInterpreter().HandleCommands (commands,
818 &(context->exe_ctx),
819 stop_on_continue,
820 data->stop_on_error,
821 echo_commands,
822 print_results,
823 result);
Caroline Tice845d6da2011-05-16 19:20:50 +0000824 result.GetImmediateOutputStream()->Flush();
825 result.GetImmediateErrorStream()->Flush();
826 }
Chris Lattner24943d22010-06-08 16:52:24 +0000827 }
828 return ret_value;
829}
830