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