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