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