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