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