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 "lldb/lldb-python.h"
11 
12 #include "CommandObjectBreakpoint.h"
13 #include "CommandObjectBreakpointCommand.h"
14 
15 // C Includes
16 // C++ Includes
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Breakpoint/Breakpoint.h"
20 #include "lldb/Breakpoint/BreakpointIDList.h"
21 #include "lldb/Breakpoint/BreakpointLocation.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Core/RegularExpression.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Interpreter/CommandCompletions.h"
29 #include "lldb/Target/StackFrame.h"
30 #include "lldb/Target/Thread.h"
31 #include "lldb/Target/ThreadSpec.h"
32 
33 #include <vector>
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 static void
39 AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level)
40 {
41     s->IndentMore();
42     bp->GetDescription (s, level, true);
43     s->IndentLess();
44     s->EOL();
45 }
46 
47 //-------------------------------------------------------------------------
48 // CommandObjectBreakpointSet
49 //-------------------------------------------------------------------------
50 
51 
52 class CommandObjectBreakpointSet : public CommandObjectParsed
53 {
54 public:
55 
56     typedef enum BreakpointSetType
57     {
58         eSetTypeInvalid,
59         eSetTypeFileAndLine,
60         eSetTypeAddress,
61         eSetTypeFunctionName,
62         eSetTypeFunctionRegexp,
63         eSetTypeSourceRegexp,
64         eSetTypeException
65     } BreakpointSetType;
66 
67     CommandObjectBreakpointSet (CommandInterpreter &interpreter) :
68         CommandObjectParsed (interpreter,
69                              "breakpoint set",
70                              "Sets a breakpoint or set of breakpoints in the executable.",
71                              "breakpoint set <cmd-options>"),
72         m_options (interpreter)
73     {
74     }
75 
76 
77     virtual
78     ~CommandObjectBreakpointSet () {}
79 
80     virtual Options *
81     GetOptions ()
82     {
83         return &m_options;
84     }
85 
86     class CommandOptions : public Options
87     {
88     public:
89 
90         CommandOptions (CommandInterpreter &interpreter) :
91             Options (interpreter),
92             m_condition (),
93             m_filenames (),
94             m_line_num (0),
95             m_column (0),
96             m_func_names (),
97             m_func_name_type_mask (eFunctionNameTypeNone),
98             m_func_regexp (),
99             m_source_text_regexp(),
100             m_modules (),
101             m_load_addr(),
102             m_ignore_count (0),
103             m_thread_id(LLDB_INVALID_THREAD_ID),
104             m_thread_index (UINT32_MAX),
105             m_thread_name(),
106             m_queue_name(),
107             m_catch_bp (false),
108             m_throw_bp (true),
109             m_hardware (false),
110             m_language (eLanguageTypeUnknown),
111             m_skip_prologue (eLazyBoolCalculate),
112             m_one_shot (false)
113         {
114         }
115 
116 
117         virtual
118         ~CommandOptions () {}
119 
120         virtual Error
121         SetOptionValue (uint32_t option_idx, const char *option_arg)
122         {
123             Error error;
124             const int short_option = m_getopt_table[option_idx].val;
125 
126             switch (short_option)
127             {
128                 case 'a':
129                     {
130                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
131                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
132                     }
133                     break;
134 
135                 case 'b':
136                     m_func_names.push_back (option_arg);
137                     m_func_name_type_mask |= eFunctionNameTypeBase;
138                     break;
139 
140                 case 'C':
141                     m_column = Args::StringToUInt32 (option_arg, 0);
142                     break;
143 
144                 case 'c':
145                     m_condition.assign(option_arg);
146                     break;
147 
148                 case 'D':
149                     m_use_dummy = true;
150                     break;
151 
152                 case 'E':
153                 {
154                     LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
155 
156                     switch (language)
157                     {
158                         case eLanguageTypeC89:
159                         case eLanguageTypeC:
160                         case eLanguageTypeC99:
161                         case eLanguageTypeC11:
162                             m_language = eLanguageTypeC;
163                             break;
164                         case eLanguageTypeC_plus_plus:
165                         case eLanguageTypeC_plus_plus_03:
166                         case eLanguageTypeC_plus_plus_11:
167                             m_language = eLanguageTypeC_plus_plus;
168                             break;
169                         case eLanguageTypeObjC:
170                             m_language = eLanguageTypeObjC;
171                             break;
172                         case eLanguageTypeObjC_plus_plus:
173                             error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
174                             break;
175                         case eLanguageTypeUnknown:
176                             error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg);
177                             break;
178                         default:
179                             error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg);
180                     }
181                 }
182                 break;
183 
184                 case 'f':
185                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
186                     break;
187 
188                 case 'F':
189                     m_func_names.push_back (option_arg);
190                     m_func_name_type_mask |= eFunctionNameTypeFull;
191                     break;
192 
193                 case 'h':
194                     {
195                         bool success;
196                         m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
197                         if (!success)
198                             error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
199                     }
200                     break;
201 
202                 case 'H':
203                     m_hardware = true;
204                     break;
205 
206                 case 'i':
207                 {
208                     m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
209                     if (m_ignore_count == UINT32_MAX)
210                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
211                     break;
212                 }
213 
214                 case 'K':
215                 {
216                     bool success;
217                     bool value;
218                     value = Args::StringToBoolean (option_arg, true, &success);
219                     if (value)
220                         m_skip_prologue = eLazyBoolYes;
221                     else
222                         m_skip_prologue = eLazyBoolNo;
223 
224                     if (!success)
225                         error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg);
226                 }
227                 break;
228 
229                 case 'l':
230                     m_line_num = Args::StringToUInt32 (option_arg, 0);
231                     break;
232 
233                 case 'M':
234                     m_func_names.push_back (option_arg);
235                     m_func_name_type_mask |= eFunctionNameTypeMethod;
236                     break;
237 
238                 case 'n':
239                     m_func_names.push_back (option_arg);
240                     m_func_name_type_mask |= eFunctionNameTypeAuto;
241                     break;
242 
243                 case 'o':
244                     m_one_shot = true;
245                     break;
246 
247                 case 'p':
248                     m_source_text_regexp.assign (option_arg);
249                     break;
250 
251                 case 'q':
252                     m_queue_name.assign (option_arg);
253                     break;
254 
255                 case 'r':
256                     m_func_regexp.assign (option_arg);
257                     break;
258 
259                 case 's':
260                 {
261                     m_modules.AppendIfUnique (FileSpec (option_arg, false));
262                     break;
263                 }
264 
265                 case 'S':
266                     m_func_names.push_back (option_arg);
267                     m_func_name_type_mask |= eFunctionNameTypeSelector;
268                     break;
269 
270                 case 't' :
271                 {
272                     m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
273                     if (m_thread_id == LLDB_INVALID_THREAD_ID)
274                        error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
275                 }
276                 break;
277 
278                 case 'T':
279                     m_thread_name.assign (option_arg);
280                     break;
281 
282                 case 'w':
283                 {
284                     bool success;
285                     m_throw_bp = Args::StringToBoolean (option_arg, true, &success);
286                     if (!success)
287                         error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
288                 }
289                 break;
290 
291                 case 'x':
292                 {
293                     m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
294                     if (m_thread_id == UINT32_MAX)
295                        error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
296 
297                 }
298                 break;
299 
300                 default:
301                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
302                     break;
303             }
304 
305             return error;
306         }
307         void
308         OptionParsingStarting ()
309         {
310             m_condition.clear();
311             m_filenames.Clear();
312             m_line_num = 0;
313             m_column = 0;
314             m_func_names.clear();
315             m_func_name_type_mask = eFunctionNameTypeNone;
316             m_func_regexp.clear();
317             m_source_text_regexp.clear();
318             m_modules.Clear();
319             m_load_addr = LLDB_INVALID_ADDRESS;
320             m_ignore_count = 0;
321             m_thread_id = LLDB_INVALID_THREAD_ID;
322             m_thread_index = UINT32_MAX;
323             m_thread_name.clear();
324             m_queue_name.clear();
325             m_catch_bp = false;
326             m_throw_bp = true;
327             m_hardware = false;
328             m_language = eLanguageTypeUnknown;
329             m_skip_prologue = eLazyBoolCalculate;
330             m_one_shot = false;
331             m_use_dummy = false;
332         }
333 
334         const OptionDefinition*
335         GetDefinitions ()
336         {
337             return g_option_table;
338         }
339 
340         // Options table: Required for subclasses of Options.
341 
342         static OptionDefinition g_option_table[];
343 
344         // Instance variables to hold the values for command options.
345 
346         std::string m_condition;
347         FileSpecList m_filenames;
348         uint32_t m_line_num;
349         uint32_t m_column;
350         std::vector<std::string> m_func_names;
351         uint32_t m_func_name_type_mask;
352         std::string m_func_regexp;
353         std::string m_source_text_regexp;
354         FileSpecList m_modules;
355         lldb::addr_t m_load_addr;
356         uint32_t m_ignore_count;
357         lldb::tid_t m_thread_id;
358         uint32_t m_thread_index;
359         std::string m_thread_name;
360         std::string m_queue_name;
361         bool m_catch_bp;
362         bool m_throw_bp;
363         bool m_hardware; // Request to use hardware breakpoints
364         lldb::LanguageType m_language;
365         LazyBool m_skip_prologue;
366         bool m_one_shot;
367         bool m_use_dummy;
368 
369     };
370 
371 protected:
372     virtual bool
373     DoExecute (Args& command,
374               CommandReturnObject &result)
375     {
376         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
377 
378         if (target == nullptr)
379         {
380             result.AppendError ("Invalid target.  Must set target before setting breakpoints (see 'target create' command).");
381             result.SetStatus (eReturnStatusFailed);
382             return false;
383         }
384 
385         // The following are the various types of breakpoints that could be set:
386         //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
387         //   2).  -a  [-s -g]         (setting breakpoint by address)
388         //   3).  -n  [-s -g]         (setting breakpoint by function name)
389         //   4).  -r  [-s -g]         (setting breakpoint by function name regular expression)
390         //   5).  -p -f               (setting a breakpoint by comparing a reg-exp to source text)
391         //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a given language.)
392 
393         BreakpointSetType break_type = eSetTypeInvalid;
394 
395         if (m_options.m_line_num != 0)
396             break_type = eSetTypeFileAndLine;
397         else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
398             break_type = eSetTypeAddress;
399         else if (!m_options.m_func_names.empty())
400             break_type = eSetTypeFunctionName;
401         else if  (!m_options.m_func_regexp.empty())
402             break_type = eSetTypeFunctionRegexp;
403         else if (!m_options.m_source_text_regexp.empty())
404             break_type = eSetTypeSourceRegexp;
405         else if (m_options.m_language != eLanguageTypeUnknown)
406             break_type = eSetTypeException;
407 
408         Breakpoint *bp = NULL;
409         FileSpec module_spec;
410         const bool internal = false;
411 
412         switch (break_type)
413         {
414             case eSetTypeFileAndLine: // Breakpoint by source position
415                 {
416                     FileSpec file;
417                     const size_t num_files = m_options.m_filenames.GetSize();
418                     if (num_files == 0)
419                     {
420                         if (!GetDefaultFile (target, file, result))
421                         {
422                             result.AppendError("No file supplied and no default file available.");
423                             result.SetStatus (eReturnStatusFailed);
424                             return false;
425                         }
426                     }
427                     else if (num_files > 1)
428                     {
429                         result.AppendError("Only one file at a time is allowed for file and line breakpoints.");
430                         result.SetStatus (eReturnStatusFailed);
431                         return false;
432                     }
433                     else
434                         file = m_options.m_filenames.GetFileSpecAtIndex(0);
435 
436                     // Only check for inline functions if
437                     LazyBool check_inlines = eLazyBoolCalculate;
438 
439                     bp = target->CreateBreakpoint (&(m_options.m_modules),
440                                                    file,
441                                                    m_options.m_line_num,
442                                                    check_inlines,
443                                                    m_options.m_skip_prologue,
444                                                    internal,
445                                                    m_options.m_hardware).get();
446                 }
447                 break;
448 
449             case eSetTypeAddress: // Breakpoint by address
450                 bp = target->CreateBreakpoint (m_options.m_load_addr,
451                                                internal,
452                                                m_options.m_hardware).get();
453                 break;
454 
455             case eSetTypeFunctionName: // Breakpoint by function name
456                 {
457                     uint32_t name_type_mask = m_options.m_func_name_type_mask;
458 
459                     if (name_type_mask == 0)
460                         name_type_mask = eFunctionNameTypeAuto;
461 
462                     bp = target->CreateBreakpoint (&(m_options.m_modules),
463                                                    &(m_options.m_filenames),
464                                                    m_options.m_func_names,
465                                                    name_type_mask,
466                                                    m_options.m_skip_prologue,
467                                                    internal,
468                                                    m_options.m_hardware).get();
469                 }
470                 break;
471 
472             case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
473                 {
474                     RegularExpression regexp(m_options.m_func_regexp.c_str());
475                     if (!regexp.IsValid())
476                     {
477                         char err_str[1024];
478                         regexp.GetErrorAsCString(err_str, sizeof(err_str));
479                         result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"",
480                                                      err_str);
481                         result.SetStatus (eReturnStatusFailed);
482                         return false;
483                     }
484 
485                     bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules),
486                                                             &(m_options.m_filenames),
487                                                             regexp,
488                                                             m_options.m_skip_prologue,
489                                                             internal,
490                                                             m_options.m_hardware).get();
491                 }
492                 break;
493             case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
494                 {
495                     const size_t num_files = m_options.m_filenames.GetSize();
496 
497                     if (num_files == 0)
498                     {
499                         FileSpec file;
500                         if (!GetDefaultFile (target, file, result))
501                         {
502                             result.AppendError ("No files provided and could not find default file.");
503                             result.SetStatus (eReturnStatusFailed);
504                             return false;
505                         }
506                         else
507                         {
508                             m_options.m_filenames.Append (file);
509                         }
510                     }
511 
512                     RegularExpression regexp(m_options.m_source_text_regexp.c_str());
513                     if (!regexp.IsValid())
514                     {
515                         char err_str[1024];
516                         regexp.GetErrorAsCString(err_str, sizeof(err_str));
517                         result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"",
518                                                      err_str);
519                         result.SetStatus (eReturnStatusFailed);
520                         return false;
521                     }
522                     bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules),
523                                                               &(m_options.m_filenames),
524                                                               regexp,
525                                                               internal,
526                                                               m_options.m_hardware).get();
527                 }
528                 break;
529             case eSetTypeException:
530                 {
531                     bp = target->CreateExceptionBreakpoint (m_options.m_language,
532                                                             m_options.m_catch_bp,
533                                                             m_options.m_throw_bp,
534                                                             m_options.m_hardware).get();
535                 }
536                 break;
537             default:
538                 break;
539         }
540 
541         // Now set the various options that were passed in:
542         if (bp)
543         {
544             if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
545                 bp->SetThreadID (m_options.m_thread_id);
546 
547             if (m_options.m_thread_index != UINT32_MAX)
548                 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
549 
550             if (!m_options.m_thread_name.empty())
551                 bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
552 
553             if (!m_options.m_queue_name.empty())
554                 bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
555 
556             if (m_options.m_ignore_count != 0)
557                 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
558 
559             if (!m_options.m_condition.empty())
560                 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
561 
562             bp->SetOneShot (m_options.m_one_shot);
563         }
564 
565         if (bp)
566         {
567             Stream &output_stream = result.GetOutputStream();
568             const bool show_locations = false;
569             bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations);
570             // Don't print out this warning for exception breakpoints.  They can get set before the target
571             // is set, but we won't know how to actually set the breakpoint till we run.
572             if (bp->GetNumLocations() == 0 && break_type != eSetTypeException)
573                 output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n");
574             result.SetStatus (eReturnStatusSuccessFinishResult);
575         }
576         else if (!bp)
577         {
578             result.AppendError ("Breakpoint creation failed: No breakpoint created.");
579             result.SetStatus (eReturnStatusFailed);
580         }
581 
582         return result.Succeeded();
583     }
584 
585 private:
586     bool
587     GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result)
588     {
589         uint32_t default_line;
590         // First use the Source Manager's default file.
591         // Then use the current stack frame's file.
592         if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
593         {
594             StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
595             if (cur_frame == NULL)
596             {
597                 result.AppendError ("No selected frame to use to find the default file.");
598                 result.SetStatus (eReturnStatusFailed);
599                 return false;
600             }
601             else if (!cur_frame->HasDebugInformation())
602             {
603                 result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info.");
604                 result.SetStatus (eReturnStatusFailed);
605                 return false;
606             }
607             else
608             {
609                 const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
610                 if (sc.line_entry.file)
611                 {
612                     file = sc.line_entry.file;
613                 }
614                 else
615                 {
616                     result.AppendError ("Can't find the file for the selected frame to use as the default file.");
617                     result.SetStatus (eReturnStatusFailed);
618                     return false;
619                 }
620             }
621         }
622         return true;
623     }
624 
625     CommandOptions m_options;
626 };
627 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
628 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
629 #define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 )
630 #define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 )
631 #define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) )
632 
633 OptionDefinition
634 CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
635 {
636     { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
637         "Set the breakpoint only in this shared library.  "
638         "Can repeat this option multiple times to specify multiple shared libraries."},
639 
640     { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument,   NULL, NULL, 0, eArgTypeCount,
641         "Set the number of times this breakpoint is skipped before stopping." },
642 
643     { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument,   NULL, NULL, 0, eArgTypeNone,
644         "The breakpoint is deleted the first time it causes a stop." },
645 
646     { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression,
647         "The breakpoint stops only if this condition expression evaluates to true."},
648 
649     { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex,
650         "The breakpoint stops only for the thread whose indeX matches this argument."},
651 
652     { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID,
653         "The breakpoint stops only for the thread whose TID matches this argument."},
654 
655     { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName,
656         "The breakpoint stops only for the thread whose thread name matches this argument."},
657 
658     { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
659         "Require the breakpoint to use hardware breakpoints."},
660 
661     { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName,
662         "The breakpoint stops only for threads in the queue whose name is given by this argument."},
663 
664     { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
665         "Specifies the source file in which to set this breakpoint.  "
666         "Note, by default lldb only looks for files that are #included if they use the standard include file extensions.  "
667         "To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy"
668         " to \"always\"."},
669 
670     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
671         "Specifies the line number on which to set this breakpoint."},
672 
673     // Comment out this option for the moment, as we don't actually use it, but will in the future.
674     // This way users won't see it, but the infrastructure is left in place.
675     //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, NULL, "<column>",
676     //    "Set the breakpoint by source location at this particular column."},
677 
678     { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
679         "Set the breakpoint by address, at the specified address."},
680 
681     { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
682         "Set the breakpoint by function name.  Can be repeated multiple times to make one breakpoint for multiple names" },
683 
684     { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
685         "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and "
686         "for Objective C this means a full function prototype with class and selector.   "
687         "Can be repeated multiple times to make one breakpoint for multiple names." },
688 
689     { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSelector,
690         "Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." },
691 
692     { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeMethod,
693         "Set the breakpoint by C++ method names.  Can be repeated multiple times to make one breakpoint for multiple methods." },
694 
695     { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
696         "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
697 
698     { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
699         "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). "
700         "Can be repeated multiple times to make one breakpoint for multiple symbols." },
701 
702     { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression,
703         "Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files "
704         "specified with the -f option.  The -f option can be specified more than once.  "
705         "If no source files are specified, uses the current \"default source file\"" },
706 
707     { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage,
708         "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" },
709 
710     { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
711         "Set the breakpoint on exception throW." },
712 
713     { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
714         "Set the breakpoint on exception catcH." },
715 
716     { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
717         "sKip the prologue if the breakpoint is at the beginning of a function.  If not set the target.skip-prologue setting is used." },
718 
719     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
720         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
721 
722     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
723 };
724 
725 //-------------------------------------------------------------------------
726 // CommandObjectBreakpointModify
727 //-------------------------------------------------------------------------
728 #pragma mark Modify
729 
730 class CommandObjectBreakpointModify : public CommandObjectParsed
731 {
732 public:
733 
734     CommandObjectBreakpointModify (CommandInterpreter &interpreter) :
735         CommandObjectParsed (interpreter,
736                              "breakpoint modify",
737                              "Modify the options on a breakpoint or set of breakpoints in the executable.  "
738                              "If no breakpoint is specified, acts on the last created breakpoint.  "
739                              "With the exception of -e, -d and -i, passing an empty argument clears the modification.",
740                              NULL),
741         m_options (interpreter)
742     {
743         CommandArgumentEntry arg;
744         CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
745         // Add the entry for the first argument for this command to the object's arguments vector.
746         m_arguments.push_back (arg);
747     }
748 
749 
750     virtual
751     ~CommandObjectBreakpointModify () {}
752 
753     virtual Options *
754     GetOptions ()
755     {
756         return &m_options;
757     }
758 
759     class CommandOptions : public Options
760     {
761     public:
762 
763         CommandOptions (CommandInterpreter &interpreter) :
764             Options (interpreter),
765             m_ignore_count (0),
766             m_thread_id(LLDB_INVALID_THREAD_ID),
767             m_thread_id_passed(false),
768             m_thread_index (UINT32_MAX),
769             m_thread_index_passed(false),
770             m_thread_name(),
771             m_queue_name(),
772             m_condition (),
773             m_one_shot (false),
774             m_enable_passed (false),
775             m_enable_value (false),
776             m_name_passed (false),
777             m_queue_passed (false),
778             m_condition_passed (false),
779             m_one_shot_passed (false),
780             m_use_dummy (false)
781         {
782         }
783 
784         virtual
785         ~CommandOptions () {}
786 
787         virtual Error
788         SetOptionValue (uint32_t option_idx, const char *option_arg)
789         {
790             Error error;
791             const int short_option = m_getopt_table[option_idx].val;
792 
793             switch (short_option)
794             {
795                 case 'c':
796                     if (option_arg != NULL)
797                         m_condition.assign (option_arg);
798                     else
799                         m_condition.clear();
800                     m_condition_passed = true;
801                     break;
802                 case 'd':
803                     m_enable_passed = true;
804                     m_enable_value = false;
805                     break;
806                 case 'D':
807                     m_use_dummy = true;
808                     break;
809                 case 'e':
810                     m_enable_passed = true;
811                     m_enable_value = true;
812                     break;
813                 case 'i':
814                 {
815                     m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
816                     if (m_ignore_count == UINT32_MAX)
817                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
818                 }
819                 break;
820                 case 'o':
821                 {
822                     bool value, success;
823                     value = Args::StringToBoolean(option_arg, false, &success);
824                     if (success)
825                     {
826                         m_one_shot_passed = true;
827                         m_one_shot = value;
828                     }
829                     else
830                         error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg);
831                 }
832                 break;
833                 case 't' :
834                 {
835                     if (option_arg[0] == '\0')
836                     {
837                         m_thread_id = LLDB_INVALID_THREAD_ID;
838                         m_thread_id_passed = true;
839                     }
840                     else
841                     {
842                         m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
843                         if (m_thread_id == LLDB_INVALID_THREAD_ID)
844                            error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
845                         else
846                             m_thread_id_passed = true;
847                     }
848                 }
849                 break;
850                 case 'T':
851                     if (option_arg != NULL)
852                         m_thread_name.assign (option_arg);
853                     else
854                         m_thread_name.clear();
855                     m_name_passed = true;
856                     break;
857                 case 'q':
858                     if (option_arg != NULL)
859                         m_queue_name.assign (option_arg);
860                     else
861                         m_queue_name.clear();
862                     m_queue_passed = true;
863                     break;
864                 case 'x':
865                 {
866                     if (option_arg[0] == '\n')
867                     {
868                         m_thread_index = UINT32_MAX;
869                         m_thread_index_passed = true;
870                     }
871                     else
872                     {
873                         m_thread_index = Args::StringToUInt32 (option_arg, UINT32_MAX, 0);
874                         if (m_thread_id == UINT32_MAX)
875                            error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
876                         else
877                             m_thread_index_passed = true;
878                     }
879                 }
880                 break;
881                 default:
882                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
883                     break;
884             }
885 
886             return error;
887         }
888         void
889         OptionParsingStarting ()
890         {
891             m_ignore_count = 0;
892             m_thread_id = LLDB_INVALID_THREAD_ID;
893             m_thread_id_passed = false;
894             m_thread_index = UINT32_MAX;
895             m_thread_index_passed = false;
896             m_thread_name.clear();
897             m_queue_name.clear();
898             m_condition.clear();
899             m_one_shot = false;
900             m_enable_passed = false;
901             m_queue_passed = false;
902             m_name_passed = false;
903             m_condition_passed = false;
904             m_one_shot_passed = false;
905             m_use_dummy = false;
906         }
907 
908         const OptionDefinition*
909         GetDefinitions ()
910         {
911             return g_option_table;
912         }
913 
914 
915         // Options table: Required for subclasses of Options.
916 
917         static OptionDefinition g_option_table[];
918 
919         // Instance variables to hold the values for command options.
920 
921         uint32_t m_ignore_count;
922         lldb::tid_t m_thread_id;
923         bool m_thread_id_passed;
924         uint32_t m_thread_index;
925         bool m_thread_index_passed;
926         std::string m_thread_name;
927         std::string m_queue_name;
928         std::string m_condition;
929         bool m_one_shot;
930         bool m_enable_passed;
931         bool m_enable_value;
932         bool m_name_passed;
933         bool m_queue_passed;
934         bool m_condition_passed;
935         bool m_one_shot_passed;
936         bool m_use_dummy;
937 
938     };
939 
940 protected:
941     virtual bool
942     DoExecute (Args& command, CommandReturnObject &result)
943     {
944         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
945         if (target == NULL)
946         {
947             result.AppendError ("Invalid target.  No existing target or breakpoints.");
948             result.SetStatus (eReturnStatusFailed);
949             return false;
950         }
951 
952         Mutex::Locker locker;
953         target->GetBreakpointList().GetListMutex(locker);
954 
955         BreakpointIDList valid_bp_ids;
956 
957         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
958 
959         if (result.Succeeded())
960         {
961             const size_t count = valid_bp_ids.GetSize();
962             for (size_t i = 0; i < count; ++i)
963             {
964                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
965 
966                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
967                 {
968                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
969                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
970                     {
971                         BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get();
972                         if (location)
973                         {
974                             if (m_options.m_thread_id_passed)
975                                 location->SetThreadID (m_options.m_thread_id);
976 
977                             if (m_options.m_thread_index_passed)
978                                 location->SetThreadIndex(m_options.m_thread_index);
979 
980                             if (m_options.m_name_passed)
981                                 location->SetThreadName(m_options.m_thread_name.c_str());
982 
983                             if (m_options.m_queue_passed)
984                                 location->SetQueueName(m_options.m_queue_name.c_str());
985 
986                             if (m_options.m_ignore_count != 0)
987                                 location->SetIgnoreCount(m_options.m_ignore_count);
988 
989                             if (m_options.m_enable_passed)
990                                 location->SetEnabled (m_options.m_enable_value);
991 
992                             if (m_options.m_condition_passed)
993                                 location->SetCondition (m_options.m_condition.c_str());
994                         }
995                     }
996                     else
997                     {
998                         if (m_options.m_thread_id_passed)
999                             bp->SetThreadID (m_options.m_thread_id);
1000 
1001                         if (m_options.m_thread_index_passed)
1002                             bp->SetThreadIndex(m_options.m_thread_index);
1003 
1004                         if (m_options.m_name_passed)
1005                             bp->SetThreadName(m_options.m_thread_name.c_str());
1006 
1007                         if (m_options.m_queue_passed)
1008                             bp->SetQueueName(m_options.m_queue_name.c_str());
1009 
1010                         if (m_options.m_ignore_count != 0)
1011                             bp->SetIgnoreCount(m_options.m_ignore_count);
1012 
1013                         if (m_options.m_enable_passed)
1014                             bp->SetEnabled (m_options.m_enable_value);
1015 
1016                         if (m_options.m_condition_passed)
1017                             bp->SetCondition (m_options.m_condition.c_str());
1018                     }
1019                 }
1020             }
1021         }
1022 
1023         return result.Succeeded();
1024     }
1025 
1026 private:
1027     CommandOptions m_options;
1028 };
1029 
1030 #pragma mark Modify::CommandOptions
1031 OptionDefinition
1032 CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
1033 {
1034 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
1035 { LLDB_OPT_SET_ALL, false, "one-shot",     'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
1036 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
1037 { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
1038 { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
1039 { LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
1040 { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
1041 { LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Enable the breakpoint."},
1042 { LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone, "Disable the breakpoint."},
1043 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1044 
1045 { 0,                false, NULL,            0 , 0,                 NULL, NULL, 0, eArgTypeNone, NULL }
1046 };
1047 
1048 //-------------------------------------------------------------------------
1049 // CommandObjectBreakpointEnable
1050 //-------------------------------------------------------------------------
1051 #pragma mark Enable
1052 
1053 class CommandObjectBreakpointEnable : public CommandObjectParsed
1054 {
1055 public:
1056     CommandObjectBreakpointEnable (CommandInterpreter &interpreter) :
1057         CommandObjectParsed (interpreter,
1058                              "enable",
1059                              "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.",
1060                              NULL)
1061     {
1062         CommandArgumentEntry arg;
1063         CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1064         // Add the entry for the first argument for this command to the object's arguments vector.
1065         m_arguments.push_back (arg);
1066     }
1067 
1068 
1069     virtual
1070     ~CommandObjectBreakpointEnable () {}
1071 
1072 protected:
1073     virtual bool
1074     DoExecute (Args& command, CommandReturnObject &result)
1075     {
1076         Target *target = GetSelectedOrDummyTarget();
1077         if (target == NULL)
1078         {
1079             result.AppendError ("Invalid target.  No existing target or breakpoints.");
1080             result.SetStatus (eReturnStatusFailed);
1081             return false;
1082         }
1083 
1084         Mutex::Locker locker;
1085         target->GetBreakpointList().GetListMutex(locker);
1086 
1087         const BreakpointList &breakpoints = target->GetBreakpointList();
1088 
1089         size_t num_breakpoints = breakpoints.GetSize();
1090 
1091         if (num_breakpoints == 0)
1092         {
1093             result.AppendError ("No breakpoints exist to be enabled.");
1094             result.SetStatus (eReturnStatusFailed);
1095             return false;
1096         }
1097 
1098         if (command.GetArgumentCount() == 0)
1099         {
1100             // No breakpoint selected; enable all currently set breakpoints.
1101             target->EnableAllBreakpoints ();
1102             result.AppendMessageWithFormat ("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
1103             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1104         }
1105         else
1106         {
1107             // Particular breakpoint selected; enable that breakpoint.
1108             BreakpointIDList valid_bp_ids;
1109             CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1110 
1111             if (result.Succeeded())
1112             {
1113                 int enable_count = 0;
1114                 int loc_count = 0;
1115                 const size_t count = valid_bp_ids.GetSize();
1116                 for (size_t i = 0; i < count; ++i)
1117                 {
1118                     BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1119 
1120                     if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1121                     {
1122                         Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1123                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1124                         {
1125                             BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1126                             if (location)
1127                             {
1128                                 location->SetEnabled (true);
1129                                 ++loc_count;
1130                             }
1131                         }
1132                         else
1133                         {
1134                             breakpoint->SetEnabled (true);
1135                             ++enable_count;
1136                         }
1137                     }
1138                 }
1139                 result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
1140                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1141             }
1142         }
1143 
1144         return result.Succeeded();
1145     }
1146 };
1147 
1148 //-------------------------------------------------------------------------
1149 // CommandObjectBreakpointDisable
1150 //-------------------------------------------------------------------------
1151 #pragma mark Disable
1152 
1153 class CommandObjectBreakpointDisable : public CommandObjectParsed
1154 {
1155 public:
1156     CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
1157         CommandObjectParsed (interpreter,
1158                              "breakpoint disable",
1159                              "Disable the specified breakpoint(s) without removing it/them.  If no breakpoints are specified, disable them all.",
1160                              NULL)
1161     {
1162         SetHelpLong(
1163 "Disable the specified breakpoint(s) without removing it/them.  \n\
1164 If no breakpoints are specified, disable them all.\n\
1165 \n\
1166 Note: disabling a breakpoint will cause none of its locations to be hit\n\
1167 regardless of whether they are enabled or disabled.  So the sequence: \n\
1168 \n\
1169     (lldb) break disable 1\n\
1170     (lldb) break enable 1.1\n\
1171 \n\
1172 will NOT cause location 1.1 to get hit.  To achieve that, do:\n\
1173 \n\
1174     (lldb) break disable 1.*\n\
1175     (lldb) break enable 1.1\n\
1176 \n\
1177 The first command disables all the locations of breakpoint 1, \n\
1178 the second re-enables the first location."
1179                     );
1180 
1181         CommandArgumentEntry arg;
1182         CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1183         // Add the entry for the first argument for this command to the object's arguments vector.
1184         m_arguments.push_back (arg);
1185 
1186     }
1187 
1188 
1189     virtual
1190     ~CommandObjectBreakpointDisable () {}
1191 
1192 protected:
1193     virtual bool
1194     DoExecute (Args& command, CommandReturnObject &result)
1195     {
1196         Target *target = GetSelectedOrDummyTarget();
1197         if (target == NULL)
1198         {
1199             result.AppendError ("Invalid target.  No existing target or breakpoints.");
1200             result.SetStatus (eReturnStatusFailed);
1201             return false;
1202         }
1203 
1204         Mutex::Locker locker;
1205         target->GetBreakpointList().GetListMutex(locker);
1206 
1207         const BreakpointList &breakpoints = target->GetBreakpointList();
1208         size_t num_breakpoints = breakpoints.GetSize();
1209 
1210         if (num_breakpoints == 0)
1211         {
1212             result.AppendError ("No breakpoints exist to be disabled.");
1213             result.SetStatus (eReturnStatusFailed);
1214             return false;
1215         }
1216 
1217         if (command.GetArgumentCount() == 0)
1218         {
1219             // No breakpoint selected; disable all currently set breakpoints.
1220             target->DisableAllBreakpoints ();
1221             result.AppendMessageWithFormat ("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints);
1222             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1223         }
1224         else
1225         {
1226             // Particular breakpoint selected; disable that breakpoint.
1227             BreakpointIDList valid_bp_ids;
1228 
1229             CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1230 
1231             if (result.Succeeded())
1232             {
1233                 int disable_count = 0;
1234                 int loc_count = 0;
1235                 const size_t count = valid_bp_ids.GetSize();
1236                 for (size_t i = 0; i < count; ++i)
1237                 {
1238                     BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1239 
1240                     if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1241                     {
1242                         Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1243                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1244                         {
1245                             BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1246                             if (location)
1247                             {
1248                                 location->SetEnabled (false);
1249                                 ++loc_count;
1250                             }
1251                         }
1252                         else
1253                         {
1254                             breakpoint->SetEnabled (false);
1255                             ++disable_count;
1256                         }
1257                     }
1258                 }
1259                 result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
1260                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1261             }
1262         }
1263 
1264         return result.Succeeded();
1265     }
1266 
1267 };
1268 
1269 //-------------------------------------------------------------------------
1270 // CommandObjectBreakpointList
1271 //-------------------------------------------------------------------------
1272 #pragma mark List
1273 
1274 class CommandObjectBreakpointList : public CommandObjectParsed
1275 {
1276 public:
1277     CommandObjectBreakpointList (CommandInterpreter &interpreter) :
1278         CommandObjectParsed (interpreter,
1279                              "breakpoint list",
1280                              "List some or all breakpoints at configurable levels of detail.",
1281                              NULL),
1282         m_options (interpreter)
1283     {
1284         CommandArgumentEntry arg;
1285         CommandArgumentData bp_id_arg;
1286 
1287         // Define the first (and only) variant of this arg.
1288         bp_id_arg.arg_type = eArgTypeBreakpointID;
1289         bp_id_arg.arg_repetition = eArgRepeatOptional;
1290 
1291         // There is only one variant this argument could be; put it into the argument entry.
1292         arg.push_back (bp_id_arg);
1293 
1294         // Push the data for the first argument into the m_arguments vector.
1295         m_arguments.push_back (arg);
1296     }
1297 
1298 
1299     virtual
1300     ~CommandObjectBreakpointList () {}
1301 
1302     virtual Options *
1303     GetOptions ()
1304     {
1305         return &m_options;
1306     }
1307 
1308     class CommandOptions : public Options
1309     {
1310     public:
1311 
1312         CommandOptions (CommandInterpreter &interpreter) :
1313             Options (interpreter),
1314             m_level (lldb::eDescriptionLevelBrief),
1315             m_use_dummy(false)
1316         {
1317         }
1318 
1319         virtual
1320         ~CommandOptions () {}
1321 
1322         virtual Error
1323         SetOptionValue (uint32_t option_idx, const char *option_arg)
1324         {
1325             Error error;
1326             const int short_option = m_getopt_table[option_idx].val;
1327 
1328             switch (short_option)
1329             {
1330                 case 'b':
1331                     m_level = lldb::eDescriptionLevelBrief;
1332                     break;
1333                 case 'D':
1334                     m_use_dummy = true;
1335                     break;
1336                 case 'f':
1337                     m_level = lldb::eDescriptionLevelFull;
1338                     break;
1339                 case 'v':
1340                     m_level = lldb::eDescriptionLevelVerbose;
1341                     break;
1342                 case 'i':
1343                     m_internal = true;
1344                     break;
1345                 default:
1346                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1347                     break;
1348             }
1349 
1350             return error;
1351         }
1352 
1353         void
1354         OptionParsingStarting ()
1355         {
1356             m_level = lldb::eDescriptionLevelFull;
1357             m_internal = false;
1358             m_use_dummy = false;
1359         }
1360 
1361         const OptionDefinition *
1362         GetDefinitions ()
1363         {
1364             return g_option_table;
1365         }
1366 
1367         // Options table: Required for subclasses of Options.
1368 
1369         static OptionDefinition g_option_table[];
1370 
1371         // Instance variables to hold the values for command options.
1372 
1373         lldb::DescriptionLevel m_level;
1374 
1375         bool m_internal;
1376         bool m_use_dummy;
1377     };
1378 
1379 protected:
1380     virtual bool
1381     DoExecute (Args& command, CommandReturnObject &result)
1382     {
1383         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1384 
1385         if (target == NULL)
1386         {
1387             result.AppendError ("Invalid target. No current target or breakpoints.");
1388             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1389             return true;
1390         }
1391 
1392         const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
1393         Mutex::Locker locker;
1394         target->GetBreakpointList(m_options.m_internal).GetListMutex(locker);
1395 
1396         size_t num_breakpoints = breakpoints.GetSize();
1397 
1398         if (num_breakpoints == 0)
1399         {
1400             result.AppendMessage ("No breakpoints currently set.");
1401             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1402             return true;
1403         }
1404 
1405         Stream &output_stream = result.GetOutputStream();
1406 
1407         if (command.GetArgumentCount() == 0)
1408         {
1409             // No breakpoint selected; show info about all currently set breakpoints.
1410             result.AppendMessage ("Current breakpoints:");
1411             for (size_t i = 0; i < num_breakpoints; ++i)
1412             {
1413                 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get();
1414                 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
1415             }
1416             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1417         }
1418         else
1419         {
1420             // Particular breakpoints selected; show info about that breakpoint.
1421             BreakpointIDList valid_bp_ids;
1422             CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1423 
1424             if (result.Succeeded())
1425             {
1426                 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i)
1427                 {
1428                     BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1429                     Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1430                     AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
1431                 }
1432                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1433             }
1434             else
1435             {
1436                 result.AppendError ("Invalid breakpoint id.");
1437                 result.SetStatus (eReturnStatusFailed);
1438             }
1439         }
1440 
1441         return result.Succeeded();
1442     }
1443 
1444 private:
1445     CommandOptions m_options;
1446 };
1447 
1448 #pragma mark List::CommandOptions
1449 OptionDefinition
1450 CommandObjectBreakpointList::CommandOptions::g_option_table[] =
1451 {
1452     { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1453         "Show debugger internal breakpoints" },
1454 
1455     { LLDB_OPT_SET_1, false, "brief",    'b', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1456         "Give a brief description of the breakpoint (no location info)."},
1457 
1458     // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1459     // But I need to see it for now, and don't want to wait.
1460     { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1461         "Give a full description of the breakpoint and its locations."},
1462 
1463     { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1464         "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1465 
1466     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1467         "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1468 
1469     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1470 };
1471 
1472 //-------------------------------------------------------------------------
1473 // CommandObjectBreakpointClear
1474 //-------------------------------------------------------------------------
1475 #pragma mark Clear
1476 
1477 class CommandObjectBreakpointClear : public CommandObjectParsed
1478 {
1479 public:
1480 
1481     typedef enum BreakpointClearType
1482     {
1483         eClearTypeInvalid,
1484         eClearTypeFileAndLine
1485     } BreakpointClearType;
1486 
1487     CommandObjectBreakpointClear (CommandInterpreter &interpreter) :
1488         CommandObjectParsed (interpreter,
1489                              "breakpoint clear",
1490                              "Clears a breakpoint or set of breakpoints in the executable.",
1491                              "breakpoint clear <cmd-options>"),
1492         m_options (interpreter)
1493     {
1494     }
1495 
1496     virtual
1497     ~CommandObjectBreakpointClear () {}
1498 
1499     virtual Options *
1500     GetOptions ()
1501     {
1502         return &m_options;
1503     }
1504 
1505     class CommandOptions : public Options
1506     {
1507     public:
1508 
1509         CommandOptions (CommandInterpreter &interpreter) :
1510             Options (interpreter),
1511             m_filename (),
1512             m_line_num (0)
1513         {
1514         }
1515 
1516         virtual
1517         ~CommandOptions () {}
1518 
1519         virtual Error
1520         SetOptionValue (uint32_t option_idx, const char *option_arg)
1521         {
1522             Error error;
1523             const int short_option = m_getopt_table[option_idx].val;
1524 
1525             switch (short_option)
1526             {
1527                 case 'f':
1528                     m_filename.assign (option_arg);
1529                     break;
1530 
1531                 case 'l':
1532                     m_line_num = Args::StringToUInt32 (option_arg, 0);
1533                     break;
1534 
1535                 default:
1536                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1537                     break;
1538             }
1539 
1540             return error;
1541         }
1542 
1543         void
1544         OptionParsingStarting ()
1545         {
1546             m_filename.clear();
1547             m_line_num = 0;
1548         }
1549 
1550         const OptionDefinition*
1551         GetDefinitions ()
1552         {
1553             return g_option_table;
1554         }
1555 
1556         // Options table: Required for subclasses of Options.
1557 
1558         static OptionDefinition g_option_table[];
1559 
1560         // Instance variables to hold the values for command options.
1561 
1562         std::string m_filename;
1563         uint32_t m_line_num;
1564 
1565     };
1566 
1567 protected:
1568     virtual bool
1569     DoExecute (Args& command, CommandReturnObject &result)
1570     {
1571         Target *target = GetSelectedOrDummyTarget();
1572         if (target == NULL)
1573         {
1574             result.AppendError ("Invalid target. No existing target or breakpoints.");
1575             result.SetStatus (eReturnStatusFailed);
1576             return false;
1577         }
1578 
1579         // The following are the various types of breakpoints that could be cleared:
1580         //   1). -f -l (clearing breakpoint by source location)
1581 
1582         BreakpointClearType break_type = eClearTypeInvalid;
1583 
1584         if (m_options.m_line_num != 0)
1585             break_type = eClearTypeFileAndLine;
1586 
1587         Mutex::Locker locker;
1588         target->GetBreakpointList().GetListMutex(locker);
1589 
1590         BreakpointList &breakpoints = target->GetBreakpointList();
1591         size_t num_breakpoints = breakpoints.GetSize();
1592 
1593         // Early return if there's no breakpoint at all.
1594         if (num_breakpoints == 0)
1595         {
1596             result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1597             result.SetStatus (eReturnStatusFailed);
1598             return result.Succeeded();
1599         }
1600 
1601         // Find matching breakpoints and delete them.
1602 
1603         // First create a copy of all the IDs.
1604         std::vector<break_id_t> BreakIDs;
1605         for (size_t i = 0; i < num_breakpoints; ++i)
1606             BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i).get()->GetID());
1607 
1608         int num_cleared = 0;
1609         StreamString ss;
1610         switch (break_type)
1611         {
1612             case eClearTypeFileAndLine: // Breakpoint by source position
1613                 {
1614                     const ConstString filename(m_options.m_filename.c_str());
1615                     BreakpointLocationCollection loc_coll;
1616 
1617                     for (size_t i = 0; i < num_breakpoints; ++i)
1618                     {
1619                         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1620 
1621                         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll))
1622                         {
1623                             // If the collection size is 0, it's a full match and we can just remove the breakpoint.
1624                             if (loc_coll.GetSize() == 0)
1625                             {
1626                                 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1627                                 ss.EOL();
1628                                 target->RemoveBreakpointByID (bp->GetID());
1629                                 ++num_cleared;
1630                             }
1631                         }
1632                     }
1633                 }
1634                 break;
1635 
1636             default:
1637                 break;
1638         }
1639 
1640         if (num_cleared > 0)
1641         {
1642             Stream &output_stream = result.GetOutputStream();
1643             output_stream.Printf ("%d breakpoints cleared:\n", num_cleared);
1644             output_stream << ss.GetData();
1645             output_stream.EOL();
1646             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1647         }
1648         else
1649         {
1650             result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1651             result.SetStatus (eReturnStatusFailed);
1652         }
1653 
1654         return result.Succeeded();
1655     }
1656 
1657 private:
1658     CommandOptions m_options;
1659 };
1660 
1661 #pragma mark Clear::CommandOptions
1662 
1663 OptionDefinition
1664 CommandObjectBreakpointClear::CommandOptions::g_option_table[] =
1665 {
1666     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1667         "Specify the breakpoint by source location in this particular file."},
1668 
1669     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
1670         "Specify the breakpoint by source location at this particular line."},
1671 
1672     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1673 };
1674 
1675 //-------------------------------------------------------------------------
1676 // CommandObjectBreakpointDelete
1677 //-------------------------------------------------------------------------
1678 #pragma mark Delete
1679 
1680 class CommandObjectBreakpointDelete : public CommandObjectParsed
1681 {
1682 public:
1683     CommandObjectBreakpointDelete (CommandInterpreter &interpreter) :
1684         CommandObjectParsed (interpreter,
1685                              "breakpoint delete",
1686                              "Delete the specified breakpoint(s).  If no breakpoints are specified, delete them all.",
1687                              NULL),
1688         m_options (interpreter)
1689     {
1690         CommandArgumentEntry arg;
1691         CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1692         // Add the entry for the first argument for this command to the object's arguments vector.
1693         m_arguments.push_back (arg);
1694     }
1695 
1696     virtual
1697     ~CommandObjectBreakpointDelete () {}
1698 
1699     virtual Options *
1700     GetOptions ()
1701     {
1702         return &m_options;
1703     }
1704 
1705     class CommandOptions : public Options
1706     {
1707     public:
1708 
1709         CommandOptions (CommandInterpreter &interpreter) :
1710             Options (interpreter),
1711             m_use_dummy (false),
1712             m_force (false)
1713         {
1714         }
1715 
1716         virtual
1717         ~CommandOptions () {}
1718 
1719         virtual Error
1720         SetOptionValue (uint32_t option_idx, const char *option_arg)
1721         {
1722             Error error;
1723             const int short_option = m_getopt_table[option_idx].val;
1724 
1725             switch (short_option)
1726             {
1727                 case 'f':
1728                     m_force = true;
1729                     break;
1730 
1731                 case 'D':
1732                     m_use_dummy = true;
1733                     break;
1734 
1735                 default:
1736                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1737                     break;
1738             }
1739 
1740             return error;
1741         }
1742 
1743         void
1744         OptionParsingStarting ()
1745         {
1746             m_use_dummy = false;
1747             m_force = false;
1748         }
1749 
1750         const OptionDefinition*
1751         GetDefinitions ()
1752         {
1753             return g_option_table;
1754         }
1755 
1756         // Options table: Required for subclasses of Options.
1757 
1758         static OptionDefinition g_option_table[];
1759 
1760         // Instance variables to hold the values for command options.
1761         bool m_use_dummy;
1762         bool m_force;
1763     };
1764 
1765 protected:
1766     virtual bool
1767     DoExecute (Args& command, CommandReturnObject &result)
1768     {
1769         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1770 
1771         if (target == NULL)
1772         {
1773             result.AppendError ("Invalid target. No existing target or breakpoints.");
1774             result.SetStatus (eReturnStatusFailed);
1775             return false;
1776         }
1777 
1778         Mutex::Locker locker;
1779         target->GetBreakpointList().GetListMutex(locker);
1780 
1781         const BreakpointList &breakpoints = target->GetBreakpointList();
1782 
1783         size_t num_breakpoints = breakpoints.GetSize();
1784 
1785         if (num_breakpoints == 0)
1786         {
1787             result.AppendError ("No breakpoints exist to be deleted.");
1788             result.SetStatus (eReturnStatusFailed);
1789             return false;
1790         }
1791 
1792         if (command.GetArgumentCount() == 0)
1793         {
1794             if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
1795             {
1796                 result.AppendMessage("Operation cancelled...");
1797             }
1798             else
1799             {
1800                 target->RemoveAllBreakpoints ();
1801                 result.AppendMessageWithFormat ("All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1802             }
1803             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1804         }
1805         else
1806         {
1807             // Particular breakpoint selected; disable that breakpoint.
1808             BreakpointIDList valid_bp_ids;
1809             CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1810 
1811             if (result.Succeeded())
1812             {
1813                 int delete_count = 0;
1814                 int disable_count = 0;
1815                 const size_t count = valid_bp_ids.GetSize();
1816                 for (size_t i = 0; i < count; ++i)
1817                 {
1818                     BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1819 
1820                     if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1821                     {
1822                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1823                         {
1824                             Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1825                             BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1826                             // It makes no sense to try to delete individual locations, so we disable them instead.
1827                             if (location)
1828                             {
1829                                 location->SetEnabled (false);
1830                                 ++disable_count;
1831                             }
1832                         }
1833                         else
1834                         {
1835                             target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
1836                             ++delete_count;
1837                         }
1838                     }
1839                 }
1840                 result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
1841                                                delete_count, disable_count);
1842                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1843             }
1844         }
1845         return result.Succeeded();
1846     }
1847 private:
1848     CommandOptions m_options;
1849 };
1850 
1851 OptionDefinition
1852 CommandObjectBreakpointDelete::CommandOptions::g_option_table[] =
1853 {
1854     { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1855         "Delete all breakpoints without querying for confirmation."},
1856 
1857     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
1858         "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1859 
1860     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1861 };
1862 
1863 //-------------------------------------------------------------------------
1864 // CommandObjectMultiwordBreakpoint
1865 //-------------------------------------------------------------------------
1866 #pragma mark MultiwordBreakpoint
1867 
1868 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter) :
1869     CommandObjectMultiword (interpreter,
1870                             "breakpoint",
1871                             "A set of commands for operating on breakpoints. Also see _regexp-break.",
1872                             "breakpoint <command> [<command-options>]")
1873 {
1874     CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter));
1875     CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter));
1876     CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter));
1877     CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter));
1878     CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter));
1879     CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));
1880     CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
1881     CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter));
1882 
1883     list_command_object->SetCommandName ("breakpoint list");
1884     enable_command_object->SetCommandName("breakpoint enable");
1885     disable_command_object->SetCommandName("breakpoint disable");
1886     clear_command_object->SetCommandName("breakpoint clear");
1887     delete_command_object->SetCommandName("breakpoint delete");
1888     set_command_object->SetCommandName("breakpoint set");
1889     command_command_object->SetCommandName ("breakpoint command");
1890     modify_command_object->SetCommandName ("breakpoint modify");
1891 
1892     LoadSubCommand ("list",       list_command_object);
1893     LoadSubCommand ("enable",     enable_command_object);
1894     LoadSubCommand ("disable",    disable_command_object);
1895     LoadSubCommand ("clear",      clear_command_object);
1896     LoadSubCommand ("delete",     delete_command_object);
1897     LoadSubCommand ("set",        set_command_object);
1898     LoadSubCommand ("command",    command_command_object);
1899     LoadSubCommand ("modify",     modify_command_object);
1900 }
1901 
1902 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
1903 {
1904 }
1905 
1906 void
1907 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
1908                                                          BreakpointIDList *valid_ids)
1909 {
1910     // args can be strings representing 1). integers (for breakpoint ids)
1911     //                                  2). the full breakpoint & location canonical representation
1912     //                                  3). the word "to" or a hyphen, representing a range (in which case there
1913     //                                      had *better* be an entry both before & after of one of the first two types.
1914     // If args is empty, we will use the last created breakpoint (if there is one.)
1915 
1916     Args temp_args;
1917 
1918     if (args.GetArgumentCount() == 0)
1919     {
1920         if (target->GetLastCreatedBreakpoint())
1921         {
1922             valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
1923             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1924         }
1925         else
1926         {
1927             result.AppendError("No breakpoint specified and no last created breakpoint.");
1928             result.SetStatus (eReturnStatusFailed);
1929         }
1930         return;
1931     }
1932 
1933     // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
1934     // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for
1935     // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
1936 
1937     BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
1938 
1939     // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
1940 
1941     valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result);
1942 
1943     // At this point,  all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
1944     // and put into valid_ids.
1945 
1946     if (result.Succeeded())
1947     {
1948         // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
1949         // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
1950 
1951         const size_t count = valid_ids->GetSize();
1952         for (size_t i = 0; i < count; ++i)
1953         {
1954             BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
1955             Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1956             if (breakpoint != NULL)
1957             {
1958                 const size_t num_locations = breakpoint->GetNumLocations();
1959                 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations)
1960                 {
1961                     StreamString id_str;
1962                     BreakpointID::GetCanonicalReference (&id_str,
1963                                                          cur_bp_id.GetBreakpointID(),
1964                                                          cur_bp_id.GetLocationID());
1965                     i = valid_ids->GetSize() + 1;
1966                     result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
1967                                                  id_str.GetData());
1968                     result.SetStatus (eReturnStatusFailed);
1969                 }
1970             }
1971             else
1972             {
1973                 i = valid_ids->GetSize() + 1;
1974                 result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
1975                 result.SetStatus (eReturnStatusFailed);
1976             }
1977         }
1978     }
1979 }
1980