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