1ac7ddfbfSEd Maste //===-- CommandObjectWatchpointCommand.cpp ----------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/lldb-python.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste // C Includes
13ac7ddfbfSEd Maste // C++ Includes
14ac7ddfbfSEd Maste 
15ac7ddfbfSEd Maste 
16ac7ddfbfSEd Maste #include "CommandObjectWatchpointCommand.h"
17ac7ddfbfSEd Maste #include "CommandObjectWatchpoint.h"
18ac7ddfbfSEd Maste 
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
20ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
21ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
22ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
23ac7ddfbfSEd Maste #include "lldb/Breakpoint/Watchpoint.h"
24ac7ddfbfSEd Maste #include "lldb/Breakpoint/StoppointCallbackContext.h"
25ac7ddfbfSEd Maste #include "lldb/Core/State.h"
26ac7ddfbfSEd Maste 
27ac7ddfbfSEd Maste #include <vector>
28ac7ddfbfSEd Maste 
29ac7ddfbfSEd Maste using namespace lldb;
30ac7ddfbfSEd Maste using namespace lldb_private;
31ac7ddfbfSEd Maste 
32ac7ddfbfSEd Maste //-------------------------------------------------------------------------
33ac7ddfbfSEd Maste // CommandObjectWatchpointCommandAdd
34ac7ddfbfSEd Maste //-------------------------------------------------------------------------
35ac7ddfbfSEd Maste 
36ac7ddfbfSEd Maste 
37ac7ddfbfSEd Maste class CommandObjectWatchpointCommandAdd : public CommandObjectParsed
38ac7ddfbfSEd Maste {
39ac7ddfbfSEd Maste public:
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste     CommandObjectWatchpointCommandAdd (CommandInterpreter &interpreter) :
42ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
43ac7ddfbfSEd Maste                              "add",
44ac7ddfbfSEd Maste                              "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
45ac7ddfbfSEd Maste                              NULL),
46ac7ddfbfSEd Maste         m_options (interpreter)
47ac7ddfbfSEd Maste     {
48ac7ddfbfSEd Maste         SetHelpLong (
49ac7ddfbfSEd Maste "\nGeneral information about entering watchpoint commands \n\
50ac7ddfbfSEd Maste ------------------------------------------------------ \n\
51ac7ddfbfSEd Maste  \n\
52ac7ddfbfSEd Maste This command will cause you to be prompted to enter the command or set \n\
53ac7ddfbfSEd Maste of commands you wish to be executed when the specified watchpoint is \n\
54ac7ddfbfSEd Maste hit.  You will be told to enter your command(s), and will see a '> ' \n\
55ac7ddfbfSEd Maste prompt. Because you can enter one or many commands to be executed when \n\
56ac7ddfbfSEd Maste a watchpoint is hit, you will continue to be prompted after each \n\
57ac7ddfbfSEd Maste new-line that you enter, until you enter the word 'DONE', which will \n\
58ac7ddfbfSEd Maste cause the commands you have entered to be stored with the watchpoint \n\
59ac7ddfbfSEd Maste and executed when the watchpoint is hit. \n\
60ac7ddfbfSEd Maste  \n\
61ac7ddfbfSEd Maste Syntax checking is not necessarily done when watchpoint commands are \n\
62ac7ddfbfSEd Maste entered.  An improperly written watchpoint command will attempt to get \n\
63ac7ddfbfSEd Maste executed when the watchpoint gets hit, and usually silently fail.  If \n\
64ac7ddfbfSEd Maste your watchpoint command does not appear to be getting executed, go \n\
65ac7ddfbfSEd Maste back and check your syntax. \n\
66ac7ddfbfSEd Maste  \n\
67ac7ddfbfSEd Maste  \n\
68ac7ddfbfSEd Maste Special information about PYTHON watchpoint commands                            \n\
69ac7ddfbfSEd Maste ----------------------------------------------------                            \n\
70ac7ddfbfSEd Maste                                                                                 \n\
71ac7ddfbfSEd Maste You may enter either one line of Python or multiple lines of Python             \n\
72ac7ddfbfSEd Maste (including defining whole functions, if desired).  If you enter a               \n\
73ac7ddfbfSEd Maste single line of Python, that will be passed to the Python interpreter            \n\
74ac7ddfbfSEd Maste 'as is' when the watchpoint gets hit.  If you enter function                    \n\
75ac7ddfbfSEd Maste definitions, they will be passed to the Python interpreter as soon as           \n\
76ac7ddfbfSEd Maste you finish entering the watchpoint command, and they can be called              \n\
77ac7ddfbfSEd Maste later (don't forget to add calls to them, if you want them called when          \n\
78ac7ddfbfSEd Maste the watchpoint is hit).  If you enter multiple lines of Python that             \n\
79ac7ddfbfSEd Maste are not function definitions, they will be collected into a new,                \n\
80ac7ddfbfSEd Maste automatically generated Python function, and a call to the newly                \n\
81ac7ddfbfSEd Maste generated function will be attached to the watchpoint.                          \n\
82ac7ddfbfSEd Maste                                                                                 \n\
83ac7ddfbfSEd Maste This auto-generated function is passed in two arguments:                        \n\
84ac7ddfbfSEd Maste                                                                                 \n\
85ac7ddfbfSEd Maste     frame:  an SBFrame object representing the frame which hit the watchpoint.  \n\
86ac7ddfbfSEd Maste             From the frame you can get back to the thread and process.          \n\
87ac7ddfbfSEd Maste     wp:     the watchpoint that was hit.                                        \n\
88ac7ddfbfSEd Maste                                                                                 \n\
89ac7ddfbfSEd Maste Important Note: Because loose Python code gets collected into functions,        \n\
90ac7ddfbfSEd Maste if you want to access global variables in the 'loose' code, you need to         \n\
91ac7ddfbfSEd Maste specify that they are global, using the 'global' keyword.  Be sure to           \n\
92ac7ddfbfSEd Maste use correct Python syntax, including indentation, when entering Python          \n\
93ac7ddfbfSEd Maste watchpoint commands.                                                            \n\
94ac7ddfbfSEd Maste                                                                                 \n\
95ac7ddfbfSEd Maste As a third option, you can pass the name of an already existing Python function \n\
96ac7ddfbfSEd Maste and that function will be attached to the watchpoint. It will get passed the    \n\
97ac7ddfbfSEd Maste frame and wp_loc arguments mentioned above.                                     \n\
98ac7ddfbfSEd Maste                                                                                 \n\
99ac7ddfbfSEd Maste Example Python one-line watchpoint command: \n\
100ac7ddfbfSEd Maste  \n\
101ac7ddfbfSEd Maste (lldb) watchpoint command add -s python 1 \n\
102ac7ddfbfSEd Maste Enter your Python command(s). Type 'DONE' to end. \n\
103ac7ddfbfSEd Maste > print \"Hit this watchpoint!\" \n\
104ac7ddfbfSEd Maste > DONE \n\
105ac7ddfbfSEd Maste  \n\
106ac7ddfbfSEd Maste As a convenience, this also works for a short Python one-liner: \n\
107ac7ddfbfSEd Maste (lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
108ac7ddfbfSEd Maste (lldb) run \n\
109ac7ddfbfSEd Maste Launching '.../a.out'  (x86_64) \n\
110ac7ddfbfSEd Maste (lldb) Fri Sep 10 12:17:45 2010 \n\
111ac7ddfbfSEd Maste Process 21778 Stopped \n\
112ac7ddfbfSEd Maste * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
113ac7ddfbfSEd Maste   36   	\n\
114ac7ddfbfSEd Maste   37   	int c(int val)\n\
115ac7ddfbfSEd Maste   38   	{\n\
116ac7ddfbfSEd Maste   39 ->	    return val + 3;\n\
117ac7ddfbfSEd Maste   40   	}\n\
118ac7ddfbfSEd Maste   41   	\n\
119ac7ddfbfSEd Maste   42   	int main (int argc, char const *argv[])\n\
120ac7ddfbfSEd Maste (lldb) \n\
121ac7ddfbfSEd Maste  \n\
122ac7ddfbfSEd Maste Example multiple line Python watchpoint command, using function definition: \n\
123ac7ddfbfSEd Maste  \n\
124ac7ddfbfSEd Maste (lldb) watchpoint command add -s python 1 \n\
125ac7ddfbfSEd Maste Enter your Python command(s). Type 'DONE' to end. \n\
126ac7ddfbfSEd Maste > def watchpoint_output (wp_no): \n\
127ac7ddfbfSEd Maste >     out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
128ac7ddfbfSEd Maste >     print out_string \n\
129ac7ddfbfSEd Maste >     return True \n\
130ac7ddfbfSEd Maste > watchpoint_output (1) \n\
131ac7ddfbfSEd Maste > DONE \n\
132ac7ddfbfSEd Maste  \n\
133ac7ddfbfSEd Maste  \n\
134ac7ddfbfSEd Maste Example multiple line Python watchpoint command, using 'loose' Python: \n\
135ac7ddfbfSEd Maste  \n\
136ac7ddfbfSEd Maste (lldb) watchpoint command add -s p 1 \n\
137ac7ddfbfSEd Maste Enter your Python command(s). Type 'DONE' to end. \n\
138ac7ddfbfSEd Maste > global wp_count \n\
139ac7ddfbfSEd Maste > wp_count = wp_count + 1 \n\
140ac7ddfbfSEd Maste > print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
141ac7ddfbfSEd Maste > DONE \n\
142ac7ddfbfSEd Maste  \n\
143ac7ddfbfSEd Maste In this case, since there is a reference to a global variable, \n\
144ac7ddfbfSEd Maste 'wp_count', you will also need to make sure 'wp_count' exists and is \n\
145ac7ddfbfSEd Maste initialized: \n\
146ac7ddfbfSEd Maste  \n\
147ac7ddfbfSEd Maste (lldb) script \n\
148ac7ddfbfSEd Maste >>> wp_count = 0 \n\
149ac7ddfbfSEd Maste >>> quit() \n\
150ac7ddfbfSEd Maste  \n\
151ac7ddfbfSEd Maste (lldb)  \n\
152ac7ddfbfSEd Maste  \n\
153ac7ddfbfSEd Maste  \n\
154ac7ddfbfSEd Maste Final Note:  If you get a warning that no watchpoint command was generated, \n\
155ac7ddfbfSEd Maste but you did not get any syntax errors, you probably forgot to add a call \n\
156ac7ddfbfSEd Maste to your functions. \n\
157ac7ddfbfSEd Maste  \n\
158ac7ddfbfSEd Maste Special information about debugger command watchpoint commands \n\
159ac7ddfbfSEd Maste -------------------------------------------------------------- \n\
160ac7ddfbfSEd Maste  \n\
161ac7ddfbfSEd Maste You may enter any debugger command, exactly as you would at the \n\
162ac7ddfbfSEd Maste debugger prompt.  You may enter as many debugger commands as you like, \n\
163ac7ddfbfSEd Maste but do NOT enter more than one command per line. \n" );
164ac7ddfbfSEd Maste 
165ac7ddfbfSEd Maste         CommandArgumentEntry arg;
166ac7ddfbfSEd Maste         CommandArgumentData wp_id_arg;
167ac7ddfbfSEd Maste 
168ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
169ac7ddfbfSEd Maste         wp_id_arg.arg_type = eArgTypeWatchpointID;
170ac7ddfbfSEd Maste         wp_id_arg.arg_repetition = eArgRepeatPlain;
171ac7ddfbfSEd Maste 
172ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
173ac7ddfbfSEd Maste         arg.push_back (wp_id_arg);
174ac7ddfbfSEd Maste 
175ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
176ac7ddfbfSEd Maste         m_arguments.push_back (arg);
177ac7ddfbfSEd Maste     }
178ac7ddfbfSEd Maste 
179ac7ddfbfSEd Maste     virtual
180ac7ddfbfSEd Maste     ~CommandObjectWatchpointCommandAdd () {}
181ac7ddfbfSEd Maste 
182ac7ddfbfSEd Maste     virtual Options *
183ac7ddfbfSEd Maste     GetOptions ()
184ac7ddfbfSEd Maste     {
185ac7ddfbfSEd Maste         return &m_options;
186ac7ddfbfSEd Maste     }
187ac7ddfbfSEd Maste 
188ac7ddfbfSEd Maste     void
189ac7ddfbfSEd Maste     CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
190ac7ddfbfSEd Maste                                              CommandReturnObject &result)
191ac7ddfbfSEd Maste     {
192ac7ddfbfSEd Maste         InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
193ac7ddfbfSEd Maste         std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
194ac7ddfbfSEd Maste         if (reader_sp && data_ap.get())
195ac7ddfbfSEd Maste         {
196ac7ddfbfSEd Maste             BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
197ac7ddfbfSEd Maste             wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
198ac7ddfbfSEd Maste 
199ac7ddfbfSEd Maste             Error err (reader_sp->Initialize (CommandObjectWatchpointCommandAdd::GenerateWatchpointCommandCallback,
200ac7ddfbfSEd Maste                                               wp_options,                   // callback_data
201ac7ddfbfSEd Maste                                               eInputReaderGranularityLine,  // token size, to pass to callback function
202ac7ddfbfSEd Maste                                               "DONE",                       // end token
203ac7ddfbfSEd Maste                                               "> ",                         // prompt
204ac7ddfbfSEd Maste                                               true));                       // echo input
205ac7ddfbfSEd Maste             if (err.Success())
206ac7ddfbfSEd Maste             {
207ac7ddfbfSEd Maste                 m_interpreter.GetDebugger().PushInputReader (reader_sp);
208ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
209ac7ddfbfSEd Maste             }
210ac7ddfbfSEd Maste             else
211ac7ddfbfSEd Maste             {
212ac7ddfbfSEd Maste                 result.AppendError (err.AsCString());
213ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
214ac7ddfbfSEd Maste             }
215ac7ddfbfSEd Maste         }
216ac7ddfbfSEd Maste         else
217ac7ddfbfSEd Maste         {
218ac7ddfbfSEd Maste             result.AppendError("out of memory");
219ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
220ac7ddfbfSEd Maste         }
221ac7ddfbfSEd Maste 
222ac7ddfbfSEd Maste     }
223ac7ddfbfSEd Maste 
224ac7ddfbfSEd Maste     /// Set a one-liner as the callback for the watchpoint.
225ac7ddfbfSEd Maste     void
226ac7ddfbfSEd Maste     SetWatchpointCommandCallback (WatchpointOptions *wp_options,
227ac7ddfbfSEd Maste                                   const char *oneliner)
228ac7ddfbfSEd Maste     {
229ac7ddfbfSEd Maste         std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
230ac7ddfbfSEd Maste 
231ac7ddfbfSEd Maste         // It's necessary to set both user_source and script_source to the oneliner.
232ac7ddfbfSEd Maste         // The former is used to generate callback description (as in watchpoint command list)
233ac7ddfbfSEd Maste         // while the latter is used for Python to interpret during the actual callback.
234ac7ddfbfSEd Maste         data_ap->user_source.AppendString (oneliner);
235ac7ddfbfSEd Maste         data_ap->script_source.assign (oneliner);
236ac7ddfbfSEd Maste         data_ap->stop_on_error = m_options.m_stop_on_error;
237ac7ddfbfSEd Maste 
238ac7ddfbfSEd Maste         BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
239ac7ddfbfSEd Maste         wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
240ac7ddfbfSEd Maste 
241ac7ddfbfSEd Maste         return;
242ac7ddfbfSEd Maste     }
243ac7ddfbfSEd Maste 
244ac7ddfbfSEd Maste     static size_t
245ac7ddfbfSEd Maste     GenerateWatchpointCommandCallback (void *callback_data,
246ac7ddfbfSEd Maste                                        InputReader &reader,
247ac7ddfbfSEd Maste                                        lldb::InputReaderAction notification,
248ac7ddfbfSEd Maste                                        const char *bytes,
249ac7ddfbfSEd Maste                                        size_t bytes_len)
250ac7ddfbfSEd Maste     {
251ac7ddfbfSEd Maste         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
252ac7ddfbfSEd Maste         bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
253ac7ddfbfSEd Maste 
254ac7ddfbfSEd Maste         switch (notification)
255ac7ddfbfSEd Maste         {
256ac7ddfbfSEd Maste         case eInputReaderActivate:
257ac7ddfbfSEd Maste             if (!batch_mode)
258ac7ddfbfSEd Maste             {
259ac7ddfbfSEd Maste                 out_stream->Printf ("%s\n", g_reader_instructions);
260ac7ddfbfSEd Maste                 if (reader.GetPrompt())
261ac7ddfbfSEd Maste                     out_stream->Printf ("%s", reader.GetPrompt());
262ac7ddfbfSEd Maste                 out_stream->Flush();
263ac7ddfbfSEd Maste             }
264ac7ddfbfSEd Maste             break;
265ac7ddfbfSEd Maste 
266ac7ddfbfSEd Maste         case eInputReaderDeactivate:
267ac7ddfbfSEd Maste             break;
268ac7ddfbfSEd Maste 
269ac7ddfbfSEd Maste         case eInputReaderReactivate:
270ac7ddfbfSEd Maste             if (reader.GetPrompt() && !batch_mode)
271ac7ddfbfSEd Maste             {
272ac7ddfbfSEd Maste                 out_stream->Printf ("%s", reader.GetPrompt());
273ac7ddfbfSEd Maste                 out_stream->Flush();
274ac7ddfbfSEd Maste             }
275ac7ddfbfSEd Maste             break;
276ac7ddfbfSEd Maste 
277ac7ddfbfSEd Maste         case eInputReaderAsynchronousOutputWritten:
278ac7ddfbfSEd Maste             break;
279ac7ddfbfSEd Maste 
280ac7ddfbfSEd Maste         case eInputReaderGotToken:
281ac7ddfbfSEd Maste             if (bytes && bytes_len && callback_data)
282ac7ddfbfSEd Maste             {
283ac7ddfbfSEd Maste                 WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
284ac7ddfbfSEd Maste                 if (wp_options)
285ac7ddfbfSEd Maste                 {
286ac7ddfbfSEd Maste                     Baton *wp_options_baton = wp_options->GetBaton();
287ac7ddfbfSEd Maste                     if (wp_options_baton)
288ac7ddfbfSEd Maste                         ((WatchpointOptions::CommandData *)wp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
289ac7ddfbfSEd Maste                 }
290ac7ddfbfSEd Maste             }
291ac7ddfbfSEd Maste             if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
292ac7ddfbfSEd Maste             {
293ac7ddfbfSEd Maste                 out_stream->Printf ("%s", reader.GetPrompt());
294ac7ddfbfSEd Maste                 out_stream->Flush();
295ac7ddfbfSEd Maste             }
296ac7ddfbfSEd Maste             break;
297ac7ddfbfSEd Maste 
298ac7ddfbfSEd Maste         case eInputReaderInterrupt:
299ac7ddfbfSEd Maste             {
300ac7ddfbfSEd Maste                 // Finish, and cancel the watchpoint command.
301ac7ddfbfSEd Maste                 reader.SetIsDone (true);
302ac7ddfbfSEd Maste                 WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
303ac7ddfbfSEd Maste                 if (wp_options)
304ac7ddfbfSEd Maste                 {
305ac7ddfbfSEd Maste                     Baton *wp_options_baton = wp_options->GetBaton ();
306ac7ddfbfSEd Maste                     if (wp_options_baton)
307ac7ddfbfSEd Maste                     {
308ac7ddfbfSEd Maste                         ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->user_source.Clear();
309ac7ddfbfSEd Maste                         ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->script_source.clear();
310ac7ddfbfSEd Maste                     }
311ac7ddfbfSEd Maste                 }
312ac7ddfbfSEd Maste                 if (!batch_mode)
313ac7ddfbfSEd Maste                 {
314ac7ddfbfSEd Maste                     out_stream->Printf ("Warning: No command attached to watchpoint.\n");
315ac7ddfbfSEd Maste                     out_stream->Flush();
316ac7ddfbfSEd Maste                 }
317ac7ddfbfSEd Maste             }
318ac7ddfbfSEd Maste             break;
319ac7ddfbfSEd Maste 
320ac7ddfbfSEd Maste         case eInputReaderEndOfFile:
321ac7ddfbfSEd Maste             reader.SetIsDone (true);
322ac7ddfbfSEd Maste             break;
323ac7ddfbfSEd Maste 
324ac7ddfbfSEd Maste         case eInputReaderDone:
325ac7ddfbfSEd Maste             break;
326ac7ddfbfSEd Maste         }
327ac7ddfbfSEd Maste 
328ac7ddfbfSEd Maste         return bytes_len;
329ac7ddfbfSEd Maste     }
330ac7ddfbfSEd Maste 
331ac7ddfbfSEd Maste     static bool
332ac7ddfbfSEd Maste     WatchpointOptionsCallbackFunction (void *baton,
333ac7ddfbfSEd Maste                                        StoppointCallbackContext *context,
334ac7ddfbfSEd Maste                                        lldb::user_id_t watch_id)
335ac7ddfbfSEd Maste     {
336ac7ddfbfSEd Maste         bool ret_value = true;
337ac7ddfbfSEd Maste         if (baton == NULL)
338ac7ddfbfSEd Maste             return true;
339ac7ddfbfSEd Maste 
340ac7ddfbfSEd Maste 
341ac7ddfbfSEd Maste         WatchpointOptions::CommandData *data = (WatchpointOptions::CommandData *) baton;
342ac7ddfbfSEd Maste         StringList &commands = data->user_source;
343ac7ddfbfSEd Maste 
344ac7ddfbfSEd Maste         if (commands.GetSize() > 0)
345ac7ddfbfSEd Maste         {
346ac7ddfbfSEd Maste             ExecutionContext exe_ctx (context->exe_ctx_ref);
347ac7ddfbfSEd Maste             Target *target = exe_ctx.GetTargetPtr();
348ac7ddfbfSEd Maste             if (target)
349ac7ddfbfSEd Maste             {
350ac7ddfbfSEd Maste                 CommandReturnObject result;
351ac7ddfbfSEd Maste                 Debugger &debugger = target->GetDebugger();
352ac7ddfbfSEd Maste                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
353ac7ddfbfSEd Maste                 // if the debugger is set up that way.
354ac7ddfbfSEd Maste 
355ac7ddfbfSEd Maste                 StreamSP output_stream (debugger.GetAsyncOutputStream());
356ac7ddfbfSEd Maste                 StreamSP error_stream (debugger.GetAsyncErrorStream());
357ac7ddfbfSEd Maste                 result.SetImmediateOutputStream (output_stream);
358ac7ddfbfSEd Maste                 result.SetImmediateErrorStream (error_stream);
359ac7ddfbfSEd Maste 
360ac7ddfbfSEd Maste                 bool stop_on_continue = true;
361ac7ddfbfSEd Maste                 bool echo_commands    = false;
362ac7ddfbfSEd Maste                 bool print_results    = true;
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste                 debugger.GetCommandInterpreter().HandleCommands (commands,
365ac7ddfbfSEd Maste                                                                  &exe_ctx,
366ac7ddfbfSEd Maste                                                                  stop_on_continue,
367ac7ddfbfSEd Maste                                                                  data->stop_on_error,
368ac7ddfbfSEd Maste                                                                  echo_commands,
369ac7ddfbfSEd Maste                                                                  print_results,
370ac7ddfbfSEd Maste                                                                  eLazyBoolNo,
371ac7ddfbfSEd Maste                                                                  result);
372ac7ddfbfSEd Maste                 result.GetImmediateOutputStream()->Flush();
373ac7ddfbfSEd Maste                 result.GetImmediateErrorStream()->Flush();
374ac7ddfbfSEd Maste            }
375ac7ddfbfSEd Maste         }
376ac7ddfbfSEd Maste         return ret_value;
377ac7ddfbfSEd Maste     }
378ac7ddfbfSEd Maste 
379ac7ddfbfSEd Maste     class CommandOptions : public Options
380ac7ddfbfSEd Maste     {
381ac7ddfbfSEd Maste     public:
382ac7ddfbfSEd Maste 
383ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
384ac7ddfbfSEd Maste             Options (interpreter),
385ac7ddfbfSEd Maste             m_use_commands (false),
386ac7ddfbfSEd Maste             m_use_script_language (false),
387ac7ddfbfSEd Maste             m_script_language (eScriptLanguageNone),
388ac7ddfbfSEd Maste             m_use_one_liner (false),
389ac7ddfbfSEd Maste             m_one_liner(),
390ac7ddfbfSEd Maste             m_function_name()
391ac7ddfbfSEd Maste         {
392ac7ddfbfSEd Maste         }
393ac7ddfbfSEd Maste 
394ac7ddfbfSEd Maste         virtual
395ac7ddfbfSEd Maste         ~CommandOptions () {}
396ac7ddfbfSEd Maste 
397ac7ddfbfSEd Maste         virtual Error
398ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
399ac7ddfbfSEd Maste         {
400ac7ddfbfSEd Maste             Error error;
401ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
402ac7ddfbfSEd Maste 
403ac7ddfbfSEd Maste             switch (short_option)
404ac7ddfbfSEd Maste             {
405ac7ddfbfSEd Maste             case 'o':
406ac7ddfbfSEd Maste                 m_use_one_liner = true;
407ac7ddfbfSEd Maste                 m_one_liner = option_arg;
408ac7ddfbfSEd Maste                 break;
409ac7ddfbfSEd Maste 
410ac7ddfbfSEd Maste             case 's':
411ac7ddfbfSEd Maste                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
412ac7ddfbfSEd Maste                                                                                      g_option_table[option_idx].enum_values,
413ac7ddfbfSEd Maste                                                                                      eScriptLanguageNone,
414ac7ddfbfSEd Maste                                                                                      error);
415ac7ddfbfSEd Maste 
416ac7ddfbfSEd Maste                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
417ac7ddfbfSEd Maste                 {
418ac7ddfbfSEd Maste                     m_use_script_language = true;
419ac7ddfbfSEd Maste                 }
420ac7ddfbfSEd Maste                 else
421ac7ddfbfSEd Maste                 {
422ac7ddfbfSEd Maste                     m_use_script_language = false;
423ac7ddfbfSEd Maste                 }
424ac7ddfbfSEd Maste                 break;
425ac7ddfbfSEd Maste 
426ac7ddfbfSEd Maste             case 'e':
427ac7ddfbfSEd Maste                 {
428ac7ddfbfSEd Maste                     bool success = false;
429ac7ddfbfSEd Maste                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
430ac7ddfbfSEd Maste                     if (!success)
431ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
432ac7ddfbfSEd Maste                 }
433ac7ddfbfSEd Maste                 break;
434ac7ddfbfSEd Maste 
435ac7ddfbfSEd Maste             case 'F':
436ac7ddfbfSEd Maste                 {
437ac7ddfbfSEd Maste                     m_use_one_liner = false;
438ac7ddfbfSEd Maste                     m_use_script_language = true;
439ac7ddfbfSEd Maste                     m_function_name.assign(option_arg);
440ac7ddfbfSEd Maste                 }
441ac7ddfbfSEd Maste                 break;
442ac7ddfbfSEd Maste 
443ac7ddfbfSEd Maste             default:
444ac7ddfbfSEd Maste                 break;
445ac7ddfbfSEd Maste             }
446ac7ddfbfSEd Maste             return error;
447ac7ddfbfSEd Maste         }
448ac7ddfbfSEd Maste         void
449ac7ddfbfSEd Maste         OptionParsingStarting ()
450ac7ddfbfSEd Maste         {
451ac7ddfbfSEd Maste             m_use_commands = true;
452ac7ddfbfSEd Maste             m_use_script_language = false;
453ac7ddfbfSEd Maste             m_script_language = eScriptLanguageNone;
454ac7ddfbfSEd Maste 
455ac7ddfbfSEd Maste             m_use_one_liner = false;
456ac7ddfbfSEd Maste             m_stop_on_error = true;
457ac7ddfbfSEd Maste             m_one_liner.clear();
458ac7ddfbfSEd Maste             m_function_name.clear();
459ac7ddfbfSEd Maste         }
460ac7ddfbfSEd Maste 
461ac7ddfbfSEd Maste         const OptionDefinition*
462ac7ddfbfSEd Maste         GetDefinitions ()
463ac7ddfbfSEd Maste         {
464ac7ddfbfSEd Maste             return g_option_table;
465ac7ddfbfSEd Maste         }
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
468ac7ddfbfSEd Maste 
469ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
470ac7ddfbfSEd Maste 
471ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
472ac7ddfbfSEd Maste 
473ac7ddfbfSEd Maste         bool m_use_commands;
474ac7ddfbfSEd Maste         bool m_use_script_language;
475ac7ddfbfSEd Maste         lldb::ScriptLanguage m_script_language;
476ac7ddfbfSEd Maste 
477ac7ddfbfSEd Maste         // Instance variables to hold the values for one_liner options.
478ac7ddfbfSEd Maste         bool m_use_one_liner;
479ac7ddfbfSEd Maste         std::string m_one_liner;
480ac7ddfbfSEd Maste         bool m_stop_on_error;
481ac7ddfbfSEd Maste         std::string m_function_name;
482ac7ddfbfSEd Maste     };
483ac7ddfbfSEd Maste 
484ac7ddfbfSEd Maste protected:
485ac7ddfbfSEd Maste     virtual bool
486ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
487ac7ddfbfSEd Maste     {
488ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
489ac7ddfbfSEd Maste 
490ac7ddfbfSEd Maste         if (target == NULL)
491ac7ddfbfSEd Maste         {
492ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no watchpoints to which to add commands");
493ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
494ac7ddfbfSEd Maste             return false;
495ac7ddfbfSEd Maste         }
496ac7ddfbfSEd Maste 
497ac7ddfbfSEd Maste         const WatchpointList &watchpoints = target->GetWatchpointList();
498ac7ddfbfSEd Maste         size_t num_watchpoints = watchpoints.GetSize();
499ac7ddfbfSEd Maste 
500ac7ddfbfSEd Maste         if (num_watchpoints == 0)
501ac7ddfbfSEd Maste         {
502ac7ddfbfSEd Maste             result.AppendError ("No watchpoints exist to have commands added");
503ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
504ac7ddfbfSEd Maste             return false;
505ac7ddfbfSEd Maste         }
506ac7ddfbfSEd Maste 
507ac7ddfbfSEd Maste         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
508ac7ddfbfSEd Maste         {
509ac7ddfbfSEd Maste             result.AppendError ("need to enable scripting to have a function run as a watchpoint command");
510ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
511ac7ddfbfSEd Maste             return false;
512ac7ddfbfSEd Maste         }
513ac7ddfbfSEd Maste 
514ac7ddfbfSEd Maste         std::vector<uint32_t> valid_wp_ids;
515ac7ddfbfSEd Maste         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
516ac7ddfbfSEd Maste         {
517ac7ddfbfSEd Maste             result.AppendError("Invalid watchpoints specification.");
518ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
519ac7ddfbfSEd Maste             return false;
520ac7ddfbfSEd Maste         }
521ac7ddfbfSEd Maste 
522ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
523ac7ddfbfSEd Maste         const size_t count = valid_wp_ids.size();
524ac7ddfbfSEd Maste         for (size_t i = 0; i < count; ++i)
525ac7ddfbfSEd Maste         {
526ac7ddfbfSEd Maste             uint32_t cur_wp_id = valid_wp_ids.at (i);
527ac7ddfbfSEd Maste             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
528ac7ddfbfSEd Maste             {
529ac7ddfbfSEd Maste                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
530ac7ddfbfSEd Maste                 // Sanity check wp first.
531ac7ddfbfSEd Maste                 if (wp == NULL) continue;
532ac7ddfbfSEd Maste 
533ac7ddfbfSEd Maste                 WatchpointOptions *wp_options = wp->GetOptions();
534ac7ddfbfSEd Maste                 // Skip this watchpoint if wp_options is not good.
535ac7ddfbfSEd Maste                 if (wp_options == NULL) continue;
536ac7ddfbfSEd Maste 
537ac7ddfbfSEd Maste                 // If we are using script language, get the script interpreter
538ac7ddfbfSEd Maste                 // in order to set or collect command callback.  Otherwise, call
539ac7ddfbfSEd Maste                 // the methods associated with this object.
540ac7ddfbfSEd Maste                 if (m_options.m_use_script_language)
541ac7ddfbfSEd Maste                 {
542ac7ddfbfSEd Maste                     // Special handling for one-liner specified inline.
543ac7ddfbfSEd Maste                     if (m_options.m_use_one_liner)
544ac7ddfbfSEd Maste                     {
545ac7ddfbfSEd Maste                         m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
546ac7ddfbfSEd Maste                                                                                             m_options.m_one_liner.c_str());
547ac7ddfbfSEd Maste                     }
548ac7ddfbfSEd Maste                     // Special handling for using a Python function by name
549ac7ddfbfSEd Maste                     // instead of extending the watchpoint callback data structures, we just automatize
550ac7ddfbfSEd Maste                     // what the user would do manually: make their watchpoint command be a function call
551ac7ddfbfSEd Maste                     else if (m_options.m_function_name.size())
552ac7ddfbfSEd Maste                     {
553ac7ddfbfSEd Maste                         std::string oneliner(m_options.m_function_name);
554ac7ddfbfSEd Maste                         oneliner += "(frame, wp, internal_dict)";
555ac7ddfbfSEd Maste                         m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
556ac7ddfbfSEd Maste                                                                                             oneliner.c_str());
557ac7ddfbfSEd Maste                     }
558ac7ddfbfSEd Maste                     else
559ac7ddfbfSEd Maste                     {
560ac7ddfbfSEd Maste                         m_interpreter.GetScriptInterpreter()->CollectDataForWatchpointCommandCallback (wp_options,
561ac7ddfbfSEd Maste                                                                                                        result);
562ac7ddfbfSEd Maste                     }
563ac7ddfbfSEd Maste                 }
564ac7ddfbfSEd Maste                 else
565ac7ddfbfSEd Maste                 {
566ac7ddfbfSEd Maste                     // Special handling for one-liner specified inline.
567ac7ddfbfSEd Maste                     if (m_options.m_use_one_liner)
568ac7ddfbfSEd Maste                         SetWatchpointCommandCallback (wp_options,
569ac7ddfbfSEd Maste                                                       m_options.m_one_liner.c_str());
570ac7ddfbfSEd Maste                     else
571ac7ddfbfSEd Maste                         CollectDataForWatchpointCommandCallback (wp_options,
572ac7ddfbfSEd Maste                                                                  result);
573ac7ddfbfSEd Maste                 }
574ac7ddfbfSEd Maste             }
575ac7ddfbfSEd Maste         }
576ac7ddfbfSEd Maste 
577ac7ddfbfSEd Maste         return result.Succeeded();
578ac7ddfbfSEd Maste     }
579ac7ddfbfSEd Maste 
580ac7ddfbfSEd Maste private:
581ac7ddfbfSEd Maste     CommandOptions m_options;
582ac7ddfbfSEd Maste     static const char *g_reader_instructions;
583ac7ddfbfSEd Maste 
584ac7ddfbfSEd Maste };
585ac7ddfbfSEd Maste 
586ac7ddfbfSEd Maste const char *
587ac7ddfbfSEd Maste CommandObjectWatchpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
588ac7ddfbfSEd Maste 
589ac7ddfbfSEd Maste // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
590ac7ddfbfSEd Maste // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
591ac7ddfbfSEd Maste 
592ac7ddfbfSEd Maste static OptionEnumValueElement
593ac7ddfbfSEd Maste g_script_option_enumeration[4] =
594ac7ddfbfSEd Maste {
595ac7ddfbfSEd Maste     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
596ac7ddfbfSEd Maste     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
597ac7ddfbfSEd Maste     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
598ac7ddfbfSEd Maste     { 0,                      NULL,              NULL }
599ac7ddfbfSEd Maste };
600ac7ddfbfSEd Maste 
601ac7ddfbfSEd Maste OptionDefinition
602ac7ddfbfSEd Maste CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
603ac7ddfbfSEd Maste {
604ac7ddfbfSEd Maste     { LLDB_OPT_SET_1,   false, "one-liner",       'o', required_argument, NULL, 0, eArgTypeOneLiner,
605ac7ddfbfSEd Maste         "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
606ac7ddfbfSEd Maste 
607ac7ddfbfSEd Maste     { LLDB_OPT_SET_ALL, false, "stop-on-error",   'e', required_argument, NULL, 0, eArgTypeBoolean,
608ac7ddfbfSEd Maste         "Specify whether watchpoint command execution should terminate on error." },
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste     { LLDB_OPT_SET_ALL, false, "script-type",     's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
611ac7ddfbfSEd Maste         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
612ac7ddfbfSEd Maste 
613ac7ddfbfSEd Maste     { LLDB_OPT_SET_2,   false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction,
614ac7ddfbfSEd Maste         "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate."},
615ac7ddfbfSEd Maste 
616ac7ddfbfSEd Maste     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
617ac7ddfbfSEd Maste };
618ac7ddfbfSEd Maste 
619ac7ddfbfSEd Maste //-------------------------------------------------------------------------
620ac7ddfbfSEd Maste // CommandObjectWatchpointCommandDelete
621ac7ddfbfSEd Maste //-------------------------------------------------------------------------
622ac7ddfbfSEd Maste 
623ac7ddfbfSEd Maste class CommandObjectWatchpointCommandDelete : public CommandObjectParsed
624ac7ddfbfSEd Maste {
625ac7ddfbfSEd Maste public:
626ac7ddfbfSEd Maste     CommandObjectWatchpointCommandDelete (CommandInterpreter &interpreter) :
627ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
628ac7ddfbfSEd Maste                              "delete",
629ac7ddfbfSEd Maste                              "Delete the set of commands from a watchpoint.",
630ac7ddfbfSEd Maste                              NULL)
631ac7ddfbfSEd Maste     {
632ac7ddfbfSEd Maste         CommandArgumentEntry arg;
633ac7ddfbfSEd Maste         CommandArgumentData wp_id_arg;
634ac7ddfbfSEd Maste 
635ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
636ac7ddfbfSEd Maste         wp_id_arg.arg_type = eArgTypeWatchpointID;
637ac7ddfbfSEd Maste         wp_id_arg.arg_repetition = eArgRepeatPlain;
638ac7ddfbfSEd Maste 
639ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
640ac7ddfbfSEd Maste         arg.push_back (wp_id_arg);
641ac7ddfbfSEd Maste 
642ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
643ac7ddfbfSEd Maste         m_arguments.push_back (arg);
644ac7ddfbfSEd Maste     }
645ac7ddfbfSEd Maste 
646ac7ddfbfSEd Maste 
647ac7ddfbfSEd Maste     virtual
648ac7ddfbfSEd Maste     ~CommandObjectWatchpointCommandDelete () {}
649ac7ddfbfSEd Maste 
650ac7ddfbfSEd Maste protected:
651ac7ddfbfSEd Maste     virtual bool
652ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
653ac7ddfbfSEd Maste     {
654ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
655ac7ddfbfSEd Maste 
656ac7ddfbfSEd Maste         if (target == NULL)
657ac7ddfbfSEd Maste         {
658ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no watchpoints from which to delete commands");
659ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
660ac7ddfbfSEd Maste             return false;
661ac7ddfbfSEd Maste         }
662ac7ddfbfSEd Maste 
663ac7ddfbfSEd Maste         const WatchpointList &watchpoints = target->GetWatchpointList();
664ac7ddfbfSEd Maste         size_t num_watchpoints = watchpoints.GetSize();
665ac7ddfbfSEd Maste 
666ac7ddfbfSEd Maste         if (num_watchpoints == 0)
667ac7ddfbfSEd Maste         {
668ac7ddfbfSEd Maste             result.AppendError ("No watchpoints exist to have commands deleted");
669ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
670ac7ddfbfSEd Maste             return false;
671ac7ddfbfSEd Maste         }
672ac7ddfbfSEd Maste 
673ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
674ac7ddfbfSEd Maste         {
675ac7ddfbfSEd Maste             result.AppendError ("No watchpoint specified from which to delete the commands");
676ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
677ac7ddfbfSEd Maste             return false;
678ac7ddfbfSEd Maste         }
679ac7ddfbfSEd Maste 
680ac7ddfbfSEd Maste         std::vector<uint32_t> valid_wp_ids;
681ac7ddfbfSEd Maste         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
682ac7ddfbfSEd Maste         {
683ac7ddfbfSEd Maste             result.AppendError("Invalid watchpoints specification.");
684ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
685ac7ddfbfSEd Maste             return false;
686ac7ddfbfSEd Maste         }
687ac7ddfbfSEd Maste 
688ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
689ac7ddfbfSEd Maste         const size_t count = valid_wp_ids.size();
690ac7ddfbfSEd Maste         for (size_t i = 0; i < count; ++i)
691ac7ddfbfSEd Maste         {
692ac7ddfbfSEd Maste             uint32_t cur_wp_id = valid_wp_ids.at (i);
693ac7ddfbfSEd Maste             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
694ac7ddfbfSEd Maste             {
695ac7ddfbfSEd Maste                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
696ac7ddfbfSEd Maste                 if (wp)
697ac7ddfbfSEd Maste                     wp->ClearCallback();
698ac7ddfbfSEd Maste             }
699ac7ddfbfSEd Maste             else
700ac7ddfbfSEd Maste             {
701ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n",
702ac7ddfbfSEd Maste                                              cur_wp_id);
703ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
704ac7ddfbfSEd Maste                 return false;
705ac7ddfbfSEd Maste             }
706ac7ddfbfSEd Maste         }
707ac7ddfbfSEd Maste         return result.Succeeded();
708ac7ddfbfSEd Maste     }
709ac7ddfbfSEd Maste };
710ac7ddfbfSEd Maste 
711ac7ddfbfSEd Maste //-------------------------------------------------------------------------
712ac7ddfbfSEd Maste // CommandObjectWatchpointCommandList
713ac7ddfbfSEd Maste //-------------------------------------------------------------------------
714ac7ddfbfSEd Maste 
715ac7ddfbfSEd Maste class CommandObjectWatchpointCommandList : public CommandObjectParsed
716ac7ddfbfSEd Maste {
717ac7ddfbfSEd Maste public:
718ac7ddfbfSEd Maste     CommandObjectWatchpointCommandList (CommandInterpreter &interpreter) :
719ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
720ac7ddfbfSEd Maste                              "list",
721ac7ddfbfSEd Maste                              "List the script or set of commands to be executed when the watchpoint is hit.",
722ac7ddfbfSEd Maste                               NULL)
723ac7ddfbfSEd Maste     {
724ac7ddfbfSEd Maste         CommandArgumentEntry arg;
725ac7ddfbfSEd Maste         CommandArgumentData wp_id_arg;
726ac7ddfbfSEd Maste 
727ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
728ac7ddfbfSEd Maste         wp_id_arg.arg_type = eArgTypeWatchpointID;
729ac7ddfbfSEd Maste         wp_id_arg.arg_repetition = eArgRepeatPlain;
730ac7ddfbfSEd Maste 
731ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
732ac7ddfbfSEd Maste         arg.push_back (wp_id_arg);
733ac7ddfbfSEd Maste 
734ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
735ac7ddfbfSEd Maste         m_arguments.push_back (arg);
736ac7ddfbfSEd Maste     }
737ac7ddfbfSEd Maste 
738ac7ddfbfSEd Maste     virtual
739ac7ddfbfSEd Maste     ~CommandObjectWatchpointCommandList () {}
740ac7ddfbfSEd Maste 
741ac7ddfbfSEd Maste protected:
742ac7ddfbfSEd Maste     virtual bool
743ac7ddfbfSEd Maste     DoExecute (Args& command,
744ac7ddfbfSEd Maste              CommandReturnObject &result)
745ac7ddfbfSEd Maste     {
746ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
747ac7ddfbfSEd Maste 
748ac7ddfbfSEd Maste         if (target == NULL)
749ac7ddfbfSEd Maste         {
750ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no watchpoints for which to list commands");
751ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
752ac7ddfbfSEd Maste             return false;
753ac7ddfbfSEd Maste         }
754ac7ddfbfSEd Maste 
755ac7ddfbfSEd Maste         const WatchpointList &watchpoints = target->GetWatchpointList();
756ac7ddfbfSEd Maste         size_t num_watchpoints = watchpoints.GetSize();
757ac7ddfbfSEd Maste 
758ac7ddfbfSEd Maste         if (num_watchpoints == 0)
759ac7ddfbfSEd Maste         {
760ac7ddfbfSEd Maste             result.AppendError ("No watchpoints exist for which to list commands");
761ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
762ac7ddfbfSEd Maste             return false;
763ac7ddfbfSEd Maste         }
764ac7ddfbfSEd Maste 
765ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
766ac7ddfbfSEd Maste         {
767ac7ddfbfSEd Maste             result.AppendError ("No watchpoint specified for which to list the commands");
768ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
769ac7ddfbfSEd Maste             return false;
770ac7ddfbfSEd Maste         }
771ac7ddfbfSEd Maste 
772ac7ddfbfSEd Maste         std::vector<uint32_t> valid_wp_ids;
773ac7ddfbfSEd Maste         if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
774ac7ddfbfSEd Maste         {
775ac7ddfbfSEd Maste             result.AppendError("Invalid watchpoints specification.");
776ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
777ac7ddfbfSEd Maste             return false;
778ac7ddfbfSEd Maste         }
779ac7ddfbfSEd Maste 
780ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
781ac7ddfbfSEd Maste         const size_t count = valid_wp_ids.size();
782ac7ddfbfSEd Maste         for (size_t i = 0; i < count; ++i)
783ac7ddfbfSEd Maste         {
784ac7ddfbfSEd Maste             uint32_t cur_wp_id = valid_wp_ids.at (i);
785ac7ddfbfSEd Maste             if (cur_wp_id != LLDB_INVALID_WATCH_ID)
786ac7ddfbfSEd Maste             {
787ac7ddfbfSEd Maste                 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
788ac7ddfbfSEd Maste 
789ac7ddfbfSEd Maste                 if (wp)
790ac7ddfbfSEd Maste                 {
791ac7ddfbfSEd Maste                     const WatchpointOptions *wp_options = wp->GetOptions();
792ac7ddfbfSEd Maste                     if (wp_options)
793ac7ddfbfSEd Maste                     {
794ac7ddfbfSEd Maste                         // Get the callback baton associated with the current watchpoint.
795ac7ddfbfSEd Maste                         const Baton *baton = wp_options->GetBaton();
796ac7ddfbfSEd Maste                         if (baton)
797ac7ddfbfSEd Maste                         {
798ac7ddfbfSEd Maste                             result.GetOutputStream().Printf ("Watchpoint %u:\n", cur_wp_id);
799ac7ddfbfSEd Maste                             result.GetOutputStream().IndentMore ();
800ac7ddfbfSEd Maste                             baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
801ac7ddfbfSEd Maste                             result.GetOutputStream().IndentLess ();
802ac7ddfbfSEd Maste                         }
803ac7ddfbfSEd Maste                         else
804ac7ddfbfSEd Maste                         {
805ac7ddfbfSEd Maste                             result.AppendMessageWithFormat ("Watchpoint %u does not have an associated command.\n",
806ac7ddfbfSEd Maste                                                             cur_wp_id);
807ac7ddfbfSEd Maste                         }
808ac7ddfbfSEd Maste                     }
809ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
810ac7ddfbfSEd Maste                 }
811ac7ddfbfSEd Maste                 else
812ac7ddfbfSEd Maste                 {
813ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id);
814ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
815ac7ddfbfSEd Maste                 }
816ac7ddfbfSEd Maste             }
817ac7ddfbfSEd Maste         }
818ac7ddfbfSEd Maste 
819ac7ddfbfSEd Maste         return result.Succeeded();
820ac7ddfbfSEd Maste     }
821ac7ddfbfSEd Maste };
822ac7ddfbfSEd Maste 
823ac7ddfbfSEd Maste //-------------------------------------------------------------------------
824ac7ddfbfSEd Maste // CommandObjectWatchpointCommand
825ac7ddfbfSEd Maste //-------------------------------------------------------------------------
826ac7ddfbfSEd Maste 
827ac7ddfbfSEd Maste CommandObjectWatchpointCommand::CommandObjectWatchpointCommand (CommandInterpreter &interpreter) :
828ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
829ac7ddfbfSEd Maste                             "command",
830ac7ddfbfSEd Maste                             "A set of commands for adding, removing and examining bits of code to be executed when the watchpoint is hit (watchpoint 'commmands').",
831ac7ddfbfSEd Maste                             "command <sub-command> [<sub-command-options>] <watchpoint-id>")
832ac7ddfbfSEd Maste {
833ac7ddfbfSEd Maste     CommandObjectSP add_command_object (new CommandObjectWatchpointCommandAdd (interpreter));
834ac7ddfbfSEd Maste     CommandObjectSP delete_command_object (new CommandObjectWatchpointCommandDelete (interpreter));
835ac7ddfbfSEd Maste     CommandObjectSP list_command_object (new CommandObjectWatchpointCommandList (interpreter));
836ac7ddfbfSEd Maste 
837ac7ddfbfSEd Maste     add_command_object->SetCommandName ("watchpoint command add");
838ac7ddfbfSEd Maste     delete_command_object->SetCommandName ("watchpoint command delete");
839ac7ddfbfSEd Maste     list_command_object->SetCommandName ("watchpoint command list");
840ac7ddfbfSEd Maste 
841ac7ddfbfSEd Maste     LoadSubCommand ("add",    add_command_object);
842ac7ddfbfSEd Maste     LoadSubCommand ("delete", delete_command_object);
843ac7ddfbfSEd Maste     LoadSubCommand ("list",   list_command_object);
844ac7ddfbfSEd Maste }
845ac7ddfbfSEd Maste 
846ac7ddfbfSEd Maste CommandObjectWatchpointCommand::~CommandObjectWatchpointCommand ()
847ac7ddfbfSEd Maste {
848ac7ddfbfSEd Maste }
849ac7ddfbfSEd Maste 
850ac7ddfbfSEd Maste 
851