blob: 68926e24b6d506cd4009ce75ea321837a23963c1 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.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#include "CommandObjectBreakpoint.h"
11#include "CommandObjectBreakpointCommand.h"
12
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16// Project includes
17#include "lldb/Breakpoint/Breakpoint.h"
18#include "lldb/Breakpoint/BreakpointIDList.h"
19#include "lldb/Breakpoint/BreakpointLocation.h"
Jim Ingham86511212010-06-15 18:47:14 +000020#include "lldb/Core/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Core/RegularExpression.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Interpreter/CommandCompletions.h"
27#include "lldb/Target/StackFrame.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32static void
33AddBreakpointDescription (CommandContext *context, StreamString *s, Breakpoint *bp, lldb::DescriptionLevel level)
34{
35 s->IndentMore();
36 bp->GetDescription (s, level, true);
37 s->IndentLess();
38 s->EOL();
39}
40
41//-------------------------------------------------------------------------
42// CommandObjectBreakpointSet::CommandOptions
43//-------------------------------------------------------------------------
44
45CommandObjectBreakpointSet::CommandOptions::CommandOptions() :
46 Options (),
47 m_filename (),
48 m_line_num (0),
49 m_column (0),
50 m_ignore_inlines (false),
51 m_func_name (),
52 m_func_regexp (),
53 m_modules (),
54 m_load_addr()
55{
56 BuildValidOptionSets();
57}
58
59CommandObjectBreakpointSet::CommandOptions::~CommandOptions ()
60{
61}
62
63lldb::OptionDefinition
64CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
65{
Jim Ingham86511212010-06-15 18:47:14 +000066 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
67 "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
68
69 { LLDB_OPT_SET_ALL, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL,
70 "Ignore inlined subroutines when setting the breakppoint." },
71
72 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<filename>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073 "Set the breakpoint by source location in this particular file."},
74
Jim Ingham86511212010-06-15 18:47:14 +000075 { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, "<linenum>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076 "Set the breakpoint by source location at this particular line."},
77
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 // Comment out this option for the moment, as we don't actually use it, but will in the future.
79 // This way users won't see it, but the infrastructure is left in place.
80 // { 0, false, "column", 'c', required_argument, NULL, "<column>",
81 // "Set the breakpoint by source location at this particular column."},
82
Jim Ingham86511212010-06-15 18:47:14 +000083 { LLDB_OPT_SET_2, true, "address", 'a', required_argument, NULL, 0, "<address>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084 "Set the breakpoint by address, at the specified address."},
85
Jim Ingham86511212010-06-15 18:47:14 +000086 { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000087 "Set the breakpoint by function name." },
88
Jim Ingham86511212010-06-15 18:47:14 +000089 { LLDB_OPT_SET_4, true, "func_regex", 'r', required_argument, NULL, 0, "<regular-expression>",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000090 "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
91
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
93};
94
95const lldb::OptionDefinition*
96CommandObjectBreakpointSet::CommandOptions::GetDefinitions ()
97{
98 return g_option_table;
99}
100
101Error
102CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
103{
104 Error error;
105 char short_option = (char) m_getopt_table[option_idx].val;
106
107 switch (short_option)
108 {
109 case 'a':
110 m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
111 if (m_load_addr == LLDB_INVALID_ADDRESS)
112 m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
113
114 if (m_load_addr == LLDB_INVALID_ADDRESS)
115 error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
116 break;
117
118 case 'c':
119 m_column = Args::StringToUInt32 (option_arg, 0);
120 break;
121 case 'f':
122 m_filename = option_arg;
123 break;
124 case 'i':
125 m_ignore_inlines = true;
126 break;
127 case 'l':
128 m_line_num = Args::StringToUInt32 (option_arg, 0);
129 break;
130 case 'n':
131 m_func_name = option_arg;
132 break;
133 case 'r':
134 m_func_regexp = option_arg;
135 break;
136 case 's':
137 {
138 m_modules.push_back (std::string (option_arg));
139 break;
140 }
141 default:
142 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
143 break;
144 }
145
146 return error;
147}
148
149void
150CommandObjectBreakpointSet::CommandOptions::ResetOptionValues ()
151{
152 Options::ResetOptionValues();
153
154 m_filename.clear();
155 m_line_num = 0;
156 m_column = 0;
157 m_ignore_inlines = false;
158 m_func_name.clear();
159 m_func_regexp.clear();
160 m_load_addr = LLDB_INVALID_ADDRESS;
161 m_modules.clear();
162}
163
164//-------------------------------------------------------------------------
165// CommandObjectBreakpointSet
166//-------------------------------------------------------------------------
167
168CommandObjectBreakpointSet::CommandObjectBreakpointSet () :
169 CommandObject ("breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.",
170 "breakpoint set <cmd-options>")
171{
172}
173
174CommandObjectBreakpointSet::~CommandObjectBreakpointSet ()
175{
176}
177
178Options *
179CommandObjectBreakpointSet::GetOptions ()
180{
181 return &m_options;
182}
183
184bool
185CommandObjectBreakpointSet::Execute
186(
187 Args& command,
188 CommandContext *context,
189 CommandInterpreter *interpreter,
190 CommandReturnObject &result
191)
192{
193 Target *target = context->GetTarget();
194 if (target == NULL)
195 {
196 result.AppendError ("Invalid target, set executable file using 'file' command.");
197 result.SetStatus (eReturnStatusFailed);
198 return false;
199 }
200
201 // The following are the various types of breakpoints that could be set:
202 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
203 // 2). -a [-s -g] (setting breakpoint by address)
204 // 3). -n [-s -g] (setting breakpoint by function name)
205 // 4). -r [-s -g] (setting breakpoint by function name regular expression)
206
207 BreakpointSetType break_type = eSetTypeInvalid;
208
209 if (m_options.m_line_num != 0)
210 break_type = eSetTypeFileAndLine;
211 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
212 break_type = eSetTypeAddress;
213 else if (!m_options.m_func_name.empty())
214 break_type = eSetTypeFunctionName;
215 else if (!m_options.m_func_regexp.empty())
216 break_type = eSetTypeFunctionRegexp;
217
218 ModuleSP module_sp = target->GetExecutableModule();
219 Breakpoint *bp = NULL;
220 FileSpec module;
221 bool use_module = false;
222 int num_modules = m_options.m_modules.size();
223
224 if ((num_modules > 0) && (break_type != eSetTypeAddress))
225 use_module = true;
226
227 switch (break_type)
228 {
229 case eSetTypeFileAndLine: // Breakpoint by source position
230 {
231 FileSpec file;
232 if (m_options.m_filename.empty())
233 {
234 StackFrame *cur_frame = context->GetExecutionContext().frame;
235 if (cur_frame == NULL)
236 {
237 result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
238 result.SetStatus (eReturnStatusFailed);
239 break;
240 }
241 else if (!cur_frame->HasDebugInformation())
242 {
243 result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
244 result.SetStatus (eReturnStatusFailed);
245 break;
246 }
247 else
248 {
249 const SymbolContext &context = cur_frame->GetSymbolContext(true);
250 if (context.line_entry.file)
251 {
252 file = context.line_entry.file;
253 }
254 else if (context.comp_unit != NULL)
255 { file = context.comp_unit;
256 }
257 else
258 {
259 result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
260 result.SetStatus (eReturnStatusFailed);
261 break;
262 }
263 }
264 }
265 else
266 {
267 file.SetFile(m_options.m_filename.c_str());
268 }
269
270 if (use_module)
271 {
272 for (int i = 0; i < num_modules; ++i)
273 {
274 module.SetFile(m_options.m_modules[i].c_str());
275 bp = target->CreateBreakpoint (&module,
276 file,
277 m_options.m_line_num,
278 m_options.m_ignore_inlines).get();
279 if (bp)
280 {
281 StreamString &output_stream = result.GetOutputStream();
282 output_stream.Printf ("Breakpoint created: ");
283 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
284 output_stream.EOL();
285 result.SetStatus (eReturnStatusSuccessFinishResult);
286 }
287 else
288 {
289 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
290 m_options.m_modules[i].c_str());
291 result.SetStatus (eReturnStatusFailed);
292 }
293 }
294 }
295 else
296 bp = target->CreateBreakpoint (NULL,
297 file,
298 m_options.m_line_num,
299 m_options.m_ignore_inlines).get();
300 }
301 break;
302 case eSetTypeAddress: // Breakpoint by address
303 bp = target->CreateBreakpoint (m_options.m_load_addr, false).get();
304 break;
305 case eSetTypeFunctionName: // Breakpoint by function name
306 if (use_module)
307 {
308 for (int i = 0; i < num_modules; ++i)
309 {
310 module.SetFile(m_options.m_modules[i].c_str());
311 bp = target->CreateBreakpoint (&module, m_options.m_func_name.c_str()).get();
312 if (bp)
313 {
314 StreamString &output_stream = result.GetOutputStream();
315 output_stream.Printf ("Breakpoint created: ");
316 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
317 output_stream.EOL();
318 result.SetStatus (eReturnStatusSuccessFinishResult);
319 }
320 else
321 {
322 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
323 m_options.m_modules[i].c_str());
324 result.SetStatus (eReturnStatusFailed);
325 }
326 }
327 }
328 else
329 bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str()).get();
330 break;
331 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
332 {
333 RegularExpression regexp(m_options.m_func_regexp.c_str());
334 if (use_module)
335 {
336 for (int i = 0; i < num_modules; ++i)
337 {
338 module.SetFile(m_options.m_modules[i].c_str());
339 bp = target->CreateBreakpoint (&module, regexp).get();
340 if (bp)
341 {
342 StreamString &output_stream = result.GetOutputStream();
343 output_stream.Printf ("Breakpoint created: ");
344 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
345 output_stream.EOL();
346 result.SetStatus (eReturnStatusSuccessFinishResult);
347 }
348 else
349 {
350 result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
351 m_options.m_modules[i].c_str());
352 result.SetStatus (eReturnStatusFailed);
353 }
354 }
355 }
356 else
357 bp = target->CreateBreakpoint (NULL, regexp).get();
358 }
359 break;
360 default:
361 break;
362 }
363
364 if (bp && !use_module)
365 {
366 StreamString &output_stream = result.GetOutputStream();
367 output_stream.Printf ("Breakpoint created: ");
368 bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
369 output_stream.EOL();
370 result.SetStatus (eReturnStatusSuccessFinishResult);
371 }
372 else if (!bp)
373 {
374 result.AppendError ("Breakpoint creation failed: No breakpoint created.");
375 result.SetStatus (eReturnStatusFailed);
376 }
377
378 return result.Succeeded();
379}
380
381
382
383//-------------------------------------------------------------------------
384// CommandObjectMultiwordBreakpoint
385//-------------------------------------------------------------------------
386
387CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter *interpreter) :
388 CommandObjectMultiword ("breakpoint",
389 "A set of commands for operating on breakpoints.",
390 "breakpoint <command> [<command-options>]")
391{
392 bool status;
393
394 CommandObjectSP list_command_object (new CommandObjectBreakpointList ());
395 CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete ());
396 CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable ());
397 CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable ());
398 CommandObjectSP set_command_object (new CommandObjectBreakpointSet ());
399 CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
400
401 enable_command_object->SetCommandName("breakpoint enable");
402 disable_command_object->SetCommandName("breakpoint disable");
403 set_command_object->SetCommandName("breakpoint set");
404 command_command_object->SetCommandName ("breakpoint command");
405 list_command_object->SetCommandName ("breakpoint list");
406
407 status = LoadSubCommand (list_command_object, "list", interpreter);
408 status = LoadSubCommand (enable_command_object, "enable", interpreter);
409 status = LoadSubCommand (disable_command_object, "disable", interpreter);
410 status = LoadSubCommand (delete_command_object, "delete", interpreter);
411 status = LoadSubCommand (set_command_object, "set", interpreter);
412 status = LoadSubCommand (command_command_object, "command", interpreter);
413}
414
415CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
416{
417}
418
419void
420CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
421 BreakpointIDList *valid_ids)
422{
423 // args can be strings representing 1). integers (for breakpoint ids)
424 // 2). the full breakpoint & location canonical representation
425 // 3). the word "to" or a hyphen, representing a range (in which case there
426 // had *better* be an entry both before & after of one of the first two types.
427
428 Args temp_args;
429
430 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
431 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for
432 // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
433
434 BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
435
436 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
437
438 valid_ids->InsertStringArray ((const char **) temp_args.GetArgumentVector(), temp_args.GetArgumentCount(), result);
439
440 // At this point, all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
441 // and put into valid_ids.
442
443 if (result.Succeeded())
444 {
445 // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
446 // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
447
448 for (int i = 0; i < valid_ids->Size(); ++i)
449 {
450 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
451 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
452 if (breakpoint != NULL)
453 {
454 int num_locations = breakpoint->GetNumLocations();
455 if (cur_bp_id.GetLocationID() > num_locations)
456 {
457 StreamString id_str;
458 BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(),
459 cur_bp_id.GetLocationID());
460 i = valid_ids->Size() + 1;
461 result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
462 id_str.GetData());
463 result.SetStatus (eReturnStatusFailed);
464 }
465 }
466 else
467 {
468 i = valid_ids->Size() + 1;
469 result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
470 result.SetStatus (eReturnStatusFailed);
471 }
472 }
473 }
474}
475
476//-------------------------------------------------------------------------
477// CommandObjectBreakpointList::Options
478//-------------------------------------------------------------------------
479
480CommandObjectBreakpointList::CommandOptions::CommandOptions() :
481 Options (),
482 m_level (lldb::eDescriptionLevelFull) // Breakpoint List defaults to brief descriptions
483{
484 BuildValidOptionSets();
485}
486
487CommandObjectBreakpointList::CommandOptions::~CommandOptions ()
488{
489}
490
491lldb::OptionDefinition
492CommandObjectBreakpointList::CommandOptions::g_option_table[] =
493{
Jim Ingham86511212010-06-15 18:47:14 +0000494 { LLDB_OPT_SET_ALL, false, "internal", 'i', no_argument, NULL, 0, NULL,
495 "Show debugger internal breakpoints" },
496
497 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, NULL,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000498 "Give a brief description of the breakpoint (no location info)."},
499
500 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
501 // But I need to see it for now, and don't want to wait.
Jim Ingham86511212010-06-15 18:47:14 +0000502 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, NULL,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000503 "Give a full description of the breakpoint and its locations."},
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000504
Jim Ingham86511212010-06-15 18:47:14 +0000505 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, NULL,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000506 "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000507
508 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
509};
510
511const lldb::OptionDefinition*
512CommandObjectBreakpointList::CommandOptions::GetDefinitions ()
513{
514 return g_option_table;
515}
516
517Error
518CommandObjectBreakpointList::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
519{
520 Error error;
521 char short_option = (char) m_getopt_table[option_idx].val;
522
523 switch (short_option)
524 {
525 case 'b':
526 m_level = lldb::eDescriptionLevelBrief;
527 break;
528 case 'f':
529 m_level = lldb::eDescriptionLevelFull;
530 break;
531 case 'v':
532 m_level = lldb::eDescriptionLevelVerbose;
533 break;
534 case 'i':
535 m_internal = true;
536 break;
537 default:
538 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
539 break;
540 }
541
542 return error;
543}
544
545void
546CommandObjectBreakpointList::CommandOptions::ResetOptionValues ()
547{
548 Options::ResetOptionValues();
549
550 m_level = lldb::eDescriptionLevelFull;
551 m_internal = false;
552}
553
554//-------------------------------------------------------------------------
555// CommandObjectBreakpointList
556//-------------------------------------------------------------------------
557
558CommandObjectBreakpointList::CommandObjectBreakpointList () :
559 CommandObject ("breakpoint list",
560 "List some or all breakpoints at configurable levels of detail.",
561 "breakpoint list [<breakpoint-id>]")
562{
563}
564
565CommandObjectBreakpointList::~CommandObjectBreakpointList ()
566{
567}
568
569Options *
570CommandObjectBreakpointList::GetOptions ()
571{
572 return &m_options;
573}
574
575bool
576CommandObjectBreakpointList::Execute
577(
578 Args& args,
579 CommandContext *context,
580 CommandInterpreter *interpreter,
581 CommandReturnObject &result
582)
583{
584 Target *target = context->GetTarget();
585 if (target == NULL)
586 {
587 result.AppendError ("Invalid target, set executable file using 'file' command.");
588 result.SetStatus (eReturnStatusSuccessFinishNoResult);
589 return true;
590 }
591
592 const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
593 size_t num_breakpoints = breakpoints.GetSize();
594
595 if (num_breakpoints == 0)
596 {
597 result.AppendMessage ("No breakpoints currently set.");
598 result.SetStatus (eReturnStatusSuccessFinishNoResult);
599 return true;
600 }
601
602 StreamString &output_stream = result.GetOutputStream();
603
604 if (args.GetArgumentCount() == 0)
605 {
606 // No breakpoint selected; show info about all currently set breakpoints.
607 result.AppendMessage ("Current breakpoints:");
608 for (int i = 0; i < num_breakpoints; ++i)
609 {
610 Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (i).get();
611 AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
612 }
613 result.SetStatus (eReturnStatusSuccessFinishNoResult);
614 }
615 else
616 {
617 // Particular breakpoints selected; show info about that breakpoint.
618 BreakpointIDList valid_bp_ids;
619 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
620
621 if (result.Succeeded())
622 {
623 for (int i = 0; i < valid_bp_ids.Size(); ++i)
624 {
625 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
626 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
627 AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
628 }
629 result.SetStatus (eReturnStatusSuccessFinishNoResult);
630 }
631 else
632 {
633 result.AppendError ("Invalid breakpoint id.");
634 result.SetStatus (eReturnStatusFailed);
635 }
636 }
637
638 return result.Succeeded();
639}
640
641//-------------------------------------------------------------------------
642// CommandObjectBreakpointEnable
643//-------------------------------------------------------------------------
644
645CommandObjectBreakpointEnable::CommandObjectBreakpointEnable () :
646 CommandObject ("enable",
647 "Enables the specified disabled breakpoint(s). If no breakpoints are specified, enables all of them.",
648 "breakpoint enable [<breakpoint-id> | <breakpoint-id-list>]")
649{
650 // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different
651 // potential invocation methods, we need to be a little tricky about generating the syntax string.
652 //StreamString tmp_string;
653 //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
654 //m_cmd_syntax.assign (tmp_string.GetData(), tmp_string.GetSize());
655}
656
657
658CommandObjectBreakpointEnable::~CommandObjectBreakpointEnable ()
659{
660}
661
662
663bool
664CommandObjectBreakpointEnable::Execute (Args& args, CommandContext *context,
665 CommandInterpreter *interpreter, CommandReturnObject &result)
666{
667 Target *target = context->GetTarget();
668 if (target == NULL)
669 {
670 result.AppendError ("Invalid target, set executable file using 'file' command.");
671 result.SetStatus (eReturnStatusFailed);
672 return false;
673 }
674
675 const BreakpointList &breakpoints = target->GetBreakpointList();
676 size_t num_breakpoints = breakpoints.GetSize();
677
678 if (num_breakpoints == 0)
679 {
680 result.AppendError ("No breakpoints exist to be enabled.");
681 result.SetStatus (eReturnStatusFailed);
682 return false;
683 }
684
685 if (args.GetArgumentCount() == 0)
686 {
687 // No breakpoint selected; enable all currently set breakpoints.
688 target->EnableAllBreakpoints ();
689 result.AppendMessageWithFormat ("All breakpoints enabled. (%d breakpoints)\n", num_breakpoints);
690 result.SetStatus (eReturnStatusSuccessFinishNoResult);
691 }
692 else
693 {
694 // Particular breakpoint selected; enable that breakpoint.
695 BreakpointIDList valid_bp_ids;
696 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
697
698 if (result.Succeeded())
699 {
700 int enable_count = 0;
701 int loc_count = 0;
702 for (int i = 0; i < valid_bp_ids.Size(); ++i)
703 {
704 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
705
706 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
707 {
708 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
709 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
710 {
711 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
712 if (location)
713 {
714 location->SetEnabled (true);
715 breakpoint->SetEnabled (true);
716 ++loc_count;
717 }
718 }
719 else
720 {
721 target->EnableBreakpointByID (cur_bp_id.GetBreakpointID());
722 ++enable_count;
723
724 int num_locations = breakpoint->GetNumLocations ();
725 for (int j = 0; j < num_locations; ++j)
726 {
727 BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
728 if (cur_loc)
729 cur_loc->SetEnabled (true);
730 }
731 }
732 }
733 }
734 result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
735 result.SetStatus (eReturnStatusSuccessFinishNoResult);
736 }
737 }
738
739 return result.Succeeded();
740}
741
742//-------------------------------------------------------------------------
743// CommandObjectBreakpointDisable
744//-------------------------------------------------------------------------
745
746CommandObjectBreakpointDisable::CommandObjectBreakpointDisable () :
747 CommandObject ("disable",
748 "Disables the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disables them all.",
749 "disable [<breakpoint-id> | <breakpoint-id-list>]")
750{
751 // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different
752 // potential invocation methods, we need to be a little tricky about generating the syntax string.
753 //StreamString tmp_string;
754 //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
755 //m_cmd_syntax.assign(tmp_string.GetData(), tmp_string.GetSize());
756}
757
758CommandObjectBreakpointDisable::~CommandObjectBreakpointDisable ()
759{
760}
761
762bool
763CommandObjectBreakpointDisable::Execute (Args& args, CommandContext *context,
764 CommandInterpreter *interpreter, CommandReturnObject &result)
765{
766 Target *target = context->GetTarget();
767 if (target == NULL)
768 {
769 result.AppendError ("Invalid target, set executable file using 'file' command.");
770 result.SetStatus (eReturnStatusFailed);
771 return false;
772 }
773
774 const BreakpointList &breakpoints = target->GetBreakpointList();
775 size_t num_breakpoints = breakpoints.GetSize();
776
777 if (num_breakpoints == 0)
778 {
779 result.AppendError ("No breakpoints exist to be disabled.");
780 result.SetStatus (eReturnStatusFailed);
781 return false;
782 }
783
784 if (args.GetArgumentCount() == 0)
785 {
786 // No breakpoint selected; disable all currently set breakpoints.
787 target->DisableAllBreakpoints ();
788 result.AppendMessageWithFormat ("All breakpoints disabled. (%d breakpoints)\n", num_breakpoints);
789 result.SetStatus (eReturnStatusSuccessFinishNoResult);
790 }
791 else
792 {
793 // Particular breakpoint selected; disable that breakpoint.
794 BreakpointIDList valid_bp_ids;
795
796 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
797
798 if (result.Succeeded())
799 {
800 int disable_count = 0;
801 int loc_count = 0;
802 for (int i = 0; i < valid_bp_ids.Size(); ++i)
803 {
804 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
805
806 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
807 {
808 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
809 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
810 {
811 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
812 if (location)
813 {
814 location->SetEnabled (false);
815 ++loc_count;
816 }
817 }
818 else
819 {
820 target->DisableBreakpointByID (cur_bp_id.GetBreakpointID());
821 ++disable_count;
822
823 int num_locations = breakpoint->GetNumLocations();
824 for (int j = 0; j < num_locations; ++j)
825 {
826 BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
827 if (cur_loc)
828 cur_loc->SetEnabled (false);
829 }
830 }
831 }
832 }
833 result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
834 result.SetStatus (eReturnStatusSuccessFinishNoResult);
835 }
836 }
837
838 return result.Succeeded();
839}
840
841//-------------------------------------------------------------------------
842// CommandObjectBreakpointDelete
843//-------------------------------------------------------------------------
844
845CommandObjectBreakpointDelete::CommandObjectBreakpointDelete() :
846 CommandObject ("breakpoint delete",
847 "Delete the specified breakpoint(s). If no breakpoints are specified, deletes them all.",
848 "breakpoint delete [<breakpoint-id> | <breakpoint-id-list>]")
849{
850}
851
852
853CommandObjectBreakpointDelete::~CommandObjectBreakpointDelete ()
854{
855}
856
857bool
858CommandObjectBreakpointDelete::Execute (Args& args, CommandContext *context,
859 CommandInterpreter *interpreter, CommandReturnObject &result)
860{
861 Target *target = context->GetTarget();
862 if (target == NULL)
863 {
864 result.AppendError ("Invalid target, set executable file using 'file' command.");
865 result.SetStatus (eReturnStatusFailed);
866 return false;
867 }
868
869 const BreakpointList &breakpoints = target->GetBreakpointList();
870 size_t num_breakpoints = breakpoints.GetSize();
871
872 if (num_breakpoints == 0)
873 {
874 result.AppendError ("No breakpoints exist to be deleted.");
875 result.SetStatus (eReturnStatusFailed);
876 return false;
877 }
878
879 if (args.GetArgumentCount() == 0)
880 {
881 // No breakpoint selected; disable all currently set breakpoints.
882 if (args.GetArgumentCount() != 0)
883 {
884 result.AppendErrorWithFormat ("Specify breakpoints to delete with the -i option.\n");
885 result.SetStatus (eReturnStatusFailed);
886 return false;
887 }
888
889 target->RemoveAllBreakpoints ();
890 result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
891 result.SetStatus (eReturnStatusSuccessFinishNoResult);
892 }
893 else
894 {
895 // Particular breakpoint selected; disable that breakpoint.
896 BreakpointIDList valid_bp_ids;
897 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
898
899 if (result.Succeeded())
900 {
901 int delete_count = 0;
902 int disable_count = 0;
903 for (int i = 0; i < valid_bp_ids.Size(); ++i)
904 {
905 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
906
907 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
908 {
909 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
910 {
911 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
912 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
913 // It makes no sense to try to delete individual locations, so we disable them instead.
914 if (location)
915 {
916 location->SetEnabled (false);
917 ++disable_count;
918 }
919 }
920 else
921 {
922 target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
923 ++delete_count;
924 }
925 }
926 }
927 result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
928 delete_count, disable_count);
929 result.SetStatus (eReturnStatusSuccessFinishNoResult);
930 }
931 }
932 return result.Succeeded();
933}