blob: a188baebdeb556d2ee05f7b75c83ca4df0a30380 [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
469 case eInputReaderGotToken:
470 if (bytes && bytes_len && baton)
471 {
472 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
473 if (bp_options)
474 {
475 Baton *bp_options_baton = bp_options->GetBaton();
476 if (bp_options_baton)
477 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
478 }
479 }
Greg Clayton58928562011-02-09 01:08:52 +0000480 if (!reader.IsDone() && reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000481 {
Greg Clayton58928562011-02-09 01:08:52 +0000482 out_file.Printf ("%s", reader.GetPrompt());
483 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000484 }
Chris Lattner24943d22010-06-08 16:52:24 +0000485 break;
486
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000487 case eInputReaderInterrupt:
488 {
489 // Finish, and cancel the breakpoint command.
490 reader.SetIsDone (true);
491 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
492 if (bp_options)
493 {
494 Baton *bp_options_baton = bp_options->GetBaton ();
495 if (bp_options_baton)
496 {
497 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
498 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
499 }
500 }
Greg Clayton58928562011-02-09 01:08:52 +0000501 out_file.Printf ("Warning: No command attached to breakpoint.\n");
502 out_file.Flush();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000503 }
504 break;
505
506 case eInputReaderEndOfFile:
507 reader.SetIsDone (true);
508 break;
509
Chris Lattner24943d22010-06-08 16:52:24 +0000510 case eInputReaderDone:
511 break;
512 }
513
514 return bytes_len;
515}
516
517
518//-------------------------------------------------------------------------
519// CommandObjectBreakpointCommandRemove
520//-------------------------------------------------------------------------
521
Greg Clayton238c0a12010-09-18 01:14:36 +0000522CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
523 CommandObject (interpreter,
524 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000525 "Remove the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000526 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000527{
Caroline Tice43b014a2010-10-04 22:28:36 +0000528 CommandArgumentEntry arg;
529 CommandArgumentData bp_id_arg;
530
531 // Define the first (and only) variant of this arg.
532 bp_id_arg.arg_type = eArgTypeBreakpointID;
533 bp_id_arg.arg_repetition = eArgRepeatPlain;
534
535 // There is only one variant this argument could be; put it into the argument entry.
536 arg.push_back (bp_id_arg);
537
538 // Push the data for the first argument into the m_arguments vector.
539 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000540}
541
542CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
543{
544}
545
546bool
Greg Clayton63094e02010-06-23 01:19:29 +0000547CommandObjectBreakpointCommandRemove::Execute
548(
Greg Clayton63094e02010-06-23 01:19:29 +0000549 Args& command,
550 CommandReturnObject &result
551)
Chris Lattner24943d22010-06-08 16:52:24 +0000552{
Greg Clayton238c0a12010-09-18 01:14:36 +0000553 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000554
555 if (target == NULL)
556 {
557 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
558 result.SetStatus (eReturnStatusFailed);
559 return false;
560 }
561
562 const BreakpointList &breakpoints = target->GetBreakpointList();
563 size_t num_breakpoints = breakpoints.GetSize();
564
565 if (num_breakpoints == 0)
566 {
567 result.AppendError ("No breakpoints exist to have commands removed");
568 result.SetStatus (eReturnStatusFailed);
569 return false;
570 }
571
572 if (command.GetArgumentCount() == 0)
573 {
574 result.AppendError ("No breakpoint specified from which to remove the commands");
575 result.SetStatus (eReturnStatusFailed);
576 return false;
577 }
578
579 BreakpointIDList valid_bp_ids;
580 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
581
582 if (result.Succeeded())
583 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000584 const size_t count = valid_bp_ids.GetSize();
585 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000586 {
587 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
588 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
589 {
590 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
591 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
592 {
593 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
594 if (bp_loc_sp)
595 bp_loc_sp->ClearCallback();
596 else
597 {
598 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
599 cur_bp_id.GetBreakpointID(),
600 cur_bp_id.GetLocationID());
601 result.SetStatus (eReturnStatusFailed);
602 return false;
603 }
604 }
605 else
606 {
607 bp->ClearCallback();
608 }
609 }
610 }
611 }
612 return result.Succeeded();
613}
614
615
616//-------------------------------------------------------------------------
617// CommandObjectBreakpointCommandList
618//-------------------------------------------------------------------------
619
Greg Clayton238c0a12010-09-18 01:14:36 +0000620CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
621 CommandObject (interpreter,
622 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000623 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000624 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000625{
Caroline Tice43b014a2010-10-04 22:28:36 +0000626 CommandArgumentEntry arg;
627 CommandArgumentData bp_id_arg;
628
629 // Define the first (and only) variant of this arg.
630 bp_id_arg.arg_type = eArgTypeBreakpointID;
631 bp_id_arg.arg_repetition = eArgRepeatPlain;
632
633 // There is only one variant this argument could be; put it into the argument entry.
634 arg.push_back (bp_id_arg);
635
636 // Push the data for the first argument into the m_arguments vector.
637 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000638}
639
640CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
641{
642}
643
644bool
Greg Clayton63094e02010-06-23 01:19:29 +0000645CommandObjectBreakpointCommandList::Execute
646(
Greg Clayton63094e02010-06-23 01:19:29 +0000647 Args& command,
648 CommandReturnObject &result
649)
Chris Lattner24943d22010-06-08 16:52:24 +0000650{
Greg Clayton238c0a12010-09-18 01:14:36 +0000651 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000652
653 if (target == NULL)
654 {
655 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
656 result.SetStatus (eReturnStatusFailed);
657 return false;
658 }
659
660 const BreakpointList &breakpoints = target->GetBreakpointList();
661 size_t num_breakpoints = breakpoints.GetSize();
662
663 if (num_breakpoints == 0)
664 {
665 result.AppendError ("No breakpoints exist for which to list commands");
666 result.SetStatus (eReturnStatusFailed);
667 return false;
668 }
669
670 if (command.GetArgumentCount() == 0)
671 {
672 result.AppendError ("No breakpoint specified for which to list the commands");
673 result.SetStatus (eReturnStatusFailed);
674 return false;
675 }
676
677 BreakpointIDList valid_bp_ids;
678 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
679
680 if (result.Succeeded())
681 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000682 const size_t count = valid_bp_ids.GetSize();
683 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000684 {
685 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
686 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
687 {
688 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
689
690 if (bp)
691 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000692 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000693 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
694 {
695 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
696 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000697 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000698 else
699 {
700 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
701 cur_bp_id.GetBreakpointID(),
702 cur_bp_id.GetLocationID());
703 result.SetStatus (eReturnStatusFailed);
704 return false;
705 }
706 }
707 else
708 {
709 bp_options = bp->GetOptions();
710 }
711
712 if (bp_options)
713 {
714 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000715 BreakpointID::GetCanonicalReference (&id_str,
716 cur_bp_id.GetBreakpointID(),
717 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000718 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000719 if (baton)
720 {
721 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
722 result.GetOutputStream().IndentMore ();
723 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
724 result.GetOutputStream().IndentLess ();
725 }
726 else
727 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000728 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
729 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000730 }
731 }
732 result.SetStatus (eReturnStatusSuccessFinishResult);
733 }
734 else
735 {
736 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
737 result.SetStatus (eReturnStatusFailed);
738 }
739
740 }
741 }
742 }
743
744 return result.Succeeded();
745}
746
747//-------------------------------------------------------------------------
748// CommandObjectBreakpointCommand
749//-------------------------------------------------------------------------
750
Greg Clayton63094e02010-06-23 01:19:29 +0000751CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000752 CommandObjectMultiword (interpreter,
753 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000754 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
755 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
756{
757 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000758 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
759 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
760 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000761
762 add_command_object->SetCommandName ("breakpoint command add");
763 remove_command_object->SetCommandName ("breakpoint command remove");
764 list_command_object->SetCommandName ("breakpoint command list");
765
Greg Clayton238c0a12010-09-18 01:14:36 +0000766 status = LoadSubCommand ("add", add_command_object);
767 status = LoadSubCommand ("remove", remove_command_object);
768 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000769}
770
771
772CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
773{
774}
775
776bool
777CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
778(
779 void *baton,
780 StoppointCallbackContext *context,
781 lldb::user_id_t break_id,
782 lldb::user_id_t break_loc_id
783)
784{
785 bool ret_value = true;
786 if (baton == NULL)
787 return true;
788
789
790 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
791 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000792
Chris Lattner24943d22010-06-08 16:52:24 +0000793 if (commands.GetSize() > 0)
794 {
Greg Clayton63094e02010-06-23 01:19:29 +0000795 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000796 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000797 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000798 Debugger &debugger = context->exe_ctx.target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000799 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
800 // if the debugger is set up that way.
801
802 result.SetImmediateOutputFile (debugger.GetOutputFile().GetStream());
803 result.SetImmediateErrorFile (debugger.GetErrorFile().GetStream());
804
Jim Ingham949d5ac2011-02-18 00:54:25 +0000805 bool stop_on_continue = true;
806 bool echo_commands = false;
807 bool print_results = true;
808
809 debugger.GetCommandInterpreter().HandleCommands (commands,
810 &(context->exe_ctx),
811 stop_on_continue,
812 data->stop_on_error,
813 echo_commands,
814 print_results,
815 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000816 }
Chris Lattner24943d22010-06-08 16:52:24 +0000817 }
818 return ret_value;
819}
820