blob: edca869e48a1d508fd91503399157b9186e828a2 [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
34CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () :
Johnny Chenb81ed0d2010-09-11 00:18:09 +000035 Options (),
36 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
51static lldb::OptionEnumValueElement
52g_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
Chris Lattner24943d22010-06-08 16:52:24 +000060lldb::OptionDefinition
61CommandObjectBreakpointCommandAdd::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
75const lldb::OptionDefinition*
76CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
77{
78 return g_option_table;
79}
80
81
82Error
83CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
84(
85 int option_idx,
86 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
136CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
137{
138 Options::ResetOptionValues();
139
Jim Ingham949d5ac2011-02-18 00:54:25 +0000140 m_use_commands = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000141 m_use_script_language = false;
142 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000143
144 m_use_one_liner = false;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000145 m_stop_on_error = true;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000146 m_one_liner.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000147}
148
149//-------------------------------------------------------------------------
150// CommandObjectBreakpointCommandAdd
151//-------------------------------------------------------------------------
152
153
Greg Clayton238c0a12010-09-18 01:14:36 +0000154CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
155 CommandObject (interpreter,
156 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000157 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000158 NULL)
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
470 case eInputReaderGotToken:
471 if (bytes && bytes_len && baton)
472 {
473 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
474 if (bp_options)
475 {
476 Baton *bp_options_baton = bp_options->GetBaton();
477 if (bp_options_baton)
478 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
479 }
480 }
Greg Clayton58928562011-02-09 01:08:52 +0000481 if (!reader.IsDone() && reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000482 {
Greg Clayton58928562011-02-09 01:08:52 +0000483 out_file.Printf ("%s", reader.GetPrompt());
484 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000485 }
Chris Lattner24943d22010-06-08 16:52:24 +0000486 break;
487
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000488 case eInputReaderInterrupt:
489 {
490 // Finish, and cancel the breakpoint command.
491 reader.SetIsDone (true);
492 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
493 if (bp_options)
494 {
495 Baton *bp_options_baton = bp_options->GetBaton ();
496 if (bp_options_baton)
497 {
498 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
499 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
500 }
501 }
Greg Clayton58928562011-02-09 01:08:52 +0000502 out_file.Printf ("Warning: No command attached to breakpoint.\n");
503 out_file.Flush();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000504 }
505 break;
506
507 case eInputReaderEndOfFile:
508 reader.SetIsDone (true);
509 break;
510
Chris Lattner24943d22010-06-08 16:52:24 +0000511 case eInputReaderDone:
512 break;
513 }
514
515 return bytes_len;
516}
517
518
519//-------------------------------------------------------------------------
520// CommandObjectBreakpointCommandRemove
521//-------------------------------------------------------------------------
522
Greg Clayton238c0a12010-09-18 01:14:36 +0000523CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
524 CommandObject (interpreter,
525 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000526 "Remove the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000527 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000528{
Caroline Tice43b014a2010-10-04 22:28:36 +0000529 CommandArgumentEntry arg;
530 CommandArgumentData bp_id_arg;
531
532 // Define the first (and only) variant of this arg.
533 bp_id_arg.arg_type = eArgTypeBreakpointID;
534 bp_id_arg.arg_repetition = eArgRepeatPlain;
535
536 // There is only one variant this argument could be; put it into the argument entry.
537 arg.push_back (bp_id_arg);
538
539 // Push the data for the first argument into the m_arguments vector.
540 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000541}
542
543CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
544{
545}
546
547bool
Greg Clayton63094e02010-06-23 01:19:29 +0000548CommandObjectBreakpointCommandRemove::Execute
549(
Greg Clayton63094e02010-06-23 01:19:29 +0000550 Args& command,
551 CommandReturnObject &result
552)
Chris Lattner24943d22010-06-08 16:52:24 +0000553{
Greg Clayton238c0a12010-09-18 01:14:36 +0000554 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000555
556 if (target == NULL)
557 {
558 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
559 result.SetStatus (eReturnStatusFailed);
560 return false;
561 }
562
563 const BreakpointList &breakpoints = target->GetBreakpointList();
564 size_t num_breakpoints = breakpoints.GetSize();
565
566 if (num_breakpoints == 0)
567 {
568 result.AppendError ("No breakpoints exist to have commands removed");
569 result.SetStatus (eReturnStatusFailed);
570 return false;
571 }
572
573 if (command.GetArgumentCount() == 0)
574 {
575 result.AppendError ("No breakpoint specified from which to remove the commands");
576 result.SetStatus (eReturnStatusFailed);
577 return false;
578 }
579
580 BreakpointIDList valid_bp_ids;
581 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
582
583 if (result.Succeeded())
584 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000585 const size_t count = valid_bp_ids.GetSize();
586 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000587 {
588 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
589 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
590 {
591 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
592 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
593 {
594 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
595 if (bp_loc_sp)
596 bp_loc_sp->ClearCallback();
597 else
598 {
599 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
600 cur_bp_id.GetBreakpointID(),
601 cur_bp_id.GetLocationID());
602 result.SetStatus (eReturnStatusFailed);
603 return false;
604 }
605 }
606 else
607 {
608 bp->ClearCallback();
609 }
610 }
611 }
612 }
613 return result.Succeeded();
614}
615
616
617//-------------------------------------------------------------------------
618// CommandObjectBreakpointCommandList
619//-------------------------------------------------------------------------
620
Greg Clayton238c0a12010-09-18 01:14:36 +0000621CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
622 CommandObject (interpreter,
623 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000624 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000625 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000626{
Caroline Tice43b014a2010-10-04 22:28:36 +0000627 CommandArgumentEntry arg;
628 CommandArgumentData bp_id_arg;
629
630 // Define the first (and only) variant of this arg.
631 bp_id_arg.arg_type = eArgTypeBreakpointID;
632 bp_id_arg.arg_repetition = eArgRepeatPlain;
633
634 // There is only one variant this argument could be; put it into the argument entry.
635 arg.push_back (bp_id_arg);
636
637 // Push the data for the first argument into the m_arguments vector.
638 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000639}
640
641CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
642{
643}
644
645bool
Greg Clayton63094e02010-06-23 01:19:29 +0000646CommandObjectBreakpointCommandList::Execute
647(
Greg Clayton63094e02010-06-23 01:19:29 +0000648 Args& command,
649 CommandReturnObject &result
650)
Chris Lattner24943d22010-06-08 16:52:24 +0000651{
Greg Clayton238c0a12010-09-18 01:14:36 +0000652 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000653
654 if (target == NULL)
655 {
656 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
657 result.SetStatus (eReturnStatusFailed);
658 return false;
659 }
660
661 const BreakpointList &breakpoints = target->GetBreakpointList();
662 size_t num_breakpoints = breakpoints.GetSize();
663
664 if (num_breakpoints == 0)
665 {
666 result.AppendError ("No breakpoints exist for which to list commands");
667 result.SetStatus (eReturnStatusFailed);
668 return false;
669 }
670
671 if (command.GetArgumentCount() == 0)
672 {
673 result.AppendError ("No breakpoint specified for which to list the commands");
674 result.SetStatus (eReturnStatusFailed);
675 return false;
676 }
677
678 BreakpointIDList valid_bp_ids;
679 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
680
681 if (result.Succeeded())
682 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000683 const size_t count = valid_bp_ids.GetSize();
684 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000685 {
686 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
687 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
688 {
689 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
690
691 if (bp)
692 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000693 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000694 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
695 {
696 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
697 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000698 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000699 else
700 {
701 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
702 cur_bp_id.GetBreakpointID(),
703 cur_bp_id.GetLocationID());
704 result.SetStatus (eReturnStatusFailed);
705 return false;
706 }
707 }
708 else
709 {
710 bp_options = bp->GetOptions();
711 }
712
713 if (bp_options)
714 {
715 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000716 BreakpointID::GetCanonicalReference (&id_str,
717 cur_bp_id.GetBreakpointID(),
718 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000719 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000720 if (baton)
721 {
722 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
723 result.GetOutputStream().IndentMore ();
724 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
725 result.GetOutputStream().IndentLess ();
726 }
727 else
728 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000729 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
730 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000731 }
732 }
733 result.SetStatus (eReturnStatusSuccessFinishResult);
734 }
735 else
736 {
737 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
738 result.SetStatus (eReturnStatusFailed);
739 }
740
741 }
742 }
743 }
744
745 return result.Succeeded();
746}
747
748//-------------------------------------------------------------------------
749// CommandObjectBreakpointCommand
750//-------------------------------------------------------------------------
751
Greg Clayton63094e02010-06-23 01:19:29 +0000752CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000753 CommandObjectMultiword (interpreter,
754 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000755 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
756 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
757{
758 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000759 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
760 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
761 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000762
763 add_command_object->SetCommandName ("breakpoint command add");
764 remove_command_object->SetCommandName ("breakpoint command remove");
765 list_command_object->SetCommandName ("breakpoint command list");
766
Greg Clayton238c0a12010-09-18 01:14:36 +0000767 status = LoadSubCommand ("add", add_command_object);
768 status = LoadSubCommand ("remove", remove_command_object);
769 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000770}
771
772
773CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
774{
775}
776
777bool
778CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
779(
780 void *baton,
781 StoppointCallbackContext *context,
782 lldb::user_id_t break_id,
783 lldb::user_id_t break_loc_id
784)
785{
786 bool ret_value = true;
787 if (baton == NULL)
788 return true;
789
790
791 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
792 StringList &commands = data->user_source;
793
794 if (commands.GetSize() > 0)
795 {
Chris Lattner24943d22010-06-08 16:52:24 +0000796 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000797 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000798 {
Greg Clayton63094e02010-06-23 01:19:29 +0000799
800 Debugger &debugger = context->exe_ctx.target->GetDebugger();
Jim Ingham949d5ac2011-02-18 00:54:25 +0000801
802 bool stop_on_continue = true;
803 bool echo_commands = false;
804 bool print_results = true;
805
806 debugger.GetCommandInterpreter().HandleCommands (commands,
807 &(context->exe_ctx),
808 stop_on_continue,
809 data->stop_on_error,
810 echo_commands,
811 print_results,
812 result);
813 // Now dump the commands to the debugger's output:
814 if (!result.Succeeded())
Chris Lattner24943d22010-06-08 16:52:24 +0000815 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000816 debugger.GetErrorFile().Printf ("%s", result.GetErrorStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000817 }
Jim Ingham949d5ac2011-02-18 00:54:25 +0000818
819 debugger.GetOutputFile().Printf ("%s", result.GetOutputStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000820
Chris Lattner24943d22010-06-08 16:52:24 +0000821 }
Chris Lattner24943d22010-06-08 16:52:24 +0000822 }
823 return ret_value;
824}
825