blob: 16466481fcf6fba8a4cbfea74c98b269fec2575f [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)
93 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +000094 case 'o':
Jim Ingham949d5ac2011-02-18 00:54:25 +000095 m_use_one_liner = true;
96 m_one_liner = option_arg;
97 break;
98 break;
Chris Lattner24943d22010-06-08 16:52:24 +000099 case 's':
Jim Ingham949d5ac2011-02-18 00:54:25 +0000100 {
101 bool found_one = false;
102 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
103 g_option_table[option_idx].enum_values,
104 eScriptLanguageNone,
105 &found_one);
106 if (!found_one)
107 error.SetErrorStringWithFormat("Invalid enumeration value '%s' for option '%c'.\n",
108 option_arg,
109 short_option);
110
111 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
112 {
113 m_use_commands = false;
114 m_use_script_language = true;
115 }
116 else
117 {
118 m_use_commands = true;
119 m_use_script_language = false;
120 }
121 }
122 break;
123 case 'e':
124 bool success_ptr;
125 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success_ptr);
126 if (!success_ptr)
127 error.SetErrorStringWithFormat("Invalid value for stop-on-error: \"%s\".\n", option_arg);
128 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000129 default:
Jim Ingham949d5ac2011-02-18 00:54:25 +0000130 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000131 }
132 return error;
133}
134
135void
Greg Clayton143fcc32011-04-13 00:18:08 +0000136CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000137{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000138 m_use_commands = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000139 m_use_script_language = false;
140 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000141
142 m_use_one_liner = false;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000143 m_stop_on_error = true;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000144 m_one_liner.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000145}
146
147//-------------------------------------------------------------------------
148// CommandObjectBreakpointCommandAdd
149//-------------------------------------------------------------------------
150
151
Greg Clayton238c0a12010-09-18 01:14:36 +0000152CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
153 CommandObject (interpreter,
154 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000155 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000156 NULL),
157 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000158{
159 SetHelpLong (
160"\nGeneral information about entering breakpoint commands \n\
161------------------------------------------------------ \n\
162 \n\
163This command will cause you to be prompted to enter the command or set \n\
164of commands you wish to be executed when the specified breakpoint is \n\
165hit. You will be told to enter your command(s), and will see a '> ' \n\
166prompt. Because you can enter one or many commands to be executed when \n\
167a breakpoint is hit, you will continue to be prompted after each \n\
168new-line that you enter, until you enter the word 'DONE', which will \n\
169cause the commands you have entered to be stored with the breakpoint \n\
170and executed when the breakpoint is hit. \n\
171 \n\
172Syntax checking is not necessarily done when breakpoint commands are \n\
173entered. An improperly written breakpoint command will attempt to get \n\
174executed when the breakpoint gets hit, and usually silently fail. If \n\
175your breakpoint command does not appear to be getting executed, go \n\
176back and check your syntax. \n\
177 \n\
178 \n\
179Special information about PYTHON breakpoint commands \n\
180---------------------------------------------------- \n\
181 \n\
182You may enter either one line of Python or multiple lines of Python \n\
183(including defining whole functions, if desired). If you enter a \n\
184single line of Python, that will be passed to the Python interpreter \n\
185'as is' when the breakpoint gets hit. If you enter function \n\
186definitions, they will be passed to the Python interpreter as soon as \n\
187you finish entering the breakpoint command, and they can be called \n\
188later (don't forget to add calls to them, if you want them called when \n\
189the breakpoint is hit). If you enter multiple lines of Python that \n\
190are not function definitions, they will be collected into a new, \n\
191automatically generated Python function, and a call to the newly \n\
192generated function will be attached to the breakpoint. Important \n\
193Note: Because loose Python code gets collected into functions, if you \n\
194want to access global variables in the 'loose' code, you need to \n\
195specify that they are global, using the 'global' keyword. Be sure to \n\
196use correct Python syntax, including indentation, when entering Python \n\
197breakpoint commands. \n\
198 \n\
199Example Python one-line breakpoint command: \n\
200 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000201(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000202Enter your Python command(s). Type 'DONE' to end. \n\
203> print \"Hit this breakpoint!\" \n\
204> DONE \n\
205 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000206As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000207(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000208(lldb) run \n\
209Launching '.../a.out' (x86_64) \n\
210(lldb) Fri Sep 10 12:17:45 2010 \n\
211Process 21778 Stopped \n\
212* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
213 36 \n\
214 37 int c(int val)\n\
215 38 {\n\
216 39 -> return val + 3;\n\
217 40 }\n\
218 41 \n\
219 42 int main (int argc, char const *argv[])\n\
220(lldb) \n\
221 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000222Example multiple line Python breakpoint command, using function definition: \n\
223 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000224(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000225Enter your Python command(s). Type 'DONE' to end. \n\
226> def breakpoint_output (bp_no): \n\
227> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
228> print out_string \n\
229> return True \n\
230> breakpoint_output (1) \n\
231> DONE \n\
232 \n\
233 \n\
234Example multiple line Python breakpoint command, using 'loose' Python: \n\
235 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000236(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000237Enter your Python command(s). Type 'DONE' to end. \n\
238> global bp_count \n\
239> bp_count = bp_count + 1 \n\
240> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
241> DONE \n\
242 \n\
243In this case, since there is a reference to a global variable, \n\
244'bp_count', you will also need to make sure 'bp_count' exists and is \n\
245initialized: \n\
246 \n\
247(lldb) script \n\
248>>> bp_count = 0 \n\
249>>> quit() \n\
250 \n\
251(lldb) \n\
252 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000253 \n\
254Final Note: If you get a warning that no breakpoint command was generated, \n\
255but you did not get any syntax errors, you probably forgot to add a call \n\
256to your functions. \n\
257 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000258Special information about debugger command breakpoint commands \n\
259-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000260 \n\
261You may enter any debugger command, exactly as you would at the \n\
262debugger prompt. You may enter as many debugger commands as you like, \n\
263but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000264
265
266 CommandArgumentEntry arg;
267 CommandArgumentData bp_id_arg;
268
269 // Define the first (and only) variant of this arg.
270 bp_id_arg.arg_type = eArgTypeBreakpointID;
271 bp_id_arg.arg_repetition = eArgRepeatPlain;
272
273 // There is only one variant this argument could be; put it into the argument entry.
274 arg.push_back (bp_id_arg);
275
276 // Push the data for the first argument into the m_arguments vector.
277 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000278}
279
280CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
281{
282}
283
284bool
285CommandObjectBreakpointCommandAdd::Execute
286(
287 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000288 CommandReturnObject &result
289)
290{
Greg Clayton238c0a12010-09-18 01:14:36 +0000291 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000292
293 if (target == NULL)
294 {
295 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
296 result.SetStatus (eReturnStatusFailed);
297 return false;
298 }
299
300 const BreakpointList &breakpoints = target->GetBreakpointList();
301 size_t num_breakpoints = breakpoints.GetSize();
302
303 if (num_breakpoints == 0)
304 {
305 result.AppendError ("No breakpoints exist to have commands added");
306 result.SetStatus (eReturnStatusFailed);
307 return false;
308 }
309
Chris Lattner24943d22010-06-08 16:52:24 +0000310 BreakpointIDList valid_bp_ids;
311 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
312
313 if (result.Succeeded())
314 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000315 const size_t count = valid_bp_ids.GetSize();
316 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000317 {
318 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
319 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
320 {
321 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000322 BreakpointOptions *bp_options = NULL;
323 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
324 {
325 // This breakpoint does not have an associated location.
326 bp_options = bp->GetOptions();
327 }
328 else
Chris Lattner24943d22010-06-08 16:52:24 +0000329 {
330 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000331 // This breakpoint does have an associated location.
332 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000333 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000334 bp_options = bp_loc_sp->GetLocationOptions();
335 }
336
Jim Ingham949d5ac2011-02-18 00:54:25 +0000337 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000338 if (bp_options == NULL) continue;
339
340 // If we are using script language, get the script interpreter
341 // in order to set or collect command callback. Otherwise, call
342 // the methods associated with this object.
343 if (m_options.m_use_script_language)
344 {
345 // Special handling for one-liner specified inline.
346 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000347 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
348 m_options.m_one_liner.c_str());
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000349 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000350 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
351 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000352 }
353 else
354 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000355 // Special handling for one-liner specified inline.
356 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000357 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000358 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000359 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000360 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000361 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000362 }
363 }
364 }
365 }
366
367 return result.Succeeded();
368}
369
370Options *
371CommandObjectBreakpointCommandAdd::GetOptions ()
372{
373 return &m_options;
374}
375
376const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
377
378void
379CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
380(
381 BreakpointOptions *bp_options,
382 CommandReturnObject &result
383)
384{
Greg Clayton238c0a12010-09-18 01:14:36 +0000385 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000386 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
387 if (reader_sp && data_ap.get())
388 {
389 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
390 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
391
392 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
393 bp_options, // baton
394 eInputReaderGranularityLine, // token size, to pass to callback function
395 "DONE", // end token
396 "> ", // prompt
397 true)); // echo input
398 if (err.Success())
399 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000400 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000401 result.SetStatus (eReturnStatusSuccessFinishNoResult);
402 }
403 else
404 {
405 result.AppendError (err.AsCString());
406 result.SetStatus (eReturnStatusFailed);
407 }
408 }
409 else
410 {
411 result.AppendError("out of memory");
412 result.SetStatus (eReturnStatusFailed);
413 }
414
415}
416
Johnny Chen3e0571b2010-09-11 00:23:59 +0000417// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000418void
Greg Clayton238c0a12010-09-18 01:14:36 +0000419CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000420 const char *oneliner)
421{
422 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
423
424 // It's necessary to set both user_source and script_source to the oneliner.
425 // The former is used to generate callback description (as in breakpoint command list)
426 // while the latter is used for Python to interpret during the actual callback.
427 data_ap->user_source.AppendString (oneliner);
428 data_ap->script_source.AppendString (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000429 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000430
431 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
432 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
433
434 return;
435}
436
Chris Lattner24943d22010-06-08 16:52:24 +0000437size_t
438CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
439(
440 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000441 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000442 lldb::InputReaderAction notification,
443 const char *bytes,
444 size_t bytes_len
445)
446{
Greg Clayton58928562011-02-09 01:08:52 +0000447 File &out_file = reader.GetDebugger().GetOutputFile();
Chris Lattner24943d22010-06-08 16:52:24 +0000448
449 switch (notification)
450 {
451 case eInputReaderActivate:
Greg Clayton58928562011-02-09 01:08:52 +0000452 out_file.Printf ("%s\n", g_reader_instructions);
453 if (reader.GetPrompt())
454 out_file.Printf ("%s", reader.GetPrompt());
455 out_file.Flush();
Chris Lattner24943d22010-06-08 16:52:24 +0000456 break;
457
458 case eInputReaderDeactivate:
459 break;
460
461 case eInputReaderReactivate:
Greg Clayton58928562011-02-09 01:08:52 +0000462 if (reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000463 {
Greg Clayton58928562011-02-09 01:08:52 +0000464 out_file.Printf ("%s", reader.GetPrompt());
465 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000466 }
Chris Lattner24943d22010-06-08 16:52:24 +0000467 break;
468
Caroline Tice4a348082011-05-02 20:41:46 +0000469 case eInputReaderAsynchronousOutputWritten:
470 break;
471
Chris Lattner24943d22010-06-08 16:52:24 +0000472 case eInputReaderGotToken:
473 if (bytes && bytes_len && baton)
474 {
475 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
476 if (bp_options)
477 {
478 Baton *bp_options_baton = bp_options->GetBaton();
479 if (bp_options_baton)
480 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
481 }
482 }
Greg Clayton58928562011-02-09 01:08:52 +0000483 if (!reader.IsDone() && reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000484 {
Greg Clayton58928562011-02-09 01:08:52 +0000485 out_file.Printf ("%s", reader.GetPrompt());
486 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000487 }
Chris Lattner24943d22010-06-08 16:52:24 +0000488 break;
489
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000490 case eInputReaderInterrupt:
491 {
492 // Finish, and cancel the breakpoint command.
493 reader.SetIsDone (true);
494 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
495 if (bp_options)
496 {
497 Baton *bp_options_baton = bp_options->GetBaton ();
498 if (bp_options_baton)
499 {
500 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
501 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
502 }
503 }
Greg Clayton58928562011-02-09 01:08:52 +0000504 out_file.Printf ("Warning: No command attached to breakpoint.\n");
505 out_file.Flush();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000506 }
507 break;
508
509 case eInputReaderEndOfFile:
510 reader.SetIsDone (true);
511 break;
512
Chris Lattner24943d22010-06-08 16:52:24 +0000513 case eInputReaderDone:
514 break;
515 }
516
517 return bytes_len;
518}
519
520
521//-------------------------------------------------------------------------
522// CommandObjectBreakpointCommandRemove
523//-------------------------------------------------------------------------
524
Greg Clayton238c0a12010-09-18 01:14:36 +0000525CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
526 CommandObject (interpreter,
527 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000528 "Remove the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000529 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000530{
Caroline Tice43b014a2010-10-04 22:28:36 +0000531 CommandArgumentEntry arg;
532 CommandArgumentData bp_id_arg;
533
534 // Define the first (and only) variant of this arg.
535 bp_id_arg.arg_type = eArgTypeBreakpointID;
536 bp_id_arg.arg_repetition = eArgRepeatPlain;
537
538 // There is only one variant this argument could be; put it into the argument entry.
539 arg.push_back (bp_id_arg);
540
541 // Push the data for the first argument into the m_arguments vector.
542 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000543}
544
545CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
546{
547}
548
549bool
Greg Clayton63094e02010-06-23 01:19:29 +0000550CommandObjectBreakpointCommandRemove::Execute
551(
Greg Clayton63094e02010-06-23 01:19:29 +0000552 Args& command,
553 CommandReturnObject &result
554)
Chris Lattner24943d22010-06-08 16:52:24 +0000555{
Greg Clayton238c0a12010-09-18 01:14:36 +0000556 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000557
558 if (target == NULL)
559 {
560 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
561 result.SetStatus (eReturnStatusFailed);
562 return false;
563 }
564
565 const BreakpointList &breakpoints = target->GetBreakpointList();
566 size_t num_breakpoints = breakpoints.GetSize();
567
568 if (num_breakpoints == 0)
569 {
570 result.AppendError ("No breakpoints exist to have commands removed");
571 result.SetStatus (eReturnStatusFailed);
572 return false;
573 }
574
575 if (command.GetArgumentCount() == 0)
576 {
577 result.AppendError ("No breakpoint specified from which to remove the commands");
578 result.SetStatus (eReturnStatusFailed);
579 return false;
580 }
581
582 BreakpointIDList valid_bp_ids;
583 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
584
585 if (result.Succeeded())
586 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000587 const size_t count = valid_bp_ids.GetSize();
588 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000589 {
590 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
591 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
592 {
593 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
594 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
595 {
596 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
597 if (bp_loc_sp)
598 bp_loc_sp->ClearCallback();
599 else
600 {
601 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
602 cur_bp_id.GetBreakpointID(),
603 cur_bp_id.GetLocationID());
604 result.SetStatus (eReturnStatusFailed);
605 return false;
606 }
607 }
608 else
609 {
610 bp->ClearCallback();
611 }
612 }
613 }
614 }
615 return result.Succeeded();
616}
617
618
619//-------------------------------------------------------------------------
620// CommandObjectBreakpointCommandList
621//-------------------------------------------------------------------------
622
Greg Clayton238c0a12010-09-18 01:14:36 +0000623CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
624 CommandObject (interpreter,
625 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000626 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000627 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000628{
Caroline Tice43b014a2010-10-04 22:28:36 +0000629 CommandArgumentEntry arg;
630 CommandArgumentData bp_id_arg;
631
632 // Define the first (and only) variant of this arg.
633 bp_id_arg.arg_type = eArgTypeBreakpointID;
634 bp_id_arg.arg_repetition = eArgRepeatPlain;
635
636 // There is only one variant this argument could be; put it into the argument entry.
637 arg.push_back (bp_id_arg);
638
639 // Push the data for the first argument into the m_arguments vector.
640 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000641}
642
643CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
644{
645}
646
647bool
Greg Clayton63094e02010-06-23 01:19:29 +0000648CommandObjectBreakpointCommandList::Execute
649(
Greg Clayton63094e02010-06-23 01:19:29 +0000650 Args& command,
651 CommandReturnObject &result
652)
Chris Lattner24943d22010-06-08 16:52:24 +0000653{
Greg Clayton238c0a12010-09-18 01:14:36 +0000654 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000655
656 if (target == NULL)
657 {
658 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
659 result.SetStatus (eReturnStatusFailed);
660 return false;
661 }
662
663 const BreakpointList &breakpoints = target->GetBreakpointList();
664 size_t num_breakpoints = breakpoints.GetSize();
665
666 if (num_breakpoints == 0)
667 {
668 result.AppendError ("No breakpoints exist for which to list commands");
669 result.SetStatus (eReturnStatusFailed);
670 return false;
671 }
672
673 if (command.GetArgumentCount() == 0)
674 {
675 result.AppendError ("No breakpoint specified for which to list the commands");
676 result.SetStatus (eReturnStatusFailed);
677 return false;
678 }
679
680 BreakpointIDList valid_bp_ids;
681 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
682
683 if (result.Succeeded())
684 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000685 const size_t count = valid_bp_ids.GetSize();
686 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000687 {
688 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
689 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
690 {
691 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
692
693 if (bp)
694 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000695 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000696 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
697 {
698 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
699 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000700 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000701 else
702 {
703 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
704 cur_bp_id.GetBreakpointID(),
705 cur_bp_id.GetLocationID());
706 result.SetStatus (eReturnStatusFailed);
707 return false;
708 }
709 }
710 else
711 {
712 bp_options = bp->GetOptions();
713 }
714
715 if (bp_options)
716 {
717 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000718 BreakpointID::GetCanonicalReference (&id_str,
719 cur_bp_id.GetBreakpointID(),
720 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000721 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000722 if (baton)
723 {
724 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
725 result.GetOutputStream().IndentMore ();
726 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
727 result.GetOutputStream().IndentLess ();
728 }
729 else
730 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000731 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
732 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000733 }
734 }
735 result.SetStatus (eReturnStatusSuccessFinishResult);
736 }
737 else
738 {
739 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
740 result.SetStatus (eReturnStatusFailed);
741 }
742
743 }
744 }
745 }
746
747 return result.Succeeded();
748}
749
750//-------------------------------------------------------------------------
751// CommandObjectBreakpointCommand
752//-------------------------------------------------------------------------
753
Greg Clayton63094e02010-06-23 01:19:29 +0000754CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000755 CommandObjectMultiword (interpreter,
756 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000757 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
758 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
759{
760 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000761 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
762 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
763 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000764
765 add_command_object->SetCommandName ("breakpoint command add");
766 remove_command_object->SetCommandName ("breakpoint command remove");
767 list_command_object->SetCommandName ("breakpoint command list");
768
Greg Clayton238c0a12010-09-18 01:14:36 +0000769 status = LoadSubCommand ("add", add_command_object);
770 status = LoadSubCommand ("remove", remove_command_object);
771 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000772}
773
774
775CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
776{
777}
778
779bool
780CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
781(
782 void *baton,
783 StoppointCallbackContext *context,
784 lldb::user_id_t break_id,
785 lldb::user_id_t break_loc_id
786)
787{
788 bool ret_value = true;
789 if (baton == NULL)
790 return true;
791
792
793 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
794 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000795
Chris Lattner24943d22010-06-08 16:52:24 +0000796 if (commands.GetSize() > 0)
797 {
Greg Clayton63094e02010-06-23 01:19:29 +0000798 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000799 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000800 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000801 Debugger &debugger = context->exe_ctx.target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000802 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
803 // if the debugger is set up that way.
804
805 result.SetImmediateOutputFile (debugger.GetOutputFile().GetStream());
806 result.SetImmediateErrorFile (debugger.GetErrorFile().GetStream());
807
Jim Ingham949d5ac2011-02-18 00:54:25 +0000808 bool stop_on_continue = true;
809 bool echo_commands = false;
810 bool print_results = true;
811
812 debugger.GetCommandInterpreter().HandleCommands (commands,
813 &(context->exe_ctx),
814 stop_on_continue,
815 data->stop_on_error,
816 echo_commands,
817 print_results,
818 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000819 }
Chris Lattner24943d22010-06-08 16:52:24 +0000820 }
821 return ret_value;
822}
823