1254721Semaste//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "CommandObjectBreakpoint.h"
13254721Semaste#include "CommandObjectBreakpointCommand.h"
14254721Semaste
15254721Semaste// C Includes
16254721Semaste// C++ Includes
17254721Semaste// Other libraries and framework includes
18254721Semaste// Project includes
19254721Semaste#include "lldb/Breakpoint/Breakpoint.h"
20254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h"
21254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h"
22254721Semaste#include "lldb/Interpreter/Options.h"
23254721Semaste#include "lldb/Core/RegularExpression.h"
24254721Semaste#include "lldb/Core/StreamString.h"
25254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
26254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
27254721Semaste#include "lldb/Target/Target.h"
28254721Semaste#include "lldb/Interpreter/CommandCompletions.h"
29254721Semaste#include "lldb/Target/StackFrame.h"
30254721Semaste#include "lldb/Target/Thread.h"
31254721Semaste#include "lldb/Target/ThreadSpec.h"
32254721Semaste
33254721Semaste#include <vector>
34254721Semaste
35254721Semasteusing namespace lldb;
36254721Semasteusing namespace lldb_private;
37254721Semaste
38254721Semastestatic void
39254721SemasteAddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level)
40254721Semaste{
41254721Semaste    s->IndentMore();
42254721Semaste    bp->GetDescription (s, level, true);
43254721Semaste    s->IndentLess();
44254721Semaste    s->EOL();
45254721Semaste}
46254721Semaste
47254721Semaste//-------------------------------------------------------------------------
48254721Semaste// CommandObjectBreakpointSet
49254721Semaste//-------------------------------------------------------------------------
50254721Semaste
51254721Semaste
52254721Semasteclass CommandObjectBreakpointSet : public CommandObjectParsed
53254721Semaste{
54254721Semastepublic:
55254721Semaste
56254721Semaste    typedef enum BreakpointSetType
57254721Semaste    {
58254721Semaste        eSetTypeInvalid,
59254721Semaste        eSetTypeFileAndLine,
60254721Semaste        eSetTypeAddress,
61254721Semaste        eSetTypeFunctionName,
62254721Semaste        eSetTypeFunctionRegexp,
63254721Semaste        eSetTypeSourceRegexp,
64254721Semaste        eSetTypeException
65254721Semaste    } BreakpointSetType;
66254721Semaste
67254721Semaste    CommandObjectBreakpointSet (CommandInterpreter &interpreter) :
68254721Semaste        CommandObjectParsed (interpreter,
69254721Semaste                             "breakpoint set",
70254721Semaste                             "Sets a breakpoint or set of breakpoints in the executable.",
71254721Semaste                             "breakpoint set <cmd-options>"),
72254721Semaste        m_options (interpreter)
73254721Semaste    {
74254721Semaste    }
75254721Semaste
76254721Semaste
77254721Semaste    virtual
78254721Semaste    ~CommandObjectBreakpointSet () {}
79254721Semaste
80254721Semaste    virtual Options *
81254721Semaste    GetOptions ()
82254721Semaste    {
83254721Semaste        return &m_options;
84254721Semaste    }
85254721Semaste
86254721Semaste    class CommandOptions : public Options
87254721Semaste    {
88254721Semaste    public:
89254721Semaste
90254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
91254721Semaste            Options (interpreter),
92254721Semaste            m_condition (),
93254721Semaste            m_filenames (),
94254721Semaste            m_line_num (0),
95254721Semaste            m_column (0),
96254721Semaste            m_func_names (),
97254721Semaste            m_func_name_type_mask (eFunctionNameTypeNone),
98254721Semaste            m_func_regexp (),
99254721Semaste            m_source_text_regexp(),
100254721Semaste            m_modules (),
101254721Semaste            m_load_addr(),
102254721Semaste            m_ignore_count (0),
103254721Semaste            m_thread_id(LLDB_INVALID_THREAD_ID),
104254721Semaste            m_thread_index (UINT32_MAX),
105254721Semaste            m_thread_name(),
106254721Semaste            m_queue_name(),
107254721Semaste            m_catch_bp (false),
108254721Semaste            m_throw_bp (true),
109263363Semaste            m_hardware (false),
110254721Semaste            m_language (eLanguageTypeUnknown),
111254721Semaste            m_skip_prologue (eLazyBoolCalculate),
112254721Semaste            m_one_shot (false)
113254721Semaste        {
114254721Semaste        }
115254721Semaste
116254721Semaste
117254721Semaste        virtual
118254721Semaste        ~CommandOptions () {}
119254721Semaste
120254721Semaste        virtual Error
121254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
122254721Semaste        {
123254721Semaste            Error error;
124254721Semaste            const int short_option = m_getopt_table[option_idx].val;
125254721Semaste
126254721Semaste            switch (short_option)
127254721Semaste            {
128254721Semaste                case 'a':
129254721Semaste                    {
130254721Semaste                        ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
131254721Semaste                        m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
132254721Semaste                    }
133254721Semaste                    break;
134254721Semaste
135254721Semaste                case 'b':
136254721Semaste                    m_func_names.push_back (option_arg);
137254721Semaste                    m_func_name_type_mask |= eFunctionNameTypeBase;
138254721Semaste                    break;
139254721Semaste
140254721Semaste                case 'C':
141254721Semaste                    m_column = Args::StringToUInt32 (option_arg, 0);
142254721Semaste                    break;
143254721Semaste
144254721Semaste                case 'c':
145254721Semaste                    m_condition.assign(option_arg);
146254721Semaste                    break;
147254721Semaste
148254721Semaste                case 'E':
149254721Semaste                {
150254721Semaste                    LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg);
151254721Semaste
152254721Semaste                    switch (language)
153254721Semaste                    {
154254721Semaste                        case eLanguageTypeC89:
155254721Semaste                        case eLanguageTypeC:
156254721Semaste                        case eLanguageTypeC99:
157254721Semaste                            m_language = eLanguageTypeC;
158254721Semaste                            break;
159254721Semaste                        case eLanguageTypeC_plus_plus:
160254721Semaste                            m_language = eLanguageTypeC_plus_plus;
161254721Semaste                            break;
162254721Semaste                        case eLanguageTypeObjC:
163254721Semaste                            m_language = eLanguageTypeObjC;
164254721Semaste                            break;
165254721Semaste                        case eLanguageTypeObjC_plus_plus:
166254721Semaste                            error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c");
167254721Semaste                            break;
168254721Semaste                        case eLanguageTypeUnknown:
169254721Semaste                            error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg);
170254721Semaste                            break;
171254721Semaste                        default:
172254721Semaste                            error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg);
173254721Semaste                    }
174254721Semaste                }
175254721Semaste                break;
176254721Semaste
177254721Semaste                case 'f':
178254721Semaste                    m_filenames.AppendIfUnique (FileSpec(option_arg, false));
179254721Semaste                    break;
180254721Semaste
181254721Semaste                case 'F':
182254721Semaste                    m_func_names.push_back (option_arg);
183254721Semaste                    m_func_name_type_mask |= eFunctionNameTypeFull;
184254721Semaste                    break;
185254721Semaste
186254721Semaste                case 'h':
187263363Semaste                    {
188263363Semaste                        bool success;
189263363Semaste                        m_catch_bp = Args::StringToBoolean (option_arg, true, &success);
190263363Semaste                        if (!success)
191263363Semaste                            error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg);
192263363Semaste                    }
193263363Semaste                    break;
194263363Semaste
195263363Semaste                case 'H':
196263363Semaste                    m_hardware = true;
197263363Semaste                    break;
198263363Semaste
199254721Semaste                case 'i':
200254721Semaste                {
201254721Semaste                    m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
202254721Semaste                    if (m_ignore_count == UINT32_MAX)
203254721Semaste                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
204254721Semaste                    break;
205254721Semaste                }
206254721Semaste
207254721Semaste                case 'K':
208254721Semaste                {
209254721Semaste                    bool success;
210254721Semaste                    bool value;
211254721Semaste                    value = Args::StringToBoolean (option_arg, true, &success);
212254721Semaste                    if (value)
213254721Semaste                        m_skip_prologue = eLazyBoolYes;
214254721Semaste                    else
215254721Semaste                        m_skip_prologue = eLazyBoolNo;
216254721Semaste
217254721Semaste                    if (!success)
218254721Semaste                        error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg);
219254721Semaste                }
220254721Semaste                break;
221254721Semaste
222254721Semaste                case 'l':
223254721Semaste                    m_line_num = Args::StringToUInt32 (option_arg, 0);
224254721Semaste                    break;
225254721Semaste
226254721Semaste                case 'M':
227254721Semaste                    m_func_names.push_back (option_arg);
228254721Semaste                    m_func_name_type_mask |= eFunctionNameTypeMethod;
229254721Semaste                    break;
230254721Semaste
231254721Semaste                case 'n':
232254721Semaste                    m_func_names.push_back (option_arg);
233254721Semaste                    m_func_name_type_mask |= eFunctionNameTypeAuto;
234254721Semaste                    break;
235254721Semaste
236254721Semaste                case 'o':
237254721Semaste                    m_one_shot = true;
238254721Semaste                    break;
239254721Semaste
240254721Semaste                case 'p':
241254721Semaste                    m_source_text_regexp.assign (option_arg);
242254721Semaste                    break;
243254721Semaste
244254721Semaste                case 'q':
245254721Semaste                    m_queue_name.assign (option_arg);
246254721Semaste                    break;
247254721Semaste
248254721Semaste                case 'r':
249254721Semaste                    m_func_regexp.assign (option_arg);
250254721Semaste                    break;
251254721Semaste
252254721Semaste                case 's':
253254721Semaste                {
254254721Semaste                    m_modules.AppendIfUnique (FileSpec (option_arg, false));
255254721Semaste                    break;
256254721Semaste                }
257254721Semaste
258254721Semaste                case 'S':
259254721Semaste                    m_func_names.push_back (option_arg);
260254721Semaste                    m_func_name_type_mask |= eFunctionNameTypeSelector;
261254721Semaste                    break;
262254721Semaste
263254721Semaste                case 't' :
264254721Semaste                {
265254721Semaste                    m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
266254721Semaste                    if (m_thread_id == LLDB_INVALID_THREAD_ID)
267254721Semaste                       error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
268254721Semaste                }
269254721Semaste                break;
270254721Semaste
271254721Semaste                case 'T':
272254721Semaste                    m_thread_name.assign (option_arg);
273254721Semaste                    break;
274254721Semaste
275254721Semaste                case 'w':
276254721Semaste                {
277254721Semaste                    bool success;
278254721Semaste                    m_throw_bp = Args::StringToBoolean (option_arg, true, &success);
279254721Semaste                    if (!success)
280254721Semaste                        error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg);
281254721Semaste                }
282254721Semaste                break;
283254721Semaste
284254721Semaste                case 'x':
285254721Semaste                {
286254721Semaste                    m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
287254721Semaste                    if (m_thread_id == UINT32_MAX)
288254721Semaste                       error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
289254721Semaste
290254721Semaste                }
291254721Semaste                break;
292254721Semaste
293254721Semaste                default:
294254721Semaste                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
295254721Semaste                    break;
296254721Semaste            }
297254721Semaste
298254721Semaste            return error;
299254721Semaste        }
300254721Semaste        void
301254721Semaste        OptionParsingStarting ()
302254721Semaste        {
303254721Semaste            m_condition.clear();
304254721Semaste            m_filenames.Clear();
305254721Semaste            m_line_num = 0;
306254721Semaste            m_column = 0;
307254721Semaste            m_func_names.clear();
308254721Semaste            m_func_name_type_mask = eFunctionNameTypeNone;
309254721Semaste            m_func_regexp.clear();
310254721Semaste            m_source_text_regexp.clear();
311254721Semaste            m_modules.Clear();
312254721Semaste            m_load_addr = LLDB_INVALID_ADDRESS;
313254721Semaste            m_ignore_count = 0;
314254721Semaste            m_thread_id = LLDB_INVALID_THREAD_ID;
315254721Semaste            m_thread_index = UINT32_MAX;
316254721Semaste            m_thread_name.clear();
317254721Semaste            m_queue_name.clear();
318254721Semaste            m_catch_bp = false;
319254721Semaste            m_throw_bp = true;
320263363Semaste            m_hardware = false;
321254721Semaste            m_language = eLanguageTypeUnknown;
322254721Semaste            m_skip_prologue = eLazyBoolCalculate;
323254721Semaste            m_one_shot = false;
324254721Semaste        }
325254721Semaste
326254721Semaste        const OptionDefinition*
327254721Semaste        GetDefinitions ()
328254721Semaste        {
329254721Semaste            return g_option_table;
330254721Semaste        }
331254721Semaste
332254721Semaste        // Options table: Required for subclasses of Options.
333254721Semaste
334254721Semaste        static OptionDefinition g_option_table[];
335254721Semaste
336254721Semaste        // Instance variables to hold the values for command options.
337254721Semaste
338254721Semaste        std::string m_condition;
339254721Semaste        FileSpecList m_filenames;
340254721Semaste        uint32_t m_line_num;
341254721Semaste        uint32_t m_column;
342254721Semaste        std::vector<std::string> m_func_names;
343254721Semaste        uint32_t m_func_name_type_mask;
344254721Semaste        std::string m_func_regexp;
345254721Semaste        std::string m_source_text_regexp;
346254721Semaste        FileSpecList m_modules;
347254721Semaste        lldb::addr_t m_load_addr;
348254721Semaste        uint32_t m_ignore_count;
349254721Semaste        lldb::tid_t m_thread_id;
350254721Semaste        uint32_t m_thread_index;
351254721Semaste        std::string m_thread_name;
352254721Semaste        std::string m_queue_name;
353254721Semaste        bool m_catch_bp;
354254721Semaste        bool m_throw_bp;
355263363Semaste        bool m_hardware; // Request to use hardware breakpoints
356254721Semaste        lldb::LanguageType m_language;
357254721Semaste        LazyBool m_skip_prologue;
358254721Semaste        bool m_one_shot;
359254721Semaste
360254721Semaste    };
361254721Semaste
362254721Semasteprotected:
363254721Semaste    virtual bool
364254721Semaste    DoExecute (Args& command,
365254721Semaste             CommandReturnObject &result)
366254721Semaste    {
367254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
368254721Semaste        if (target == NULL)
369254721Semaste        {
370254721Semaste            result.AppendError ("Invalid target.  Must set target before setting breakpoints (see 'target create' command).");
371254721Semaste            result.SetStatus (eReturnStatusFailed);
372254721Semaste            return false;
373254721Semaste        }
374254721Semaste
375254721Semaste        // The following are the various types of breakpoints that could be set:
376254721Semaste        //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
377254721Semaste        //   2).  -a  [-s -g]         (setting breakpoint by address)
378254721Semaste        //   3).  -n  [-s -g]         (setting breakpoint by function name)
379254721Semaste        //   4).  -r  [-s -g]         (setting breakpoint by function name regular expression)
380254721Semaste        //   5).  -p -f               (setting a breakpoint by comparing a reg-exp to source text)
381254721Semaste        //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a given language.)
382254721Semaste
383254721Semaste        BreakpointSetType break_type = eSetTypeInvalid;
384254721Semaste
385254721Semaste        if (m_options.m_line_num != 0)
386254721Semaste            break_type = eSetTypeFileAndLine;
387254721Semaste        else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
388254721Semaste            break_type = eSetTypeAddress;
389254721Semaste        else if (!m_options.m_func_names.empty())
390254721Semaste            break_type = eSetTypeFunctionName;
391254721Semaste        else if  (!m_options.m_func_regexp.empty())
392254721Semaste            break_type = eSetTypeFunctionRegexp;
393254721Semaste        else if (!m_options.m_source_text_regexp.empty())
394254721Semaste            break_type = eSetTypeSourceRegexp;
395254721Semaste        else if (m_options.m_language != eLanguageTypeUnknown)
396254721Semaste            break_type = eSetTypeException;
397254721Semaste
398254721Semaste        Breakpoint *bp = NULL;
399254721Semaste        FileSpec module_spec;
400254721Semaste        const bool internal = false;
401254721Semaste
402254721Semaste        switch (break_type)
403254721Semaste        {
404254721Semaste            case eSetTypeFileAndLine: // Breakpoint by source position
405254721Semaste                {
406254721Semaste                    FileSpec file;
407254721Semaste                    const size_t num_files = m_options.m_filenames.GetSize();
408254721Semaste                    if (num_files == 0)
409254721Semaste                    {
410254721Semaste                        if (!GetDefaultFile (target, file, result))
411254721Semaste                        {
412254721Semaste                            result.AppendError("No file supplied and no default file available.");
413254721Semaste                            result.SetStatus (eReturnStatusFailed);
414254721Semaste                            return false;
415254721Semaste                        }
416254721Semaste                    }
417254721Semaste                    else if (num_files > 1)
418254721Semaste                    {
419254721Semaste                        result.AppendError("Only one file at a time is allowed for file and line breakpoints.");
420254721Semaste                        result.SetStatus (eReturnStatusFailed);
421254721Semaste                        return false;
422254721Semaste                    }
423254721Semaste                    else
424254721Semaste                        file = m_options.m_filenames.GetFileSpecAtIndex(0);
425254721Semaste
426254721Semaste                    // Only check for inline functions if
427254721Semaste                    LazyBool check_inlines = eLazyBoolCalculate;
428254721Semaste
429254721Semaste                    bp = target->CreateBreakpoint (&(m_options.m_modules),
430254721Semaste                                                   file,
431254721Semaste                                                   m_options.m_line_num,
432254721Semaste                                                   check_inlines,
433254721Semaste                                                   m_options.m_skip_prologue,
434263363Semaste                                                   internal,
435263363Semaste                                                   m_options.m_hardware).get();
436254721Semaste                }
437254721Semaste                break;
438254721Semaste
439254721Semaste            case eSetTypeAddress: // Breakpoint by address
440263363Semaste                bp = target->CreateBreakpoint (m_options.m_load_addr,
441263363Semaste                                               internal,
442263363Semaste                                               m_options.m_hardware).get();
443254721Semaste                break;
444254721Semaste
445254721Semaste            case eSetTypeFunctionName: // Breakpoint by function name
446254721Semaste                {
447254721Semaste                    uint32_t name_type_mask = m_options.m_func_name_type_mask;
448254721Semaste
449254721Semaste                    if (name_type_mask == 0)
450254721Semaste                        name_type_mask = eFunctionNameTypeAuto;
451254721Semaste
452254721Semaste                    bp = target->CreateBreakpoint (&(m_options.m_modules),
453254721Semaste                                                   &(m_options.m_filenames),
454254721Semaste                                                   m_options.m_func_names,
455254721Semaste                                                   name_type_mask,
456254721Semaste                                                   m_options.m_skip_prologue,
457263363Semaste                                                   internal,
458263363Semaste                                                   m_options.m_hardware).get();
459254721Semaste                }
460254721Semaste                break;
461254721Semaste
462254721Semaste            case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
463254721Semaste                {
464254721Semaste                    RegularExpression regexp(m_options.m_func_regexp.c_str());
465254721Semaste                    if (!regexp.IsValid())
466254721Semaste                    {
467254721Semaste                        char err_str[1024];
468254721Semaste                        regexp.GetErrorAsCString(err_str, sizeof(err_str));
469254721Semaste                        result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"",
470254721Semaste                                                     err_str);
471254721Semaste                        result.SetStatus (eReturnStatusFailed);
472254721Semaste                        return false;
473254721Semaste                    }
474254721Semaste
475254721Semaste                    bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules),
476254721Semaste                                                            &(m_options.m_filenames),
477254721Semaste                                                            regexp,
478254721Semaste                                                            m_options.m_skip_prologue,
479263363Semaste                                                            internal,
480263363Semaste                                                            m_options.m_hardware).get();
481254721Semaste                }
482254721Semaste                break;
483254721Semaste            case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
484254721Semaste                {
485254721Semaste                    const size_t num_files = m_options.m_filenames.GetSize();
486254721Semaste
487254721Semaste                    if (num_files == 0)
488254721Semaste                    {
489254721Semaste                        FileSpec file;
490254721Semaste                        if (!GetDefaultFile (target, file, result))
491254721Semaste                        {
492254721Semaste                            result.AppendError ("No files provided and could not find default file.");
493254721Semaste                            result.SetStatus (eReturnStatusFailed);
494254721Semaste                            return false;
495254721Semaste                        }
496254721Semaste                        else
497254721Semaste                        {
498254721Semaste                            m_options.m_filenames.Append (file);
499254721Semaste                        }
500254721Semaste                    }
501254721Semaste
502254721Semaste                    RegularExpression regexp(m_options.m_source_text_regexp.c_str());
503254721Semaste                    if (!regexp.IsValid())
504254721Semaste                    {
505254721Semaste                        char err_str[1024];
506254721Semaste                        regexp.GetErrorAsCString(err_str, sizeof(err_str));
507254721Semaste                        result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"",
508254721Semaste                                                     err_str);
509254721Semaste                        result.SetStatus (eReturnStatusFailed);
510254721Semaste                        return false;
511254721Semaste                    }
512263363Semaste                    bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules),
513263363Semaste                                                              &(m_options.m_filenames),
514263363Semaste                                                              regexp,
515263363Semaste                                                              internal,
516263363Semaste                                                              m_options.m_hardware).get();
517254721Semaste                }
518254721Semaste                break;
519254721Semaste            case eSetTypeException:
520254721Semaste                {
521263363Semaste                    bp = target->CreateExceptionBreakpoint (m_options.m_language,
522263363Semaste                                                            m_options.m_catch_bp,
523263363Semaste                                                            m_options.m_throw_bp,
524263363Semaste                                                            m_options.m_hardware).get();
525254721Semaste                }
526254721Semaste                break;
527254721Semaste            default:
528254721Semaste                break;
529254721Semaste        }
530254721Semaste
531254721Semaste        // Now set the various options that were passed in:
532254721Semaste        if (bp)
533254721Semaste        {
534254721Semaste            if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
535254721Semaste                bp->SetThreadID (m_options.m_thread_id);
536254721Semaste
537254721Semaste            if (m_options.m_thread_index != UINT32_MAX)
538254721Semaste                bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
539254721Semaste
540254721Semaste            if (!m_options.m_thread_name.empty())
541254721Semaste                bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str());
542254721Semaste
543254721Semaste            if (!m_options.m_queue_name.empty())
544254721Semaste                bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str());
545254721Semaste
546254721Semaste            if (m_options.m_ignore_count != 0)
547254721Semaste                bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
548254721Semaste
549254721Semaste            if (!m_options.m_condition.empty())
550254721Semaste                bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
551254721Semaste
552254721Semaste            bp->SetOneShot (m_options.m_one_shot);
553254721Semaste        }
554254721Semaste
555254721Semaste        if (bp)
556254721Semaste        {
557254721Semaste            Stream &output_stream = result.GetOutputStream();
558254721Semaste            const bool show_locations = false;
559254721Semaste            bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations);
560254721Semaste            // Don't print out this warning for exception breakpoints.  They can get set before the target
561254721Semaste            // is set, but we won't know how to actually set the breakpoint till we run.
562254721Semaste            if (bp->GetNumLocations() == 0 && break_type != eSetTypeException)
563254721Semaste                output_stream.Printf ("WARNING:  Unable to resolve breakpoint to any actual locations.\n");
564254721Semaste            result.SetStatus (eReturnStatusSuccessFinishResult);
565254721Semaste        }
566254721Semaste        else if (!bp)
567254721Semaste        {
568254721Semaste            result.AppendError ("Breakpoint creation failed: No breakpoint created.");
569254721Semaste            result.SetStatus (eReturnStatusFailed);
570254721Semaste        }
571254721Semaste
572254721Semaste        return result.Succeeded();
573254721Semaste    }
574254721Semaste
575254721Semasteprivate:
576254721Semaste    bool
577254721Semaste    GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result)
578254721Semaste    {
579254721Semaste        uint32_t default_line;
580254721Semaste        // First use the Source Manager's default file.
581254721Semaste        // Then use the current stack frame's file.
582254721Semaste        if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
583254721Semaste        {
584254721Semaste            StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
585254721Semaste            if (cur_frame == NULL)
586254721Semaste            {
587254721Semaste                result.AppendError ("No selected frame to use to find the default file.");
588254721Semaste                result.SetStatus (eReturnStatusFailed);
589254721Semaste                return false;
590254721Semaste            }
591254721Semaste            else if (!cur_frame->HasDebugInformation())
592254721Semaste            {
593254721Semaste                result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info.");
594254721Semaste                result.SetStatus (eReturnStatusFailed);
595254721Semaste                return false;
596254721Semaste            }
597254721Semaste            else
598254721Semaste            {
599254721Semaste                const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry);
600254721Semaste                if (sc.line_entry.file)
601254721Semaste                {
602254721Semaste                    file = sc.line_entry.file;
603254721Semaste                }
604254721Semaste                else
605254721Semaste                {
606254721Semaste                    result.AppendError ("Can't find the file for the selected frame to use as the default file.");
607254721Semaste                    result.SetStatus (eReturnStatusFailed);
608254721Semaste                    return false;
609254721Semaste                }
610254721Semaste            }
611254721Semaste        }
612254721Semaste        return true;
613254721Semaste    }
614254721Semaste
615254721Semaste    CommandOptions m_options;
616254721Semaste};
617254721Semaste// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
618254721Semaste// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
619254721Semaste#define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 )
620254721Semaste#define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 )
621254721Semaste#define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) )
622254721Semaste
623254721SemasteOptionDefinition
624254721SemasteCommandObjectBreakpointSet::CommandOptions::g_option_table[] =
625254721Semaste{
626263363Semaste    { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
627254721Semaste        "Set the breakpoint only in this shared library.  "
628254721Semaste        "Can repeat this option multiple times to specify multiple shared libraries."},
629254721Semaste
630263363Semaste    { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument,   NULL, 0, eArgTypeCount,
631254721Semaste        "Set the number of times this breakpoint is skipped before stopping." },
632254721Semaste
633263363Semaste    { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument,   NULL, 0, eArgTypeNone,
634254721Semaste        "The breakpoint is deleted the first time it causes a stop." },
635254721Semaste
636263363Semaste    { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression,
637254721Semaste        "The breakpoint stops only if this condition expression evaluates to true."},
638254721Semaste
639263363Semaste    { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex,
640254721Semaste        "The breakpoint stops only for the thread whose indeX matches this argument."},
641254721Semaste
642263363Semaste    { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID,
643254721Semaste        "The breakpoint stops only for the thread whose TID matches this argument."},
644254721Semaste
645263363Semaste    { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName,
646254721Semaste        "The breakpoint stops only for the thread whose thread name matches this argument."},
647254721Semaste
648263363Semaste    { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
649263363Semaste        "Require the breakpoint to use hardware breakpoints."},
650263363Semaste
651263363Semaste    { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName,
652254721Semaste        "The breakpoint stops only for threads in the queue whose name is given by this argument."},
653254721Semaste
654263363Semaste    { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
655254721Semaste        "Specifies the source file in which to set this breakpoint.  "
656254721Semaste        "Note, by default lldb only looks for files that are #included if they use the standard include file extensions.  "
657254721Semaste        "To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy"
658254721Semaste        " to \"always\"."},
659254721Semaste
660263363Semaste    { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
661254721Semaste        "Specifies the line number on which to set this breakpoint."},
662254721Semaste
663254721Semaste    // Comment out this option for the moment, as we don't actually use it, but will in the future.
664254721Semaste    // This way users won't see it, but the infrastructure is left in place.
665263363Semaste    //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, NULL, "<column>",
666254721Semaste    //    "Set the breakpoint by source location at this particular column."},
667254721Semaste
668263363Semaste    { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression,
669254721Semaste        "Set the breakpoint by address, at the specified address."},
670254721Semaste
671263363Semaste    { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
672254721Semaste        "Set the breakpoint by function name.  Can be repeated multiple times to make one breakpoint for multiple names" },
673254721Semaste
674263363Semaste    { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName,
675254721Semaste        "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and "
676254721Semaste        "for Objective C this means a full function prototype with class and selector.   "
677254721Semaste        "Can be repeated multiple times to make one breakpoint for multiple names." },
678254721Semaste
679263363Semaste    { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSelector,
680254721Semaste        "Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." },
681254721Semaste
682263363Semaste    { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, 0, eArgTypeMethod,
683254721Semaste        "Set the breakpoint by C++ method names.  Can be repeated multiple times to make one breakpoint for multiple methods." },
684254721Semaste
685263363Semaste    { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression,
686254721Semaste        "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
687254721Semaste
688263363Semaste    { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
689254721Semaste        "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). "
690254721Semaste        "Can be repeated multiple times to make one breakpoint for multiple symbols." },
691254721Semaste
692263363Semaste    { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression,
693254721Semaste        "Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files "
694254721Semaste        "specified with the -f option.  The -f option can be specified more than once.  "
695254721Semaste        "If no source files are specified, uses the current \"default source file\"" },
696254721Semaste
697263363Semaste    { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLanguage,
698254721Semaste        "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" },
699254721Semaste
700263363Semaste    { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
701254721Semaste        "Set the breakpoint on exception throW." },
702254721Semaste
703263363Semaste    { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
704254721Semaste        "Set the breakpoint on exception catcH." },
705254721Semaste
706263363Semaste    { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
707254721Semaste        "sKip the prologue if the breakpoint is at the beginning of a function.  If not set the target.skip-prologue setting is used." },
708254721Semaste
709254721Semaste    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
710254721Semaste};
711254721Semaste
712254721Semaste//-------------------------------------------------------------------------
713254721Semaste// CommandObjectBreakpointModify
714254721Semaste//-------------------------------------------------------------------------
715254721Semaste#pragma mark Modify
716254721Semaste
717254721Semasteclass CommandObjectBreakpointModify : public CommandObjectParsed
718254721Semaste{
719254721Semastepublic:
720254721Semaste
721254721Semaste    CommandObjectBreakpointModify (CommandInterpreter &interpreter) :
722254721Semaste        CommandObjectParsed (interpreter,
723254721Semaste                             "breakpoint modify",
724254721Semaste                             "Modify the options on a breakpoint or set of breakpoints in the executable.  "
725254721Semaste                             "If no breakpoint is specified, acts on the last created breakpoint.  "
726254721Semaste                             "With the exception of -e, -d and -i, passing an empty argument clears the modification.",
727254721Semaste                             NULL),
728254721Semaste        m_options (interpreter)
729254721Semaste    {
730254721Semaste        CommandArgumentEntry arg;
731254721Semaste        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
732254721Semaste        // Add the entry for the first argument for this command to the object's arguments vector.
733254721Semaste        m_arguments.push_back (arg);
734254721Semaste    }
735254721Semaste
736254721Semaste
737254721Semaste    virtual
738254721Semaste    ~CommandObjectBreakpointModify () {}
739254721Semaste
740254721Semaste    virtual Options *
741254721Semaste    GetOptions ()
742254721Semaste    {
743254721Semaste        return &m_options;
744254721Semaste    }
745254721Semaste
746254721Semaste    class CommandOptions : public Options
747254721Semaste    {
748254721Semaste    public:
749254721Semaste
750254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
751254721Semaste            Options (interpreter),
752254721Semaste            m_ignore_count (0),
753254721Semaste            m_thread_id(LLDB_INVALID_THREAD_ID),
754254721Semaste            m_thread_id_passed(false),
755254721Semaste            m_thread_index (UINT32_MAX),
756254721Semaste            m_thread_index_passed(false),
757254721Semaste            m_thread_name(),
758254721Semaste            m_queue_name(),
759254721Semaste            m_condition (),
760254721Semaste            m_one_shot (false),
761254721Semaste            m_enable_passed (false),
762254721Semaste            m_enable_value (false),
763254721Semaste            m_name_passed (false),
764254721Semaste            m_queue_passed (false),
765254721Semaste            m_condition_passed (false),
766254721Semaste            m_one_shot_passed (false)
767254721Semaste        {
768254721Semaste        }
769254721Semaste
770254721Semaste        virtual
771254721Semaste        ~CommandOptions () {}
772254721Semaste
773254721Semaste        virtual Error
774254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
775254721Semaste        {
776254721Semaste            Error error;
777254721Semaste            const int short_option = m_getopt_table[option_idx].val;
778254721Semaste
779254721Semaste            switch (short_option)
780254721Semaste            {
781254721Semaste                case 'c':
782254721Semaste                    if (option_arg != NULL)
783254721Semaste                        m_condition.assign (option_arg);
784254721Semaste                    else
785254721Semaste                        m_condition.clear();
786254721Semaste                    m_condition_passed = true;
787254721Semaste                    break;
788254721Semaste                case 'd':
789254721Semaste                    m_enable_passed = true;
790254721Semaste                    m_enable_value = false;
791254721Semaste                    break;
792254721Semaste                case 'e':
793254721Semaste                    m_enable_passed = true;
794254721Semaste                    m_enable_value = true;
795254721Semaste                    break;
796254721Semaste                case 'i':
797254721Semaste                {
798254721Semaste                    m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
799254721Semaste                    if (m_ignore_count == UINT32_MAX)
800254721Semaste                       error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
801254721Semaste                }
802254721Semaste                break;
803254721Semaste                case 'o':
804254721Semaste                {
805254721Semaste                    bool value, success;
806254721Semaste                    value = Args::StringToBoolean(option_arg, false, &success);
807254721Semaste                    if (success)
808254721Semaste                    {
809254721Semaste                        m_one_shot_passed = true;
810254721Semaste                        m_one_shot = value;
811254721Semaste                    }
812254721Semaste                    else
813254721Semaste                        error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg);
814254721Semaste                }
815254721Semaste                break;
816254721Semaste                case 't' :
817254721Semaste                {
818254721Semaste                    if (option_arg[0] == '\0')
819254721Semaste                    {
820254721Semaste                        m_thread_id = LLDB_INVALID_THREAD_ID;
821254721Semaste                        m_thread_id_passed = true;
822254721Semaste                    }
823254721Semaste                    else
824254721Semaste                    {
825254721Semaste                        m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
826254721Semaste                        if (m_thread_id == LLDB_INVALID_THREAD_ID)
827254721Semaste                           error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg);
828254721Semaste                        else
829254721Semaste                            m_thread_id_passed = true;
830254721Semaste                    }
831254721Semaste                }
832254721Semaste                break;
833254721Semaste                case 'T':
834254721Semaste                    if (option_arg != NULL)
835254721Semaste                        m_thread_name.assign (option_arg);
836254721Semaste                    else
837254721Semaste                        m_thread_name.clear();
838254721Semaste                    m_name_passed = true;
839254721Semaste                    break;
840254721Semaste                case 'q':
841254721Semaste                    if (option_arg != NULL)
842254721Semaste                        m_queue_name.assign (option_arg);
843254721Semaste                    else
844254721Semaste                        m_queue_name.clear();
845254721Semaste                    m_queue_passed = true;
846254721Semaste                    break;
847254721Semaste                case 'x':
848254721Semaste                {
849254721Semaste                    if (option_arg[0] == '\n')
850254721Semaste                    {
851254721Semaste                        m_thread_index = UINT32_MAX;
852254721Semaste                        m_thread_index_passed = true;
853254721Semaste                    }
854254721Semaste                    else
855254721Semaste                    {
856254721Semaste                        m_thread_index = Args::StringToUInt32 (option_arg, UINT32_MAX, 0);
857254721Semaste                        if (m_thread_id == UINT32_MAX)
858254721Semaste                           error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg);
859254721Semaste                        else
860254721Semaste                            m_thread_index_passed = true;
861254721Semaste                    }
862254721Semaste                }
863254721Semaste                break;
864254721Semaste                default:
865254721Semaste                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
866254721Semaste                    break;
867254721Semaste            }
868254721Semaste
869254721Semaste            return error;
870254721Semaste        }
871254721Semaste        void
872254721Semaste        OptionParsingStarting ()
873254721Semaste        {
874254721Semaste            m_ignore_count = 0;
875254721Semaste            m_thread_id = LLDB_INVALID_THREAD_ID;
876254721Semaste            m_thread_id_passed = false;
877254721Semaste            m_thread_index = UINT32_MAX;
878254721Semaste            m_thread_index_passed = false;
879254721Semaste            m_thread_name.clear();
880254721Semaste            m_queue_name.clear();
881254721Semaste            m_condition.clear();
882254721Semaste            m_one_shot = false;
883254721Semaste            m_enable_passed = false;
884254721Semaste            m_queue_passed = false;
885254721Semaste            m_name_passed = false;
886254721Semaste            m_condition_passed = false;
887254721Semaste            m_one_shot_passed = false;
888254721Semaste        }
889254721Semaste
890254721Semaste        const OptionDefinition*
891254721Semaste        GetDefinitions ()
892254721Semaste        {
893254721Semaste            return g_option_table;
894254721Semaste        }
895254721Semaste
896254721Semaste
897254721Semaste        // Options table: Required for subclasses of Options.
898254721Semaste
899254721Semaste        static OptionDefinition g_option_table[];
900254721Semaste
901254721Semaste        // Instance variables to hold the values for command options.
902254721Semaste
903254721Semaste        uint32_t m_ignore_count;
904254721Semaste        lldb::tid_t m_thread_id;
905254721Semaste        bool m_thread_id_passed;
906254721Semaste        uint32_t m_thread_index;
907254721Semaste        bool m_thread_index_passed;
908254721Semaste        std::string m_thread_name;
909254721Semaste        std::string m_queue_name;
910254721Semaste        std::string m_condition;
911254721Semaste        bool m_one_shot;
912254721Semaste        bool m_enable_passed;
913254721Semaste        bool m_enable_value;
914254721Semaste        bool m_name_passed;
915254721Semaste        bool m_queue_passed;
916254721Semaste        bool m_condition_passed;
917254721Semaste        bool m_one_shot_passed;
918254721Semaste
919254721Semaste    };
920254721Semaste
921254721Semasteprotected:
922254721Semaste    virtual bool
923254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
924254721Semaste    {
925254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
926254721Semaste        if (target == NULL)
927254721Semaste        {
928254721Semaste            result.AppendError ("Invalid target.  No existing target or breakpoints.");
929254721Semaste            result.SetStatus (eReturnStatusFailed);
930254721Semaste            return false;
931254721Semaste        }
932254721Semaste
933254721Semaste        Mutex::Locker locker;
934254721Semaste        target->GetBreakpointList().GetListMutex(locker);
935254721Semaste
936254721Semaste        BreakpointIDList valid_bp_ids;
937254721Semaste
938254721Semaste        CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
939254721Semaste
940254721Semaste        if (result.Succeeded())
941254721Semaste        {
942254721Semaste            const size_t count = valid_bp_ids.GetSize();
943254721Semaste            for (size_t i = 0; i < count; ++i)
944254721Semaste            {
945254721Semaste                BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
946254721Semaste
947254721Semaste                if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
948254721Semaste                {
949254721Semaste                    Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
950254721Semaste                    if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
951254721Semaste                    {
952254721Semaste                        BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get();
953254721Semaste                        if (location)
954254721Semaste                        {
955254721Semaste                            if (m_options.m_thread_id_passed)
956254721Semaste                                location->SetThreadID (m_options.m_thread_id);
957254721Semaste
958254721Semaste                            if (m_options.m_thread_index_passed)
959254721Semaste                                location->SetThreadIndex(m_options.m_thread_index);
960254721Semaste
961254721Semaste                            if (m_options.m_name_passed)
962254721Semaste                                location->SetThreadName(m_options.m_thread_name.c_str());
963254721Semaste
964254721Semaste                            if (m_options.m_queue_passed)
965254721Semaste                                location->SetQueueName(m_options.m_queue_name.c_str());
966254721Semaste
967254721Semaste                            if (m_options.m_ignore_count != 0)
968254721Semaste                                location->SetIgnoreCount(m_options.m_ignore_count);
969254721Semaste
970254721Semaste                            if (m_options.m_enable_passed)
971254721Semaste                                location->SetEnabled (m_options.m_enable_value);
972254721Semaste
973254721Semaste                            if (m_options.m_condition_passed)
974254721Semaste                                location->SetCondition (m_options.m_condition.c_str());
975254721Semaste                        }
976254721Semaste                    }
977254721Semaste                    else
978254721Semaste                    {
979254721Semaste                        if (m_options.m_thread_id_passed)
980254721Semaste                            bp->SetThreadID (m_options.m_thread_id);
981254721Semaste
982254721Semaste                        if (m_options.m_thread_index_passed)
983254721Semaste                            bp->SetThreadIndex(m_options.m_thread_index);
984254721Semaste
985254721Semaste                        if (m_options.m_name_passed)
986254721Semaste                            bp->SetThreadName(m_options.m_thread_name.c_str());
987254721Semaste
988254721Semaste                        if (m_options.m_queue_passed)
989254721Semaste                            bp->SetQueueName(m_options.m_queue_name.c_str());
990254721Semaste
991254721Semaste                        if (m_options.m_ignore_count != 0)
992254721Semaste                            bp->SetIgnoreCount(m_options.m_ignore_count);
993254721Semaste
994254721Semaste                        if (m_options.m_enable_passed)
995254721Semaste                            bp->SetEnabled (m_options.m_enable_value);
996254721Semaste
997254721Semaste                        if (m_options.m_condition_passed)
998254721Semaste                            bp->SetCondition (m_options.m_condition.c_str());
999254721Semaste                    }
1000254721Semaste                }
1001254721Semaste            }
1002254721Semaste        }
1003254721Semaste
1004254721Semaste        return result.Succeeded();
1005254721Semaste    }
1006254721Semaste
1007254721Semasteprivate:
1008254721Semaste    CommandOptions m_options;
1009254721Semaste};
1010254721Semaste
1011254721Semaste#pragma mark Modify::CommandOptions
1012254721SemasteOptionDefinition
1013254721SemasteCommandObjectBreakpointModify::CommandOptions::g_option_table[] =
1014254721Semaste{
1015263363Semaste{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
1016263363Semaste{ LLDB_OPT_SET_ALL, false, "one-shot",     'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
1017263363Semaste{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."},
1018263363Semaste{ LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
1019263363Semaste{ LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
1020263363Semaste{ LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
1021263363Semaste{ LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
1022263363Semaste{ LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone, "Enable the breakpoint."},
1023263363Semaste{ LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone, "Disable the breakpoint."},
1024254721Semaste{ 0,                false, NULL,            0 , 0,                 NULL, 0, eArgTypeNone, NULL }
1025254721Semaste};
1026254721Semaste
1027254721Semaste//-------------------------------------------------------------------------
1028254721Semaste// CommandObjectBreakpointEnable
1029254721Semaste//-------------------------------------------------------------------------
1030254721Semaste#pragma mark Enable
1031254721Semaste
1032254721Semasteclass CommandObjectBreakpointEnable : public CommandObjectParsed
1033254721Semaste{
1034254721Semastepublic:
1035254721Semaste    CommandObjectBreakpointEnable (CommandInterpreter &interpreter) :
1036254721Semaste        CommandObjectParsed (interpreter,
1037254721Semaste                             "enable",
1038254721Semaste                             "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.",
1039254721Semaste                             NULL)
1040254721Semaste    {
1041254721Semaste        CommandArgumentEntry arg;
1042254721Semaste        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1043254721Semaste        // Add the entry for the first argument for this command to the object's arguments vector.
1044254721Semaste        m_arguments.push_back (arg);
1045254721Semaste    }
1046254721Semaste
1047254721Semaste
1048254721Semaste    virtual
1049254721Semaste    ~CommandObjectBreakpointEnable () {}
1050254721Semaste
1051254721Semasteprotected:
1052254721Semaste    virtual bool
1053254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1054254721Semaste    {
1055254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1056254721Semaste        if (target == NULL)
1057254721Semaste        {
1058254721Semaste            result.AppendError ("Invalid target.  No existing target or breakpoints.");
1059254721Semaste            result.SetStatus (eReturnStatusFailed);
1060254721Semaste            return false;
1061254721Semaste        }
1062254721Semaste
1063254721Semaste        Mutex::Locker locker;
1064254721Semaste        target->GetBreakpointList().GetListMutex(locker);
1065254721Semaste
1066254721Semaste        const BreakpointList &breakpoints = target->GetBreakpointList();
1067254721Semaste
1068254721Semaste        size_t num_breakpoints = breakpoints.GetSize();
1069254721Semaste
1070254721Semaste        if (num_breakpoints == 0)
1071254721Semaste        {
1072254721Semaste            result.AppendError ("No breakpoints exist to be enabled.");
1073254721Semaste            result.SetStatus (eReturnStatusFailed);
1074254721Semaste            return false;
1075254721Semaste        }
1076254721Semaste
1077254721Semaste        if (command.GetArgumentCount() == 0)
1078254721Semaste        {
1079254721Semaste            // No breakpoint selected; enable all currently set breakpoints.
1080254721Semaste            target->EnableAllBreakpoints ();
1081263363Semaste            result.AppendMessageWithFormat ("All breakpoints enabled. (%zu breakpoints)\n", num_breakpoints);
1082254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1083254721Semaste        }
1084254721Semaste        else
1085254721Semaste        {
1086254721Semaste            // Particular breakpoint selected; enable that breakpoint.
1087254721Semaste            BreakpointIDList valid_bp_ids;
1088254721Semaste            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1089254721Semaste
1090254721Semaste            if (result.Succeeded())
1091254721Semaste            {
1092254721Semaste                int enable_count = 0;
1093254721Semaste                int loc_count = 0;
1094254721Semaste                const size_t count = valid_bp_ids.GetSize();
1095254721Semaste                for (size_t i = 0; i < count; ++i)
1096254721Semaste                {
1097254721Semaste                    BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1098254721Semaste
1099254721Semaste                    if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1100254721Semaste                    {
1101254721Semaste                        Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1102254721Semaste                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1103254721Semaste                        {
1104254721Semaste                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1105254721Semaste                            if (location)
1106254721Semaste                            {
1107254721Semaste                                location->SetEnabled (true);
1108254721Semaste                                ++loc_count;
1109254721Semaste                            }
1110254721Semaste                        }
1111254721Semaste                        else
1112254721Semaste                        {
1113254721Semaste                            breakpoint->SetEnabled (true);
1114254721Semaste                            ++enable_count;
1115254721Semaste                        }
1116254721Semaste                    }
1117254721Semaste                }
1118254721Semaste                result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
1119254721Semaste                result.SetStatus (eReturnStatusSuccessFinishNoResult);
1120254721Semaste            }
1121254721Semaste        }
1122254721Semaste
1123254721Semaste        return result.Succeeded();
1124254721Semaste    }
1125254721Semaste};
1126254721Semaste
1127254721Semaste//-------------------------------------------------------------------------
1128254721Semaste// CommandObjectBreakpointDisable
1129254721Semaste//-------------------------------------------------------------------------
1130254721Semaste#pragma mark Disable
1131254721Semaste
1132254721Semasteclass CommandObjectBreakpointDisable : public CommandObjectParsed
1133254721Semaste{
1134254721Semastepublic:
1135254721Semaste    CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
1136254721Semaste        CommandObjectParsed (interpreter,
1137254721Semaste                             "breakpoint disable",
1138254721Semaste                             "Disable the specified breakpoint(s) without removing it/them.  If no breakpoints are specified, disable them all.",
1139254721Semaste                             NULL)
1140254721Semaste    {
1141254721Semaste        SetHelpLong(
1142254721Semaste"Disable the specified breakpoint(s) without removing it/them.  \n\
1143254721SemasteIf no breakpoints are specified, disable them all.\n\
1144254721Semaste\n\
1145254721SemasteNote: disabling a breakpoint will cause none of its locations to be hit\n\
1146254721Semasteregardless of whether they are enabled or disabled.  So the sequence: \n\
1147254721Semaste\n\
1148254721Semaste    (lldb) break disable 1\n\
1149254721Semaste    (lldb) break enable 1.1\n\
1150254721Semaste\n\
1151254721Semastewill NOT cause location 1.1 to get hit.  To achieve that, do:\n\
1152254721Semaste\n\
1153254721Semaste    (lldb) break disable 1.*\n\
1154254721Semaste    (lldb) break enable 1.1\n\
1155254721Semaste\n\
1156254721SemasteThe first command disables all the locations of breakpoint 1, \n\
1157254721Semastethe second re-enables the first location."
1158254721Semaste                    );
1159254721Semaste
1160254721Semaste        CommandArgumentEntry arg;
1161254721Semaste        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1162254721Semaste        // Add the entry for the first argument for this command to the object's arguments vector.
1163254721Semaste        m_arguments.push_back (arg);
1164254721Semaste
1165254721Semaste    }
1166254721Semaste
1167254721Semaste
1168254721Semaste    virtual
1169254721Semaste    ~CommandObjectBreakpointDisable () {}
1170254721Semaste
1171254721Semasteprotected:
1172254721Semaste    virtual bool
1173254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1174254721Semaste    {
1175254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1176254721Semaste        if (target == NULL)
1177254721Semaste        {
1178254721Semaste            result.AppendError ("Invalid target.  No existing target or breakpoints.");
1179254721Semaste            result.SetStatus (eReturnStatusFailed);
1180254721Semaste            return false;
1181254721Semaste        }
1182254721Semaste
1183254721Semaste        Mutex::Locker locker;
1184254721Semaste        target->GetBreakpointList().GetListMutex(locker);
1185254721Semaste
1186254721Semaste        const BreakpointList &breakpoints = target->GetBreakpointList();
1187254721Semaste        size_t num_breakpoints = breakpoints.GetSize();
1188254721Semaste
1189254721Semaste        if (num_breakpoints == 0)
1190254721Semaste        {
1191254721Semaste            result.AppendError ("No breakpoints exist to be disabled.");
1192254721Semaste            result.SetStatus (eReturnStatusFailed);
1193254721Semaste            return false;
1194254721Semaste        }
1195254721Semaste
1196254721Semaste        if (command.GetArgumentCount() == 0)
1197254721Semaste        {
1198254721Semaste            // No breakpoint selected; disable all currently set breakpoints.
1199254721Semaste            target->DisableAllBreakpoints ();
1200263363Semaste            result.AppendMessageWithFormat ("All breakpoints disabled. (%zu breakpoints)\n", num_breakpoints);
1201254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1202254721Semaste        }
1203254721Semaste        else
1204254721Semaste        {
1205254721Semaste            // Particular breakpoint selected; disable that breakpoint.
1206254721Semaste            BreakpointIDList valid_bp_ids;
1207254721Semaste
1208254721Semaste            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1209254721Semaste
1210254721Semaste            if (result.Succeeded())
1211254721Semaste            {
1212254721Semaste                int disable_count = 0;
1213254721Semaste                int loc_count = 0;
1214254721Semaste                const size_t count = valid_bp_ids.GetSize();
1215254721Semaste                for (size_t i = 0; i < count; ++i)
1216254721Semaste                {
1217254721Semaste                    BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1218254721Semaste
1219254721Semaste                    if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1220254721Semaste                    {
1221254721Semaste                        Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1222254721Semaste                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1223254721Semaste                        {
1224254721Semaste                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1225254721Semaste                            if (location)
1226254721Semaste                            {
1227254721Semaste                                location->SetEnabled (false);
1228254721Semaste                                ++loc_count;
1229254721Semaste                            }
1230254721Semaste                        }
1231254721Semaste                        else
1232254721Semaste                        {
1233254721Semaste                            breakpoint->SetEnabled (false);
1234254721Semaste                            ++disable_count;
1235254721Semaste                        }
1236254721Semaste                    }
1237254721Semaste                }
1238254721Semaste                result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
1239254721Semaste                result.SetStatus (eReturnStatusSuccessFinishNoResult);
1240254721Semaste            }
1241254721Semaste        }
1242254721Semaste
1243254721Semaste        return result.Succeeded();
1244254721Semaste    }
1245254721Semaste
1246254721Semaste};
1247254721Semaste
1248254721Semaste//-------------------------------------------------------------------------
1249254721Semaste// CommandObjectBreakpointList
1250254721Semaste//-------------------------------------------------------------------------
1251254721Semaste#pragma mark List
1252254721Semaste
1253254721Semasteclass CommandObjectBreakpointList : public CommandObjectParsed
1254254721Semaste{
1255254721Semastepublic:
1256254721Semaste    CommandObjectBreakpointList (CommandInterpreter &interpreter) :
1257254721Semaste        CommandObjectParsed (interpreter,
1258254721Semaste                             "breakpoint list",
1259254721Semaste                             "List some or all breakpoints at configurable levels of detail.",
1260254721Semaste                             NULL),
1261254721Semaste        m_options (interpreter)
1262254721Semaste    {
1263254721Semaste        CommandArgumentEntry arg;
1264254721Semaste        CommandArgumentData bp_id_arg;
1265254721Semaste
1266254721Semaste        // Define the first (and only) variant of this arg.
1267254721Semaste        bp_id_arg.arg_type = eArgTypeBreakpointID;
1268254721Semaste        bp_id_arg.arg_repetition = eArgRepeatOptional;
1269254721Semaste
1270254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
1271254721Semaste        arg.push_back (bp_id_arg);
1272254721Semaste
1273254721Semaste        // Push the data for the first argument into the m_arguments vector.
1274254721Semaste        m_arguments.push_back (arg);
1275254721Semaste    }
1276254721Semaste
1277254721Semaste
1278254721Semaste    virtual
1279254721Semaste    ~CommandObjectBreakpointList () {}
1280254721Semaste
1281254721Semaste    virtual Options *
1282254721Semaste    GetOptions ()
1283254721Semaste    {
1284254721Semaste        return &m_options;
1285254721Semaste    }
1286254721Semaste
1287254721Semaste    class CommandOptions : public Options
1288254721Semaste    {
1289254721Semaste    public:
1290254721Semaste
1291254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
1292254721Semaste            Options (interpreter),
1293254721Semaste            m_level (lldb::eDescriptionLevelBrief)  // Breakpoint List defaults to brief descriptions
1294254721Semaste        {
1295254721Semaste        }
1296254721Semaste
1297254721Semaste        virtual
1298254721Semaste        ~CommandOptions () {}
1299254721Semaste
1300254721Semaste        virtual Error
1301254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
1302254721Semaste        {
1303254721Semaste            Error error;
1304254721Semaste            const int short_option = m_getopt_table[option_idx].val;
1305254721Semaste
1306254721Semaste            switch (short_option)
1307254721Semaste            {
1308254721Semaste                case 'b':
1309254721Semaste                    m_level = lldb::eDescriptionLevelBrief;
1310254721Semaste                    break;
1311254721Semaste                case 'f':
1312254721Semaste                    m_level = lldb::eDescriptionLevelFull;
1313254721Semaste                    break;
1314254721Semaste                case 'v':
1315254721Semaste                    m_level = lldb::eDescriptionLevelVerbose;
1316254721Semaste                    break;
1317254721Semaste                case 'i':
1318254721Semaste                    m_internal = true;
1319254721Semaste                    break;
1320254721Semaste                default:
1321254721Semaste                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1322254721Semaste                    break;
1323254721Semaste            }
1324254721Semaste
1325254721Semaste            return error;
1326254721Semaste        }
1327254721Semaste
1328254721Semaste        void
1329254721Semaste        OptionParsingStarting ()
1330254721Semaste        {
1331254721Semaste            m_level = lldb::eDescriptionLevelFull;
1332254721Semaste            m_internal = false;
1333254721Semaste        }
1334254721Semaste
1335254721Semaste        const OptionDefinition *
1336254721Semaste        GetDefinitions ()
1337254721Semaste        {
1338254721Semaste            return g_option_table;
1339254721Semaste        }
1340254721Semaste
1341254721Semaste        // Options table: Required for subclasses of Options.
1342254721Semaste
1343254721Semaste        static OptionDefinition g_option_table[];
1344254721Semaste
1345254721Semaste        // Instance variables to hold the values for command options.
1346254721Semaste
1347254721Semaste        lldb::DescriptionLevel m_level;
1348254721Semaste
1349254721Semaste        bool m_internal;
1350254721Semaste    };
1351254721Semaste
1352254721Semasteprotected:
1353254721Semaste    virtual bool
1354254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1355254721Semaste    {
1356254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1357254721Semaste        if (target == NULL)
1358254721Semaste        {
1359254721Semaste            result.AppendError ("Invalid target. No current target or breakpoints.");
1360254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1361254721Semaste            return true;
1362254721Semaste        }
1363254721Semaste
1364254721Semaste        const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
1365254721Semaste        Mutex::Locker locker;
1366254721Semaste        target->GetBreakpointList(m_options.m_internal).GetListMutex(locker);
1367254721Semaste
1368254721Semaste        size_t num_breakpoints = breakpoints.GetSize();
1369254721Semaste
1370254721Semaste        if (num_breakpoints == 0)
1371254721Semaste        {
1372254721Semaste            result.AppendMessage ("No breakpoints currently set.");
1373254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1374254721Semaste            return true;
1375254721Semaste        }
1376254721Semaste
1377254721Semaste        Stream &output_stream = result.GetOutputStream();
1378254721Semaste
1379254721Semaste        if (command.GetArgumentCount() == 0)
1380254721Semaste        {
1381254721Semaste            // No breakpoint selected; show info about all currently set breakpoints.
1382254721Semaste            result.AppendMessage ("Current breakpoints:");
1383254721Semaste            for (size_t i = 0; i < num_breakpoints; ++i)
1384254721Semaste            {
1385254721Semaste                Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get();
1386254721Semaste                AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
1387254721Semaste            }
1388254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1389254721Semaste        }
1390254721Semaste        else
1391254721Semaste        {
1392254721Semaste            // Particular breakpoints selected; show info about that breakpoint.
1393254721Semaste            BreakpointIDList valid_bp_ids;
1394254721Semaste            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1395254721Semaste
1396254721Semaste            if (result.Succeeded())
1397254721Semaste            {
1398254721Semaste                for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i)
1399254721Semaste                {
1400254721Semaste                    BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1401254721Semaste                    Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1402254721Semaste                    AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level);
1403254721Semaste                }
1404254721Semaste                result.SetStatus (eReturnStatusSuccessFinishNoResult);
1405254721Semaste            }
1406254721Semaste            else
1407254721Semaste            {
1408254721Semaste                result.AppendError ("Invalid breakpoint id.");
1409254721Semaste                result.SetStatus (eReturnStatusFailed);
1410254721Semaste            }
1411254721Semaste        }
1412254721Semaste
1413254721Semaste        return result.Succeeded();
1414254721Semaste    }
1415254721Semaste
1416254721Semasteprivate:
1417254721Semaste    CommandOptions m_options;
1418254721Semaste};
1419254721Semaste
1420254721Semaste#pragma mark List::CommandOptions
1421254721SemasteOptionDefinition
1422254721SemasteCommandObjectBreakpointList::CommandOptions::g_option_table[] =
1423254721Semaste{
1424263363Semaste    { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
1425254721Semaste        "Show debugger internal breakpoints" },
1426254721Semaste
1427263363Semaste    { LLDB_OPT_SET_1, false, "brief",    'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
1428254721Semaste        "Give a brief description of the breakpoint (no location info)."},
1429254721Semaste
1430254721Semaste    // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1431254721Semaste    // But I need to see it for now, and don't want to wait.
1432263363Semaste    { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
1433254721Semaste        "Give a full description of the breakpoint and its locations."},
1434254721Semaste
1435263363Semaste    { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,
1436254721Semaste        "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1437254721Semaste
1438254721Semaste    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1439254721Semaste};
1440254721Semaste
1441254721Semaste//-------------------------------------------------------------------------
1442254721Semaste// CommandObjectBreakpointClear
1443254721Semaste//-------------------------------------------------------------------------
1444254721Semaste#pragma mark Clear
1445254721Semaste
1446254721Semasteclass CommandObjectBreakpointClear : public CommandObjectParsed
1447254721Semaste{
1448254721Semastepublic:
1449254721Semaste
1450254721Semaste    typedef enum BreakpointClearType
1451254721Semaste    {
1452254721Semaste        eClearTypeInvalid,
1453254721Semaste        eClearTypeFileAndLine
1454254721Semaste    } BreakpointClearType;
1455254721Semaste
1456254721Semaste    CommandObjectBreakpointClear (CommandInterpreter &interpreter) :
1457254721Semaste        CommandObjectParsed (interpreter,
1458254721Semaste                             "breakpoint clear",
1459254721Semaste                             "Clears a breakpoint or set of breakpoints in the executable.",
1460254721Semaste                             "breakpoint clear <cmd-options>"),
1461254721Semaste        m_options (interpreter)
1462254721Semaste    {
1463254721Semaste    }
1464254721Semaste
1465254721Semaste    virtual
1466254721Semaste    ~CommandObjectBreakpointClear () {}
1467254721Semaste
1468254721Semaste    virtual Options *
1469254721Semaste    GetOptions ()
1470254721Semaste    {
1471254721Semaste        return &m_options;
1472254721Semaste    }
1473254721Semaste
1474254721Semaste    class CommandOptions : public Options
1475254721Semaste    {
1476254721Semaste    public:
1477254721Semaste
1478254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
1479254721Semaste            Options (interpreter),
1480254721Semaste            m_filename (),
1481254721Semaste            m_line_num (0)
1482254721Semaste        {
1483254721Semaste        }
1484254721Semaste
1485254721Semaste        virtual
1486254721Semaste        ~CommandOptions () {}
1487254721Semaste
1488254721Semaste        virtual Error
1489254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
1490254721Semaste        {
1491254721Semaste            Error error;
1492254721Semaste            const int short_option = m_getopt_table[option_idx].val;
1493254721Semaste
1494254721Semaste            switch (short_option)
1495254721Semaste            {
1496254721Semaste                case 'f':
1497254721Semaste                    m_filename.assign (option_arg);
1498254721Semaste                    break;
1499254721Semaste
1500254721Semaste                case 'l':
1501254721Semaste                    m_line_num = Args::StringToUInt32 (option_arg, 0);
1502254721Semaste                    break;
1503254721Semaste
1504254721Semaste                default:
1505254721Semaste                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1506254721Semaste                    break;
1507254721Semaste            }
1508254721Semaste
1509254721Semaste            return error;
1510254721Semaste        }
1511254721Semaste
1512254721Semaste        void
1513254721Semaste        OptionParsingStarting ()
1514254721Semaste        {
1515254721Semaste            m_filename.clear();
1516254721Semaste            m_line_num = 0;
1517254721Semaste        }
1518254721Semaste
1519254721Semaste        const OptionDefinition*
1520254721Semaste        GetDefinitions ()
1521254721Semaste        {
1522254721Semaste            return g_option_table;
1523254721Semaste        }
1524254721Semaste
1525254721Semaste        // Options table: Required for subclasses of Options.
1526254721Semaste
1527254721Semaste        static OptionDefinition g_option_table[];
1528254721Semaste
1529254721Semaste        // Instance variables to hold the values for command options.
1530254721Semaste
1531254721Semaste        std::string m_filename;
1532254721Semaste        uint32_t m_line_num;
1533254721Semaste
1534254721Semaste    };
1535254721Semaste
1536254721Semasteprotected:
1537254721Semaste    virtual bool
1538254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1539254721Semaste    {
1540254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1541254721Semaste        if (target == NULL)
1542254721Semaste        {
1543254721Semaste            result.AppendError ("Invalid target. No existing target or breakpoints.");
1544254721Semaste            result.SetStatus (eReturnStatusFailed);
1545254721Semaste            return false;
1546254721Semaste        }
1547254721Semaste
1548254721Semaste        // The following are the various types of breakpoints that could be cleared:
1549254721Semaste        //   1). -f -l (clearing breakpoint by source location)
1550254721Semaste
1551254721Semaste        BreakpointClearType break_type = eClearTypeInvalid;
1552254721Semaste
1553254721Semaste        if (m_options.m_line_num != 0)
1554254721Semaste            break_type = eClearTypeFileAndLine;
1555254721Semaste
1556254721Semaste        Mutex::Locker locker;
1557254721Semaste        target->GetBreakpointList().GetListMutex(locker);
1558254721Semaste
1559254721Semaste        BreakpointList &breakpoints = target->GetBreakpointList();
1560254721Semaste        size_t num_breakpoints = breakpoints.GetSize();
1561254721Semaste
1562254721Semaste        // Early return if there's no breakpoint at all.
1563254721Semaste        if (num_breakpoints == 0)
1564254721Semaste        {
1565254721Semaste            result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1566254721Semaste            result.SetStatus (eReturnStatusFailed);
1567254721Semaste            return result.Succeeded();
1568254721Semaste        }
1569254721Semaste
1570254721Semaste        // Find matching breakpoints and delete them.
1571254721Semaste
1572254721Semaste        // First create a copy of all the IDs.
1573254721Semaste        std::vector<break_id_t> BreakIDs;
1574254721Semaste        for (size_t i = 0; i < num_breakpoints; ++i)
1575254721Semaste            BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i).get()->GetID());
1576254721Semaste
1577254721Semaste        int num_cleared = 0;
1578254721Semaste        StreamString ss;
1579254721Semaste        switch (break_type)
1580254721Semaste        {
1581254721Semaste            case eClearTypeFileAndLine: // Breakpoint by source position
1582254721Semaste                {
1583254721Semaste                    const ConstString filename(m_options.m_filename.c_str());
1584254721Semaste                    BreakpointLocationCollection loc_coll;
1585254721Semaste
1586254721Semaste                    for (size_t i = 0; i < num_breakpoints; ++i)
1587254721Semaste                    {
1588254721Semaste                        Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1589254721Semaste
1590254721Semaste                        if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll))
1591254721Semaste                        {
1592254721Semaste                            // If the collection size is 0, it's a full match and we can just remove the breakpoint.
1593254721Semaste                            if (loc_coll.GetSize() == 0)
1594254721Semaste                            {
1595254721Semaste                                bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1596254721Semaste                                ss.EOL();
1597254721Semaste                                target->RemoveBreakpointByID (bp->GetID());
1598254721Semaste                                ++num_cleared;
1599254721Semaste                            }
1600254721Semaste                        }
1601254721Semaste                    }
1602254721Semaste                }
1603254721Semaste                break;
1604254721Semaste
1605254721Semaste            default:
1606254721Semaste                break;
1607254721Semaste        }
1608254721Semaste
1609254721Semaste        if (num_cleared > 0)
1610254721Semaste        {
1611254721Semaste            Stream &output_stream = result.GetOutputStream();
1612254721Semaste            output_stream.Printf ("%d breakpoints cleared:\n", num_cleared);
1613254721Semaste            output_stream << ss.GetData();
1614254721Semaste            output_stream.EOL();
1615254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1616254721Semaste        }
1617254721Semaste        else
1618254721Semaste        {
1619254721Semaste            result.AppendError ("Breakpoint clear: No breakpoint cleared.");
1620254721Semaste            result.SetStatus (eReturnStatusFailed);
1621254721Semaste        }
1622254721Semaste
1623254721Semaste        return result.Succeeded();
1624254721Semaste    }
1625254721Semaste
1626254721Semasteprivate:
1627254721Semaste    CommandOptions m_options;
1628254721Semaste};
1629254721Semaste
1630254721Semaste#pragma mark Clear::CommandOptions
1631254721Semaste
1632254721SemasteOptionDefinition
1633254721SemasteCommandObjectBreakpointClear::CommandOptions::g_option_table[] =
1634254721Semaste{
1635263363Semaste    { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1636254721Semaste        "Specify the breakpoint by source location in this particular file."},
1637254721Semaste
1638263363Semaste    { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
1639254721Semaste        "Specify the breakpoint by source location at this particular line."},
1640254721Semaste
1641254721Semaste    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1642254721Semaste};
1643254721Semaste
1644254721Semaste//-------------------------------------------------------------------------
1645254721Semaste// CommandObjectBreakpointDelete
1646254721Semaste//-------------------------------------------------------------------------
1647254721Semaste#pragma mark Delete
1648254721Semaste
1649254721Semasteclass CommandObjectBreakpointDelete : public CommandObjectParsed
1650254721Semaste{
1651254721Semastepublic:
1652254721Semaste    CommandObjectBreakpointDelete (CommandInterpreter &interpreter) :
1653254721Semaste        CommandObjectParsed (interpreter,
1654254721Semaste                             "breakpoint delete",
1655254721Semaste                             "Delete the specified breakpoint(s).  If no breakpoints are specified, delete them all.",
1656254721Semaste                             NULL)
1657254721Semaste    {
1658254721Semaste        CommandArgumentEntry arg;
1659254721Semaste        CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);
1660254721Semaste        // Add the entry for the first argument for this command to the object's arguments vector.
1661254721Semaste        m_arguments.push_back (arg);
1662254721Semaste    }
1663254721Semaste
1664254721Semaste    virtual
1665254721Semaste    ~CommandObjectBreakpointDelete () {}
1666254721Semaste
1667254721Semasteprotected:
1668254721Semaste    virtual bool
1669254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1670254721Semaste    {
1671254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1672254721Semaste        if (target == NULL)
1673254721Semaste        {
1674254721Semaste            result.AppendError ("Invalid target. No existing target or breakpoints.");
1675254721Semaste            result.SetStatus (eReturnStatusFailed);
1676254721Semaste            return false;
1677254721Semaste        }
1678254721Semaste
1679254721Semaste        Mutex::Locker locker;
1680254721Semaste        target->GetBreakpointList().GetListMutex(locker);
1681254721Semaste
1682254721Semaste        const BreakpointList &breakpoints = target->GetBreakpointList();
1683254721Semaste
1684254721Semaste        size_t num_breakpoints = breakpoints.GetSize();
1685254721Semaste
1686254721Semaste        if (num_breakpoints == 0)
1687254721Semaste        {
1688254721Semaste            result.AppendError ("No breakpoints exist to be deleted.");
1689254721Semaste            result.SetStatus (eReturnStatusFailed);
1690254721Semaste            return false;
1691254721Semaste        }
1692254721Semaste
1693254721Semaste        if (command.GetArgumentCount() == 0)
1694254721Semaste        {
1695254721Semaste            if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
1696254721Semaste            {
1697254721Semaste                result.AppendMessage("Operation cancelled...");
1698254721Semaste            }
1699254721Semaste            else
1700254721Semaste            {
1701254721Semaste                target->RemoveAllBreakpoints ();
1702263363Semaste                result.AppendMessageWithFormat ("All breakpoints removed. (%zu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint");
1703254721Semaste            }
1704254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1705254721Semaste        }
1706254721Semaste        else
1707254721Semaste        {
1708254721Semaste            // Particular breakpoint selected; disable that breakpoint.
1709254721Semaste            BreakpointIDList valid_bp_ids;
1710254721Semaste            CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
1711254721Semaste
1712254721Semaste            if (result.Succeeded())
1713254721Semaste            {
1714254721Semaste                int delete_count = 0;
1715254721Semaste                int disable_count = 0;
1716254721Semaste                const size_t count = valid_bp_ids.GetSize();
1717254721Semaste                for (size_t i = 0; i < count; ++i)
1718254721Semaste                {
1719254721Semaste                    BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
1720254721Semaste
1721254721Semaste                    if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
1722254721Semaste                    {
1723254721Semaste                        if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
1724254721Semaste                        {
1725254721Semaste                            Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1726254721Semaste                            BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
1727254721Semaste                            // It makes no sense to try to delete individual locations, so we disable them instead.
1728254721Semaste                            if (location)
1729254721Semaste                            {
1730254721Semaste                                location->SetEnabled (false);
1731254721Semaste                                ++disable_count;
1732254721Semaste                            }
1733254721Semaste                        }
1734254721Semaste                        else
1735254721Semaste                        {
1736254721Semaste                            target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
1737254721Semaste                            ++delete_count;
1738254721Semaste                        }
1739254721Semaste                    }
1740254721Semaste                }
1741254721Semaste                result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
1742254721Semaste                                               delete_count, disable_count);
1743254721Semaste                result.SetStatus (eReturnStatusSuccessFinishNoResult);
1744254721Semaste            }
1745254721Semaste        }
1746254721Semaste        return result.Succeeded();
1747254721Semaste    }
1748254721Semaste};
1749254721Semaste
1750254721Semaste//-------------------------------------------------------------------------
1751254721Semaste// CommandObjectMultiwordBreakpoint
1752254721Semaste//-------------------------------------------------------------------------
1753254721Semaste#pragma mark MultiwordBreakpoint
1754254721Semaste
1755254721SemasteCommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter) :
1756254721Semaste    CommandObjectMultiword (interpreter,
1757254721Semaste                            "breakpoint",
1758254721Semaste                            "A set of commands for operating on breakpoints. Also see _regexp-break.",
1759254721Semaste                            "breakpoint <command> [<command-options>]")
1760254721Semaste{
1761254721Semaste    CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter));
1762254721Semaste    CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter));
1763254721Semaste    CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter));
1764254721Semaste    CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter));
1765254721Semaste    CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter));
1766254721Semaste    CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter));
1767254721Semaste    CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
1768254721Semaste    CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter));
1769254721Semaste
1770254721Semaste    list_command_object->SetCommandName ("breakpoint list");
1771254721Semaste    enable_command_object->SetCommandName("breakpoint enable");
1772254721Semaste    disable_command_object->SetCommandName("breakpoint disable");
1773254721Semaste    clear_command_object->SetCommandName("breakpoint clear");
1774254721Semaste    delete_command_object->SetCommandName("breakpoint delete");
1775254721Semaste    set_command_object->SetCommandName("breakpoint set");
1776254721Semaste    command_command_object->SetCommandName ("breakpoint command");
1777254721Semaste    modify_command_object->SetCommandName ("breakpoint modify");
1778254721Semaste
1779254721Semaste    LoadSubCommand ("list",       list_command_object);
1780254721Semaste    LoadSubCommand ("enable",     enable_command_object);
1781254721Semaste    LoadSubCommand ("disable",    disable_command_object);
1782254721Semaste    LoadSubCommand ("clear",      clear_command_object);
1783254721Semaste    LoadSubCommand ("delete",     delete_command_object);
1784254721Semaste    LoadSubCommand ("set",        set_command_object);
1785254721Semaste    LoadSubCommand ("command",    command_command_object);
1786254721Semaste    LoadSubCommand ("modify",     modify_command_object);
1787254721Semaste}
1788254721Semaste
1789254721SemasteCommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
1790254721Semaste{
1791254721Semaste}
1792254721Semaste
1793254721Semastevoid
1794254721SemasteCommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
1795254721Semaste                                                         BreakpointIDList *valid_ids)
1796254721Semaste{
1797254721Semaste    // args can be strings representing 1). integers (for breakpoint ids)
1798254721Semaste    //                                  2). the full breakpoint & location canonical representation
1799254721Semaste    //                                  3). the word "to" or a hyphen, representing a range (in which case there
1800254721Semaste    //                                      had *better* be an entry both before & after of one of the first two types.
1801254721Semaste    // If args is empty, we will use the last created breakpoint (if there is one.)
1802254721Semaste
1803254721Semaste    Args temp_args;
1804254721Semaste
1805254721Semaste    if (args.GetArgumentCount() == 0)
1806254721Semaste    {
1807254721Semaste        if (target->GetLastCreatedBreakpoint())
1808254721Semaste        {
1809254721Semaste            valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
1810254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1811254721Semaste        }
1812254721Semaste        else
1813254721Semaste        {
1814254721Semaste            result.AppendError("No breakpoint specified and no last created breakpoint.");
1815254721Semaste            result.SetStatus (eReturnStatusFailed);
1816254721Semaste        }
1817254721Semaste        return;
1818254721Semaste    }
1819254721Semaste
1820254721Semaste    // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
1821254721Semaste    // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead generate a list of strings for
1822254721Semaste    // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
1823254721Semaste
1824254721Semaste    BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
1825254721Semaste
1826254721Semaste    // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
1827254721Semaste
1828254721Semaste    valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result);
1829254721Semaste
1830254721Semaste    // At this point,  all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
1831254721Semaste    // and put into valid_ids.
1832254721Semaste
1833254721Semaste    if (result.Succeeded())
1834254721Semaste    {
1835254721Semaste        // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
1836254721Semaste        // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
1837254721Semaste
1838254721Semaste        const size_t count = valid_ids->GetSize();
1839254721Semaste        for (size_t i = 0; i < count; ++i)
1840254721Semaste        {
1841254721Semaste            BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
1842254721Semaste            Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
1843254721Semaste            if (breakpoint != NULL)
1844254721Semaste            {
1845254721Semaste                const size_t num_locations = breakpoint->GetNumLocations();
1846254721Semaste                if (cur_bp_id.GetLocationID() > num_locations)
1847254721Semaste                {
1848254721Semaste                    StreamString id_str;
1849254721Semaste                    BreakpointID::GetCanonicalReference (&id_str,
1850254721Semaste                                                         cur_bp_id.GetBreakpointID(),
1851254721Semaste                                                         cur_bp_id.GetLocationID());
1852254721Semaste                    i = valid_ids->GetSize() + 1;
1853254721Semaste                    result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
1854254721Semaste                                                 id_str.GetData());
1855254721Semaste                    result.SetStatus (eReturnStatusFailed);
1856254721Semaste                }
1857254721Semaste            }
1858254721Semaste            else
1859254721Semaste            {
1860254721Semaste                i = valid_ids->GetSize() + 1;
1861254721Semaste                result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
1862254721Semaste                result.SetStatus (eReturnStatusFailed);
1863254721Semaste            }
1864254721Semaste        }
1865254721Semaste    }
1866254721Semaste}
1867