1254721Semaste//===-- CommandObjectWatchpointCommand.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// C Includes
13254721Semaste// C++ Includes
14254721Semaste
15254721Semaste
16254721Semaste#include "CommandObjectWatchpointCommand.h"
17254721Semaste#include "CommandObjectWatchpoint.h"
18254721Semaste
19254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
20254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
21254721Semaste#include "lldb/Target/Target.h"
22254721Semaste#include "lldb/Target/Thread.h"
23254721Semaste#include "lldb/Breakpoint/Watchpoint.h"
24254721Semaste#include "lldb/Breakpoint/StoppointCallbackContext.h"
25254721Semaste#include "lldb/Core/State.h"
26254721Semaste
27254721Semaste#include <vector>
28254721Semaste
29254721Semasteusing namespace lldb;
30254721Semasteusing namespace lldb_private;
31254721Semaste
32254721Semaste//-------------------------------------------------------------------------
33254721Semaste// CommandObjectWatchpointCommandAdd
34254721Semaste//-------------------------------------------------------------------------
35254721Semaste
36254721Semaste
37254721Semasteclass CommandObjectWatchpointCommandAdd : public CommandObjectParsed
38254721Semaste{
39254721Semastepublic:
40254721Semaste
41254721Semaste    CommandObjectWatchpointCommandAdd (CommandInterpreter &interpreter) :
42254721Semaste        CommandObjectParsed (interpreter,
43254721Semaste                             "add",
44254721Semaste                             "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
45254721Semaste                             NULL),
46254721Semaste        m_options (interpreter)
47254721Semaste    {
48254721Semaste        SetHelpLong (
49254721Semaste"\nGeneral information about entering watchpoint commands \n\
50254721Semaste------------------------------------------------------ \n\
51254721Semaste \n\
52254721SemasteThis command will cause you to be prompted to enter the command or set \n\
53254721Semasteof commands you wish to be executed when the specified watchpoint is \n\
54254721Semastehit.  You will be told to enter your command(s), and will see a '> ' \n\
55254721Semasteprompt. Because you can enter one or many commands to be executed when \n\
56254721Semastea watchpoint is hit, you will continue to be prompted after each \n\
57254721Semastenew-line that you enter, until you enter the word 'DONE', which will \n\
58254721Semastecause the commands you have entered to be stored with the watchpoint \n\
59254721Semasteand executed when the watchpoint is hit. \n\
60254721Semaste \n\
61254721SemasteSyntax checking is not necessarily done when watchpoint commands are \n\
62254721Semasteentered.  An improperly written watchpoint command will attempt to get \n\
63254721Semasteexecuted when the watchpoint gets hit, and usually silently fail.  If \n\
64254721Semasteyour watchpoint command does not appear to be getting executed, go \n\
65254721Semasteback and check your syntax. \n\
66254721Semaste \n\
67254721Semaste \n\
68254721SemasteSpecial information about PYTHON watchpoint commands                            \n\
69254721Semaste----------------------------------------------------                            \n\
70254721Semaste                                                                                \n\
71254721SemasteYou may enter either one line of Python or multiple lines of Python             \n\
72254721Semaste(including defining whole functions, if desired).  If you enter a               \n\
73254721Semastesingle line of Python, that will be passed to the Python interpreter            \n\
74254721Semaste'as is' when the watchpoint gets hit.  If you enter function                    \n\
75254721Semastedefinitions, they will be passed to the Python interpreter as soon as           \n\
76254721Semasteyou finish entering the watchpoint command, and they can be called              \n\
77254721Semastelater (don't forget to add calls to them, if you want them called when          \n\
78254721Semastethe watchpoint is hit).  If you enter multiple lines of Python that             \n\
79254721Semasteare not function definitions, they will be collected into a new,                \n\
80254721Semasteautomatically generated Python function, and a call to the newly                \n\
81254721Semastegenerated function will be attached to the watchpoint.                          \n\
82254721Semaste                                                                                \n\
83254721SemasteThis auto-generated function is passed in two arguments:                        \n\
84254721Semaste                                                                                \n\
85254721Semaste    frame:  an SBFrame object representing the frame which hit the watchpoint.  \n\
86254721Semaste            From the frame you can get back to the thread and process.          \n\
87254721Semaste    wp:     the watchpoint that was hit.                                        \n\
88254721Semaste                                                                                \n\
89254721SemasteImportant Note: Because loose Python code gets collected into functions,        \n\
90254721Semasteif you want to access global variables in the 'loose' code, you need to         \n\
91254721Semastespecify that they are global, using the 'global' keyword.  Be sure to           \n\
92254721Semasteuse correct Python syntax, including indentation, when entering Python          \n\
93254721Semastewatchpoint commands.                                                            \n\
94254721Semaste                                                                                \n\
95254721SemasteAs a third option, you can pass the name of an already existing Python function \n\
96254721Semasteand that function will be attached to the watchpoint. It will get passed the    \n\
97254721Semasteframe and wp_loc arguments mentioned above.                                     \n\
98254721Semaste                                                                                \n\
99254721SemasteExample Python one-line watchpoint command: \n\
100254721Semaste \n\
101254721Semaste(lldb) watchpoint command add -s python 1 \n\
102254721SemasteEnter your Python command(s). Type 'DONE' to end. \n\
103254721Semaste> print \"Hit this watchpoint!\" \n\
104254721Semaste> DONE \n\
105254721Semaste \n\
106254721SemasteAs a convenience, this also works for a short Python one-liner: \n\
107254721Semaste(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
108254721Semaste(lldb) run \n\
109254721SemasteLaunching '.../a.out'  (x86_64) \n\
110254721Semaste(lldb) Fri Sep 10 12:17:45 2010 \n\
111254721SemasteProcess 21778 Stopped \n\
112254721Semaste* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
113254721Semaste  36   	\n\
114254721Semaste  37   	int c(int val)\n\
115254721Semaste  38   	{\n\
116254721Semaste  39 ->	    return val + 3;\n\
117254721Semaste  40   	}\n\
118254721Semaste  41   	\n\
119254721Semaste  42   	int main (int argc, char const *argv[])\n\
120254721Semaste(lldb) \n\
121254721Semaste \n\
122254721SemasteExample multiple line Python watchpoint command, using function definition: \n\
123254721Semaste \n\
124254721Semaste(lldb) watchpoint command add -s python 1 \n\
125254721SemasteEnter your Python command(s). Type 'DONE' to end. \n\
126254721Semaste> def watchpoint_output (wp_no): \n\
127254721Semaste>     out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
128254721Semaste>     print out_string \n\
129254721Semaste>     return True \n\
130254721Semaste> watchpoint_output (1) \n\
131254721Semaste> DONE \n\
132254721Semaste \n\
133254721Semaste \n\
134254721SemasteExample multiple line Python watchpoint command, using 'loose' Python: \n\
135254721Semaste \n\
136254721Semaste(lldb) watchpoint command add -s p 1 \n\
137254721SemasteEnter your Python command(s). Type 'DONE' to end. \n\
138254721Semaste> global wp_count \n\
139254721Semaste> wp_count = wp_count + 1 \n\
140254721Semaste> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
141254721Semaste> DONE \n\
142254721Semaste \n\
143254721SemasteIn this case, since there is a reference to a global variable, \n\
144254721Semaste'wp_count', you will also need to make sure 'wp_count' exists and is \n\
145254721Semasteinitialized: \n\
146254721Semaste \n\
147254721Semaste(lldb) script \n\
148254721Semaste>>> wp_count = 0 \n\
149254721Semaste>>> quit() \n\
150254721Semaste \n\
151254721Semaste(lldb)  \n\
152254721Semaste \n\
153254721Semaste \n\
154254721SemasteFinal Note:  If you get a warning that no watchpoint command was generated, \n\
155254721Semastebut you did not get any syntax errors, you probably forgot to add a call \n\
156254721Semasteto your functions. \n\
157254721Semaste \n\
158254721SemasteSpecial information about debugger command watchpoint commands \n\
159254721Semaste-------------------------------------------------------------- \n\
160254721Semaste \n\
161254721SemasteYou may enter any debugger command, exactly as you would at the \n\
162254721Semastedebugger prompt.  You may enter as many debugger commands as you like, \n\
163254721Semastebut do NOT enter more than one command per line. \n" );
164254721Semaste
165254721Semaste        CommandArgumentEntry arg;
166254721Semaste        CommandArgumentData wp_id_arg;
167254721Semaste
168254721Semaste        // Define the first (and only) variant of this arg.
169254721Semaste        wp_id_arg.arg_type = eArgTypeWatchpointID;
170254721Semaste        wp_id_arg.arg_repetition = eArgRepeatPlain;
171254721Semaste
172254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
173254721Semaste        arg.push_back (wp_id_arg);
174254721Semaste
175254721Semaste        // Push the data for the first argument into the m_arguments vector.
176254721Semaste        m_arguments.push_back (arg);
177254721Semaste    }
178254721Semaste
179254721Semaste    virtual
180254721Semaste    ~CommandObjectWatchpointCommandAdd () {}
181254721Semaste
182254721Semaste    virtual Options *
183254721Semaste    GetOptions ()
184254721Semaste    {
185254721Semaste        return &m_options;
186254721Semaste    }
187254721Semaste
188254721Semaste    void
189254721Semaste    CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
190254721Semaste                                             CommandReturnObject &result)
191254721Semaste    {
192254721Semaste        InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
193254721Semaste        std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
194254721Semaste        if (reader_sp && data_ap.get())
195254721Semaste        {
196254721Semaste            BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
197254721Semaste            wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
198254721Semaste
199254721Semaste            Error err (reader_sp->Initialize (CommandObjectWatchpointCommandAdd::GenerateWatchpointCommandCallback,
200254721Semaste                                              wp_options,                   // callback_data
201254721Semaste                                              eInputReaderGranularityLine,  // token size, to pass to callback function
202254721Semaste                                              "DONE",                       // end token
203254721Semaste                                              "> ",                         // prompt
204254721Semaste                                              true));                       // echo input
205254721Semaste            if (err.Success())
206254721Semaste            {
207254721Semaste                m_interpreter.GetDebugger().PushInputReader (reader_sp);
208254721Semaste                result.SetStatus (eReturnStatusSuccessFinishNoResult);
209254721Semaste            }
210254721Semaste            else
211254721Semaste            {
212254721Semaste                result.AppendError (err.AsCString());
213254721Semaste                result.SetStatus (eReturnStatusFailed);
214254721Semaste            }
215254721Semaste        }
216254721Semaste        else
217254721Semaste        {
218254721Semaste            result.AppendError("out of memory");
219254721Semaste            result.SetStatus (eReturnStatusFailed);
220254721Semaste        }
221254721Semaste
222254721Semaste    }
223254721Semaste
224254721Semaste    /// Set a one-liner as the callback for the watchpoint.
225254721Semaste    void
226254721Semaste    SetWatchpointCommandCallback (WatchpointOptions *wp_options,
227254721Semaste                                  const char *oneliner)
228254721Semaste    {
229254721Semaste        std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
230254721Semaste
231254721Semaste        // It's necessary to set both user_source and script_source to the oneliner.
232254721Semaste        // The former is used to generate callback description (as in watchpoint command list)
233254721Semaste        // while the latter is used for Python to interpret during the actual callback.
234254721Semaste        data_ap->user_source.AppendString (oneliner);
235254721Semaste        data_ap->script_source.assign (oneliner);
236254721Semaste        data_ap->stop_on_error = m_options.m_stop_on_error;
237254721Semaste
238254721Semaste        BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
239254721Semaste        wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
240254721Semaste
241254721Semaste        return;
242254721Semaste    }
243254721Semaste
244254721Semaste    static size_t
245254721Semaste    GenerateWatchpointCommandCallback (void *callback_data,
246254721Semaste                                       InputReader &reader,
247254721Semaste                                       lldb::InputReaderAction notification,
248254721Semaste                                       const char *bytes,
249254721Semaste                                       size_t bytes_len)
250254721Semaste    {
251254721Semaste        StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
252254721Semaste        bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
253254721Semaste
254254721Semaste        switch (notification)
255254721Semaste        {
256254721Semaste        case eInputReaderActivate:
257254721Semaste            if (!batch_mode)
258254721Semaste            {
259254721Semaste                out_stream->Printf ("%s\n", g_reader_instructions);
260254721Semaste                if (reader.GetPrompt())
261254721Semaste                    out_stream->Printf ("%s", reader.GetPrompt());
262254721Semaste                out_stream->Flush();
263254721Semaste            }
264254721Semaste            break;
265254721Semaste
266254721Semaste        case eInputReaderDeactivate:
267254721Semaste            break;
268254721Semaste
269254721Semaste        case eInputReaderReactivate:
270254721Semaste            if (reader.GetPrompt() && !batch_mode)
271254721Semaste            {
272254721Semaste                out_stream->Printf ("%s", reader.GetPrompt());
273254721Semaste                out_stream->Flush();
274254721Semaste            }
275254721Semaste            break;
276254721Semaste
277254721Semaste        case eInputReaderAsynchronousOutputWritten:
278254721Semaste            break;
279254721Semaste
280254721Semaste        case eInputReaderGotToken:
281254721Semaste            if (bytes && bytes_len && callback_data)
282254721Semaste            {
283254721Semaste                WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
284254721Semaste                if (wp_options)
285254721Semaste                {
286254721Semaste                    Baton *wp_options_baton = wp_options->GetBaton();
287254721Semaste                    if (wp_options_baton)
288254721Semaste                        ((WatchpointOptions::CommandData *)wp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
289254721Semaste                }
290254721Semaste            }
291254721Semaste            if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
292254721Semaste            {
293254721Semaste                out_stream->Printf ("%s", reader.GetPrompt());
294254721Semaste                out_stream->Flush();
295254721Semaste            }
296254721Semaste            break;
297254721Semaste
298254721Semaste        case eInputReaderInterrupt:
299254721Semaste            {
300254721Semaste                // Finish, and cancel the watchpoint command.
301254721Semaste                reader.SetIsDone (true);
302254721Semaste                WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
303254721Semaste                if (wp_options)
304254721Semaste                {
305254721Semaste                    Baton *wp_options_baton = wp_options->GetBaton ();
306254721Semaste                    if (wp_options_baton)
307254721Semaste                    {
308254721Semaste                        ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->user_source.Clear();
309254721Semaste                        ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->script_source.clear();
310254721Semaste                    }
311254721Semaste                }
312254721Semaste                if (!batch_mode)
313254721Semaste                {
314254721Semaste                    out_stream->Printf ("Warning: No command attached to watchpoint.\n");
315254721Semaste                    out_stream->Flush();
316254721Semaste                }
317254721Semaste            }
318254721Semaste            break;
319254721Semaste
320254721Semaste        case eInputReaderEndOfFile:
321254721Semaste            reader.SetIsDone (true);
322254721Semaste            break;
323254721Semaste
324254721Semaste        case eInputReaderDone:
325254721Semaste            break;
326254721Semaste        }
327254721Semaste
328254721Semaste        return bytes_len;
329254721Semaste    }
330254721Semaste
331254721Semaste    static bool
332254721Semaste    WatchpointOptionsCallbackFunction (void *baton,
333254721Semaste                                       StoppointCallbackContext *context,
334254721Semaste                                       lldb::user_id_t watch_id)
335254721Semaste    {
336254721Semaste        bool ret_value = true;
337254721Semaste        if (baton == NULL)
338254721Semaste            return true;
339254721Semaste
340254721Semaste
341254721Semaste        WatchpointOptions::CommandData *data = (WatchpointOptions::CommandData *) baton;
342254721Semaste        StringList &commands = data->user_source;
343254721Semaste
344254721Semaste        if (commands.GetSize() > 0)
345254721Semaste        {
346254721Semaste            ExecutionContext exe_ctx (context->exe_ctx_ref);
347254721Semaste            Target *target = exe_ctx.GetTargetPtr();
348254721Semaste            if (target)
349254721Semaste            {
350254721Semaste                CommandReturnObject result;
351254721Semaste                Debugger &debugger = target->GetDebugger();
352254721Semaste                // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
353254721Semaste                // if the debugger is set up that way.
354254721Semaste
355254721Semaste                StreamSP output_stream (debugger.GetAsyncOutputStream());
356254721Semaste                StreamSP error_stream (debugger.GetAsyncErrorStream());
357254721Semaste                result.SetImmediateOutputStream (output_stream);
358254721Semaste                result.SetImmediateErrorStream (error_stream);
359254721Semaste
360254721Semaste                bool stop_on_continue = true;
361254721Semaste                bool echo_commands    = false;
362254721Semaste                bool print_results    = true;
363254721Semaste
364254721Semaste                debugger.GetCommandInterpreter().HandleCommands (commands,
365254721Semaste                                                                 &exe_ctx,
366254721Semaste                                                                 stop_on_continue,
367254721Semaste                                                                 data->stop_on_error,
368254721Semaste                                                                 echo_commands,
369254721Semaste                                                                 print_results,
370254721Semaste                                                                 eLazyBoolNo,
371254721Semaste                                                                 result);
372254721Semaste                result.GetImmediateOutputStream()->Flush();
373254721Semaste                result.GetImmediateErrorStream()->Flush();
374254721Semaste           }
375254721Semaste        }
376254721Semaste        return ret_value;
377254721Semaste    }
378254721Semaste
379254721Semaste    class CommandOptions : public Options
380254721Semaste    {
381254721Semaste    public:
382254721Semaste
383254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
384254721Semaste            Options (interpreter),
385254721Semaste            m_use_commands (false),
386254721Semaste            m_use_script_language (false),
387254721Semaste            m_script_language (eScriptLanguageNone),
388254721Semaste            m_use_one_liner (false),
389254721Semaste            m_one_liner(),
390254721Semaste            m_function_name()
391254721Semaste        {
392254721Semaste        }
393254721Semaste
394254721Semaste        virtual
395254721Semaste        ~CommandOptions () {}
396254721Semaste
397254721Semaste        virtual Error
398254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
399254721Semaste        {
400254721Semaste            Error error;
401254721Semaste            const int short_option = m_getopt_table[option_idx].val;
402254721Semaste
403254721Semaste            switch (short_option)
404254721Semaste            {
405254721Semaste            case 'o':
406254721Semaste                m_use_one_liner = true;
407254721Semaste                m_one_liner = option_arg;
408254721Semaste                break;
409254721Semaste
410254721Semaste            case 's':
411254721Semaste                m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
412254721Semaste                                                                                     g_option_table[option_idx].enum_values,
413254721Semaste                                                                                     eScriptLanguageNone,
414254721Semaste                                                                                     error);
415254721Semaste
416254721Semaste                if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
417254721Semaste                {
418254721Semaste                    m_use_script_language = true;
419254721Semaste                }
420254721Semaste                else
421254721Semaste                {
422254721Semaste                    m_use_script_language = false;
423254721Semaste                }
424254721Semaste                break;
425254721Semaste
426254721Semaste            case 'e':
427254721Semaste                {
428254721Semaste                    bool success = false;
429254721Semaste                    m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
430254721Semaste                    if (!success)
431254721Semaste                        error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
432254721Semaste                }
433254721Semaste                break;
434254721Semaste
435254721Semaste            case 'F':
436254721Semaste                {
437254721Semaste                    m_use_one_liner = false;
438254721Semaste                    m_use_script_language = true;
439254721Semaste                    m_function_name.assign(option_arg);
440254721Semaste                }
441254721Semaste                break;
442254721Semaste
443254721Semaste            default:
444254721Semaste                break;
445254721Semaste            }
446254721Semaste            return error;
447254721Semaste        }
448254721Semaste        void
449254721Semaste        OptionParsingStarting ()
450254721Semaste        {
451254721Semaste            m_use_commands = true;
452254721Semaste            m_use_script_language = false;
453254721Semaste            m_script_language = eScriptLanguageNone;
454254721Semaste
455254721Semaste            m_use_one_liner = false;
456254721Semaste            m_stop_on_error = true;
457254721Semaste            m_one_liner.clear();
458254721Semaste            m_function_name.clear();
459254721Semaste        }
460254721Semaste
461254721Semaste        const OptionDefinition*
462254721Semaste        GetDefinitions ()
463254721Semaste        {
464254721Semaste            return g_option_table;
465254721Semaste        }
466254721Semaste
467254721Semaste        // Options table: Required for subclasses of Options.
468254721Semaste
469254721Semaste        static OptionDefinition g_option_table[];
470254721Semaste
471254721Semaste        // Instance variables to hold the values for command options.
472254721Semaste
473254721Semaste        bool m_use_commands;
474254721Semaste        bool m_use_script_language;
475254721Semaste        lldb::ScriptLanguage m_script_language;
476254721Semaste
477254721Semaste        // Instance variables to hold the values for one_liner options.
478254721Semaste        bool m_use_one_liner;
479254721Semaste        std::string m_one_liner;
480254721Semaste        bool m_stop_on_error;
481254721Semaste        std::string m_function_name;
482254721Semaste    };
483254721Semaste
484254721Semasteprotected:
485254721Semaste    virtual bool
486254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
487254721Semaste    {
488254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
489254721Semaste
490254721Semaste        if (target == NULL)
491254721Semaste        {
492254721Semaste            result.AppendError ("There is not a current executable; there are no watchpoints to which to add commands");
493254721Semaste            result.SetStatus (eReturnStatusFailed);
494254721Semaste            return false;
495254721Semaste        }
496254721Semaste
497254721Semaste        const WatchpointList &watchpoints = target->GetWatchpointList();
498254721Semaste        size_t num_watchpoints = watchpoints.GetSize();
499254721Semaste
500254721Semaste        if (num_watchpoints == 0)
501254721Semaste        {
502254721Semaste            result.AppendError ("No watchpoints exist to have commands added");
503254721Semaste            result.SetStatus (eReturnStatusFailed);
504254721Semaste            return false;
505254721Semaste        }
506254721Semaste
507254721Semaste        if (m_options.m_use_script_language == false && m_options.m_function_name.size())
508254721Semaste        {
509254721Semaste            result.AppendError ("need to enable scripting to have a function run as a watchpoint command");
510254721Semaste            result.SetStatus (eReturnStatusFailed);
511254721Semaste            return false;
512254721Semaste        }
513254721Semaste
514254721Semaste        std::vector<uint32_t> valid_wp_ids;
515254721Semaste        if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
516254721Semaste        {
517254721Semaste            result.AppendError("Invalid watchpoints specification.");
518254721Semaste            result.SetStatus(eReturnStatusFailed);
519254721Semaste            return false;
520254721Semaste        }
521254721Semaste
522254721Semaste        result.SetStatus(eReturnStatusSuccessFinishNoResult);
523254721Semaste        const size_t count = valid_wp_ids.size();
524254721Semaste        for (size_t i = 0; i < count; ++i)
525254721Semaste        {
526254721Semaste            uint32_t cur_wp_id = valid_wp_ids.at (i);
527254721Semaste            if (cur_wp_id != LLDB_INVALID_WATCH_ID)
528254721Semaste            {
529254721Semaste                Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
530254721Semaste                // Sanity check wp first.
531254721Semaste                if (wp == NULL) continue;
532254721Semaste
533254721Semaste                WatchpointOptions *wp_options = wp->GetOptions();
534254721Semaste                // Skip this watchpoint if wp_options is not good.
535254721Semaste                if (wp_options == NULL) continue;
536254721Semaste
537254721Semaste                // If we are using script language, get the script interpreter
538254721Semaste                // in order to set or collect command callback.  Otherwise, call
539254721Semaste                // the methods associated with this object.
540254721Semaste                if (m_options.m_use_script_language)
541254721Semaste                {
542254721Semaste                    // Special handling for one-liner specified inline.
543254721Semaste                    if (m_options.m_use_one_liner)
544254721Semaste                    {
545254721Semaste                        m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
546254721Semaste                                                                                            m_options.m_one_liner.c_str());
547254721Semaste                    }
548254721Semaste                    // Special handling for using a Python function by name
549254721Semaste                    // instead of extending the watchpoint callback data structures, we just automatize
550254721Semaste                    // what the user would do manually: make their watchpoint command be a function call
551254721Semaste                    else if (m_options.m_function_name.size())
552254721Semaste                    {
553254721Semaste                        std::string oneliner(m_options.m_function_name);
554254721Semaste                        oneliner += "(frame, wp, internal_dict)";
555254721Semaste                        m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
556254721Semaste                                                                                            oneliner.c_str());
557254721Semaste                    }
558254721Semaste                    else
559254721Semaste                    {
560254721Semaste                        m_interpreter.GetScriptInterpreter()->CollectDataForWatchpointCommandCallback (wp_options,
561254721Semaste                                                                                                       result);
562254721Semaste                    }
563254721Semaste                }
564254721Semaste                else
565254721Semaste                {
566254721Semaste                    // Special handling for one-liner specified inline.
567254721Semaste                    if (m_options.m_use_one_liner)
568254721Semaste                        SetWatchpointCommandCallback (wp_options,
569254721Semaste                                                      m_options.m_one_liner.c_str());
570254721Semaste                    else
571254721Semaste                        CollectDataForWatchpointCommandCallback (wp_options,
572254721Semaste                                                                 result);
573254721Semaste                }
574254721Semaste            }
575254721Semaste        }
576254721Semaste
577254721Semaste        return result.Succeeded();
578254721Semaste    }
579254721Semaste
580254721Semasteprivate:
581254721Semaste    CommandOptions m_options;
582254721Semaste    static const char *g_reader_instructions;
583254721Semaste
584254721Semaste};
585254721Semaste
586254721Semasteconst char *
587254721SemasteCommandObjectWatchpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
588254721Semaste
589254721Semaste// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
590254721Semaste// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
591254721Semaste
592254721Semastestatic OptionEnumValueElement
593254721Semasteg_script_option_enumeration[4] =
594254721Semaste{
595254721Semaste    { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
596254721Semaste    { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
597254721Semaste    { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
598254721Semaste    { 0,                      NULL,              NULL }
599254721Semaste};
600254721Semaste
601254721SemasteOptionDefinition
602254721SemasteCommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
603254721Semaste{
604254721Semaste    { LLDB_OPT_SET_1,   false, "one-liner",       'o', required_argument, NULL, 0, eArgTypeOneLiner,
605254721Semaste        "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
606254721Semaste
607254721Semaste    { LLDB_OPT_SET_ALL, false, "stop-on-error",   'e', required_argument, NULL, 0, eArgTypeBoolean,
608254721Semaste        "Specify whether watchpoint command execution should terminate on error." },
609254721Semaste
610254721Semaste    { LLDB_OPT_SET_ALL, false, "script-type",     's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
611254721Semaste        "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
612254721Semaste
613254721Semaste    { LLDB_OPT_SET_2,   false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction,
614254721Semaste        "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate."},
615254721Semaste
616254721Semaste    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
617254721Semaste};
618254721Semaste
619254721Semaste//-------------------------------------------------------------------------
620254721Semaste// CommandObjectWatchpointCommandDelete
621254721Semaste//-------------------------------------------------------------------------
622254721Semaste
623254721Semasteclass CommandObjectWatchpointCommandDelete : public CommandObjectParsed
624254721Semaste{
625254721Semastepublic:
626254721Semaste    CommandObjectWatchpointCommandDelete (CommandInterpreter &interpreter) :
627254721Semaste        CommandObjectParsed (interpreter,
628254721Semaste                             "delete",
629254721Semaste                             "Delete the set of commands from a watchpoint.",
630254721Semaste                             NULL)
631254721Semaste    {
632254721Semaste        CommandArgumentEntry arg;
633254721Semaste        CommandArgumentData wp_id_arg;
634254721Semaste
635254721Semaste        // Define the first (and only) variant of this arg.
636254721Semaste        wp_id_arg.arg_type = eArgTypeWatchpointID;
637254721Semaste        wp_id_arg.arg_repetition = eArgRepeatPlain;
638254721Semaste
639254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
640254721Semaste        arg.push_back (wp_id_arg);
641254721Semaste
642254721Semaste        // Push the data for the first argument into the m_arguments vector.
643254721Semaste        m_arguments.push_back (arg);
644254721Semaste    }
645254721Semaste
646254721Semaste
647254721Semaste    virtual
648254721Semaste    ~CommandObjectWatchpointCommandDelete () {}
649254721Semaste
650254721Semasteprotected:
651254721Semaste    virtual bool
652254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
653254721Semaste    {
654254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
655254721Semaste
656254721Semaste        if (target == NULL)
657254721Semaste        {
658254721Semaste            result.AppendError ("There is not a current executable; there are no watchpoints from which to delete commands");
659254721Semaste            result.SetStatus (eReturnStatusFailed);
660254721Semaste            return false;
661254721Semaste        }
662254721Semaste
663254721Semaste        const WatchpointList &watchpoints = target->GetWatchpointList();
664254721Semaste        size_t num_watchpoints = watchpoints.GetSize();
665254721Semaste
666254721Semaste        if (num_watchpoints == 0)
667254721Semaste        {
668254721Semaste            result.AppendError ("No watchpoints exist to have commands deleted");
669254721Semaste            result.SetStatus (eReturnStatusFailed);
670254721Semaste            return false;
671254721Semaste        }
672254721Semaste
673254721Semaste        if (command.GetArgumentCount() == 0)
674254721Semaste        {
675254721Semaste            result.AppendError ("No watchpoint specified from which to delete the commands");
676254721Semaste            result.SetStatus (eReturnStatusFailed);
677254721Semaste            return false;
678254721Semaste        }
679254721Semaste
680254721Semaste        std::vector<uint32_t> valid_wp_ids;
681254721Semaste        if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
682254721Semaste        {
683254721Semaste            result.AppendError("Invalid watchpoints specification.");
684254721Semaste            result.SetStatus(eReturnStatusFailed);
685254721Semaste            return false;
686254721Semaste        }
687254721Semaste
688254721Semaste        result.SetStatus(eReturnStatusSuccessFinishNoResult);
689254721Semaste        const size_t count = valid_wp_ids.size();
690254721Semaste        for (size_t i = 0; i < count; ++i)
691254721Semaste        {
692254721Semaste            uint32_t cur_wp_id = valid_wp_ids.at (i);
693254721Semaste            if (cur_wp_id != LLDB_INVALID_WATCH_ID)
694254721Semaste            {
695254721Semaste                Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
696254721Semaste                if (wp)
697254721Semaste                    wp->ClearCallback();
698254721Semaste            }
699254721Semaste            else
700254721Semaste            {
701254721Semaste                result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n",
702254721Semaste                                             cur_wp_id);
703254721Semaste                result.SetStatus (eReturnStatusFailed);
704254721Semaste                return false;
705254721Semaste            }
706254721Semaste        }
707254721Semaste        return result.Succeeded();
708254721Semaste    }
709254721Semaste};
710254721Semaste
711254721Semaste//-------------------------------------------------------------------------
712254721Semaste// CommandObjectWatchpointCommandList
713254721Semaste//-------------------------------------------------------------------------
714254721Semaste
715254721Semasteclass CommandObjectWatchpointCommandList : public CommandObjectParsed
716254721Semaste{
717254721Semastepublic:
718254721Semaste    CommandObjectWatchpointCommandList (CommandInterpreter &interpreter) :
719254721Semaste        CommandObjectParsed (interpreter,
720254721Semaste                             "list",
721254721Semaste                             "List the script or set of commands to be executed when the watchpoint is hit.",
722254721Semaste                              NULL)
723254721Semaste    {
724254721Semaste        CommandArgumentEntry arg;
725254721Semaste        CommandArgumentData wp_id_arg;
726254721Semaste
727254721Semaste        // Define the first (and only) variant of this arg.
728254721Semaste        wp_id_arg.arg_type = eArgTypeWatchpointID;
729254721Semaste        wp_id_arg.arg_repetition = eArgRepeatPlain;
730254721Semaste
731254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
732254721Semaste        arg.push_back (wp_id_arg);
733254721Semaste
734254721Semaste        // Push the data for the first argument into the m_arguments vector.
735254721Semaste        m_arguments.push_back (arg);
736254721Semaste    }
737254721Semaste
738254721Semaste    virtual
739254721Semaste    ~CommandObjectWatchpointCommandList () {}
740254721Semaste
741254721Semasteprotected:
742254721Semaste    virtual bool
743254721Semaste    DoExecute (Args& command,
744254721Semaste             CommandReturnObject &result)
745254721Semaste    {
746254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
747254721Semaste
748254721Semaste        if (target == NULL)
749254721Semaste        {
750254721Semaste            result.AppendError ("There is not a current executable; there are no watchpoints for which to list commands");
751254721Semaste            result.SetStatus (eReturnStatusFailed);
752254721Semaste            return false;
753254721Semaste        }
754254721Semaste
755254721Semaste        const WatchpointList &watchpoints = target->GetWatchpointList();
756254721Semaste        size_t num_watchpoints = watchpoints.GetSize();
757254721Semaste
758254721Semaste        if (num_watchpoints == 0)
759254721Semaste        {
760254721Semaste            result.AppendError ("No watchpoints exist for which to list commands");
761254721Semaste            result.SetStatus (eReturnStatusFailed);
762254721Semaste            return false;
763254721Semaste        }
764254721Semaste
765254721Semaste        if (command.GetArgumentCount() == 0)
766254721Semaste        {
767254721Semaste            result.AppendError ("No watchpoint specified for which to list the commands");
768254721Semaste            result.SetStatus (eReturnStatusFailed);
769254721Semaste            return false;
770254721Semaste        }
771254721Semaste
772254721Semaste        std::vector<uint32_t> valid_wp_ids;
773254721Semaste        if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
774254721Semaste        {
775254721Semaste            result.AppendError("Invalid watchpoints specification.");
776254721Semaste            result.SetStatus(eReturnStatusFailed);
777254721Semaste            return false;
778254721Semaste        }
779254721Semaste
780254721Semaste        result.SetStatus(eReturnStatusSuccessFinishNoResult);
781254721Semaste        const size_t count = valid_wp_ids.size();
782254721Semaste        for (size_t i = 0; i < count; ++i)
783254721Semaste        {
784254721Semaste            uint32_t cur_wp_id = valid_wp_ids.at (i);
785254721Semaste            if (cur_wp_id != LLDB_INVALID_WATCH_ID)
786254721Semaste            {
787254721Semaste                Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
788254721Semaste
789254721Semaste                if (wp)
790254721Semaste                {
791254721Semaste                    const WatchpointOptions *wp_options = wp->GetOptions();
792254721Semaste                    if (wp_options)
793254721Semaste                    {
794254721Semaste                        // Get the callback baton associated with the current watchpoint.
795254721Semaste                        const Baton *baton = wp_options->GetBaton();
796254721Semaste                        if (baton)
797254721Semaste                        {
798254721Semaste                            result.GetOutputStream().Printf ("Watchpoint %u:\n", cur_wp_id);
799254721Semaste                            result.GetOutputStream().IndentMore ();
800254721Semaste                            baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
801254721Semaste                            result.GetOutputStream().IndentLess ();
802254721Semaste                        }
803254721Semaste                        else
804254721Semaste                        {
805254721Semaste                            result.AppendMessageWithFormat ("Watchpoint %u does not have an associated command.\n",
806254721Semaste                                                            cur_wp_id);
807254721Semaste                        }
808254721Semaste                    }
809254721Semaste                    result.SetStatus (eReturnStatusSuccessFinishResult);
810254721Semaste                }
811254721Semaste                else
812254721Semaste                {
813254721Semaste                    result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id);
814254721Semaste                    result.SetStatus (eReturnStatusFailed);
815254721Semaste                }
816254721Semaste            }
817254721Semaste        }
818254721Semaste
819254721Semaste        return result.Succeeded();
820254721Semaste    }
821254721Semaste};
822254721Semaste
823254721Semaste//-------------------------------------------------------------------------
824254721Semaste// CommandObjectWatchpointCommand
825254721Semaste//-------------------------------------------------------------------------
826254721Semaste
827254721SemasteCommandObjectWatchpointCommand::CommandObjectWatchpointCommand (CommandInterpreter &interpreter) :
828254721Semaste    CommandObjectMultiword (interpreter,
829254721Semaste                            "command",
830254721Semaste                            "A set of commands for adding, removing and examining bits of code to be executed when the watchpoint is hit (watchpoint 'commmands').",
831254721Semaste                            "command <sub-command> [<sub-command-options>] <watchpoint-id>")
832254721Semaste{
833254721Semaste    CommandObjectSP add_command_object (new CommandObjectWatchpointCommandAdd (interpreter));
834254721Semaste    CommandObjectSP delete_command_object (new CommandObjectWatchpointCommandDelete (interpreter));
835254721Semaste    CommandObjectSP list_command_object (new CommandObjectWatchpointCommandList (interpreter));
836254721Semaste
837254721Semaste    add_command_object->SetCommandName ("watchpoint command add");
838254721Semaste    delete_command_object->SetCommandName ("watchpoint command delete");
839254721Semaste    list_command_object->SetCommandName ("watchpoint command list");
840254721Semaste
841254721Semaste    LoadSubCommand ("add",    add_command_object);
842254721Semaste    LoadSubCommand ("delete", delete_command_object);
843254721Semaste    LoadSubCommand ("list",   list_command_object);
844254721Semaste}
845254721Semaste
846254721SemasteCommandObjectWatchpointCommand::~CommandObjectWatchpointCommand ()
847254721Semaste{
848254721Semaste}
849254721Semaste
850254721Semaste
851