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