blob: c3d50ea0209394081a26f2995a98ad057b1cb268 [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
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(
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{
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.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000156 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000157{
158 SetHelpLong (
159"\nGeneral information about entering breakpoint commands \n\
160------------------------------------------------------ \n\
161 \n\
162This command will cause you to be prompted to enter the command or set \n\
163of commands you wish to be executed when the specified breakpoint is \n\
164hit. You will be told to enter your command(s), and will see a '> ' \n\
165prompt. Because you can enter one or many commands to be executed when \n\
166a breakpoint is hit, you will continue to be prompted after each \n\
167new-line that you enter, until you enter the word 'DONE', which will \n\
168cause the commands you have entered to be stored with the breakpoint \n\
169and executed when the breakpoint is hit. \n\
170 \n\
171Syntax checking is not necessarily done when breakpoint commands are \n\
172entered. An improperly written breakpoint command will attempt to get \n\
173executed when the breakpoint gets hit, and usually silently fail. If \n\
174your breakpoint command does not appear to be getting executed, go \n\
175back and check your syntax. \n\
176 \n\
177 \n\
178Special information about PYTHON breakpoint commands \n\
179---------------------------------------------------- \n\
180 \n\
181You may enter either one line of Python or multiple lines of Python \n\
182(including defining whole functions, if desired). If you enter a \n\
183single line of Python, that will be passed to the Python interpreter \n\
184'as is' when the breakpoint gets hit. If you enter function \n\
185definitions, they will be passed to the Python interpreter as soon as \n\
186you finish entering the breakpoint command, and they can be called \n\
187later (don't forget to add calls to them, if you want them called when \n\
188the breakpoint is hit). If you enter multiple lines of Python that \n\
189are not function definitions, they will be collected into a new, \n\
190automatically generated Python function, and a call to the newly \n\
191generated function will be attached to the breakpoint. Important \n\
192Note: Because loose Python code gets collected into functions, if you \n\
193want to access global variables in the 'loose' code, you need to \n\
194specify that they are global, using the 'global' keyword. Be sure to \n\
195use correct Python syntax, including indentation, when entering Python \n\
196breakpoint commands. \n\
197 \n\
198Example Python one-line breakpoint command: \n\
199 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000200(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000201Enter your Python command(s). Type 'DONE' to end. \n\
202> print \"Hit this breakpoint!\" \n\
203> DONE \n\
204 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000205As a convenience, this also works for a short Python one-liner: \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000206(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000207(lldb) run \n\
208Launching '.../a.out' (x86_64) \n\
209(lldb) Fri Sep 10 12:17:45 2010 \n\
210Process 21778 Stopped \n\
211* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
212 36 \n\
213 37 int c(int val)\n\
214 38 {\n\
215 39 -> return val + 3;\n\
216 40 }\n\
217 41 \n\
218 42 int main (int argc, char const *argv[])\n\
219(lldb) \n\
220 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000221Example multiple line Python breakpoint command, using function definition: \n\
222 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000223(lldb) breakpoint command add -s python 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000224Enter your Python command(s). Type 'DONE' to end. \n\
225> def breakpoint_output (bp_no): \n\
226> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
227> print out_string \n\
228> return True \n\
229> breakpoint_output (1) \n\
230> DONE \n\
231 \n\
232 \n\
233Example multiple line Python breakpoint command, using 'loose' Python: \n\
234 \n\
Jim Ingham949d5ac2011-02-18 00:54:25 +0000235(lldb) breakpoint command add -s p 1 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000236Enter your Python command(s). Type 'DONE' to end. \n\
237> global bp_count \n\
238> bp_count = bp_count + 1 \n\
239> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
240> DONE \n\
241 \n\
242In this case, since there is a reference to a global variable, \n\
243'bp_count', you will also need to make sure 'bp_count' exists and is \n\
244initialized: \n\
245 \n\
246(lldb) script \n\
247>>> bp_count = 0 \n\
248>>> quit() \n\
249 \n\
250(lldb) \n\
251 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000252 \n\
253Final Note: If you get a warning that no breakpoint command was generated, \n\
254but you did not get any syntax errors, you probably forgot to add a call \n\
255to your functions. \n\
256 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000257Special information about debugger command breakpoint commands \n\
258-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000259 \n\
260You may enter any debugger command, exactly as you would at the \n\
261debugger prompt. You may enter as many debugger commands as you like, \n\
262but do NOT enter more than one command per line. \n" );
Caroline Tice43b014a2010-10-04 22:28:36 +0000263
264
265 CommandArgumentEntry arg;
266 CommandArgumentData bp_id_arg;
267
268 // Define the first (and only) variant of this arg.
269 bp_id_arg.arg_type = eArgTypeBreakpointID;
270 bp_id_arg.arg_repetition = eArgRepeatPlain;
271
272 // There is only one variant this argument could be; put it into the argument entry.
273 arg.push_back (bp_id_arg);
274
275 // Push the data for the first argument into the m_arguments vector.
276 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000277}
278
279CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
280{
281}
282
283bool
284CommandObjectBreakpointCommandAdd::Execute
285(
286 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000287 CommandReturnObject &result
288)
289{
Greg Clayton238c0a12010-09-18 01:14:36 +0000290 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000291
292 if (target == NULL)
293 {
294 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
295 result.SetStatus (eReturnStatusFailed);
296 return false;
297 }
298
299 const BreakpointList &breakpoints = target->GetBreakpointList();
300 size_t num_breakpoints = breakpoints.GetSize();
301
302 if (num_breakpoints == 0)
303 {
304 result.AppendError ("No breakpoints exist to have commands added");
305 result.SetStatus (eReturnStatusFailed);
306 return false;
307 }
308
Chris Lattner24943d22010-06-08 16:52:24 +0000309 BreakpointIDList valid_bp_ids;
310 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
311
312 if (result.Succeeded())
313 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000314 const size_t count = valid_bp_ids.GetSize();
315 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000316 {
317 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
318 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
319 {
320 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000321 BreakpointOptions *bp_options = NULL;
322 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
323 {
324 // This breakpoint does not have an associated location.
325 bp_options = bp->GetOptions();
326 }
327 else
Chris Lattner24943d22010-06-08 16:52:24 +0000328 {
329 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000330 // This breakpoint does have an associated location.
331 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000332 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000333 bp_options = bp_loc_sp->GetLocationOptions();
334 }
335
Jim Ingham949d5ac2011-02-18 00:54:25 +0000336 // Skip this breakpoint if bp_options is not good.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000337 if (bp_options == NULL) continue;
338
339 // If we are using script language, get the script interpreter
340 // in order to set or collect command callback. Otherwise, call
341 // the methods associated with this object.
342 if (m_options.m_use_script_language)
343 {
344 // Special handling for one-liner specified inline.
345 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000346 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
347 m_options.m_one_liner.c_str());
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000348 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000349 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
350 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000351 }
352 else
353 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000354 // Special handling for one-liner specified inline.
355 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000356 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000357 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000358 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000359 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000360 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000361 }
362 }
363 }
364 }
365
366 return result.Succeeded();
367}
368
369Options *
370CommandObjectBreakpointCommandAdd::GetOptions ()
371{
372 return &m_options;
373}
374
375const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
376
377void
378CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
379(
380 BreakpointOptions *bp_options,
381 CommandReturnObject &result
382)
383{
Greg Clayton238c0a12010-09-18 01:14:36 +0000384 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000385 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
386 if (reader_sp && data_ap.get())
387 {
388 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
389 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
390
391 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
392 bp_options, // baton
393 eInputReaderGranularityLine, // token size, to pass to callback function
394 "DONE", // end token
395 "> ", // prompt
396 true)); // echo input
397 if (err.Success())
398 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000399 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000400 result.SetStatus (eReturnStatusSuccessFinishNoResult);
401 }
402 else
403 {
404 result.AppendError (err.AsCString());
405 result.SetStatus (eReturnStatusFailed);
406 }
407 }
408 else
409 {
410 result.AppendError("out of memory");
411 result.SetStatus (eReturnStatusFailed);
412 }
413
414}
415
Johnny Chen3e0571b2010-09-11 00:23:59 +0000416// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000417void
Greg Clayton238c0a12010-09-18 01:14:36 +0000418CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000419 const char *oneliner)
420{
421 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
422
423 // It's necessary to set both user_source and script_source to the oneliner.
424 // The former is used to generate callback description (as in breakpoint command list)
425 // while the latter is used for Python to interpret during the actual callback.
426 data_ap->user_source.AppendString (oneliner);
427 data_ap->script_source.AppendString (oneliner);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000428 data_ap->stop_on_error = m_options.m_stop_on_error;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000429
430 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
431 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
432
433 return;
434}
435
Chris Lattner24943d22010-06-08 16:52:24 +0000436size_t
437CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
438(
439 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000440 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000441 lldb::InputReaderAction notification,
442 const char *bytes,
443 size_t bytes_len
444)
445{
Greg Clayton58928562011-02-09 01:08:52 +0000446 File &out_file = reader.GetDebugger().GetOutputFile();
Chris Lattner24943d22010-06-08 16:52:24 +0000447
448 switch (notification)
449 {
450 case eInputReaderActivate:
Greg Clayton58928562011-02-09 01:08:52 +0000451 out_file.Printf ("%s\n", g_reader_instructions);
452 if (reader.GetPrompt())
453 out_file.Printf ("%s", reader.GetPrompt());
454 out_file.Flush();
Chris Lattner24943d22010-06-08 16:52:24 +0000455 break;
456
457 case eInputReaderDeactivate:
458 break;
459
460 case eInputReaderReactivate:
Greg Clayton58928562011-02-09 01:08:52 +0000461 if (reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000462 {
Greg Clayton58928562011-02-09 01:08:52 +0000463 out_file.Printf ("%s", reader.GetPrompt());
464 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000465 }
Chris Lattner24943d22010-06-08 16:52:24 +0000466 break;
467
468 case eInputReaderGotToken:
469 if (bytes && bytes_len && baton)
470 {
471 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
472 if (bp_options)
473 {
474 Baton *bp_options_baton = bp_options->GetBaton();
475 if (bp_options_baton)
476 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
477 }
478 }
Greg Clayton58928562011-02-09 01:08:52 +0000479 if (!reader.IsDone() && reader.GetPrompt())
Caroline Ticef81b4c52010-10-27 18:34:42 +0000480 {
Greg Clayton58928562011-02-09 01:08:52 +0000481 out_file.Printf ("%s", reader.GetPrompt());
482 out_file.Flush();
Caroline Ticef81b4c52010-10-27 18:34:42 +0000483 }
Chris Lattner24943d22010-06-08 16:52:24 +0000484 break;
485
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000486 case eInputReaderInterrupt:
487 {
488 // Finish, and cancel the breakpoint command.
489 reader.SetIsDone (true);
490 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
491 if (bp_options)
492 {
493 Baton *bp_options_baton = bp_options->GetBaton ();
494 if (bp_options_baton)
495 {
496 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
497 ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.Clear();
498 }
499 }
Greg Clayton58928562011-02-09 01:08:52 +0000500 out_file.Printf ("Warning: No command attached to breakpoint.\n");
501 out_file.Flush();
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000502 }
503 break;
504
505 case eInputReaderEndOfFile:
506 reader.SetIsDone (true);
507 break;
508
Chris Lattner24943d22010-06-08 16:52:24 +0000509 case eInputReaderDone:
510 break;
511 }
512
513 return bytes_len;
514}
515
516
517//-------------------------------------------------------------------------
518// CommandObjectBreakpointCommandRemove
519//-------------------------------------------------------------------------
520
Greg Clayton238c0a12010-09-18 01:14:36 +0000521CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
522 CommandObject (interpreter,
523 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000524 "Remove the set of commands from a breakpoint.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000525 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000526{
Caroline Tice43b014a2010-10-04 22:28:36 +0000527 CommandArgumentEntry arg;
528 CommandArgumentData bp_id_arg;
529
530 // Define the first (and only) variant of this arg.
531 bp_id_arg.arg_type = eArgTypeBreakpointID;
532 bp_id_arg.arg_repetition = eArgRepeatPlain;
533
534 // There is only one variant this argument could be; put it into the argument entry.
535 arg.push_back (bp_id_arg);
536
537 // Push the data for the first argument into the m_arguments vector.
538 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000539}
540
541CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
542{
543}
544
545bool
Greg Clayton63094e02010-06-23 01:19:29 +0000546CommandObjectBreakpointCommandRemove::Execute
547(
Greg Clayton63094e02010-06-23 01:19:29 +0000548 Args& command,
549 CommandReturnObject &result
550)
Chris Lattner24943d22010-06-08 16:52:24 +0000551{
Greg Clayton238c0a12010-09-18 01:14:36 +0000552 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000553
554 if (target == NULL)
555 {
556 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
557 result.SetStatus (eReturnStatusFailed);
558 return false;
559 }
560
561 const BreakpointList &breakpoints = target->GetBreakpointList();
562 size_t num_breakpoints = breakpoints.GetSize();
563
564 if (num_breakpoints == 0)
565 {
566 result.AppendError ("No breakpoints exist to have commands removed");
567 result.SetStatus (eReturnStatusFailed);
568 return false;
569 }
570
571 if (command.GetArgumentCount() == 0)
572 {
573 result.AppendError ("No breakpoint specified from which to remove the commands");
574 result.SetStatus (eReturnStatusFailed);
575 return false;
576 }
577
578 BreakpointIDList valid_bp_ids;
579 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
580
581 if (result.Succeeded())
582 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000583 const size_t count = valid_bp_ids.GetSize();
584 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000585 {
586 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
587 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
588 {
589 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
590 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
591 {
592 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
593 if (bp_loc_sp)
594 bp_loc_sp->ClearCallback();
595 else
596 {
597 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
598 cur_bp_id.GetBreakpointID(),
599 cur_bp_id.GetLocationID());
600 result.SetStatus (eReturnStatusFailed);
601 return false;
602 }
603 }
604 else
605 {
606 bp->ClearCallback();
607 }
608 }
609 }
610 }
611 return result.Succeeded();
612}
613
614
615//-------------------------------------------------------------------------
616// CommandObjectBreakpointCommandList
617//-------------------------------------------------------------------------
618
Greg Clayton238c0a12010-09-18 01:14:36 +0000619CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
620 CommandObject (interpreter,
621 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000622 "List the script or set of commands to be executed when the breakpoint is hit.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000623 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000624{
Caroline Tice43b014a2010-10-04 22:28:36 +0000625 CommandArgumentEntry arg;
626 CommandArgumentData bp_id_arg;
627
628 // Define the first (and only) variant of this arg.
629 bp_id_arg.arg_type = eArgTypeBreakpointID;
630 bp_id_arg.arg_repetition = eArgRepeatPlain;
631
632 // There is only one variant this argument could be; put it into the argument entry.
633 arg.push_back (bp_id_arg);
634
635 // Push the data for the first argument into the m_arguments vector.
636 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000637}
638
639CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
640{
641}
642
643bool
Greg Clayton63094e02010-06-23 01:19:29 +0000644CommandObjectBreakpointCommandList::Execute
645(
Greg Clayton63094e02010-06-23 01:19:29 +0000646 Args& command,
647 CommandReturnObject &result
648)
Chris Lattner24943d22010-06-08 16:52:24 +0000649{
Greg Clayton238c0a12010-09-18 01:14:36 +0000650 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000651
652 if (target == NULL)
653 {
654 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
655 result.SetStatus (eReturnStatusFailed);
656 return false;
657 }
658
659 const BreakpointList &breakpoints = target->GetBreakpointList();
660 size_t num_breakpoints = breakpoints.GetSize();
661
662 if (num_breakpoints == 0)
663 {
664 result.AppendError ("No breakpoints exist for which to list commands");
665 result.SetStatus (eReturnStatusFailed);
666 return false;
667 }
668
669 if (command.GetArgumentCount() == 0)
670 {
671 result.AppendError ("No breakpoint specified for which to list the commands");
672 result.SetStatus (eReturnStatusFailed);
673 return false;
674 }
675
676 BreakpointIDList valid_bp_ids;
677 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
678
679 if (result.Succeeded())
680 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000681 const size_t count = valid_bp_ids.GetSize();
682 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000683 {
684 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
685 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
686 {
687 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
688
689 if (bp)
690 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000691 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000692 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
693 {
694 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
695 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000696 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000697 else
698 {
699 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
700 cur_bp_id.GetBreakpointID(),
701 cur_bp_id.GetLocationID());
702 result.SetStatus (eReturnStatusFailed);
703 return false;
704 }
705 }
706 else
707 {
708 bp_options = bp->GetOptions();
709 }
710
711 if (bp_options)
712 {
713 StreamString id_str;
Jim Ingham949d5ac2011-02-18 00:54:25 +0000714 BreakpointID::GetCanonicalReference (&id_str,
715 cur_bp_id.GetBreakpointID(),
716 cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000717 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000718 if (baton)
719 {
720 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
721 result.GetOutputStream().IndentMore ();
722 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
723 result.GetOutputStream().IndentLess ();
724 }
725 else
726 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000727 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
728 id_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000729 }
730 }
731 result.SetStatus (eReturnStatusSuccessFinishResult);
732 }
733 else
734 {
735 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
736 result.SetStatus (eReturnStatusFailed);
737 }
738
739 }
740 }
741 }
742
743 return result.Succeeded();
744}
745
746//-------------------------------------------------------------------------
747// CommandObjectBreakpointCommand
748//-------------------------------------------------------------------------
749
Greg Clayton63094e02010-06-23 01:19:29 +0000750CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000751 CommandObjectMultiword (interpreter,
752 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000753 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
754 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
755{
756 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000757 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
758 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
759 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000760
761 add_command_object->SetCommandName ("breakpoint command add");
762 remove_command_object->SetCommandName ("breakpoint command remove");
763 list_command_object->SetCommandName ("breakpoint command list");
764
Greg Clayton238c0a12010-09-18 01:14:36 +0000765 status = LoadSubCommand ("add", add_command_object);
766 status = LoadSubCommand ("remove", remove_command_object);
767 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000768}
769
770
771CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
772{
773}
774
775bool
776CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
777(
778 void *baton,
779 StoppointCallbackContext *context,
780 lldb::user_id_t break_id,
781 lldb::user_id_t break_loc_id
782)
783{
784 bool ret_value = true;
785 if (baton == NULL)
786 return true;
787
788
789 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
790 StringList &commands = data->user_source;
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000791
Chris Lattner24943d22010-06-08 16:52:24 +0000792 if (commands.GetSize() > 0)
793 {
Greg Clayton63094e02010-06-23 01:19:29 +0000794 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000795 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000796 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000797 Debugger &debugger = context->exe_ctx.target->GetDebugger();
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000798 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
799 // if the debugger is set up that way.
800
801 result.SetImmediateOutputFile (debugger.GetOutputFile().GetStream());
802 result.SetImmediateErrorFile (debugger.GetErrorFile().GetStream());
803
Jim Ingham949d5ac2011-02-18 00:54:25 +0000804 bool stop_on_continue = true;
805 bool echo_commands = false;
806 bool print_results = true;
807
808 debugger.GetCommandInterpreter().HandleCommands (commands,
809 &(context->exe_ctx),
810 stop_on_continue,
811 data->stop_on_error,
812 echo_commands,
813 print_results,
814 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000815 }
Chris Lattner24943d22010-06-08 16:52:24 +0000816 }
817 return ret_value;
818}
819