blob: 85971bd6a9b6ffac1931573a98907527a5459ea2 [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
48lldb::OptionDefinition
49CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
50{
Greg Claytonfe424a92010-09-18 03:37:20 +000051 { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, 0, "<one-liner>",
Caroline Tice8bb61f02010-09-21 23:25:40 +000052 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
Johnny Chenb81ed0d2010-09-11 00:18:09 +000053
Jim Ingham34e9a982010-06-15 18:47:14 +000054 { LLDB_OPT_SET_1, true, "script", 's', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000055 "Write the breakpoint command script in the default scripting language."},
56
Jim Ingham34e9a982010-06-15 18:47:14 +000057 { LLDB_OPT_SET_2, true, "python", 'p', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000058 "Write the breakpoint command script in the Python scripting language."},
59
Jim Ingham34e9a982010-06-15 18:47:14 +000060 { LLDB_OPT_SET_3, true, "commands", 'c', no_argument, NULL, 0, NULL,
Caroline Ticeabb507a2010-09-08 21:06:11 +000061 "Write the breakpoint command script using standard debugger commands."},
Chris Lattner24943d22010-06-08 16:52:24 +000062
63 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
64};
65
66const lldb::OptionDefinition*
67CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
68{
69 return g_option_table;
70}
71
72
73Error
74CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
75(
76 int option_idx,
77 const char *option_arg
78)
79{
80 Error error;
81 char short_option = (char) m_getopt_table[option_idx].val;
82
83 switch (short_option)
84 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +000085 case 'o':
86 m_use_one_liner = true;
87 m_one_liner = option_arg;
88 break;
Chris Lattner24943d22010-06-08 16:52:24 +000089 case 's':
90 m_use_commands = false;
91 m_use_script_language = true;
92 m_script_language = eScriptLanguageDefault;
93 break;
94 case 'p':
95 m_use_commands = false;
96 m_use_script_language = true;
97 m_script_language = eScriptLanguagePython;
98 break;
99 case 'c':
100 m_use_commands = true;
101 m_use_script_language = false;
102 m_script_language = eScriptLanguageNone;
103 break;
104 default:
105 break;
106 }
107 return error;
108}
109
110void
111CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
112{
113 Options::ResetOptionValues();
114
115 m_use_commands = false;
116 m_use_script_language = false;
117 m_script_language = eScriptLanguageNone;
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000118
119 m_use_one_liner = false;
120 m_one_liner.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000121}
122
123//-------------------------------------------------------------------------
124// CommandObjectBreakpointCommandAdd
125//-------------------------------------------------------------------------
126
127
Greg Clayton238c0a12010-09-18 01:14:36 +0000128CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
129 CommandObject (interpreter,
130 "add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000131 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Chris Lattner24943d22010-06-08 16:52:24 +0000132 "breakpoint command add <cmd-options> <breakpoint-id>")
133{
134 SetHelpLong (
135"\nGeneral information about entering breakpoint commands \n\
136------------------------------------------------------ \n\
137 \n\
138This command will cause you to be prompted to enter the command or set \n\
139of commands you wish to be executed when the specified breakpoint is \n\
140hit. You will be told to enter your command(s), and will see a '> ' \n\
141prompt. Because you can enter one or many commands to be executed when \n\
142a breakpoint is hit, you will continue to be prompted after each \n\
143new-line that you enter, until you enter the word 'DONE', which will \n\
144cause the commands you have entered to be stored with the breakpoint \n\
145and executed when the breakpoint is hit. \n\
146 \n\
147Syntax checking is not necessarily done when breakpoint commands are \n\
148entered. An improperly written breakpoint command will attempt to get \n\
149executed when the breakpoint gets hit, and usually silently fail. If \n\
150your breakpoint command does not appear to be getting executed, go \n\
151back and check your syntax. \n\
152 \n\
153 \n\
154Special information about PYTHON breakpoint commands \n\
155---------------------------------------------------- \n\
156 \n\
157You may enter either one line of Python or multiple lines of Python \n\
158(including defining whole functions, if desired). If you enter a \n\
159single line of Python, that will be passed to the Python interpreter \n\
160'as is' when the breakpoint gets hit. If you enter function \n\
161definitions, they will be passed to the Python interpreter as soon as \n\
162you finish entering the breakpoint command, and they can be called \n\
163later (don't forget to add calls to them, if you want them called when \n\
164the breakpoint is hit). If you enter multiple lines of Python that \n\
165are not function definitions, they will be collected into a new, \n\
166automatically generated Python function, and a call to the newly \n\
167generated function will be attached to the breakpoint. Important \n\
168Note: Because loose Python code gets collected into functions, if you \n\
169want to access global variables in the 'loose' code, you need to \n\
170specify that they are global, using the 'global' keyword. Be sure to \n\
171use correct Python syntax, including indentation, when entering Python \n\
172breakpoint commands. \n\
173 \n\
174Example Python one-line breakpoint command: \n\
175 \n\
176(lldb) breakpoint command add -p 1 \n\
177Enter your Python command(s). Type 'DONE' to end. \n\
178> print \"Hit this breakpoint!\" \n\
179> DONE \n\
180 \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000181As a convenience, this also works for a short Python one-liner: \n\
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000182(lldb) breakpoint command add -p 1 -o \"import time; print time.asctime()\" \n\
Johnny Chen4c1b2182010-09-10 19:34:12 +0000183(lldb) run \n\
184Launching '.../a.out' (x86_64) \n\
185(lldb) Fri Sep 10 12:17:45 2010 \n\
186Process 21778 Stopped \n\
187* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
188 36 \n\
189 37 int c(int val)\n\
190 38 {\n\
191 39 -> return val + 3;\n\
192 40 }\n\
193 41 \n\
194 42 int main (int argc, char const *argv[])\n\
195(lldb) \n\
196 \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000197Example multiple line Python breakpoint command, using function definition: \n\
198 \n\
199(lldb) breakpoint command add -p 1 \n\
200Enter your Python command(s). Type 'DONE' to end. \n\
201> def breakpoint_output (bp_no): \n\
202> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
203> print out_string \n\
204> return True \n\
205> breakpoint_output (1) \n\
206> DONE \n\
207 \n\
208 \n\
209Example multiple line Python breakpoint command, using 'loose' Python: \n\
210 \n\
211(lldb) breakpoint command add -p 1 \n\
212Enter your Python command(s). Type 'DONE' to end. \n\
213> global bp_count \n\
214> bp_count = bp_count + 1 \n\
215> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
216> DONE \n\
217 \n\
218In this case, since there is a reference to a global variable, \n\
219'bp_count', you will also need to make sure 'bp_count' exists and is \n\
220initialized: \n\
221 \n\
222(lldb) script \n\
223>>> bp_count = 0 \n\
224>>> quit() \n\
225 \n\
226(lldb) \n\
227 \n\
Caroline Ticeb447e842010-09-21 19:25:28 +0000228 \n\
229Final Note: If you get a warning that no breakpoint command was generated, \n\
230but you did not get any syntax errors, you probably forgot to add a call \n\
231to your functions. \n\
232 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000233Special information about debugger command breakpoint commands \n\
234-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000235 \n\
236You may enter any debugger command, exactly as you would at the \n\
237debugger prompt. You may enter as many debugger commands as you like, \n\
238but do NOT enter more than one command per line. \n" );
239}
240
241CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
242{
243}
244
245bool
246CommandObjectBreakpointCommandAdd::Execute
247(
248 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000249 CommandReturnObject &result
250)
251{
Greg Clayton238c0a12010-09-18 01:14:36 +0000252 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000253
254 if (target == NULL)
255 {
256 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
257 result.SetStatus (eReturnStatusFailed);
258 return false;
259 }
260
261 const BreakpointList &breakpoints = target->GetBreakpointList();
262 size_t num_breakpoints = breakpoints.GetSize();
263
264 if (num_breakpoints == 0)
265 {
266 result.AppendError ("No breakpoints exist to have commands added");
267 result.SetStatus (eReturnStatusFailed);
268 return false;
269 }
270
271 if (command.GetArgumentCount() == 0)
272 {
273 result.AppendError ("No breakpoint specified to which to add the commands");
274 result.SetStatus (eReturnStatusFailed);
275 return false;
276 }
277
278 BreakpointIDList valid_bp_ids;
279 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
280
281 if (result.Succeeded())
282 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000283 const size_t count = valid_bp_ids.GetSize();
284 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000285 {
286 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
287 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
288 {
289 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000290 BreakpointOptions *bp_options = NULL;
291 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
292 {
293 // This breakpoint does not have an associated location.
294 bp_options = bp->GetOptions();
295 }
296 else
Chris Lattner24943d22010-06-08 16:52:24 +0000297 {
298 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000299 // This breakpoint does have an associated location.
300 // Get its breakpoint options.
Chris Lattner24943d22010-06-08 16:52:24 +0000301 if (bp_loc_sp)
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000302 bp_options = bp_loc_sp->GetLocationOptions();
303 }
304
305 // Skip this breakpoiont if bp_options is not good.
306 if (bp_options == NULL) continue;
307
308 // If we are using script language, get the script interpreter
309 // in order to set or collect command callback. Otherwise, call
310 // the methods associated with this object.
311 if (m_options.m_use_script_language)
312 {
313 // Special handling for one-liner specified inline.
314 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000315 m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
316 m_options.m_one_liner.c_str());
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000317 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000318 m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
319 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000320 }
321 else
322 {
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000323 // Special handling for one-liner specified inline.
324 if (m_options.m_use_one_liner)
Greg Clayton238c0a12010-09-18 01:14:36 +0000325 SetBreakpointCommandCallback (bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000326 m_options.m_one_liner.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000327 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000328 CollectDataForBreakpointCommandCallback (bp_options,
Greg Claytonbef15832010-07-14 00:18:15 +0000329 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000330 }
331 }
332 }
333 }
334
335 return result.Succeeded();
336}
337
338Options *
339CommandObjectBreakpointCommandAdd::GetOptions ()
340{
341 return &m_options;
342}
343
344const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
345
346void
347CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
348(
349 BreakpointOptions *bp_options,
350 CommandReturnObject &result
351)
352{
Greg Clayton238c0a12010-09-18 01:14:36 +0000353 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000354 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
355 if (reader_sp && data_ap.get())
356 {
357 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
358 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
359
360 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
361 bp_options, // baton
362 eInputReaderGranularityLine, // token size, to pass to callback function
363 "DONE", // end token
364 "> ", // prompt
365 true)); // echo input
366 if (err.Success())
367 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000368 m_interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000369 result.SetStatus (eReturnStatusSuccessFinishNoResult);
370 }
371 else
372 {
373 result.AppendError (err.AsCString());
374 result.SetStatus (eReturnStatusFailed);
375 }
376 }
377 else
378 {
379 result.AppendError("out of memory");
380 result.SetStatus (eReturnStatusFailed);
381 }
382
383}
384
Johnny Chen3e0571b2010-09-11 00:23:59 +0000385// Set a one-liner as the callback for the breakpoint.
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000386void
Greg Clayton238c0a12010-09-18 01:14:36 +0000387CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Johnny Chenb81ed0d2010-09-11 00:18:09 +0000388 const char *oneliner)
389{
390 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
391
392 // It's necessary to set both user_source and script_source to the oneliner.
393 // The former is used to generate callback description (as in breakpoint command list)
394 // while the latter is used for Python to interpret during the actual callback.
395 data_ap->user_source.AppendString (oneliner);
396 data_ap->script_source.AppendString (oneliner);
397
398 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
399 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
400
401 return;
402}
403
Chris Lattner24943d22010-06-08 16:52:24 +0000404size_t
405CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
406(
407 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000408 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000409 lldb::InputReaderAction notification,
410 const char *bytes,
411 size_t bytes_len
412)
413{
Greg Clayton63094e02010-06-23 01:19:29 +0000414 FILE *out_fh = reader.GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000415
416 switch (notification)
417 {
418 case eInputReaderActivate:
419 if (out_fh)
420 {
421 ::fprintf (out_fh, "%s\n", g_reader_instructions);
Greg Clayton63094e02010-06-23 01:19:29 +0000422 if (reader.GetPrompt())
423 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000424 }
425 break;
426
427 case eInputReaderDeactivate:
428 break;
429
430 case eInputReaderReactivate:
Greg Clayton63094e02010-06-23 01:19:29 +0000431 if (out_fh && reader.GetPrompt())
432 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000433 break;
434
435 case eInputReaderGotToken:
436 if (bytes && bytes_len && baton)
437 {
438 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
439 if (bp_options)
440 {
441 Baton *bp_options_baton = bp_options->GetBaton();
442 if (bp_options_baton)
443 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
444 }
445 }
Greg Clayton63094e02010-06-23 01:19:29 +0000446 if (out_fh && !reader.IsDone() && reader.GetPrompt())
447 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000448 break;
449
450 case eInputReaderDone:
451 break;
452 }
453
454 return bytes_len;
455}
456
457
458//-------------------------------------------------------------------------
459// CommandObjectBreakpointCommandRemove
460//-------------------------------------------------------------------------
461
Greg Clayton238c0a12010-09-18 01:14:36 +0000462CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove (CommandInterpreter &interpreter) :
463 CommandObject (interpreter,
464 "remove",
Chris Lattner24943d22010-06-08 16:52:24 +0000465 "Remove the set of commands from a breakpoint.",
466 "breakpoint command remove <breakpoint-id>")
467{
468}
469
470CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
471{
472}
473
474bool
Greg Clayton63094e02010-06-23 01:19:29 +0000475CommandObjectBreakpointCommandRemove::Execute
476(
Greg Clayton63094e02010-06-23 01:19:29 +0000477 Args& command,
478 CommandReturnObject &result
479)
Chris Lattner24943d22010-06-08 16:52:24 +0000480{
Greg Clayton238c0a12010-09-18 01:14:36 +0000481 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000482
483 if (target == NULL)
484 {
485 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
486 result.SetStatus (eReturnStatusFailed);
487 return false;
488 }
489
490 const BreakpointList &breakpoints = target->GetBreakpointList();
491 size_t num_breakpoints = breakpoints.GetSize();
492
493 if (num_breakpoints == 0)
494 {
495 result.AppendError ("No breakpoints exist to have commands removed");
496 result.SetStatus (eReturnStatusFailed);
497 return false;
498 }
499
500 if (command.GetArgumentCount() == 0)
501 {
502 result.AppendError ("No breakpoint specified from which to remove the commands");
503 result.SetStatus (eReturnStatusFailed);
504 return false;
505 }
506
507 BreakpointIDList valid_bp_ids;
508 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
509
510 if (result.Succeeded())
511 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000512 const size_t count = valid_bp_ids.GetSize();
513 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000514 {
515 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
516 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
517 {
518 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
519 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
520 {
521 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
522 if (bp_loc_sp)
523 bp_loc_sp->ClearCallback();
524 else
525 {
526 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
527 cur_bp_id.GetBreakpointID(),
528 cur_bp_id.GetLocationID());
529 result.SetStatus (eReturnStatusFailed);
530 return false;
531 }
532 }
533 else
534 {
535 bp->ClearCallback();
536 }
537 }
538 }
539 }
540 return result.Succeeded();
541}
542
543
544//-------------------------------------------------------------------------
545// CommandObjectBreakpointCommandList
546//-------------------------------------------------------------------------
547
Greg Clayton238c0a12010-09-18 01:14:36 +0000548CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
549 CommandObject (interpreter,
550 "list",
Chris Lattner24943d22010-06-08 16:52:24 +0000551 "List the script or set of commands to be executed when the breakpoint is hit.",
552 "breakpoint command list <breakpoint-id>")
553{
554}
555
556CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
557{
558}
559
560bool
Greg Clayton63094e02010-06-23 01:19:29 +0000561CommandObjectBreakpointCommandList::Execute
562(
Greg Clayton63094e02010-06-23 01:19:29 +0000563 Args& command,
564 CommandReturnObject &result
565)
Chris Lattner24943d22010-06-08 16:52:24 +0000566{
Greg Clayton238c0a12010-09-18 01:14:36 +0000567 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000568
569 if (target == NULL)
570 {
571 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
572 result.SetStatus (eReturnStatusFailed);
573 return false;
574 }
575
576 const BreakpointList &breakpoints = target->GetBreakpointList();
577 size_t num_breakpoints = breakpoints.GetSize();
578
579 if (num_breakpoints == 0)
580 {
581 result.AppendError ("No breakpoints exist for which to list commands");
582 result.SetStatus (eReturnStatusFailed);
583 return false;
584 }
585
586 if (command.GetArgumentCount() == 0)
587 {
588 result.AppendError ("No breakpoint specified for which to list the commands");
589 result.SetStatus (eReturnStatusFailed);
590 return false;
591 }
592
593 BreakpointIDList valid_bp_ids;
594 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
595
596 if (result.Succeeded())
597 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000598 const size_t count = valid_bp_ids.GetSize();
599 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000600 {
601 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
602 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
603 {
604 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
605
606 if (bp)
607 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000608 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000609 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
610 {
611 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
612 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000613 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000614 else
615 {
616 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
617 cur_bp_id.GetBreakpointID(),
618 cur_bp_id.GetLocationID());
619 result.SetStatus (eReturnStatusFailed);
620 return false;
621 }
622 }
623 else
624 {
625 bp_options = bp->GetOptions();
626 }
627
628 if (bp_options)
629 {
630 StreamString id_str;
631 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000632 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000633 if (baton)
634 {
635 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
636 result.GetOutputStream().IndentMore ();
637 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
638 result.GetOutputStream().IndentLess ();
639 }
640 else
641 {
642 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
643 }
644 }
645 result.SetStatus (eReturnStatusSuccessFinishResult);
646 }
647 else
648 {
649 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
650 result.SetStatus (eReturnStatusFailed);
651 }
652
653 }
654 }
655 }
656
657 return result.Succeeded();
658}
659
660//-------------------------------------------------------------------------
661// CommandObjectBreakpointCommand
662//-------------------------------------------------------------------------
663
Greg Clayton63094e02010-06-23 01:19:29 +0000664CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000665 CommandObjectMultiword (interpreter,
666 "command",
Chris Lattner24943d22010-06-08 16:52:24 +0000667 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
668 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
669{
670 bool status;
Greg Clayton238c0a12010-09-18 01:14:36 +0000671 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
672 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove (interpreter));
673 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
Chris Lattner24943d22010-06-08 16:52:24 +0000674
675 add_command_object->SetCommandName ("breakpoint command add");
676 remove_command_object->SetCommandName ("breakpoint command remove");
677 list_command_object->SetCommandName ("breakpoint command list");
678
Greg Clayton238c0a12010-09-18 01:14:36 +0000679 status = LoadSubCommand ("add", add_command_object);
680 status = LoadSubCommand ("remove", remove_command_object);
681 status = LoadSubCommand ("list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000682}
683
684
685CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
686{
687}
688
689bool
690CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
691(
692 void *baton,
693 StoppointCallbackContext *context,
694 lldb::user_id_t break_id,
695 lldb::user_id_t break_loc_id
696)
697{
698 bool ret_value = true;
699 if (baton == NULL)
700 return true;
701
702
703 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
704 StringList &commands = data->user_source;
705
706 if (commands.GetSize() > 0)
707 {
708 uint32_t num_commands = commands.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000709 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000710 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000711 {
Greg Clayton63094e02010-06-23 01:19:29 +0000712
713 Debugger &debugger = context->exe_ctx.target->GetDebugger();
714 CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
715
716 FILE *out_fh = debugger.GetOutputFileHandle();
717 FILE *err_fh = debugger.GetErrorFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000718
Greg Clayton63094e02010-06-23 01:19:29 +0000719 uint32_t i;
720 for (i = 0; i < num_commands; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000721 {
Greg Clayton63094e02010-06-23 01:19:29 +0000722
723 // First time through we use the context from the stoppoint, after that we use whatever
724 // has been set by the previous command.
725
726 if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx))
727 break;
728
729 // FIXME: This isn't really the right way to do this. We should be able to peek at the public
730 // to see if there is any new events, but that is racey, since the internal process thread has to run and
731 // deliver the event to the public queue before a run will show up. So for now we check
732 // the internal thread state.
733
734 lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState();
735 if (internal_state != eStateStopped)
Chris Lattner24943d22010-06-08 16:52:24 +0000736 {
Greg Clayton63094e02010-06-23 01:19:29 +0000737 if (i < num_commands - 1)
738 {
739 if (out_fh)
740 ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
741 " last command: \"%s\"\n", StateAsCString(internal_state),
742 commands.GetStringAtIndex(i));
743 }
744 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000745 }
Greg Clayton63094e02010-06-23 01:19:29 +0000746
747 if (out_fh)
748 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
749 if (err_fh)
750 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
751 result.Clear();
752 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000753 }
Chris Lattner24943d22010-06-08 16:52:24 +0000754
Greg Clayton63094e02010-06-23 01:19:29 +0000755 if (err_fh && !result.Succeeded() && i < num_commands)
756 ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
757
Chris Lattner24943d22010-06-08 16:52:24 +0000758 if (out_fh)
759 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
Greg Clayton63094e02010-06-23 01:19:29 +0000760
Chris Lattner24943d22010-06-08 16:52:24 +0000761 if (err_fh)
Greg Clayton63094e02010-06-23 01:19:29 +0000762 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000763 }
Chris Lattner24943d22010-06-08 16:52:24 +0000764 }
765 return ret_value;
766}
767