1 //===-- 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"
20 #include "lldb/Interpreter/Options.h"
21 #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 #include "lldb/Target/Thread.h"
29 #include "lldb/Target/ThreadSpec.h"
30 
31 #include <vector>
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 static void
37 AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level)
38 {
39     s->IndentMore();
40     bp->GetDescription (s, level, true);
41     s->IndentLess();
42     s->EOL();
43 }
44 
45 //-------------------------------------------------------------------------
46 // CommandObjectBreakpointSet::CommandOptions
47 //-------------------------------------------------------------------------
48 #pragma mark Set::CommandOptions
49 
50 CommandObjectBreakpointSet::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
51     Options (interpreter),
52     m_filename (),
53     m_line_num (0),
54     m_column (0),
55     m_check_inlines (true),
56     m_func_name (),
57     m_func_name_type_mask (0),
58     m_func_regexp (),
59     m_modules (),
60     m_load_addr(),
61     m_ignore_count (0),
62     m_thread_id(LLDB_INVALID_THREAD_ID),
63     m_thread_index (UINT32_MAX),
64     m_thread_name(),
65     m_queue_name()
66 {
67 }
68 
69 CommandObjectBreakpointSet::CommandOptions::~CommandOptions ()
70 {
71 }
72 
73 OptionDefinition
74 CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
75 {
76     { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
77         "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
78 
79     { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument,   NULL, 0, eArgTypeCount,
80         "Set the number of times this breakpoint is skipped before stopping." },
81 
82     { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex,
83         "The breakpoint stops only for the thread whose index matches this argument."},
84 
85     { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID,
86         "The breakpoint stops only for the thread whose TID matches this argument."},
87 
88     { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName,
89         "The breakpoint stops only for the thread whose thread name matches this argument."},
90 
91     { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName,
92         "The breakpoint stops only for threads in the queue whose name is given by this argument."},
93 
94     { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
95         "Set the breakpoint by source location in this particular file."},
96 
97     { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
98         "Set the breakpoint by source location at this particular line."},
99 
100     // Comment out this option for the moment, as we don't actually use it, but will in the future.
101     // This way users won't see it, but the infrastructure is left in place.
102     //    { 0, false, "column",     'c', required_argument, NULL, "<column>",
103     //    "Set the breakpoint by source location at this particular column."},
104 
105     { LLDB_OPT_SET_2, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddress,
106         "Set the breakpoint by address, at the specified address."},
107 
108     { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
109         "Set the breakpoint by function name." },
110 
111     { LLDB_OPT_SET_4, true, "fullname", 'F', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
112         "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguemnts, and "
113         "for Objective C this means a full function prototype with class and selector." },
114 
115     { LLDB_OPT_SET_5, true, "selector", 'S', required_argument, NULL, 0, eArgTypeSelector,
116         "Set the breakpoint by ObjC selector name." },
117 
118     { LLDB_OPT_SET_6, true, "method", 'M', required_argument, NULL, 0, eArgTypeMethod,
119         "Set the breakpoint by C++ method names." },
120 
121     { LLDB_OPT_SET_7, true, "func-regex", 'r', required_argument, NULL, 0, eArgTypeRegularExpression,
122         "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
123 
124     { LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
125         "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored)." },
126 
127     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
128 };
129 
130 const OptionDefinition*
131 CommandObjectBreakpointSet::CommandOptions::GetDefinitions ()
132 {
133     return g_option_table;
134 }
135 
136 Error
137 CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
138 {
139     Error error;
140     char short_option = (char) m_getopt_table[option_idx].val;
141 
142     switch (short_option)
143     {
144         case 'a':
145             m_load_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
146             if (m_load_addr == LLDB_INVALID_ADDRESS)
147                 m_load_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
148 
149             if (m_load_addr == LLDB_INVALID_ADDRESS)
150                 error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
151             break;
152 
153         case 'c':
154             m_column = Args::StringToUInt32 (option_arg, 0);
155             break;
156 
157         case 'f':
158             m_filename.assign (option_arg);
159             break;
160 
161         case 'l':
162             m_line_num = Args::StringToUInt32 (option_arg, 0);
163             break;
164 
165         case 'b':
166             m_func_name.assign (option_arg);
167             m_func_name_type_mask |= eFunctionNameTypeBase;
168             break;
169 
170         case 'n':
171             m_func_name.assign (option_arg);
172             m_func_name_type_mask |= eFunctionNameTypeAuto;
173             break;
174 
175         case 'F':
176             m_func_name.assign (option_arg);
177             m_func_name_type_mask |= eFunctionNameTypeFull;
178             break;
179 
180         case 'S':
181             m_func_name.assign (option_arg);
182             m_func_name_type_mask |= eFunctionNameTypeSelector;
183             break;
184 
185         case 'M':
186             m_func_name.assign (option_arg);
187             m_func_name_type_mask |= eFunctionNameTypeMethod;
188             break;
189 
190         case 'r':
191             m_func_regexp.assign (option_arg);
192             break;
193 
194         case 's':
195             {
196                 m_modules.push_back (std::string (option_arg));
197                 break;
198             }
199         case 'i':
200         {
201             m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
202             if (m_ignore_count == UINT32_MAX)
203                error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", option_arg);
204         }
205         break;
206         case 't' :
207         {
208             m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
209             if (m_thread_id == LLDB_INVALID_THREAD_ID)
210                error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg);
211         }
212         break;
213         case 'T':
214             m_thread_name.assign (option_arg);
215             break;
216         case 'q':
217             m_queue_name.assign (option_arg);
218             break;
219         case 'x':
220         {
221             m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
222             if (m_thread_id == UINT32_MAX)
223                error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg);
224 
225         }
226         break;
227         default:
228             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
229             break;
230     }
231 
232     return error;
233 }
234 
235 void
236 CommandObjectBreakpointSet::CommandOptions::OptionParsingStarting ()
237 {
238     m_filename.clear();
239     m_line_num = 0;
240     m_column = 0;
241     m_func_name.clear();
242     m_func_name_type_mask = 0;
243     m_func_regexp.clear();
244     m_load_addr = LLDB_INVALID_ADDRESS;
245     m_modules.clear();
246     m_ignore_count = 0;
247     m_thread_id = LLDB_INVALID_THREAD_ID;
248     m_thread_index = UINT32_MAX;
249     m_thread_name.clear();
250     m_queue_name.clear();
251 }
252 
253 //-------------------------------------------------------------------------
254 // CommandObjectBreakpointSet
255 //-------------------------------------------------------------------------
256 #pragma mark Set
257 
258 CommandObjectBreakpointSet::CommandObjectBreakpointSet (CommandInterpreter &interpreter) :
259     CommandObject (interpreter,
260                    "breakpoint set",
261                    "Sets a breakpoint or set of breakpoints in the executable.",
262                    "breakpoint set <cmd-options>"),
263     m_options (interpreter)
264 {
265 }
266 
267 CommandObjectBreakpointSet::~CommandObjectBreakpointSet ()
268 {
269 }
270 
271 Options *
272 CommandObjectBreakpointSet::GetOptions ()
273 {
274     return &m_options;
275 }
276 
277 bool
278 CommandObjectBreakpointSet::Execute
279 (
280     Args& command,
281     CommandReturnObject &result
282 )
283 {
284     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
285     if (target == NULL)
286     {
287         result.AppendError ("Invalid target.  Must set target before setting breakpoints (see 'file' command).");
288         result.SetStatus (eReturnStatusFailed);
289         return false;
290     }
291 
292     // The following are the various types of breakpoints that could be set:
293     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
294     //   2).  -a  [-s -g]         (setting breakpoint by address)
295     //   3).  -n  [-s -g]         (setting breakpoint by function name)
296     //   4).  -r  [-s -g]         (setting breakpoint by function name regular expression)
297 
298     BreakpointSetType break_type = eSetTypeInvalid;
299 
300     if (m_options.m_line_num != 0)
301         break_type = eSetTypeFileAndLine;
302     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
303         break_type = eSetTypeAddress;
304     else if (!m_options.m_func_name.empty())
305         break_type = eSetTypeFunctionName;
306     else if  (!m_options.m_func_regexp.empty())
307         break_type = eSetTypeFunctionRegexp;
308 
309     ModuleSP module_sp = target->GetExecutableModule();
310     Breakpoint *bp = NULL;
311     FileSpec module_spec;
312     bool use_module = false;
313     int num_modules = m_options.m_modules.size();
314 
315     if ((num_modules > 0) && (break_type != eSetTypeAddress))
316         use_module = true;
317 
318     switch (break_type)
319     {
320         case eSetTypeFileAndLine: // Breakpoint by source position
321             {
322                 FileSpec file;
323                 if (m_options.m_filename.empty())
324                 {
325                     StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame;
326                     if (cur_frame == NULL)
327                     {
328                         result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
329                         result.SetStatus (eReturnStatusFailed);
330                         break;
331                     }
332                     else if (!cur_frame->HasDebugInformation())
333                     {
334                         result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
335                         result.SetStatus (eReturnStatusFailed);
336                         break;
337                     }
338                     else
339                     {
340                         const SymbolContext &context = cur_frame->GetSymbolContext(true);
341                         if (context.line_entry.file)
342                         {
343                             file = context.line_entry.file;
344                         }
345                         else if (context.comp_unit != NULL)
346                         {    file = context.comp_unit;
347                         }
348                         else
349                         {
350                             result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
351                             result.SetStatus (eReturnStatusFailed);
352                             break;
353                         }
354                     }
355                 }
356                 else
357                 {
358                     file.SetFile(m_options.m_filename.c_str(), false);
359                 }
360 
361                 if (use_module)
362                 {
363                     for (int i = 0; i < num_modules; ++i)
364                     {
365                         module_spec.SetFile(m_options.m_modules[i].c_str(), false);
366                         bp = target->CreateBreakpoint (&module_spec,
367                                                        file,
368                                                        m_options.m_line_num,
369                                                        m_options.m_check_inlines).get();
370                         if (bp)
371                         {
372                             Stream &output_stream = result.GetOutputStream();
373                             result.AppendMessage ("Breakpoint created: ");
374                             bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
375                             output_stream.EOL();
376                             if (bp->GetNumLocations() == 0)
377                                 output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual"
378                                                       " locations.\n");
379                             result.SetStatus (eReturnStatusSuccessFinishResult);
380                         }
381                         else
382                         {
383                             result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
384                                                         m_options.m_modules[i].c_str());
385                             result.SetStatus (eReturnStatusFailed);
386                         }
387                     }
388                 }
389                 else
390                     bp = target->CreateBreakpoint (NULL,
391                                                    file,
392                                                    m_options.m_line_num,
393                                                    m_options.m_check_inlines).get();
394             }
395             break;
396 
397         case eSetTypeAddress: // Breakpoint by address
398             bp = target->CreateBreakpoint (m_options.m_load_addr, false).get();
399             break;
400 
401         case eSetTypeFunctionName: // Breakpoint by function name
402             {
403                 uint32_t name_type_mask = m_options.m_func_name_type_mask;
404 
405                 if (name_type_mask == 0)
406                     name_type_mask = eFunctionNameTypeAuto;
407 
408                 if (use_module)
409                 {
410                     for (int i = 0; i < num_modules; ++i)
411                     {
412                         module_spec.SetFile(m_options.m_modules[i].c_str(), false);
413                         bp = target->CreateBreakpoint (&module_spec,
414                                                        m_options.m_func_name.c_str(),
415                                                        name_type_mask,
416                                                        Breakpoint::Exact).get();
417                         if (bp)
418                         {
419                             Stream &output_stream = result.GetOutputStream();
420                             output_stream.Printf ("Breakpoint created: ");
421                             bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
422                             output_stream.EOL();
423                             if (bp->GetNumLocations() == 0)
424                                 output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual"
425                                                       " locations.\n");
426                             result.SetStatus (eReturnStatusSuccessFinishResult);
427                         }
428                         else
429                         {
430                             result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
431                                                         m_options.m_modules[i].c_str());
432                             result.SetStatus (eReturnStatusFailed);
433                         }
434                     }
435                 }
436                 else
437                     bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get();
438             }
439             break;
440 
441         case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
442             {
443                 RegularExpression regexp(m_options.m_func_regexp.c_str());
444                 if (use_module)
445                 {
446                     for (int i = 0; i < num_modules; ++i)
447                     {
448                         module_spec.SetFile(m_options.m_modules[i].c_str(), false);
449                         bp = target->CreateBreakpoint (&module_spec, regexp).get();
450                         if (bp)
451                         {
452                             Stream &output_stream = result.GetOutputStream();
453                             output_stream.Printf ("Breakpoint created: ");
454                             bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
455                             output_stream.EOL();
456                             if (bp->GetNumLocations() == 0)
457                                 output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual"
458                                                       " locations.\n");
459                             result.SetStatus (eReturnStatusSuccessFinishResult);
460                         }
461                         else
462                         {
463                             result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
464                                                         m_options.m_modules[i].c_str());
465                             result.SetStatus (eReturnStatusFailed);
466                         }
467                     }
468                 }
469                 else
470                     bp = target->CreateBreakpoint (NULL, regexp).get();
471             }
472             break;
473 
474         default:
475             break;
476     }
477 
478     // Now set the various options that were passed in:
479     if (bp)
480     {
481         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
482             bp->SetThreadID (m_options.m_thread_id);
483 
484         if (m_options.m_thread_index != UINT32_MAX)
485             bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
486 
487         if (!m_options.m_thread_name.empty())
488             bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
489 
490         if (!m_options.m_queue_name.empty())
491             bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
492 
493         if (m_options.m_ignore_count != 0)
494             bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
495     }
496 
497     if (bp && !use_module)
498     {
499         Stream &output_stream = result.GetOutputStream();
500         output_stream.Printf ("Breakpoint created: ");
501         bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
502         output_stream.EOL();
503         if (bp->GetNumLocations() == 0)
504             output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n");
505         result.SetStatus (eReturnStatusSuccessFinishResult);
506     }
507     else if (!bp)
508     {
509         result.AppendError ("Breakpoint creation failed: No breakpoint created.");
510         result.SetStatus (eReturnStatusFailed);
511     }
512 
513     return result.Succeeded();
514 }
515 
516 //-------------------------------------------------------------------------
517 // CommandObjectMultiwordBreakpoint
518 //-------------------------------------------------------------------------
519 #pragma mark MultiwordBreakpoint
520 
521 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter) :
522     CommandObjectMultiword (interpreter,
523                             "breakpoint",
524                             "A set of commands for operating on breakpoints. Also see regexp-break.",
525                             "breakpoint <command> [<command-options>]")
526 {
527     bool status;
528 
529     CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter));
530     CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter));
531     CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter));
532     CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter));
533     CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter));
534     CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));
535     CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
536     CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter));
537 
538     list_command_object->SetCommandName ("breakpoint list");
539     enable_command_object->SetCommandName("breakpoint enable");
540     disable_command_object->SetCommandName("breakpoint disable");
541     clear_command_object->SetCommandName("breakpoint clear");
542     delete_command_object->SetCommandName("breakpoint delete");
543     set_command_object->SetCommandName("breakpoint set");
544     command_command_object->SetCommandName ("breakpoint command");
545     modify_command_object->SetCommandName ("breakpoint modify");
546 
547     status = LoadSubCommand ("list",       list_command_object);
548     status = LoadSubCommand ("enable",     enable_command_object);
549     status = LoadSubCommand ("disable",    disable_command_object);
550     status = LoadSubCommand ("clear",      clear_command_object);
551     status = LoadSubCommand ("delete",     delete_command_object);
552     status = LoadSubCommand ("set",        set_command_object);
553     status = LoadSubCommand ("command",    command_command_object);
554     status = LoadSubCommand ("modify",     modify_command_object);
555 }
556 
557 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
558 {
559 }
560 
561 void
562 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
563                                                          BreakpointIDList *valid_ids)
564 {
565     // args can be strings representing 1). integers (for breakpoint ids)
566     //                                  2). the full breakpoint & location canonical representation
567     //                                  3). the word "to" or a hyphen, representing a range (in which case there
568     //                                      had *better* be an entry both before & after of one of the first two types.
569     // If args is empty, we will use the last created breakpoint (if there is one.)
570 
571     Args temp_args;
572 
573     if (args.GetArgumentCount() == 0)
574     {
575         if (target->GetLastCreatedBreakpoint() != NULL)
576         {
577             valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
578             result.SetStatus (eReturnStatusSuccessFinishNoResult);
579         }
580         else
581         {
582             result.AppendError("No breakpoint specified and no last created breakpoint.");
583             result.SetStatus (eReturnStatusFailed);
584         }
585         return;
586     }
587 
588     // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
589     // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for
590     // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
591 
592     BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
593 
594     // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
595 
596     valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result);
597 
598     // At this point,  all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
599     // and put into valid_ids.
600 
601     if (result.Succeeded())
602     {
603         // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
604         // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
605 
606         const size_t count = valid_ids->GetSize();
607         for (size_t i = 0; i < count; ++i)
608         {
609             BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
610             Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
611             if (breakpoint != NULL)
612             {
613                 int num_locations = breakpoint->GetNumLocations();
614                 if (cur_bp_id.GetLocationID() > num_locations)
615                 {
616                     StreamString id_str;
617                     BreakpointID::GetCanonicalReference (&id_str,
618                                                          cur_bp_id.GetBreakpointID(),
619                                                          cur_bp_id.GetLocationID());
620                     i = valid_ids->GetSize() + 1;
621                     result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
622                                                  id_str.GetData());
623                     result.SetStatus (eReturnStatusFailed);
624                 }
625             }
626             else
627             {
628                 i = valid_ids->GetSize() + 1;
629                 result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
630                 result.SetStatus (eReturnStatusFailed);
631             }
632         }
633     }
634 }
635 
636 //-------------------------------------------------------------------------
637 // CommandObjectBreakpointList::Options
638 //-------------------------------------------------------------------------
639 #pragma mark List::CommandOptions
640 
641 CommandObjectBreakpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
642     Options (interpreter),
643     m_level (lldb::eDescriptionLevelBrief)  // Breakpoint List defaults to brief descriptions
644 {
645 }
646 
647 CommandObjectBreakpointList::CommandOptions::~CommandOptions ()
648 {
649 }
650 
651 OptionDefinition
652 CommandObjectBreakpointList::CommandOptions::g_option_table[] =
653 {
654     { LLDB_OPT_SET_ALL, false, "internal", 'i', no_argument, NULL, 0, eArgTypeNone,
655         "Show debugger internal breakpoints" },
656 
657     { LLDB_OPT_SET_1, false, "brief",    'b', no_argument, NULL, 0, eArgTypeNone,
658         "Give a brief description of the breakpoint (no location info)."},
659 
660     // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
661     // But I need to see it for now, and don't want to wait.
662     { LLDB_OPT_SET_2, false, "full",    'f', no_argument, NULL, 0, eArgTypeNone,
663         "Give a full description of the breakpoint and its locations."},
664 
665     { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone,
666         "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
667 
668     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
669 };
670 
671 const OptionDefinition*
672 CommandObjectBreakpointList::CommandOptions::GetDefinitions ()
673 {
674     return g_option_table;
675 }
676 
677 Error
678 CommandObjectBreakpointList::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
679 {
680     Error error;
681     char short_option = (char) m_getopt_table[option_idx].val;
682 
683     switch (short_option)
684     {
685         case 'b':
686             m_level = lldb::eDescriptionLevelBrief;
687             break;
688         case 'f':
689             m_level = lldb::eDescriptionLevelFull;
690             break;
691         case 'v':
692             m_level = lldb::eDescriptionLevelVerbose;
693             break;
694         case 'i':
695             m_internal = true;
696             break;
697         default:
698             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
699             break;
700     }
701 
702     return error;
703 }
704 
705 void
706 CommandObjectBreakpointList::CommandOptions::OptionParsingStarting ()
707 {
708     m_level = lldb::eDescriptionLevelBrief;
709     m_internal = false;
710 }
711 
712 //-------------------------------------------------------------------------
713 // CommandObjectBreakpointList
714 //-------------------------------------------------------------------------
715 #pragma mark List
716 
717 CommandObjectBreakpointList::CommandObjectBreakpointList (CommandInterpreter &interpreter) :
718     CommandObject (interpreter,
719                    "breakpoint list",
720                    "List some or all breakpoints at configurable levels of detail.",
721                    NULL),
722     m_options (interpreter)
723 {
724     CommandArgumentEntry arg;
725     CommandArgumentData bp_id_arg;
726 
727     // Define the first (and only) variant of this arg.
728     bp_id_arg.arg_type = eArgTypeBreakpointID;
729     bp_id_arg.arg_repetition = eArgRepeatOptional;
730 
731     // There is only one variant this argument could be; put it into the argument entry.
732     arg.push_back (bp_id_arg);
733 
734     // Push the data for the first argument into the m_arguments vector.
735     m_arguments.push_back (arg);
736 }
737 
738 CommandObjectBreakpointList::~CommandObjectBreakpointList ()
739 {
740 }
741 
742 Options *
743 CommandObjectBreakpointList::GetOptions ()
744 {
745     return &m_options;
746 }
747 
748 bool
749 CommandObjectBreakpointList::Execute
750 (
751     Args& args,
752     CommandReturnObject &result
753 )
754 {
755     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
756     if (target == NULL)
757     {
758         result.AppendError ("Invalid target. No current target or breakpoints.");
759         result.SetStatus (eReturnStatusSuccessFinishNoResult);
760         return true;
761     }
762 
763     const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
764     Mutex::Locker locker;
765     target->GetBreakpointList(m_options.m_internal).GetListMutex(locker);
766 
767     size_t num_breakpoints = breakpoints.GetSize();
768 
769     if (num_breakpoints == 0)
770     {
771         result.AppendMessage ("No breakpoints currently set.");
772         result.SetStatus (eReturnStatusSuccessFinishNoResult);
773         return true;
774     }
775 
776     Stream &output_stream = result.GetOutputStream();
777 
778     if (args.GetArgumentCount() == 0)
779     {
780         // No breakpoint selected; show info about all currently set breakpoints.
781         result.AppendMessage ("Current breakpoints:");
782         for (size_t i = 0; i < num_breakpoints; ++i)
783         {
784             Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get();
785             AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
786         }
787         result.SetStatus (eReturnStatusSuccessFinishNoResult);
788     }
789     else
790     {
791         // Particular breakpoints selected; show info about that breakpoint.
792         BreakpointIDList valid_bp_ids;
793         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
794 
795         if (result.Succeeded())
796         {
797             for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i)
798             {
799                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
800                 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
801                 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
802             }
803             result.SetStatus (eReturnStatusSuccessFinishNoResult);
804         }
805         else
806         {
807             result.AppendError ("Invalid breakpoint id.");
808             result.SetStatus (eReturnStatusFailed);
809         }
810     }
811 
812     return result.Succeeded();
813 }
814 
815 //-------------------------------------------------------------------------
816 // CommandObjectBreakpointEnable
817 //-------------------------------------------------------------------------
818 #pragma mark Enable
819 
820 CommandObjectBreakpointEnable::CommandObjectBreakpointEnable (CommandInterpreter &interpreter) :
821     CommandObject (interpreter,
822                    "enable",
823                    "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.",
824                    NULL)
825 {
826     CommandArgumentEntry arg;
827     CommandArgumentData bp_id_arg;
828     CommandArgumentData bp_id_range_arg;
829 
830     // Create the first variant for the first (and only) argument for this command.
831     bp_id_arg.arg_type = eArgTypeBreakpointID;
832     bp_id_arg.arg_repetition = eArgRepeatOptional;
833 
834     // Create the second variant for the first (and only) argument for this command.
835     bp_id_range_arg.arg_type = eArgTypeBreakpointIDRange;
836     bp_id_range_arg.arg_repetition = eArgRepeatOptional;
837 
838     // The first (and only) argument for this command could be either a bp_id or a bp_id_range.
839     // Push both variants into the entry for the first argument for this command.
840     arg.push_back (bp_id_arg);
841     arg.push_back (bp_id_range_arg);
842 
843     // Add the entry for the first argument for this command to the object's arguments vector.
844     m_arguments.push_back (arg);
845 }
846 
847 
848 CommandObjectBreakpointEnable::~CommandObjectBreakpointEnable ()
849 {
850 }
851 
852 
853 bool
854 CommandObjectBreakpointEnable::Execute
855 (
856     Args& args,
857     CommandReturnObject &result
858 )
859 {
860     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
861     if (target == NULL)
862     {
863         result.AppendError ("Invalid target.  No existing target or breakpoints.");
864         result.SetStatus (eReturnStatusFailed);
865         return false;
866     }
867 
868     Mutex::Locker locker;
869     target->GetBreakpointList().GetListMutex(locker);
870 
871     const BreakpointList &breakpoints = target->GetBreakpointList();
872 
873     size_t num_breakpoints = breakpoints.GetSize();
874 
875     if (num_breakpoints == 0)
876     {
877         result.AppendError ("No breakpoints exist to be enabled.");
878         result.SetStatus (eReturnStatusFailed);
879         return false;
880     }
881 
882     if (args.GetArgumentCount() == 0)
883     {
884         // No breakpoint selected; enable all currently set breakpoints.
885         target->EnableAllBreakpoints ();
886         result.AppendMessageWithFormat ("All breakpoints enabled. (%d breakpoints)\n", num_breakpoints);
887         result.SetStatus (eReturnStatusSuccessFinishNoResult);
888     }
889     else
890     {
891         // Particular breakpoint selected; enable that breakpoint.
892         BreakpointIDList valid_bp_ids;
893         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
894 
895         if (result.Succeeded())
896         {
897             int enable_count = 0;
898             int loc_count = 0;
899             const size_t count = valid_bp_ids.GetSize();
900             for (size_t i = 0; i < count; ++i)
901             {
902                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
903 
904                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
905                 {
906                     Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
907                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
908                     {
909                         BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
910                         if (location)
911                         {
912                             location->SetEnabled (true);
913                             ++loc_count;
914                         }
915                     }
916                     else
917                     {
918                         breakpoint->SetEnabled (true);
919                         ++enable_count;
920                     }
921                 }
922             }
923             result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
924             result.SetStatus (eReturnStatusSuccessFinishNoResult);
925         }
926     }
927 
928     return result.Succeeded();
929 }
930 
931 //-------------------------------------------------------------------------
932 // CommandObjectBreakpointDisable
933 //-------------------------------------------------------------------------
934 #pragma mark Disable
935 
936 CommandObjectBreakpointDisable::CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
937     CommandObject (interpreter,
938                    "breakpoint disable",
939                    "Disable the specified breakpoint(s) without removing it/them.  If no breakpoints are specified, disable them all.",
940                    NULL)
941 {
942     CommandArgumentEntry arg;
943     CommandArgumentData bp_id_arg;
944     CommandArgumentData bp_id_range_arg;
945 
946     // Create the first variant for the first (and only) argument for this command.
947     bp_id_arg.arg_type = eArgTypeBreakpointID;
948     bp_id_arg.arg_repetition = eArgRepeatOptional;
949 
950     // Create the second variant for the first (and only) argument for this command.
951     bp_id_range_arg.arg_type = eArgTypeBreakpointIDRange;
952     bp_id_range_arg.arg_repetition = eArgRepeatOptional;
953 
954     // The first (and only) argument for this command could be either a bp_id or a bp_id_range.
955     // Push both variants into the entry for the first argument for this command.
956     arg.push_back (bp_id_arg);
957     arg.push_back (bp_id_range_arg);
958 
959     // Add the entry for the first argument for this command to the object's arguments vector.
960     m_arguments.push_back (arg);
961 }
962 
963 CommandObjectBreakpointDisable::~CommandObjectBreakpointDisable ()
964 {
965 }
966 
967 bool
968 CommandObjectBreakpointDisable::Execute
969 (
970     Args& args,
971     CommandReturnObject &result
972 )
973 {
974     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
975     if (target == NULL)
976     {
977         result.AppendError ("Invalid target.  No existing target or breakpoints.");
978         result.SetStatus (eReturnStatusFailed);
979         return false;
980     }
981 
982     Mutex::Locker locker;
983     target->GetBreakpointList().GetListMutex(locker);
984 
985     const BreakpointList &breakpoints = target->GetBreakpointList();
986     size_t num_breakpoints = breakpoints.GetSize();
987 
988     if (num_breakpoints == 0)
989     {
990         result.AppendError ("No breakpoints exist to be disabled.");
991         result.SetStatus (eReturnStatusFailed);
992         return false;
993     }
994 
995     if (args.GetArgumentCount() == 0)
996     {
997         // No breakpoint selected; disable all currently set breakpoints.
998         target->DisableAllBreakpoints ();
999         result.AppendMessageWithFormat ("All breakpoints disabled. (%d breakpoints)\n", num_breakpoints);
1000         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1001     }
1002     else
1003     {
1004         // Particular breakpoint selected; disable that breakpoint.
1005         BreakpointIDList valid_bp_ids;
1006 
1007         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
1008 
1009         if (result.Succeeded())
1010         {
1011             int disable_count = 0;
1012             int loc_count = 0;
1013             const size_t count = valid_bp_ids.GetSize();
1014             for (size_t i = 0; i < count; ++i)
1015             {
1016                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1017 
1018                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1019                 {
1020                     Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1021                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1022                     {
1023                         BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1024                         if (location)
1025                         {
1026                             location->SetEnabled (false);
1027                             ++loc_count;
1028                         }
1029                     }
1030                     else
1031                     {
1032                         breakpoint->SetEnabled (false);
1033                         ++disable_count;
1034                     }
1035                 }
1036             }
1037             result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
1038             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1039         }
1040     }
1041 
1042     return result.Succeeded();
1043 }
1044 
1045 //-------------------------------------------------------------------------
1046 // CommandObjectBreakpointClear::CommandOptions
1047 //-------------------------------------------------------------------------
1048 #pragma mark Clear::CommandOptions
1049 
1050 CommandObjectBreakpointClear::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
1051     Options (interpreter),
1052     m_filename (),
1053     m_line_num (0)
1054 {
1055 }
1056 
1057 CommandObjectBreakpointClear::CommandOptions::~CommandOptions ()
1058 {
1059 }
1060 
1061 OptionDefinition
1062 CommandObjectBreakpointClear::CommandOptions::g_option_table[] =
1063 {
1064     { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1065         "Specify the breakpoint by source location in this particular file."},
1066 
1067     { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
1068         "Specify the breakpoint by source location at this particular line."},
1069 
1070     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1071 };
1072 
1073 const OptionDefinition*
1074 CommandObjectBreakpointClear::CommandOptions::GetDefinitions ()
1075 {
1076     return g_option_table;
1077 }
1078 
1079 Error
1080 CommandObjectBreakpointClear::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
1081 {
1082     Error error;
1083     char short_option = (char) m_getopt_table[option_idx].val;
1084 
1085     switch (short_option)
1086     {
1087         case 'f':
1088             m_filename.assign (option_arg);
1089             break;
1090 
1091         case 'l':
1092             m_line_num = Args::StringToUInt32 (option_arg, 0);
1093             break;
1094 
1095         default:
1096             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1097             break;
1098     }
1099 
1100     return error;
1101 }
1102 
1103 void
1104 CommandObjectBreakpointClear::CommandOptions::OptionParsingStarting ()
1105 {
1106     m_filename.clear();
1107     m_line_num = 0;
1108 }
1109 
1110 //-------------------------------------------------------------------------
1111 // CommandObjectBreakpointClear
1112 //-------------------------------------------------------------------------
1113 #pragma mark Clear
1114 
1115 CommandObjectBreakpointClear::CommandObjectBreakpointClear (CommandInterpreter &interpreter) :
1116     CommandObject (interpreter,
1117                    "breakpoint clear",
1118                    "Clears a breakpoint or set of breakpoints in the executable.",
1119                    "breakpoint clear <cmd-options>"),
1120     m_options (interpreter)
1121 {
1122 }
1123 
1124 CommandObjectBreakpointClear::~CommandObjectBreakpointClear ()
1125 {
1126 }
1127 
1128 Options *
1129 CommandObjectBreakpointClear::GetOptions ()
1130 {
1131     return &m_options;
1132 }
1133 
1134 bool
1135 CommandObjectBreakpointClear::Execute
1136 (
1137     Args& command,
1138     CommandReturnObject &result
1139 )
1140 {
1141     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1142     if (target == NULL)
1143     {
1144         result.AppendError ("Invalid target. No existing target or breakpoints.");
1145         result.SetStatus (eReturnStatusFailed);
1146         return false;
1147     }
1148 
1149     // The following are the various types of breakpoints that could be cleared:
1150     //   1). -f -l (clearing breakpoint by source location)
1151 
1152     BreakpointClearType break_type = eClearTypeInvalid;
1153 
1154     if (m_options.m_line_num != 0)
1155         break_type = eClearTypeFileAndLine;
1156 
1157     Mutex::Locker locker;
1158     target->GetBreakpointList().GetListMutex(locker);
1159 
1160     BreakpointList &breakpoints = target->GetBreakpointList();
1161     size_t num_breakpoints = breakpoints.GetSize();
1162 
1163     // Early return if there's no breakpoint at all.
1164     if (num_breakpoints == 0)
1165     {
1166         result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1167         result.SetStatus (eReturnStatusFailed);
1168         return result.Succeeded();
1169     }
1170 
1171     // Find matching breakpoints and delete them.
1172 
1173     // First create a copy of all the IDs.
1174     std::vector<break_id_t> BreakIDs;
1175     for (size_t i = 0; i < num_breakpoints; ++i)
1176         BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i).get()->GetID());
1177 
1178     int num_cleared = 0;
1179     StreamString ss;
1180     switch (break_type)
1181     {
1182         case eClearTypeFileAndLine: // Breakpoint by source position
1183             {
1184                 const ConstString filename(m_options.m_filename.c_str());
1185                 BreakpointLocationCollection loc_coll;
1186 
1187                 for (size_t i = 0; i < num_breakpoints; ++i)
1188                 {
1189                     Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1190 
1191                     if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll))
1192                     {
1193                         // If the collection size is 0, it's a full match and we can just remove the breakpoint.
1194                         if (loc_coll.GetSize() == 0)
1195                         {
1196                             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1197                             ss.EOL();
1198                             target->RemoveBreakpointByID (bp->GetID());
1199                             ++num_cleared;
1200                         }
1201                     }
1202                 }
1203             }
1204             break;
1205 
1206         default:
1207             break;
1208     }
1209 
1210     if (num_cleared > 0)
1211     {
1212         Stream &output_stream = result.GetOutputStream();
1213         output_stream.Printf ("%d breakpoints cleared:\n", num_cleared);
1214         output_stream << ss.GetData();
1215         output_stream.EOL();
1216         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1217     }
1218     else
1219     {
1220         result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1221         result.SetStatus (eReturnStatusFailed);
1222     }
1223 
1224     return result.Succeeded();
1225 }
1226 
1227 //-------------------------------------------------------------------------
1228 // CommandObjectBreakpointDelete
1229 //-------------------------------------------------------------------------
1230 #pragma mark Delete
1231 
1232 CommandObjectBreakpointDelete::CommandObjectBreakpointDelete(CommandInterpreter &interpreter) :
1233     CommandObject (interpreter,
1234                    "breakpoint delete",
1235                    "Delete the specified breakpoint(s).  If no breakpoints are specified, delete them all.",
1236                    NULL)
1237 {
1238     CommandArgumentEntry arg;
1239     CommandArgumentData bp_id_arg;
1240     CommandArgumentData bp_id_range_arg;
1241 
1242     // Create the first variant for the first (and only) argument for this command.
1243     bp_id_arg.arg_type = eArgTypeBreakpointID;
1244     bp_id_arg.arg_repetition = eArgRepeatOptional;
1245 
1246     // Create the second variant for the first (and only) argument for this command.
1247     bp_id_range_arg.arg_type = eArgTypeBreakpointIDRange;
1248     bp_id_range_arg.arg_repetition = eArgRepeatOptional;
1249 
1250     // The first (and only) argument for this command could be either a bp_id or a bp_id_range.
1251     // Push both variants into the entry for the first argument for this command.
1252     arg.push_back (bp_id_arg);
1253     arg.push_back (bp_id_range_arg);
1254 
1255     // Add the entry for the first argument for this command to the object's arguments vector.
1256     m_arguments.push_back (arg);
1257 }
1258 
1259 
1260 CommandObjectBreakpointDelete::~CommandObjectBreakpointDelete ()
1261 {
1262 }
1263 
1264 bool
1265 CommandObjectBreakpointDelete::Execute
1266 (
1267     Args& args,
1268     CommandReturnObject &result
1269 )
1270 {
1271     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1272     if (target == NULL)
1273     {
1274         result.AppendError ("Invalid target. No existing target or breakpoints.");
1275         result.SetStatus (eReturnStatusFailed);
1276         return false;
1277     }
1278 
1279     Mutex::Locker locker;
1280     target->GetBreakpointList().GetListMutex(locker);
1281 
1282     const BreakpointList &breakpoints = target->GetBreakpointList();
1283 
1284     size_t num_breakpoints = breakpoints.GetSize();
1285 
1286     if (num_breakpoints == 0)
1287     {
1288         result.AppendError ("No breakpoints exist to be deleted.");
1289         result.SetStatus (eReturnStatusFailed);
1290         return false;
1291     }
1292 
1293     if (args.GetArgumentCount() == 0)
1294     {
1295         if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
1296         {
1297             result.AppendMessage("Operation cancelled...");
1298         }
1299         else
1300         {
1301             target->RemoveAllBreakpoints ();
1302             result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
1303         }
1304         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1305     }
1306     else
1307     {
1308         // Particular breakpoint selected; disable that breakpoint.
1309         BreakpointIDList valid_bp_ids;
1310         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
1311 
1312         if (result.Succeeded())
1313         {
1314             int delete_count = 0;
1315             int disable_count = 0;
1316             const size_t count = valid_bp_ids.GetSize();
1317             for (size_t i = 0; i < count; ++i)
1318             {
1319                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1320 
1321                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1322                 {
1323                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1324                     {
1325                         Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1326                         BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1327                         // It makes no sense to try to delete individual locations, so we disable them instead.
1328                         if (location)
1329                         {
1330                             location->SetEnabled (false);
1331                             ++disable_count;
1332                         }
1333                     }
1334                     else
1335                     {
1336                         target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
1337                         ++delete_count;
1338                     }
1339                 }
1340             }
1341             result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
1342                                            delete_count, disable_count);
1343             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1344         }
1345     }
1346     return result.Succeeded();
1347 }
1348 
1349 //-------------------------------------------------------------------------
1350 // CommandObjectBreakpointModify::CommandOptions
1351 //-------------------------------------------------------------------------
1352 #pragma mark Modify::CommandOptions
1353 
1354 CommandObjectBreakpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
1355     Options (interpreter),
1356     m_ignore_count (0),
1357     m_thread_id(LLDB_INVALID_THREAD_ID),
1358     m_thread_id_passed(false),
1359     m_thread_index (UINT32_MAX),
1360     m_thread_index_passed(false),
1361     m_thread_name(),
1362     m_queue_name(),
1363     m_condition (),
1364     m_enable_passed (false),
1365     m_enable_value (false),
1366     m_name_passed (false),
1367     m_queue_passed (false),
1368     m_condition_passed (false)
1369 {
1370 }
1371 
1372 CommandObjectBreakpointModify::CommandOptions::~CommandOptions ()
1373 {
1374 }
1375 
1376 OptionDefinition
1377 CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
1378 {
1379 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
1380 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument."},
1381 { LLDB_OPT_SET_ALL, false, "thread-id",    't', required_argument, NULL, NULL, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
1382 { LLDB_OPT_SET_ALL, false, "thread-name",  'T', required_argument, NULL, NULL, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
1383 { LLDB_OPT_SET_ALL, false, "queue-name",   'q', required_argument, NULL, NULL, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
1384 { LLDB_OPT_SET_ALL, false, "condition",    'c', required_argument, NULL, NULL, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
1385 { LLDB_OPT_SET_1,   false, "enable",       'e', no_argument,       NULL, NULL, eArgTypeNone, "Enable the breakpoint."},
1386 { LLDB_OPT_SET_2,   false, "disable",      'd', no_argument,       NULL, NULL, eArgTypeNone, "Disable the breakpoint."},
1387 { 0,                false, NULL,            0 , 0,                 NULL, 0,    eArgTypeNone, NULL }
1388 };
1389 
1390 const OptionDefinition*
1391 CommandObjectBreakpointModify::CommandOptions::GetDefinitions ()
1392 {
1393     return g_option_table;
1394 }
1395 
1396 Error
1397 CommandObjectBreakpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
1398 {
1399     Error error;
1400     char short_option = (char) m_getopt_table[option_idx].val;
1401 
1402     switch (short_option)
1403     {
1404         case 'c':
1405             if (option_arg != NULL)
1406                 m_condition.assign (option_arg);
1407             else
1408                 m_condition.clear();
1409             m_condition_passed = true;
1410             break;
1411         case 'd':
1412             m_enable_passed = true;
1413             m_enable_value = false;
1414             break;
1415         case 'e':
1416             m_enable_passed = true;
1417             m_enable_value = true;
1418             break;
1419         case 'i':
1420         {
1421             m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
1422             if (m_ignore_count == UINT32_MAX)
1423                error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", option_arg);
1424         }
1425         break;
1426         case 't' :
1427         {
1428             if (option_arg[0] == '\0')
1429             {
1430                 m_thread_id = LLDB_INVALID_THREAD_ID;
1431                 m_thread_id_passed = true;
1432             }
1433             else
1434             {
1435                 m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
1436                 if (m_thread_id == LLDB_INVALID_THREAD_ID)
1437                    error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg);
1438                 else
1439                     m_thread_id_passed = true;
1440             }
1441         }
1442         break;
1443         case 'T':
1444             if (option_arg != NULL)
1445                 m_thread_name.assign (option_arg);
1446             else
1447                 m_thread_name.clear();
1448             m_name_passed = true;
1449             break;
1450         case 'q':
1451             if (option_arg != NULL)
1452                 m_queue_name.assign (option_arg);
1453             else
1454                 m_queue_name.clear();
1455             m_queue_passed = true;
1456             break;
1457         case 'x':
1458         {
1459             if (option_arg[0] == '\n')
1460             {
1461                 m_thread_index = UINT32_MAX;
1462                 m_thread_index_passed = true;
1463             }
1464             else
1465             {
1466                 m_thread_index = Args::StringToUInt32 (option_arg, UINT32_MAX, 0);
1467                 if (m_thread_id == UINT32_MAX)
1468                    error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg);
1469                 else
1470                     m_thread_index_passed = true;
1471             }
1472         }
1473         break;
1474         default:
1475             error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1476             break;
1477     }
1478 
1479     return error;
1480 }
1481 
1482 void
1483 CommandObjectBreakpointModify::CommandOptions::OptionParsingStarting ()
1484 {
1485     m_ignore_count = 0;
1486     m_thread_id = LLDB_INVALID_THREAD_ID;
1487     m_thread_id_passed = false;
1488     m_thread_index = UINT32_MAX;
1489     m_thread_index_passed = false;
1490     m_thread_name.clear();
1491     m_queue_name.clear();
1492     m_condition.clear();
1493     m_enable_passed = false;
1494     m_queue_passed = false;
1495     m_name_passed = false;
1496     m_condition_passed = false;
1497 }
1498 
1499 //-------------------------------------------------------------------------
1500 // CommandObjectBreakpointModify
1501 //-------------------------------------------------------------------------
1502 #pragma mark Modify
1503 
1504 CommandObjectBreakpointModify::CommandObjectBreakpointModify (CommandInterpreter &interpreter) :
1505     CommandObject (interpreter,
1506                    "breakpoint modify",
1507                    "Modify the options on a breakpoint or set of breakpoints in the executable.  "
1508                    "If no breakpoint is specified, acts on the last created breakpoint.  "
1509                    "With the exception of -e, -d and -i, passing an empty argument clears the modification.",
1510                    NULL),
1511     m_options (interpreter)
1512 {
1513     CommandArgumentEntry arg;
1514     CommandArgumentData bp_id_arg;
1515     CommandArgumentData bp_id_range_arg;
1516 
1517     // Create the first variant for the first (and only) argument for this command.
1518     bp_id_arg.arg_type = eArgTypeBreakpointID;
1519     bp_id_arg.arg_repetition = eArgRepeatPlain;
1520 
1521     // Create the second variant for the first (and only) argument for this command.
1522     bp_id_range_arg.arg_type = eArgTypeBreakpointIDRange;
1523     bp_id_range_arg.arg_repetition = eArgRepeatPlain;
1524 
1525     // The first (and only) argument for this command could be either a bp_id or a bp_id_range.
1526     // Push both variants into the entry for the first argument for this command.
1527     arg.push_back (bp_id_arg);
1528     arg.push_back (bp_id_range_arg);
1529 
1530     // Add the entry for the first argument for this command to the object's arguments vector.
1531     m_arguments.push_back (arg);
1532 }
1533 
1534 CommandObjectBreakpointModify::~CommandObjectBreakpointModify ()
1535 {
1536 }
1537 
1538 Options *
1539 CommandObjectBreakpointModify::GetOptions ()
1540 {
1541     return &m_options;
1542 }
1543 
1544 bool
1545 CommandObjectBreakpointModify::Execute
1546 (
1547     Args& command,
1548     CommandReturnObject &result
1549 )
1550 {
1551     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1552     if (target == NULL)
1553     {
1554         result.AppendError ("Invalid target.  No existing target or breakpoints.");
1555         result.SetStatus (eReturnStatusFailed);
1556         return false;
1557     }
1558 
1559     Mutex::Locker locker;
1560     target->GetBreakpointList().GetListMutex(locker);
1561 
1562     BreakpointIDList valid_bp_ids;
1563 
1564     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1565 
1566     if (result.Succeeded())
1567     {
1568         const size_t count = valid_bp_ids.GetSize();
1569         for (size_t i = 0; i < count; ++i)
1570         {
1571             BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1572 
1573             if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1574             {
1575                 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1576                 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1577                 {
1578                     BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get();
1579                     if (location)
1580                     {
1581                         if (m_options.m_thread_id_passed)
1582                             location->SetThreadID (m_options.m_thread_id);
1583 
1584                         if (m_options.m_thread_index_passed)
1585                             location->GetLocationOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
1586 
1587                         if (m_options.m_name_passed)
1588                             location->GetLocationOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
1589 
1590                         if (m_options.m_queue_passed)
1591                             location->GetLocationOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
1592 
1593                         if (m_options.m_ignore_count != 0)
1594                             location->GetLocationOptions()->SetIgnoreCount(m_options.m_ignore_count);
1595 
1596                         if (m_options.m_enable_passed)
1597                             location->SetEnabled (m_options.m_enable_value);
1598 
1599                         if (m_options.m_condition_passed)
1600                             location->SetCondition (m_options.m_condition.c_str());
1601                     }
1602                 }
1603                 else
1604                 {
1605                     if (m_options.m_thread_id_passed)
1606                         bp->SetThreadID (m_options.m_thread_id);
1607 
1608                     if (m_options.m_thread_index_passed)
1609                         bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
1610 
1611                     if (m_options.m_name_passed)
1612                         bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
1613 
1614                     if (m_options.m_queue_passed)
1615                         bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
1616 
1617                     if (m_options.m_ignore_count != 0)
1618                         bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
1619 
1620                     if (m_options.m_enable_passed)
1621                         bp->SetEnabled (m_options.m_enable_value);
1622 
1623                     if (m_options.m_condition_passed)
1624                         bp->SetCondition (m_options.m_condition.c_str());
1625                 }
1626             }
1627         }
1628     }
1629 
1630     return result.Succeeded();
1631 }
1632 
1633 
1634