blob: 396933a03810cceed6ee15bbe9373aa3e8b7e4bf [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 () :
35 Options ()
36{
Chris Lattner24943d22010-06-08 16:52:24 +000037}
38
39CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
40{
41}
42
43lldb::OptionDefinition
44CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
45{
Jim Ingham34e9a982010-06-15 18:47:14 +000046 { LLDB_OPT_SET_1, true, "script", 's', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000047 "Write the breakpoint command script in the default scripting language."},
48
Jim Ingham34e9a982010-06-15 18:47:14 +000049 { LLDB_OPT_SET_2, true, "python", 'p', no_argument, NULL, 0, NULL,
Chris Lattner24943d22010-06-08 16:52:24 +000050 "Write the breakpoint command script in the Python scripting language."},
51
Jim Ingham34e9a982010-06-15 18:47:14 +000052 { LLDB_OPT_SET_3, true, "commands", 'c', no_argument, NULL, 0, NULL,
Caroline Ticeabb507a2010-09-08 21:06:11 +000053 "Write the breakpoint command script using standard debugger commands."},
Chris Lattner24943d22010-06-08 16:52:24 +000054
55 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
56};
57
58const lldb::OptionDefinition*
59CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
60{
61 return g_option_table;
62}
63
64
65Error
66CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
67(
68 int option_idx,
69 const char *option_arg
70)
71{
72 Error error;
73 char short_option = (char) m_getopt_table[option_idx].val;
74
75 switch (short_option)
76 {
77 case 's':
78 m_use_commands = false;
79 m_use_script_language = true;
80 m_script_language = eScriptLanguageDefault;
81 break;
82 case 'p':
83 m_use_commands = false;
84 m_use_script_language = true;
85 m_script_language = eScriptLanguagePython;
86 break;
87 case 'c':
88 m_use_commands = true;
89 m_use_script_language = false;
90 m_script_language = eScriptLanguageNone;
91 break;
92 default:
93 break;
94 }
95 return error;
96}
97
98void
99CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
100{
101 Options::ResetOptionValues();
102
103 m_use_commands = false;
104 m_use_script_language = false;
105 m_script_language = eScriptLanguageNone;
106}
107
108//-------------------------------------------------------------------------
109// CommandObjectBreakpointCommandAdd
110//-------------------------------------------------------------------------
111
112
113CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd () :
114 CommandObject ("add",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000115 "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
Chris Lattner24943d22010-06-08 16:52:24 +0000116 "breakpoint command add <cmd-options> <breakpoint-id>")
117{
118 SetHelpLong (
119"\nGeneral information about entering breakpoint commands \n\
120------------------------------------------------------ \n\
121 \n\
122This command will cause you to be prompted to enter the command or set \n\
123of commands you wish to be executed when the specified breakpoint is \n\
124hit. You will be told to enter your command(s), and will see a '> ' \n\
125prompt. Because you can enter one or many commands to be executed when \n\
126a breakpoint is hit, you will continue to be prompted after each \n\
127new-line that you enter, until you enter the word 'DONE', which will \n\
128cause the commands you have entered to be stored with the breakpoint \n\
129and executed when the breakpoint is hit. \n\
130 \n\
131Syntax checking is not necessarily done when breakpoint commands are \n\
132entered. An improperly written breakpoint command will attempt to get \n\
133executed when the breakpoint gets hit, and usually silently fail. If \n\
134your breakpoint command does not appear to be getting executed, go \n\
135back and check your syntax. \n\
136 \n\
137 \n\
138Special information about PYTHON breakpoint commands \n\
139---------------------------------------------------- \n\
140 \n\
141You may enter either one line of Python or multiple lines of Python \n\
142(including defining whole functions, if desired). If you enter a \n\
143single line of Python, that will be passed to the Python interpreter \n\
144'as is' when the breakpoint gets hit. If you enter function \n\
145definitions, they will be passed to the Python interpreter as soon as \n\
146you finish entering the breakpoint command, and they can be called \n\
147later (don't forget to add calls to them, if you want them called when \n\
148the breakpoint is hit). If you enter multiple lines of Python that \n\
149are not function definitions, they will be collected into a new, \n\
150automatically generated Python function, and a call to the newly \n\
151generated function will be attached to the breakpoint. Important \n\
152Note: Because loose Python code gets collected into functions, if you \n\
153want to access global variables in the 'loose' code, you need to \n\
154specify that they are global, using the 'global' keyword. Be sure to \n\
155use correct Python syntax, including indentation, when entering Python \n\
156breakpoint commands. \n\
157 \n\
158Example Python one-line breakpoint command: \n\
159 \n\
160(lldb) breakpoint command add -p 1 \n\
161Enter your Python command(s). Type 'DONE' to end. \n\
162> print \"Hit this breakpoint!\" \n\
163> DONE \n\
164 \n\
165Example multiple line Python breakpoint command, using function definition: \n\
166 \n\
167(lldb) breakpoint command add -p 1 \n\
168Enter your Python command(s). Type 'DONE' to end. \n\
169> def breakpoint_output (bp_no): \n\
170> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
171> print out_string \n\
172> return True \n\
173> breakpoint_output (1) \n\
174> DONE \n\
175 \n\
176 \n\
177Example multiple line Python breakpoint command, using 'loose' Python: \n\
178 \n\
179(lldb) breakpoint command add -p 1 \n\
180Enter your Python command(s). Type 'DONE' to end. \n\
181> global bp_count \n\
182> bp_count = bp_count + 1 \n\
183> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
184> DONE \n\
185 \n\
186In this case, since there is a reference to a global variable, \n\
187'bp_count', you will also need to make sure 'bp_count' exists and is \n\
188initialized: \n\
189 \n\
190(lldb) script \n\
191>>> bp_count = 0 \n\
192>>> quit() \n\
193 \n\
194(lldb) \n\
195 \n\
Caroline Ticeabb507a2010-09-08 21:06:11 +0000196Special information about debugger command breakpoint commands \n\
197-------------------------------------------------------------- \n\
Chris Lattner24943d22010-06-08 16:52:24 +0000198 \n\
199You may enter any debugger command, exactly as you would at the \n\
200debugger prompt. You may enter as many debugger commands as you like, \n\
201but do NOT enter more than one command per line. \n" );
202}
203
204CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
205{
206}
207
208bool
209CommandObjectBreakpointCommandAdd::Execute
210(
Greg Clayton63094e02010-06-23 01:19:29 +0000211 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000212 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000213 CommandReturnObject &result
214)
215{
Jim Inghamc8332952010-08-26 21:32:51 +0000216 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000217
218 if (target == NULL)
219 {
220 result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
221 result.SetStatus (eReturnStatusFailed);
222 return false;
223 }
224
225 const BreakpointList &breakpoints = target->GetBreakpointList();
226 size_t num_breakpoints = breakpoints.GetSize();
227
228 if (num_breakpoints == 0)
229 {
230 result.AppendError ("No breakpoints exist to have commands added");
231 result.SetStatus (eReturnStatusFailed);
232 return false;
233 }
234
235 if (command.GetArgumentCount() == 0)
236 {
237 result.AppendError ("No breakpoint specified to which to add the commands");
238 result.SetStatus (eReturnStatusFailed);
239 return false;
240 }
241
242 BreakpointIDList valid_bp_ids;
243 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
244
245 if (result.Succeeded())
246 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000247 const size_t count = valid_bp_ids.GetSize();
248 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000249 {
250 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
251 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
252 {
253 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
254 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
255 {
256 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
257 if (bp_loc_sp)
258 {
259 if (m_options.m_use_script_language)
260 {
Johnny Chend1c2dca2010-09-10 18:21:10 +0000261 // Special handling for one-liner.
262 if (command.GetArgumentCount() == 2)
263 interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter,
264 bp_loc_sp->GetLocationOptions(),
265 command.GetArgumentAtIndex(1));
266 else
267 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
268 bp_loc_sp->GetLocationOptions(),
269 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000270 }
271 else
272 {
Greg Claytonbef15832010-07-14 00:18:15 +0000273 CollectDataForBreakpointCommandCallback (interpreter,
274 bp_loc_sp->GetLocationOptions(),
275 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000276 }
277 }
278 }
279 else
280 {
281 if (m_options.m_use_script_language)
282 {
Johnny Chend1c2dca2010-09-10 18:21:10 +0000283 // Special handling for one-liner.
284 if (command.GetArgumentCount() == 2)
285 interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (interpreter,
286 bp->GetOptions(),
287 command.GetArgumentAtIndex(1));
288 else
289 interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (interpreter,
290 bp->GetOptions(),
291 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000292 }
293 else
294 {
Greg Claytonbef15832010-07-14 00:18:15 +0000295 CollectDataForBreakpointCommandCallback (interpreter,
296 bp->GetOptions(),
297 result);
Chris Lattner24943d22010-06-08 16:52:24 +0000298 }
299 }
300 }
301 }
302 }
303
304 return result.Succeeded();
305}
306
307Options *
308CommandObjectBreakpointCommandAdd::GetOptions ()
309{
310 return &m_options;
311}
312
313const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
314
315void
316CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
317(
Greg Clayton63094e02010-06-23 01:19:29 +0000318 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000319 BreakpointOptions *bp_options,
320 CommandReturnObject &result
321)
322{
Greg Clayton63094e02010-06-23 01:19:29 +0000323 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger()));
Chris Lattner24943d22010-06-08 16:52:24 +0000324 std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
325 if (reader_sp && data_ap.get())
326 {
327 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
328 bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
329
330 Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
331 bp_options, // baton
332 eInputReaderGranularityLine, // token size, to pass to callback function
333 "DONE", // end token
334 "> ", // prompt
335 true)); // echo input
336 if (err.Success())
337 {
Greg Clayton63094e02010-06-23 01:19:29 +0000338 interpreter.GetDebugger().PushInputReader (reader_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000339 result.SetStatus (eReturnStatusSuccessFinishNoResult);
340 }
341 else
342 {
343 result.AppendError (err.AsCString());
344 result.SetStatus (eReturnStatusFailed);
345 }
346 }
347 else
348 {
349 result.AppendError("out of memory");
350 result.SetStatus (eReturnStatusFailed);
351 }
352
353}
354
355size_t
356CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
357(
358 void *baton,
Greg Clayton63094e02010-06-23 01:19:29 +0000359 InputReader &reader,
Chris Lattner24943d22010-06-08 16:52:24 +0000360 lldb::InputReaderAction notification,
361 const char *bytes,
362 size_t bytes_len
363)
364{
Greg Clayton63094e02010-06-23 01:19:29 +0000365 FILE *out_fh = reader.GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000366
367 switch (notification)
368 {
369 case eInputReaderActivate:
370 if (out_fh)
371 {
372 ::fprintf (out_fh, "%s\n", g_reader_instructions);
Greg Clayton63094e02010-06-23 01:19:29 +0000373 if (reader.GetPrompt())
374 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000375 }
376 break;
377
378 case eInputReaderDeactivate:
379 break;
380
381 case eInputReaderReactivate:
Greg Clayton63094e02010-06-23 01:19:29 +0000382 if (out_fh && reader.GetPrompt())
383 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000384 break;
385
386 case eInputReaderGotToken:
387 if (bytes && bytes_len && baton)
388 {
389 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
390 if (bp_options)
391 {
392 Baton *bp_options_baton = bp_options->GetBaton();
393 if (bp_options_baton)
394 ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
395 }
396 }
Greg Clayton63094e02010-06-23 01:19:29 +0000397 if (out_fh && !reader.IsDone() && reader.GetPrompt())
398 ::fprintf (out_fh, "%s", reader.GetPrompt());
Chris Lattner24943d22010-06-08 16:52:24 +0000399 break;
400
401 case eInputReaderDone:
402 break;
403 }
404
405 return bytes_len;
406}
407
408
409//-------------------------------------------------------------------------
410// CommandObjectBreakpointCommandRemove
411//-------------------------------------------------------------------------
412
413CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () :
414 CommandObject ("remove",
415 "Remove the set of commands from a breakpoint.",
416 "breakpoint command remove <breakpoint-id>")
417{
418}
419
420CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
421{
422}
423
424bool
Greg Clayton63094e02010-06-23 01:19:29 +0000425CommandObjectBreakpointCommandRemove::Execute
426(
427 CommandInterpreter &interpreter,
428 Args& command,
429 CommandReturnObject &result
430)
Chris Lattner24943d22010-06-08 16:52:24 +0000431{
Jim Inghamc8332952010-08-26 21:32:51 +0000432 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000433
434 if (target == NULL)
435 {
436 result.AppendError ("There is not a current executable; there are no breakpoints from which to remove commands");
437 result.SetStatus (eReturnStatusFailed);
438 return false;
439 }
440
441 const BreakpointList &breakpoints = target->GetBreakpointList();
442 size_t num_breakpoints = breakpoints.GetSize();
443
444 if (num_breakpoints == 0)
445 {
446 result.AppendError ("No breakpoints exist to have commands removed");
447 result.SetStatus (eReturnStatusFailed);
448 return false;
449 }
450
451 if (command.GetArgumentCount() == 0)
452 {
453 result.AppendError ("No breakpoint specified from which to remove the commands");
454 result.SetStatus (eReturnStatusFailed);
455 return false;
456 }
457
458 BreakpointIDList valid_bp_ids;
459 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
460
461 if (result.Succeeded())
462 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000463 const size_t count = valid_bp_ids.GetSize();
464 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000465 {
466 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
467 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
468 {
469 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
470 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
471 {
472 BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
473 if (bp_loc_sp)
474 bp_loc_sp->ClearCallback();
475 else
476 {
477 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
478 cur_bp_id.GetBreakpointID(),
479 cur_bp_id.GetLocationID());
480 result.SetStatus (eReturnStatusFailed);
481 return false;
482 }
483 }
484 else
485 {
486 bp->ClearCallback();
487 }
488 }
489 }
490 }
491 return result.Succeeded();
492}
493
494
495//-------------------------------------------------------------------------
496// CommandObjectBreakpointCommandList
497//-------------------------------------------------------------------------
498
499CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () :
500 CommandObject ("List",
501 "List the script or set of commands to be executed when the breakpoint is hit.",
502 "breakpoint command list <breakpoint-id>")
503{
504}
505
506CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
507{
508}
509
510bool
Greg Clayton63094e02010-06-23 01:19:29 +0000511CommandObjectBreakpointCommandList::Execute
512(
513 CommandInterpreter &interpreter,
514 Args& command,
515 CommandReturnObject &result
516)
Chris Lattner24943d22010-06-08 16:52:24 +0000517{
Jim Inghamc8332952010-08-26 21:32:51 +0000518 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000519
520 if (target == NULL)
521 {
522 result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
523 result.SetStatus (eReturnStatusFailed);
524 return false;
525 }
526
527 const BreakpointList &breakpoints = target->GetBreakpointList();
528 size_t num_breakpoints = breakpoints.GetSize();
529
530 if (num_breakpoints == 0)
531 {
532 result.AppendError ("No breakpoints exist for which to list commands");
533 result.SetStatus (eReturnStatusFailed);
534 return false;
535 }
536
537 if (command.GetArgumentCount() == 0)
538 {
539 result.AppendError ("No breakpoint specified for which to list the commands");
540 result.SetStatus (eReturnStatusFailed);
541 return false;
542 }
543
544 BreakpointIDList valid_bp_ids;
545 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
546
547 if (result.Succeeded())
548 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000549 const size_t count = valid_bp_ids.GetSize();
550 for (size_t i = 0; i < count; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000551 {
552 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
553 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
554 {
555 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
556
557 if (bp)
558 {
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000559 const BreakpointOptions *bp_options = NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000560 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
561 {
562 BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
563 if (bp_loc_sp)
Jim Ingham9c6898b2010-06-22 21:12:54 +0000564 bp_options = bp_loc_sp->GetOptionsNoCreate();
Chris Lattner24943d22010-06-08 16:52:24 +0000565 else
566 {
567 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
568 cur_bp_id.GetBreakpointID(),
569 cur_bp_id.GetLocationID());
570 result.SetStatus (eReturnStatusFailed);
571 return false;
572 }
573 }
574 else
575 {
576 bp_options = bp->GetOptions();
577 }
578
579 if (bp_options)
580 {
581 StreamString id_str;
582 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000583 const Baton *baton = bp_options->GetBaton();
Chris Lattner24943d22010-06-08 16:52:24 +0000584 if (baton)
585 {
586 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
587 result.GetOutputStream().IndentMore ();
588 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
589 result.GetOutputStream().IndentLess ();
590 }
591 else
592 {
593 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
594 }
595 }
596 result.SetStatus (eReturnStatusSuccessFinishResult);
597 }
598 else
599 {
600 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
601 result.SetStatus (eReturnStatusFailed);
602 }
603
604 }
605 }
606 }
607
608 return result.Succeeded();
609}
610
611//-------------------------------------------------------------------------
612// CommandObjectBreakpointCommand
613//-------------------------------------------------------------------------
614
Greg Clayton63094e02010-06-23 01:19:29 +0000615CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000616 CommandObjectMultiword ("command",
617 "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
618 "command <sub-command> [<sub-command-options>] <breakpoint-id>")
619{
620 bool status;
621 CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ());
622 CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ());
623 CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ());
624
625 add_command_object->SetCommandName ("breakpoint command add");
626 remove_command_object->SetCommandName ("breakpoint command remove");
627 list_command_object->SetCommandName ("breakpoint command list");
628
Greg Clayton63094e02010-06-23 01:19:29 +0000629 status = LoadSubCommand (interpreter, "add", add_command_object);
630 status = LoadSubCommand (interpreter, "remove", remove_command_object);
631 status = LoadSubCommand (interpreter, "list", list_command_object);
Chris Lattner24943d22010-06-08 16:52:24 +0000632}
633
634
635CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
636{
637}
638
639bool
640CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
641(
642 void *baton,
643 StoppointCallbackContext *context,
644 lldb::user_id_t break_id,
645 lldb::user_id_t break_loc_id
646)
647{
648 bool ret_value = true;
649 if (baton == NULL)
650 return true;
651
652
653 BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
654 StringList &commands = data->user_source;
655
656 if (commands.GetSize() > 0)
657 {
658 uint32_t num_commands = commands.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000659 CommandReturnObject result;
Greg Clayton63094e02010-06-23 01:19:29 +0000660 if (context->exe_ctx.target)
Chris Lattner24943d22010-06-08 16:52:24 +0000661 {
Greg Clayton63094e02010-06-23 01:19:29 +0000662
663 Debugger &debugger = context->exe_ctx.target->GetDebugger();
664 CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
665
666 FILE *out_fh = debugger.GetOutputFileHandle();
667 FILE *err_fh = debugger.GetErrorFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000668
Greg Clayton63094e02010-06-23 01:19:29 +0000669 uint32_t i;
670 for (i = 0; i < num_commands; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000671 {
Greg Clayton63094e02010-06-23 01:19:29 +0000672
673 // First time through we use the context from the stoppoint, after that we use whatever
674 // has been set by the previous command.
675
676 if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx))
677 break;
678
679 // FIXME: This isn't really the right way to do this. We should be able to peek at the public
680 // to see if there is any new events, but that is racey, since the internal process thread has to run and
681 // deliver the event to the public queue before a run will show up. So for now we check
682 // the internal thread state.
683
684 lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState();
685 if (internal_state != eStateStopped)
Chris Lattner24943d22010-06-08 16:52:24 +0000686 {
Greg Clayton63094e02010-06-23 01:19:29 +0000687 if (i < num_commands - 1)
688 {
689 if (out_fh)
690 ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
691 " last command: \"%s\"\n", StateAsCString(internal_state),
692 commands.GetStringAtIndex(i));
693 }
694 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000695 }
Greg Clayton63094e02010-06-23 01:19:29 +0000696
697 if (out_fh)
698 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
699 if (err_fh)
700 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
701 result.Clear();
702 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000703 }
Chris Lattner24943d22010-06-08 16:52:24 +0000704
Greg Clayton63094e02010-06-23 01:19:29 +0000705 if (err_fh && !result.Succeeded() && i < num_commands)
706 ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
707
Chris Lattner24943d22010-06-08 16:52:24 +0000708 if (out_fh)
709 ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
Greg Clayton63094e02010-06-23 01:19:29 +0000710
Chris Lattner24943d22010-06-08 16:52:24 +0000711 if (err_fh)
Greg Clayton63094e02010-06-23 01:19:29 +0000712 ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000713 }
Chris Lattner24943d22010-06-08 16:52:24 +0000714 }
715 return ret_value;
716}
717