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