1ac7ddfbfSEd Maste //===-- CommandObjectThread.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 #include "CommandObjectThread.h"
13ac7ddfbfSEd Maste 
14ac7ddfbfSEd Maste // C Includes
15ac7ddfbfSEd Maste // C++ Includes
16ac7ddfbfSEd Maste // Other libraries and framework includes
17ac7ddfbfSEd Maste // Project includes
18ac7ddfbfSEd Maste #include "lldb/lldb-private.h"
19ac7ddfbfSEd Maste #include "lldb/Core/State.h"
20ac7ddfbfSEd Maste #include "lldb/Core/SourceManager.h"
21ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
22ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
23ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h"
25ac7ddfbfSEd Maste #include "lldb/Symbol/CompileUnit.h"
26ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
27ac7ddfbfSEd Maste #include "lldb/Symbol/LineTable.h"
28ac7ddfbfSEd Maste #include "lldb/Symbol/LineEntry.h"
29ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
30ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
33ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h"
34ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
35ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
36ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
37ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInRange.h"
38ac7ddfbfSEd Maste 
39ac7ddfbfSEd Maste 
40ac7ddfbfSEd Maste using namespace lldb;
41ac7ddfbfSEd Maste using namespace lldb_private;
42ac7ddfbfSEd Maste 
43ac7ddfbfSEd Maste 
44ac7ddfbfSEd Maste //-------------------------------------------------------------------------
45ac7ddfbfSEd Maste // CommandObjectThreadBacktrace
46ac7ddfbfSEd Maste //-------------------------------------------------------------------------
47ac7ddfbfSEd Maste 
48ac7ddfbfSEd Maste class CommandObjectThreadBacktrace : public CommandObjectParsed
49ac7ddfbfSEd Maste {
50ac7ddfbfSEd Maste public:
51ac7ddfbfSEd Maste 
52ac7ddfbfSEd Maste     class CommandOptions : public Options
53ac7ddfbfSEd Maste     {
54ac7ddfbfSEd Maste     public:
55ac7ddfbfSEd Maste 
56ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
57ac7ddfbfSEd Maste             Options(interpreter)
58ac7ddfbfSEd Maste         {
59ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
60ac7ddfbfSEd Maste             OptionParsingStarting ();
61ac7ddfbfSEd Maste         }
62ac7ddfbfSEd Maste 
63ac7ddfbfSEd Maste         virtual
64ac7ddfbfSEd Maste         ~CommandOptions ()
65ac7ddfbfSEd Maste         {
66ac7ddfbfSEd Maste         }
67ac7ddfbfSEd Maste 
68ac7ddfbfSEd Maste         virtual Error
69ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
70ac7ddfbfSEd Maste         {
71ac7ddfbfSEd Maste             Error error;
72ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
73ac7ddfbfSEd Maste 
74ac7ddfbfSEd Maste             switch (short_option)
75ac7ddfbfSEd Maste             {
76ac7ddfbfSEd Maste                 case 'c':
77ac7ddfbfSEd Maste                 {
78ac7ddfbfSEd Maste                     bool success;
79ac7ddfbfSEd Maste                     int32_t input_count =  Args::StringToSInt32 (option_arg, -1, 0, &success);
80ac7ddfbfSEd Maste                     if (!success)
81ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
82ac7ddfbfSEd Maste                     if (input_count < -1)
83ac7ddfbfSEd Maste                         m_count = UINT32_MAX;
84ac7ddfbfSEd Maste                     else
85ac7ddfbfSEd Maste                         m_count = input_count;
86ac7ddfbfSEd Maste                 }
87ac7ddfbfSEd Maste                 break;
88ac7ddfbfSEd Maste                 case 's':
89ac7ddfbfSEd Maste                 {
90ac7ddfbfSEd Maste                     bool success;
91ac7ddfbfSEd Maste                     m_start =  Args::StringToUInt32 (option_arg, 0, 0, &success);
92ac7ddfbfSEd Maste                     if (!success)
93ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
94ac7ddfbfSEd Maste                 }
95ac7ddfbfSEd Maste                 break;
96ac7ddfbfSEd Maste                 default:
97ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
98ac7ddfbfSEd Maste                     break;
99ac7ddfbfSEd Maste 
100ac7ddfbfSEd Maste             }
101ac7ddfbfSEd Maste             return error;
102ac7ddfbfSEd Maste         }
103ac7ddfbfSEd Maste 
104ac7ddfbfSEd Maste         void
105ac7ddfbfSEd Maste         OptionParsingStarting ()
106ac7ddfbfSEd Maste         {
107ac7ddfbfSEd Maste             m_count = UINT32_MAX;
108ac7ddfbfSEd Maste             m_start = 0;
109ac7ddfbfSEd Maste         }
110ac7ddfbfSEd Maste 
111ac7ddfbfSEd Maste         const OptionDefinition*
112ac7ddfbfSEd Maste         GetDefinitions ()
113ac7ddfbfSEd Maste         {
114ac7ddfbfSEd Maste             return g_option_table;
115ac7ddfbfSEd Maste         }
116ac7ddfbfSEd Maste 
117ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
118ac7ddfbfSEd Maste 
119ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
120ac7ddfbfSEd Maste 
121ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
122ac7ddfbfSEd Maste         uint32_t m_count;
123ac7ddfbfSEd Maste         uint32_t m_start;
124ac7ddfbfSEd Maste     };
125ac7ddfbfSEd Maste 
126ac7ddfbfSEd Maste     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
127ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
128ac7ddfbfSEd Maste                              "thread backtrace",
129ac7ddfbfSEd Maste                              "Show the stack for one or more threads.  If no threads are specified, show the currently selected thread.  Use the thread-index \"all\" to see all threads.",
130ac7ddfbfSEd Maste                              NULL,
131ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
132ac7ddfbfSEd Maste                              eFlagRequiresThread        |
133ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
134ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
135ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
136ac7ddfbfSEd Maste         m_options(interpreter)
137ac7ddfbfSEd Maste     {
138ac7ddfbfSEd Maste         CommandArgumentEntry arg;
139ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
140ac7ddfbfSEd Maste 
141ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
142ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
143ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatStar;
144ac7ddfbfSEd Maste 
145ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
146ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
147ac7ddfbfSEd Maste 
148ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
149ac7ddfbfSEd Maste         m_arguments.push_back (arg);
150ac7ddfbfSEd Maste     }
151ac7ddfbfSEd Maste 
152ac7ddfbfSEd Maste     ~CommandObjectThreadBacktrace()
153ac7ddfbfSEd Maste     {
154ac7ddfbfSEd Maste     }
155ac7ddfbfSEd Maste 
156ac7ddfbfSEd Maste     virtual Options *
157ac7ddfbfSEd Maste     GetOptions ()
158ac7ddfbfSEd Maste     {
159ac7ddfbfSEd Maste         return &m_options;
160ac7ddfbfSEd Maste     }
161ac7ddfbfSEd Maste 
162ac7ddfbfSEd Maste protected:
163ac7ddfbfSEd Maste     virtual bool
164ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
165ac7ddfbfSEd Maste     {
166ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
167ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
168ac7ddfbfSEd Maste 
169ac7ddfbfSEd Maste         // Don't show source context when doing backtraces.
170ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
171ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
172ac7ddfbfSEd Maste         {
173ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
174ac7ddfbfSEd Maste             // Thread::GetStatus() returns the number of frames shown.
175ac7ddfbfSEd Maste             if (thread->GetStatus (strm,
176ac7ddfbfSEd Maste                                    m_options.m_start,
177ac7ddfbfSEd Maste                                    m_options.m_count,
178ac7ddfbfSEd Maste                                    num_frames_with_source))
179ac7ddfbfSEd Maste             {
180ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
181ac7ddfbfSEd Maste             }
182ac7ddfbfSEd Maste         }
183ac7ddfbfSEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
184ac7ddfbfSEd Maste         {
185ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
186ac7ddfbfSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
187ac7ddfbfSEd Maste             uint32_t num_threads = process->GetThreadList().GetSize();
188ac7ddfbfSEd Maste             for (uint32_t i = 0; i < num_threads; i++)
189ac7ddfbfSEd Maste             {
190ac7ddfbfSEd Maste                 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
191ac7ddfbfSEd Maste                 if (!thread_sp->GetStatus (strm,
192ac7ddfbfSEd Maste                                            m_options.m_start,
193ac7ddfbfSEd Maste                                            m_options.m_count,
194ac7ddfbfSEd Maste                                            num_frames_with_source))
195ac7ddfbfSEd Maste                 {
196ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
197ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
198ac7ddfbfSEd Maste                     return false;
199ac7ddfbfSEd Maste                 }
200ac7ddfbfSEd Maste 
201ac7ddfbfSEd Maste                 if (i < num_threads - 1)
202ac7ddfbfSEd Maste                     result.AppendMessage("");
203ac7ddfbfSEd Maste 
204ac7ddfbfSEd Maste             }
205ac7ddfbfSEd Maste         }
206ac7ddfbfSEd Maste         else
207ac7ddfbfSEd Maste         {
208ac7ddfbfSEd Maste             const size_t num_args = command.GetArgumentCount();
209ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
210ac7ddfbfSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
211ac7ddfbfSEd Maste             std::vector<ThreadSP> thread_sps;
212ac7ddfbfSEd Maste 
213ac7ddfbfSEd Maste             for (size_t i = 0; i < num_args; i++)
214ac7ddfbfSEd Maste             {
215ac7ddfbfSEd Maste                 bool success;
216ac7ddfbfSEd Maste 
217ac7ddfbfSEd Maste                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
218ac7ddfbfSEd Maste                 if (!success)
219ac7ddfbfSEd Maste                 {
220ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
221ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
222ac7ddfbfSEd Maste                     return false;
223ac7ddfbfSEd Maste                 }
224ac7ddfbfSEd Maste 
225ac7ddfbfSEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
226ac7ddfbfSEd Maste 
227ac7ddfbfSEd Maste                 if (!thread_sps[i])
228ac7ddfbfSEd Maste                 {
229ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
230ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
231ac7ddfbfSEd Maste                     return false;
232ac7ddfbfSEd Maste                 }
233ac7ddfbfSEd Maste 
234ac7ddfbfSEd Maste             }
235ac7ddfbfSEd Maste 
236ac7ddfbfSEd Maste             for (uint32_t i = 0; i < num_args; i++)
237ac7ddfbfSEd Maste             {
238ac7ddfbfSEd Maste                 if (!thread_sps[i]->GetStatus (strm,
239ac7ddfbfSEd Maste                                                m_options.m_start,
240ac7ddfbfSEd Maste                                                m_options.m_count,
241ac7ddfbfSEd Maste                                                num_frames_with_source))
242ac7ddfbfSEd Maste                 {
243ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
244ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
245ac7ddfbfSEd Maste                     return false;
246ac7ddfbfSEd Maste                 }
247ac7ddfbfSEd Maste 
248ac7ddfbfSEd Maste                 if (i < num_args - 1)
249ac7ddfbfSEd Maste                     result.AppendMessage("");
250ac7ddfbfSEd Maste             }
251ac7ddfbfSEd Maste         }
252ac7ddfbfSEd Maste         return result.Succeeded();
253ac7ddfbfSEd Maste     }
254ac7ddfbfSEd Maste 
255ac7ddfbfSEd Maste     CommandOptions m_options;
256ac7ddfbfSEd Maste };
257ac7ddfbfSEd Maste 
258ac7ddfbfSEd Maste OptionDefinition
259ac7ddfbfSEd Maste CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
260ac7ddfbfSEd Maste {
261ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
262ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
263ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
264ac7ddfbfSEd Maste };
265ac7ddfbfSEd Maste 
266ac7ddfbfSEd Maste enum StepScope
267ac7ddfbfSEd Maste {
268ac7ddfbfSEd Maste     eStepScopeSource,
269ac7ddfbfSEd Maste     eStepScopeInstruction
270ac7ddfbfSEd Maste };
271ac7ddfbfSEd Maste 
272ac7ddfbfSEd Maste class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
273ac7ddfbfSEd Maste {
274ac7ddfbfSEd Maste public:
275ac7ddfbfSEd Maste 
276ac7ddfbfSEd Maste     class CommandOptions : public Options
277ac7ddfbfSEd Maste     {
278ac7ddfbfSEd Maste     public:
279ac7ddfbfSEd Maste 
280ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
281ac7ddfbfSEd Maste             Options (interpreter)
282ac7ddfbfSEd Maste         {
283ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
284ac7ddfbfSEd Maste             OptionParsingStarting ();
285ac7ddfbfSEd Maste         }
286ac7ddfbfSEd Maste 
287ac7ddfbfSEd Maste         virtual
288ac7ddfbfSEd Maste         ~CommandOptions ()
289ac7ddfbfSEd Maste         {
290ac7ddfbfSEd Maste         }
291ac7ddfbfSEd Maste 
292ac7ddfbfSEd Maste         virtual Error
293ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
294ac7ddfbfSEd Maste         {
295ac7ddfbfSEd Maste             Error error;
296ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
297ac7ddfbfSEd Maste 
298ac7ddfbfSEd Maste             switch (short_option)
299ac7ddfbfSEd Maste             {
300ac7ddfbfSEd Maste             case 'a':
301ac7ddfbfSEd Maste                 {
302ac7ddfbfSEd Maste                     bool success;
303ac7ddfbfSEd Maste                     m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
304ac7ddfbfSEd Maste                     if (!success)
305ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
306ac7ddfbfSEd Maste                 }
307ac7ddfbfSEd Maste                 break;
308ac7ddfbfSEd Maste 
309ac7ddfbfSEd Maste             case 'm':
310ac7ddfbfSEd Maste                 {
311ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
312ac7ddfbfSEd Maste                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
313ac7ddfbfSEd Maste                 }
314ac7ddfbfSEd Maste                 break;
315ac7ddfbfSEd Maste 
316ac7ddfbfSEd Maste             case 'r':
317ac7ddfbfSEd Maste                 {
318ac7ddfbfSEd Maste                     m_avoid_regexp.clear();
319ac7ddfbfSEd Maste                     m_avoid_regexp.assign(option_arg);
320ac7ddfbfSEd Maste                 }
321ac7ddfbfSEd Maste                 break;
322ac7ddfbfSEd Maste 
323ac7ddfbfSEd Maste             case 't':
324ac7ddfbfSEd Maste                 {
325ac7ddfbfSEd Maste                     m_step_in_target.clear();
326ac7ddfbfSEd Maste                     m_step_in_target.assign(option_arg);
327ac7ddfbfSEd Maste 
328ac7ddfbfSEd Maste                 }
329ac7ddfbfSEd Maste                 break;
330ac7ddfbfSEd Maste             default:
331ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
332ac7ddfbfSEd Maste                 break;
333ac7ddfbfSEd Maste 
334ac7ddfbfSEd Maste             }
335ac7ddfbfSEd Maste             return error;
336ac7ddfbfSEd Maste         }
337ac7ddfbfSEd Maste 
338ac7ddfbfSEd Maste         void
339ac7ddfbfSEd Maste         OptionParsingStarting ()
340ac7ddfbfSEd Maste         {
341ac7ddfbfSEd Maste             m_avoid_no_debug = true;
342ac7ddfbfSEd Maste             m_run_mode = eOnlyDuringStepping;
343ac7ddfbfSEd Maste             m_avoid_regexp.clear();
344ac7ddfbfSEd Maste             m_step_in_target.clear();
345ac7ddfbfSEd Maste         }
346ac7ddfbfSEd Maste 
347ac7ddfbfSEd Maste         const OptionDefinition*
348ac7ddfbfSEd Maste         GetDefinitions ()
349ac7ddfbfSEd Maste         {
350ac7ddfbfSEd Maste             return g_option_table;
351ac7ddfbfSEd Maste         }
352ac7ddfbfSEd Maste 
353ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
354ac7ddfbfSEd Maste 
355ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
358ac7ddfbfSEd Maste         bool m_avoid_no_debug;
359ac7ddfbfSEd Maste         RunMode m_run_mode;
360ac7ddfbfSEd Maste         std::string m_avoid_regexp;
361ac7ddfbfSEd Maste         std::string m_step_in_target;
362ac7ddfbfSEd Maste     };
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
365ac7ddfbfSEd Maste                                              const char *name,
366ac7ddfbfSEd Maste                                              const char *help,
367ac7ddfbfSEd Maste                                              const char *syntax,
368ac7ddfbfSEd Maste                                              StepType step_type,
369ac7ddfbfSEd Maste                                              StepScope step_scope) :
370ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax,
371ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
372ac7ddfbfSEd Maste                              eFlagRequiresThread        |
373ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
374ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
375ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
376ac7ddfbfSEd Maste         m_step_type (step_type),
377ac7ddfbfSEd Maste         m_step_scope (step_scope),
378ac7ddfbfSEd Maste         m_options (interpreter)
379ac7ddfbfSEd Maste     {
380ac7ddfbfSEd Maste         CommandArgumentEntry arg;
381ac7ddfbfSEd Maste         CommandArgumentData thread_id_arg;
382ac7ddfbfSEd Maste 
383ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
384ac7ddfbfSEd Maste         thread_id_arg.arg_type = eArgTypeThreadID;
385ac7ddfbfSEd Maste         thread_id_arg.arg_repetition = eArgRepeatOptional;
386ac7ddfbfSEd Maste 
387ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
388ac7ddfbfSEd Maste         arg.push_back (thread_id_arg);
389ac7ddfbfSEd Maste 
390ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
391ac7ddfbfSEd Maste         m_arguments.push_back (arg);
392ac7ddfbfSEd Maste     }
393ac7ddfbfSEd Maste 
394ac7ddfbfSEd Maste     virtual
395ac7ddfbfSEd Maste     ~CommandObjectThreadStepWithTypeAndScope ()
396ac7ddfbfSEd Maste     {
397ac7ddfbfSEd Maste     }
398ac7ddfbfSEd Maste 
399ac7ddfbfSEd Maste     virtual
400ac7ddfbfSEd Maste     Options *
401ac7ddfbfSEd Maste     GetOptions ()
402ac7ddfbfSEd Maste     {
403ac7ddfbfSEd Maste         return &m_options;
404ac7ddfbfSEd Maste     }
405ac7ddfbfSEd Maste 
406ac7ddfbfSEd Maste protected:
407ac7ddfbfSEd Maste     virtual bool
408ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
409ac7ddfbfSEd Maste     {
410ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
411ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous();
412ac7ddfbfSEd Maste 
413ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
414ac7ddfbfSEd Maste         Thread *thread = NULL;
415ac7ddfbfSEd Maste 
416ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
417ac7ddfbfSEd Maste         {
418ac7ddfbfSEd Maste             thread = process->GetThreadList().GetSelectedThread().get();
419ac7ddfbfSEd Maste             if (thread == NULL)
420ac7ddfbfSEd Maste             {
421ac7ddfbfSEd Maste                 result.AppendError ("no selected thread in process");
422ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
423ac7ddfbfSEd Maste                 return false;
424ac7ddfbfSEd Maste             }
425ac7ddfbfSEd Maste         }
426ac7ddfbfSEd Maste         else
427ac7ddfbfSEd Maste         {
428ac7ddfbfSEd Maste             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
429ac7ddfbfSEd Maste             uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
430ac7ddfbfSEd Maste             if (step_thread_idx == LLDB_INVALID_INDEX32)
431ac7ddfbfSEd Maste             {
432ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
433ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
434ac7ddfbfSEd Maste                 return false;
435ac7ddfbfSEd Maste             }
436ac7ddfbfSEd Maste             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
437ac7ddfbfSEd Maste             if (thread == NULL)
438ac7ddfbfSEd Maste             {
439ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
440ac7ddfbfSEd Maste                                               step_thread_idx, num_threads);
441ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
442ac7ddfbfSEd Maste                 return false;
443ac7ddfbfSEd Maste             }
444ac7ddfbfSEd Maste         }
445ac7ddfbfSEd Maste 
446ac7ddfbfSEd Maste         const bool abort_other_plans = false;
447ac7ddfbfSEd Maste         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
448ac7ddfbfSEd Maste 
449ac7ddfbfSEd Maste         // This is a bit unfortunate, but not all the commands in this command object support
450ac7ddfbfSEd Maste         // only while stepping, so I use the bool for them.
451ac7ddfbfSEd Maste         bool bool_stop_other_threads;
452ac7ddfbfSEd Maste         if (m_options.m_run_mode == eAllThreads)
453ac7ddfbfSEd Maste             bool_stop_other_threads = false;
454ac7ddfbfSEd Maste         else if (m_options.m_run_mode == eOnlyDuringStepping)
455ac7ddfbfSEd Maste         {
456ac7ddfbfSEd Maste             if (m_step_type == eStepTypeOut)
457ac7ddfbfSEd Maste                 bool_stop_other_threads = false;
458ac7ddfbfSEd Maste             else
459ac7ddfbfSEd Maste                 bool_stop_other_threads = true;
460ac7ddfbfSEd Maste         }
461ac7ddfbfSEd Maste         else
462ac7ddfbfSEd Maste             bool_stop_other_threads = true;
463ac7ddfbfSEd Maste 
464ac7ddfbfSEd Maste         ThreadPlanSP new_plan_sp;
465ac7ddfbfSEd Maste 
466ac7ddfbfSEd Maste         if (m_step_type == eStepTypeInto)
467ac7ddfbfSEd Maste         {
468ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
469ac7ddfbfSEd Maste 
470ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
471ac7ddfbfSEd Maste             {
472ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
473ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
474ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything),
475ac7ddfbfSEd Maste                                                                 m_options.m_step_in_target.c_str(),
476ac7ddfbfSEd Maste                                                                 stop_other_threads,
477ac7ddfbfSEd Maste                                                                 m_options.m_avoid_no_debug);
478ac7ddfbfSEd Maste                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
479ac7ddfbfSEd Maste                 {
480ac7ddfbfSEd Maste                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
481ac7ddfbfSEd Maste                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
482ac7ddfbfSEd Maste                 }
483ac7ddfbfSEd Maste             }
484ac7ddfbfSEd Maste             else
485ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
486ac7ddfbfSEd Maste 
487ac7ddfbfSEd Maste         }
488ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOver)
489ac7ddfbfSEd Maste         {
490ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
491ac7ddfbfSEd Maste 
492ac7ddfbfSEd Maste             if (frame->HasDebugInformation())
493ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
494ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
495ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything),
496ac7ddfbfSEd Maste                                                                     stop_other_threads);
497ac7ddfbfSEd Maste             else
498ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
499ac7ddfbfSEd Maste                                                                             abort_other_plans,
500ac7ddfbfSEd Maste                                                                             bool_stop_other_threads);
501ac7ddfbfSEd Maste 
502ac7ddfbfSEd Maste         }
503ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTrace)
504ac7ddfbfSEd Maste         {
505ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
506ac7ddfbfSEd Maste         }
507ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTraceOver)
508ac7ddfbfSEd Maste         {
509ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
510ac7ddfbfSEd Maste         }
511ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOut)
512ac7ddfbfSEd Maste         {
513ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
514ac7ddfbfSEd Maste                                                           NULL,
515ac7ddfbfSEd Maste                                                           false,
516ac7ddfbfSEd Maste                                                           bool_stop_other_threads,
517ac7ddfbfSEd Maste                                                           eVoteYes,
518ac7ddfbfSEd Maste                                                           eVoteNoOpinion,
519ac7ddfbfSEd Maste                                                           thread->GetSelectedFrameIndex());
520ac7ddfbfSEd Maste         }
521ac7ddfbfSEd Maste         else
522ac7ddfbfSEd Maste         {
523ac7ddfbfSEd Maste             result.AppendError ("step type is not supported");
524ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
525ac7ddfbfSEd Maste             return false;
526ac7ddfbfSEd Maste         }
527ac7ddfbfSEd Maste 
528ac7ddfbfSEd Maste         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
529ac7ddfbfSEd Maste         // so that they can be interruptible).  Then resume the process.
530ac7ddfbfSEd Maste 
531ac7ddfbfSEd Maste         if (new_plan_sp)
532ac7ddfbfSEd Maste         {
533ac7ddfbfSEd Maste             new_plan_sp->SetIsMasterPlan (true);
534ac7ddfbfSEd Maste             new_plan_sp->SetOkayToDiscard (false);
535ac7ddfbfSEd Maste 
536ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
537ac7ddfbfSEd Maste             process->Resume ();
538ac7ddfbfSEd Maste 
539ac7ddfbfSEd Maste 
540ac7ddfbfSEd Maste             if (synchronous_execution)
541ac7ddfbfSEd Maste             {
542ac7ddfbfSEd Maste                 StateType state = process->WaitForProcessToStop (NULL);
543ac7ddfbfSEd Maste 
544ac7ddfbfSEd Maste                 //EventSP event_sp;
545ac7ddfbfSEd Maste                 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
546ac7ddfbfSEd Maste                 //while (! StateIsStoppedState (state))
547ac7ddfbfSEd Maste                 //  {
548ac7ddfbfSEd Maste                 //    state = process->WaitForStateChangedEvents (NULL, event_sp);
549ac7ddfbfSEd Maste                 //  }
550ac7ddfbfSEd Maste                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
551ac7ddfbfSEd Maste                 result.SetDidChangeProcessState (true);
552ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
553ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
554ac7ddfbfSEd Maste             }
555ac7ddfbfSEd Maste             else
556ac7ddfbfSEd Maste             {
557ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
558ac7ddfbfSEd Maste             }
559ac7ddfbfSEd Maste         }
560ac7ddfbfSEd Maste         else
561ac7ddfbfSEd Maste         {
562ac7ddfbfSEd Maste             result.AppendError ("Couldn't find thread plan to implement step type.");
563ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
564ac7ddfbfSEd Maste         }
565ac7ddfbfSEd Maste         return result.Succeeded();
566ac7ddfbfSEd Maste     }
567ac7ddfbfSEd Maste 
568ac7ddfbfSEd Maste protected:
569ac7ddfbfSEd Maste     StepType m_step_type;
570ac7ddfbfSEd Maste     StepScope m_step_scope;
571ac7ddfbfSEd Maste     CommandOptions m_options;
572ac7ddfbfSEd Maste };
573ac7ddfbfSEd Maste 
574ac7ddfbfSEd Maste static OptionEnumValueElement
575ac7ddfbfSEd Maste g_tri_running_mode[] =
576ac7ddfbfSEd Maste {
577ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
578ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
579ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
580ac7ddfbfSEd Maste { 0, NULL, NULL }
581ac7ddfbfSEd Maste };
582ac7ddfbfSEd Maste 
583ac7ddfbfSEd Maste static OptionEnumValueElement
584ac7ddfbfSEd Maste g_duo_running_mode[] =
585ac7ddfbfSEd Maste {
586ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
587ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
588ac7ddfbfSEd Maste { 0, NULL, NULL }
589ac7ddfbfSEd Maste };
590ac7ddfbfSEd Maste 
591ac7ddfbfSEd Maste OptionDefinition
592ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
593ac7ddfbfSEd Maste {
594ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "avoid-no-debug",  'a', required_argument, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether step-in will step over functions with no debug information."},
595ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "run-mode",        'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
596ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
597ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "step-in-target",  't', required_argument, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
598ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
599ac7ddfbfSEd Maste };
600ac7ddfbfSEd Maste 
601ac7ddfbfSEd Maste 
602ac7ddfbfSEd Maste //-------------------------------------------------------------------------
603ac7ddfbfSEd Maste // CommandObjectThreadContinue
604ac7ddfbfSEd Maste //-------------------------------------------------------------------------
605ac7ddfbfSEd Maste 
606ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed
607ac7ddfbfSEd Maste {
608ac7ddfbfSEd Maste public:
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
611ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
612ac7ddfbfSEd Maste                              "thread continue",
613ac7ddfbfSEd Maste                              "Continue execution of one or more threads in an active process.",
614ac7ddfbfSEd Maste                              NULL,
615ac7ddfbfSEd Maste                              eFlagRequiresThread        |
616ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
617ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
618ac7ddfbfSEd Maste                              eFlagProcessMustBePaused)
619ac7ddfbfSEd Maste     {
620ac7ddfbfSEd Maste         CommandArgumentEntry arg;
621ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
622ac7ddfbfSEd Maste 
623ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
624ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
625ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlus;
626ac7ddfbfSEd Maste 
627ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
628ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
629ac7ddfbfSEd Maste 
630ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
631ac7ddfbfSEd Maste         m_arguments.push_back (arg);
632ac7ddfbfSEd Maste     }
633ac7ddfbfSEd Maste 
634ac7ddfbfSEd Maste 
635ac7ddfbfSEd Maste     virtual
636ac7ddfbfSEd Maste     ~CommandObjectThreadContinue ()
637ac7ddfbfSEd Maste     {
638ac7ddfbfSEd Maste     }
639ac7ddfbfSEd Maste 
640ac7ddfbfSEd Maste     virtual bool
641ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
642ac7ddfbfSEd Maste     {
643ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
644ac7ddfbfSEd Maste 
645ac7ddfbfSEd Maste         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
646ac7ddfbfSEd Maste         {
647ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
648ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
649ac7ddfbfSEd Maste             return false;
650ac7ddfbfSEd Maste         }
651ac7ddfbfSEd Maste 
652ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
653ac7ddfbfSEd Maste         if (process == NULL)
654ac7ddfbfSEd Maste         {
655ac7ddfbfSEd Maste             result.AppendError ("no process exists. Cannot continue");
656ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
657ac7ddfbfSEd Maste             return false;
658ac7ddfbfSEd Maste         }
659ac7ddfbfSEd Maste 
660ac7ddfbfSEd Maste         StateType state = process->GetState();
661ac7ddfbfSEd Maste         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
662ac7ddfbfSEd Maste         {
663ac7ddfbfSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
664ac7ddfbfSEd Maste             const uint32_t num_threads = process->GetThreadList().GetSize();
665ac7ddfbfSEd Maste             const size_t argc = command.GetArgumentCount();
666ac7ddfbfSEd Maste             if (argc > 0)
667ac7ddfbfSEd Maste             {
668ac7ddfbfSEd Maste                 std::vector<Thread *> resume_threads;
669ac7ddfbfSEd Maste                 for (uint32_t i=0; i<argc; ++i)
670ac7ddfbfSEd Maste                 {
671ac7ddfbfSEd Maste                     bool success;
672ac7ddfbfSEd Maste                     const int base = 0;
673ac7ddfbfSEd Maste                     uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
674ac7ddfbfSEd Maste                     if (success)
675ac7ddfbfSEd Maste                     {
676ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
677ac7ddfbfSEd Maste 
678ac7ddfbfSEd Maste                         if (thread)
679ac7ddfbfSEd Maste                         {
680ac7ddfbfSEd Maste                             resume_threads.push_back(thread);
681ac7ddfbfSEd Maste                         }
682ac7ddfbfSEd Maste                         else
683ac7ddfbfSEd Maste                         {
684ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
685ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
686ac7ddfbfSEd Maste                             return false;
687ac7ddfbfSEd Maste                         }
688ac7ddfbfSEd Maste                     }
689ac7ddfbfSEd Maste                     else
690ac7ddfbfSEd Maste                     {
691ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
692ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
693ac7ddfbfSEd Maste                         return false;
694ac7ddfbfSEd Maste                     }
695ac7ddfbfSEd Maste                 }
696ac7ddfbfSEd Maste 
697ac7ddfbfSEd Maste                 if (resume_threads.empty())
698ac7ddfbfSEd Maste                 {
699ac7ddfbfSEd Maste                     result.AppendError ("no valid thread indexes were specified");
700ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
701ac7ddfbfSEd Maste                     return false;
702ac7ddfbfSEd Maste                 }
703ac7ddfbfSEd Maste                 else
704ac7ddfbfSEd Maste                 {
705ac7ddfbfSEd Maste                     if (resume_threads.size() == 1)
706ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread: ");
707ac7ddfbfSEd Maste                     else
708ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming threads: ");
709ac7ddfbfSEd Maste 
710ac7ddfbfSEd Maste                     for (uint32_t idx=0; idx<num_threads; ++idx)
711ac7ddfbfSEd Maste                     {
712ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
713ac7ddfbfSEd Maste                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
714ac7ddfbfSEd Maste 
715ac7ddfbfSEd Maste                         if (this_thread_pos != resume_threads.end())
716ac7ddfbfSEd Maste                         {
717ac7ddfbfSEd Maste                             resume_threads.erase(this_thread_pos);
718ac7ddfbfSEd Maste                             if (resume_threads.size() > 0)
719ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
720ac7ddfbfSEd Maste                             else
721ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
722ac7ddfbfSEd Maste 
723ac7ddfbfSEd Maste                             thread->SetResumeState (eStateRunning);
724ac7ddfbfSEd Maste                         }
725ac7ddfbfSEd Maste                         else
726ac7ddfbfSEd Maste                         {
727ac7ddfbfSEd Maste                             thread->SetResumeState (eStateSuspended);
728ac7ddfbfSEd Maste                         }
729ac7ddfbfSEd Maste                     }
730ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
731ac7ddfbfSEd Maste                 }
732ac7ddfbfSEd Maste             }
733ac7ddfbfSEd Maste             else
734ac7ddfbfSEd Maste             {
735ac7ddfbfSEd Maste                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
736ac7ddfbfSEd Maste                 if (current_thread == NULL)
737ac7ddfbfSEd Maste                 {
738ac7ddfbfSEd Maste                     result.AppendError ("the process doesn't have a current thread");
739ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
740ac7ddfbfSEd Maste                     return false;
741ac7ddfbfSEd Maste                 }
742ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
743ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
744ac7ddfbfSEd Maste                 {
745ac7ddfbfSEd Maste                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
746ac7ddfbfSEd Maste                     if (thread == current_thread)
747ac7ddfbfSEd Maste                     {
748ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
749ac7ddfbfSEd Maste                         thread->SetResumeState (eStateRunning);
750ac7ddfbfSEd Maste                     }
751ac7ddfbfSEd Maste                     else
752ac7ddfbfSEd Maste                     {
753ac7ddfbfSEd Maste                         thread->SetResumeState (eStateSuspended);
754ac7ddfbfSEd Maste                     }
755ac7ddfbfSEd Maste                 }
756ac7ddfbfSEd Maste             }
757ac7ddfbfSEd Maste 
758ac7ddfbfSEd Maste             Error error (process->Resume());
759ac7ddfbfSEd Maste             if (error.Success())
760ac7ddfbfSEd Maste             {
761ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
762ac7ddfbfSEd Maste                 if (synchronous_execution)
763ac7ddfbfSEd Maste                 {
764ac7ddfbfSEd Maste                     state = process->WaitForProcessToStop (NULL);
765ac7ddfbfSEd Maste 
766ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
767ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
768ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
769ac7ddfbfSEd Maste                 }
770ac7ddfbfSEd Maste                 else
771ac7ddfbfSEd Maste                 {
772ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
773ac7ddfbfSEd Maste                 }
774ac7ddfbfSEd Maste             }
775ac7ddfbfSEd Maste             else
776ac7ddfbfSEd Maste             {
777ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
778ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
779ac7ddfbfSEd Maste             }
780ac7ddfbfSEd Maste         }
781ac7ddfbfSEd Maste         else
782ac7ddfbfSEd Maste         {
783ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
784ac7ddfbfSEd Maste                                           StateAsCString(state));
785ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
786ac7ddfbfSEd Maste         }
787ac7ddfbfSEd Maste 
788ac7ddfbfSEd Maste         return result.Succeeded();
789ac7ddfbfSEd Maste     }
790ac7ddfbfSEd Maste 
791ac7ddfbfSEd Maste };
792ac7ddfbfSEd Maste 
793ac7ddfbfSEd Maste //-------------------------------------------------------------------------
794ac7ddfbfSEd Maste // CommandObjectThreadUntil
795ac7ddfbfSEd Maste //-------------------------------------------------------------------------
796ac7ddfbfSEd Maste 
797ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed
798ac7ddfbfSEd Maste {
799ac7ddfbfSEd Maste public:
800ac7ddfbfSEd Maste 
801ac7ddfbfSEd Maste     class CommandOptions : public Options
802ac7ddfbfSEd Maste     {
803ac7ddfbfSEd Maste     public:
804ac7ddfbfSEd Maste         uint32_t m_thread_idx;
805ac7ddfbfSEd Maste         uint32_t m_frame_idx;
806ac7ddfbfSEd Maste 
807ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
808ac7ddfbfSEd Maste             Options (interpreter),
809ac7ddfbfSEd Maste             m_thread_idx(LLDB_INVALID_THREAD_ID),
810ac7ddfbfSEd Maste             m_frame_idx(LLDB_INVALID_FRAME_ID)
811ac7ddfbfSEd Maste         {
812ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
813ac7ddfbfSEd Maste             OptionParsingStarting ();
814ac7ddfbfSEd Maste         }
815ac7ddfbfSEd Maste 
816ac7ddfbfSEd Maste         virtual
817ac7ddfbfSEd Maste         ~CommandOptions ()
818ac7ddfbfSEd Maste         {
819ac7ddfbfSEd Maste         }
820ac7ddfbfSEd Maste 
821ac7ddfbfSEd Maste         virtual Error
822ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
823ac7ddfbfSEd Maste         {
824ac7ddfbfSEd Maste             Error error;
825ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
826ac7ddfbfSEd Maste 
827ac7ddfbfSEd Maste             switch (short_option)
828ac7ddfbfSEd Maste             {
829ac7ddfbfSEd Maste                 case 't':
830ac7ddfbfSEd Maste                 {
831ac7ddfbfSEd Maste                     m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
832ac7ddfbfSEd Maste                     if (m_thread_idx == LLDB_INVALID_INDEX32)
833ac7ddfbfSEd Maste                     {
834ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
835ac7ddfbfSEd Maste                     }
836ac7ddfbfSEd Maste                 }
837ac7ddfbfSEd Maste                 break;
838ac7ddfbfSEd Maste                 case 'f':
839ac7ddfbfSEd Maste                 {
840ac7ddfbfSEd Maste                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
841ac7ddfbfSEd Maste                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
842ac7ddfbfSEd Maste                     {
843ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
844ac7ddfbfSEd Maste                     }
845ac7ddfbfSEd Maste                 }
846ac7ddfbfSEd Maste                 break;
847ac7ddfbfSEd Maste                 case 'm':
848ac7ddfbfSEd Maste                 {
849ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
850ac7ddfbfSEd Maste                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
851ac7ddfbfSEd Maste 
852ac7ddfbfSEd Maste                     if (error.Success())
853ac7ddfbfSEd Maste                     {
854ac7ddfbfSEd Maste                         if (run_mode == eAllThreads)
855ac7ddfbfSEd Maste                             m_stop_others = false;
856ac7ddfbfSEd Maste                         else
857ac7ddfbfSEd Maste                             m_stop_others = true;
858ac7ddfbfSEd Maste                     }
859ac7ddfbfSEd Maste                 }
860ac7ddfbfSEd Maste                 break;
861ac7ddfbfSEd Maste                 default:
862ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
863ac7ddfbfSEd Maste                     break;
864ac7ddfbfSEd Maste 
865ac7ddfbfSEd Maste             }
866ac7ddfbfSEd Maste             return error;
867ac7ddfbfSEd Maste         }
868ac7ddfbfSEd Maste 
869ac7ddfbfSEd Maste         void
870ac7ddfbfSEd Maste         OptionParsingStarting ()
871ac7ddfbfSEd Maste         {
872ac7ddfbfSEd Maste             m_thread_idx = LLDB_INVALID_THREAD_ID;
873ac7ddfbfSEd Maste             m_frame_idx = 0;
874ac7ddfbfSEd Maste             m_stop_others = false;
875ac7ddfbfSEd Maste         }
876ac7ddfbfSEd Maste 
877ac7ddfbfSEd Maste         const OptionDefinition*
878ac7ddfbfSEd Maste         GetDefinitions ()
879ac7ddfbfSEd Maste         {
880ac7ddfbfSEd Maste             return g_option_table;
881ac7ddfbfSEd Maste         }
882ac7ddfbfSEd Maste 
883ac7ddfbfSEd Maste         uint32_t m_step_thread_idx;
884ac7ddfbfSEd Maste         bool m_stop_others;
885ac7ddfbfSEd Maste 
886ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
887ac7ddfbfSEd Maste 
888ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
889ac7ddfbfSEd Maste 
890ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
891ac7ddfbfSEd Maste     };
892ac7ddfbfSEd Maste 
893ac7ddfbfSEd Maste     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
894ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
895ac7ddfbfSEd Maste                              "thread until",
896ac7ddfbfSEd Maste                              "Run the current or specified thread until it reaches a given line number or leaves the current function.",
897ac7ddfbfSEd Maste                              NULL,
898ac7ddfbfSEd Maste                              eFlagRequiresThread        |
899ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
900ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
901ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
902ac7ddfbfSEd Maste         m_options (interpreter)
903ac7ddfbfSEd Maste     {
904ac7ddfbfSEd Maste         CommandArgumentEntry arg;
905ac7ddfbfSEd Maste         CommandArgumentData line_num_arg;
906ac7ddfbfSEd Maste 
907ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
908ac7ddfbfSEd Maste         line_num_arg.arg_type = eArgTypeLineNum;
909ac7ddfbfSEd Maste         line_num_arg.arg_repetition = eArgRepeatPlain;
910ac7ddfbfSEd Maste 
911ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
912ac7ddfbfSEd Maste         arg.push_back (line_num_arg);
913ac7ddfbfSEd Maste 
914ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
915ac7ddfbfSEd Maste         m_arguments.push_back (arg);
916ac7ddfbfSEd Maste     }
917ac7ddfbfSEd Maste 
918ac7ddfbfSEd Maste 
919ac7ddfbfSEd Maste     virtual
920ac7ddfbfSEd Maste     ~CommandObjectThreadUntil ()
921ac7ddfbfSEd Maste     {
922ac7ddfbfSEd Maste     }
923ac7ddfbfSEd Maste 
924ac7ddfbfSEd Maste     virtual
925ac7ddfbfSEd Maste     Options *
926ac7ddfbfSEd Maste     GetOptions ()
927ac7ddfbfSEd Maste     {
928ac7ddfbfSEd Maste         return &m_options;
929ac7ddfbfSEd Maste     }
930ac7ddfbfSEd Maste 
931ac7ddfbfSEd Maste protected:
932ac7ddfbfSEd Maste     virtual bool
933ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
934ac7ddfbfSEd Maste     {
935ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
936ac7ddfbfSEd Maste 
937ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
938ac7ddfbfSEd Maste         if (target == NULL)
939ac7ddfbfSEd Maste         {
940ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
941ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
942ac7ddfbfSEd Maste             return false;
943ac7ddfbfSEd Maste         }
944ac7ddfbfSEd Maste 
945ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
946ac7ddfbfSEd Maste         if (process == NULL)
947ac7ddfbfSEd Maste         {
948ac7ddfbfSEd Maste             result.AppendError ("need a valid process to step");
949ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
950ac7ddfbfSEd Maste 
951ac7ddfbfSEd Maste         }
952ac7ddfbfSEd Maste         else
953ac7ddfbfSEd Maste         {
954ac7ddfbfSEd Maste             Thread *thread = NULL;
955ac7ddfbfSEd Maste             uint32_t line_number;
956ac7ddfbfSEd Maste 
957ac7ddfbfSEd Maste             if (command.GetArgumentCount() != 1)
958ac7ddfbfSEd Maste             {
959ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
960ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
961ac7ddfbfSEd Maste                 return false;
962ac7ddfbfSEd Maste             }
963ac7ddfbfSEd Maste 
964ac7ddfbfSEd Maste             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
965ac7ddfbfSEd Maste             if (line_number == UINT32_MAX)
966ac7ddfbfSEd Maste             {
967ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
968ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
969ac7ddfbfSEd Maste                 return false;
970ac7ddfbfSEd Maste             }
971ac7ddfbfSEd Maste 
972ac7ddfbfSEd Maste             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
973ac7ddfbfSEd Maste             {
974ac7ddfbfSEd Maste                 thread = process->GetThreadList().GetSelectedThread().get();
975ac7ddfbfSEd Maste             }
976ac7ddfbfSEd Maste             else
977ac7ddfbfSEd Maste             {
978ac7ddfbfSEd Maste                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
979ac7ddfbfSEd Maste             }
980ac7ddfbfSEd Maste 
981ac7ddfbfSEd Maste             if (thread == NULL)
982ac7ddfbfSEd Maste             {
983ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
984ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
985ac7ddfbfSEd Maste                                               m_options.m_thread_idx,
986ac7ddfbfSEd Maste                                               num_threads);
987ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
988ac7ddfbfSEd Maste                 return false;
989ac7ddfbfSEd Maste             }
990ac7ddfbfSEd Maste 
991ac7ddfbfSEd Maste             const bool abort_other_plans = false;
992ac7ddfbfSEd Maste 
993ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
994ac7ddfbfSEd Maste             if (frame == NULL)
995ac7ddfbfSEd Maste             {
996ac7ddfbfSEd Maste 
997ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
998ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
999ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1000ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1001ac7ddfbfSEd Maste                 return false;
1002ac7ddfbfSEd Maste             }
1003ac7ddfbfSEd Maste 
1004ac7ddfbfSEd Maste             ThreadPlanSP new_plan_sp;
1005ac7ddfbfSEd Maste 
1006ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
1007ac7ddfbfSEd Maste             {
1008ac7ddfbfSEd Maste                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1009ac7ddfbfSEd Maste                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1010ac7ddfbfSEd Maste                 LineTable *line_table = NULL;
1011ac7ddfbfSEd Maste                 if (sc.comp_unit)
1012ac7ddfbfSEd Maste                     line_table = sc.comp_unit->GetLineTable();
1013ac7ddfbfSEd Maste 
1014ac7ddfbfSEd Maste                 if (line_table == NULL)
1015ac7ddfbfSEd Maste                 {
1016ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1017ac7ddfbfSEd Maste                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1018ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1019ac7ddfbfSEd Maste                     return false;
1020ac7ddfbfSEd Maste                 }
1021ac7ddfbfSEd Maste 
1022ac7ddfbfSEd Maste                 LineEntry function_start;
1023ac7ddfbfSEd Maste                 uint32_t index_ptr = 0, end_ptr;
1024ac7ddfbfSEd Maste                 std::vector<addr_t> address_list;
1025ac7ddfbfSEd Maste 
1026ac7ddfbfSEd Maste                 // Find the beginning & end index of the
1027ac7ddfbfSEd Maste                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1028ac7ddfbfSEd Maste                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1029ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1030ac7ddfbfSEd Maste 
1031ac7ddfbfSEd Maste                 Address fun_end_addr(fun_start_addr.GetSection(),
1032ac7ddfbfSEd Maste                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1033ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1034ac7ddfbfSEd Maste 
1035ac7ddfbfSEd Maste                 bool all_in_function = true;
1036ac7ddfbfSEd Maste 
1037ac7ddfbfSEd Maste                 while (index_ptr <= end_ptr)
1038ac7ddfbfSEd Maste                 {
1039ac7ddfbfSEd Maste                     LineEntry line_entry;
1040ac7ddfbfSEd Maste                     const bool exact = false;
1041ac7ddfbfSEd Maste                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
1042ac7ddfbfSEd Maste                     if (index_ptr == UINT32_MAX)
1043ac7ddfbfSEd Maste                         break;
1044ac7ddfbfSEd Maste 
1045ac7ddfbfSEd Maste                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1046ac7ddfbfSEd Maste                     if (address != LLDB_INVALID_ADDRESS)
1047ac7ddfbfSEd Maste                     {
1048ac7ddfbfSEd Maste                         if (fun_addr_range.ContainsLoadAddress (address, target))
1049ac7ddfbfSEd Maste                             address_list.push_back (address);
1050ac7ddfbfSEd Maste                         else
1051ac7ddfbfSEd Maste                             all_in_function = false;
1052ac7ddfbfSEd Maste                     }
1053ac7ddfbfSEd Maste                     index_ptr++;
1054ac7ddfbfSEd Maste                 }
1055ac7ddfbfSEd Maste 
1056ac7ddfbfSEd Maste                 if (address_list.size() == 0)
1057ac7ddfbfSEd Maste                 {
1058ac7ddfbfSEd Maste                     if (all_in_function)
1059ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1060ac7ddfbfSEd Maste                     else
1061ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1062ac7ddfbfSEd Maste 
1063ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1064ac7ddfbfSEd Maste                     return false;
1065ac7ddfbfSEd Maste                 }
1066ac7ddfbfSEd Maste 
1067ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1068ac7ddfbfSEd Maste                                                                 &address_list.front(),
1069ac7ddfbfSEd Maste                                                                 address_list.size(),
1070ac7ddfbfSEd Maste                                                                 m_options.m_stop_others,
1071ac7ddfbfSEd Maste                                                                 m_options.m_frame_idx);
1072ac7ddfbfSEd Maste                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1073ac7ddfbfSEd Maste                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1074ac7ddfbfSEd Maste                 // will resume the original plan.
1075ac7ddfbfSEd Maste                 new_plan_sp->SetIsMasterPlan (true);
1076ac7ddfbfSEd Maste                 new_plan_sp->SetOkayToDiscard(false);
1077ac7ddfbfSEd Maste             }
1078ac7ddfbfSEd Maste             else
1079ac7ddfbfSEd Maste             {
1080ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1081ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1082ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1083ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1084ac7ddfbfSEd Maste                 return false;
1085ac7ddfbfSEd Maste 
1086ac7ddfbfSEd Maste             }
1087ac7ddfbfSEd Maste 
1088ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
1089ac7ddfbfSEd Maste             Error error (process->Resume ());
1090ac7ddfbfSEd Maste             if (error.Success())
1091ac7ddfbfSEd Maste             {
1092ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1093ac7ddfbfSEd Maste                 if (synchronous_execution)
1094ac7ddfbfSEd Maste                 {
1095ac7ddfbfSEd Maste                     StateType state = process->WaitForProcessToStop (NULL);
1096ac7ddfbfSEd Maste 
1097ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
1098ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
1099ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1100ac7ddfbfSEd Maste                 }
1101ac7ddfbfSEd Maste                 else
1102ac7ddfbfSEd Maste                 {
1103ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1104ac7ddfbfSEd Maste                 }
1105ac7ddfbfSEd Maste             }
1106ac7ddfbfSEd Maste             else
1107ac7ddfbfSEd Maste             {
1108ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1109ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1110ac7ddfbfSEd Maste             }
1111ac7ddfbfSEd Maste 
1112ac7ddfbfSEd Maste         }
1113ac7ddfbfSEd Maste         return result.Succeeded();
1114ac7ddfbfSEd Maste     }
1115ac7ddfbfSEd Maste 
1116ac7ddfbfSEd Maste     CommandOptions m_options;
1117ac7ddfbfSEd Maste 
1118ac7ddfbfSEd Maste };
1119ac7ddfbfSEd Maste 
1120ac7ddfbfSEd Maste OptionDefinition
1121ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1122ac7ddfbfSEd Maste {
1123ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "frame",   'f', required_argument, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
1124ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "thread",  't', required_argument, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
1125ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
1126ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1127ac7ddfbfSEd Maste };
1128ac7ddfbfSEd Maste 
1129ac7ddfbfSEd Maste 
1130ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1131ac7ddfbfSEd Maste // CommandObjectThreadSelect
1132ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1133ac7ddfbfSEd Maste 
1134ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed
1135ac7ddfbfSEd Maste {
1136ac7ddfbfSEd Maste public:
1137ac7ddfbfSEd Maste 
1138ac7ddfbfSEd Maste     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1139ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1140ac7ddfbfSEd Maste                              "thread select",
1141ac7ddfbfSEd Maste                              "Select a thread as the currently active thread.",
1142ac7ddfbfSEd Maste                              NULL,
1143ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1144ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1145ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1146ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1147ac7ddfbfSEd Maste     {
1148ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1149ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
1150ac7ddfbfSEd Maste 
1151ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1152ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1153ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1154ac7ddfbfSEd Maste 
1155ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1156ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
1157ac7ddfbfSEd Maste 
1158ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1159ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1160ac7ddfbfSEd Maste     }
1161ac7ddfbfSEd Maste 
1162ac7ddfbfSEd Maste 
1163ac7ddfbfSEd Maste     virtual
1164ac7ddfbfSEd Maste     ~CommandObjectThreadSelect ()
1165ac7ddfbfSEd Maste     {
1166ac7ddfbfSEd Maste     }
1167ac7ddfbfSEd Maste 
1168ac7ddfbfSEd Maste protected:
1169ac7ddfbfSEd Maste     virtual bool
1170ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1171ac7ddfbfSEd Maste     {
1172ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1173ac7ddfbfSEd Maste         if (process == NULL)
1174ac7ddfbfSEd Maste         {
1175ac7ddfbfSEd Maste             result.AppendError ("no process");
1176ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1177ac7ddfbfSEd Maste             return false;
1178ac7ddfbfSEd Maste         }
1179ac7ddfbfSEd Maste         else if (command.GetArgumentCount() != 1)
1180ac7ddfbfSEd Maste         {
1181ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1182ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1183ac7ddfbfSEd Maste             return false;
1184ac7ddfbfSEd Maste         }
1185ac7ddfbfSEd Maste 
1186ac7ddfbfSEd Maste         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1187ac7ddfbfSEd Maste 
1188ac7ddfbfSEd Maste         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1189ac7ddfbfSEd Maste         if (new_thread == NULL)
1190ac7ddfbfSEd Maste         {
1191ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1192ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1193ac7ddfbfSEd Maste             return false;
1194ac7ddfbfSEd Maste         }
1195ac7ddfbfSEd Maste 
1196ac7ddfbfSEd Maste         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1197ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1198ac7ddfbfSEd Maste 
1199ac7ddfbfSEd Maste         return result.Succeeded();
1200ac7ddfbfSEd Maste     }
1201ac7ddfbfSEd Maste 
1202ac7ddfbfSEd Maste };
1203ac7ddfbfSEd Maste 
1204ac7ddfbfSEd Maste 
1205ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1206ac7ddfbfSEd Maste // CommandObjectThreadList
1207ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1208ac7ddfbfSEd Maste 
1209ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed
1210ac7ddfbfSEd Maste {
1211ac7ddfbfSEd Maste public:
1212ac7ddfbfSEd Maste 
1213ac7ddfbfSEd Maste 
1214ac7ddfbfSEd Maste     CommandObjectThreadList (CommandInterpreter &interpreter):
1215ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1216ac7ddfbfSEd Maste                              "thread list",
1217ac7ddfbfSEd Maste                              "Show a summary of all current threads in a process.",
1218ac7ddfbfSEd Maste                              "thread list",
1219ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1220ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1221ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1222ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1223ac7ddfbfSEd Maste     {
1224ac7ddfbfSEd Maste     }
1225ac7ddfbfSEd Maste 
1226ac7ddfbfSEd Maste     ~CommandObjectThreadList()
1227ac7ddfbfSEd Maste     {
1228ac7ddfbfSEd Maste     }
1229ac7ddfbfSEd Maste 
1230ac7ddfbfSEd Maste protected:
1231ac7ddfbfSEd Maste     bool
1232ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1233ac7ddfbfSEd Maste     {
1234ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1235ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1236ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1237ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = false;
1238ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1239ac7ddfbfSEd Maste         const uint32_t num_frames = 0;
1240ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
1241ac7ddfbfSEd Maste         process->GetStatus(strm);
1242ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1243ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1244ac7ddfbfSEd Maste                                   start_frame,
1245ac7ddfbfSEd Maste                                   num_frames,
1246ac7ddfbfSEd Maste                                   num_frames_with_source);
1247ac7ddfbfSEd Maste         return result.Succeeded();
1248ac7ddfbfSEd Maste     }
1249ac7ddfbfSEd Maste };
1250ac7ddfbfSEd Maste 
1251ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1252ac7ddfbfSEd Maste // CommandObjectThreadReturn
1253ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1254ac7ddfbfSEd Maste 
1255ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw
1256ac7ddfbfSEd Maste {
1257ac7ddfbfSEd Maste public:
1258ac7ddfbfSEd Maste     class CommandOptions : public Options
1259ac7ddfbfSEd Maste     {
1260ac7ddfbfSEd Maste     public:
1261ac7ddfbfSEd Maste 
1262ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1263ac7ddfbfSEd Maste             Options (interpreter),
1264ac7ddfbfSEd Maste             m_from_expression (false)
1265ac7ddfbfSEd Maste         {
1266ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1267ac7ddfbfSEd Maste             OptionParsingStarting ();
1268ac7ddfbfSEd Maste         }
1269ac7ddfbfSEd Maste 
1270ac7ddfbfSEd Maste         virtual
1271ac7ddfbfSEd Maste         ~CommandOptions ()
1272ac7ddfbfSEd Maste         {
1273ac7ddfbfSEd Maste         }
1274ac7ddfbfSEd Maste 
1275ac7ddfbfSEd Maste         virtual Error
1276ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1277ac7ddfbfSEd Maste         {
1278ac7ddfbfSEd Maste             Error error;
1279ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1280ac7ddfbfSEd Maste 
1281ac7ddfbfSEd Maste             switch (short_option)
1282ac7ddfbfSEd Maste             {
1283ac7ddfbfSEd Maste                 case 'x':
1284ac7ddfbfSEd Maste                 {
1285ac7ddfbfSEd Maste                     bool success;
1286ac7ddfbfSEd Maste                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1287ac7ddfbfSEd Maste                     if (success)
1288ac7ddfbfSEd Maste                         m_from_expression = tmp_value;
1289ac7ddfbfSEd Maste                     else
1290ac7ddfbfSEd Maste                     {
1291ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1292ac7ddfbfSEd Maste                     }
1293ac7ddfbfSEd Maste                 }
1294ac7ddfbfSEd Maste                 break;
1295ac7ddfbfSEd Maste                 default:
1296ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1297ac7ddfbfSEd Maste                     break;
1298ac7ddfbfSEd Maste 
1299ac7ddfbfSEd Maste             }
1300ac7ddfbfSEd Maste             return error;
1301ac7ddfbfSEd Maste         }
1302ac7ddfbfSEd Maste 
1303ac7ddfbfSEd Maste         void
1304ac7ddfbfSEd Maste         OptionParsingStarting ()
1305ac7ddfbfSEd Maste         {
1306ac7ddfbfSEd Maste             m_from_expression = false;
1307ac7ddfbfSEd Maste         }
1308ac7ddfbfSEd Maste 
1309ac7ddfbfSEd Maste         const OptionDefinition*
1310ac7ddfbfSEd Maste         GetDefinitions ()
1311ac7ddfbfSEd Maste         {
1312ac7ddfbfSEd Maste             return g_option_table;
1313ac7ddfbfSEd Maste         }
1314ac7ddfbfSEd Maste 
1315ac7ddfbfSEd Maste         bool m_from_expression;
1316ac7ddfbfSEd Maste 
1317ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1318ac7ddfbfSEd Maste 
1319ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1320ac7ddfbfSEd Maste 
1321ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1322ac7ddfbfSEd Maste     };
1323ac7ddfbfSEd Maste 
1324ac7ddfbfSEd Maste     virtual
1325ac7ddfbfSEd Maste     Options *
1326ac7ddfbfSEd Maste     GetOptions ()
1327ac7ddfbfSEd Maste     {
1328ac7ddfbfSEd Maste         return &m_options;
1329ac7ddfbfSEd Maste     }
1330ac7ddfbfSEd Maste 
1331ac7ddfbfSEd Maste     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1332ac7ddfbfSEd Maste         CommandObjectRaw (interpreter,
1333ac7ddfbfSEd Maste                           "thread return",
1334ac7ddfbfSEd Maste                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1335ac7ddfbfSEd Maste                           " or with the -x option from the innermost function evaluation.",
1336ac7ddfbfSEd Maste                           "thread return",
1337ac7ddfbfSEd Maste                           eFlagRequiresFrame         |
1338ac7ddfbfSEd Maste                           eFlagTryTargetAPILock      |
1339ac7ddfbfSEd Maste                           eFlagProcessMustBeLaunched |
1340ac7ddfbfSEd Maste                           eFlagProcessMustBePaused   ),
1341ac7ddfbfSEd Maste         m_options (interpreter)
1342ac7ddfbfSEd Maste     {
1343ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1344ac7ddfbfSEd Maste         CommandArgumentData expression_arg;
1345ac7ddfbfSEd Maste 
1346ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1347ac7ddfbfSEd Maste         expression_arg.arg_type = eArgTypeExpression;
1348ac7ddfbfSEd Maste         expression_arg.arg_repetition = eArgRepeatOptional;
1349ac7ddfbfSEd Maste 
1350ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1351ac7ddfbfSEd Maste         arg.push_back (expression_arg);
1352ac7ddfbfSEd Maste 
1353ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1354ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1355ac7ddfbfSEd Maste 
1356ac7ddfbfSEd Maste 
1357ac7ddfbfSEd Maste     }
1358ac7ddfbfSEd Maste 
1359ac7ddfbfSEd Maste     ~CommandObjectThreadReturn()
1360ac7ddfbfSEd Maste     {
1361ac7ddfbfSEd Maste     }
1362ac7ddfbfSEd Maste 
1363ac7ddfbfSEd Maste protected:
1364ac7ddfbfSEd Maste 
1365ac7ddfbfSEd Maste     bool DoExecute
1366ac7ddfbfSEd Maste     (
1367ac7ddfbfSEd Maste         const char *command,
1368ac7ddfbfSEd Maste         CommandReturnObject &result
1369ac7ddfbfSEd Maste     )
1370ac7ddfbfSEd Maste     {
1371ac7ddfbfSEd Maste         // I am going to handle this by hand, because I don't want you to have to say:
1372ac7ddfbfSEd Maste         // "thread return -- -5".
1373ac7ddfbfSEd Maste         if (command[0] == '-' && command[1] == 'x')
1374ac7ddfbfSEd Maste         {
1375ac7ddfbfSEd Maste             if (command && command[2] != '\0')
1376ac7ddfbfSEd Maste                 result.AppendWarning("Return values ignored when returning from user called expressions");
1377ac7ddfbfSEd Maste 
1378ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
1379ac7ddfbfSEd Maste             Error error;
1380ac7ddfbfSEd Maste             error = thread->UnwindInnermostExpression();
1381ac7ddfbfSEd Maste             if (!error.Success())
1382ac7ddfbfSEd Maste             {
1383ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1384ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1385ac7ddfbfSEd Maste             }
1386ac7ddfbfSEd Maste             else
1387ac7ddfbfSEd Maste             {
1388ac7ddfbfSEd Maste                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1389ac7ddfbfSEd Maste                 if (success)
1390ac7ddfbfSEd Maste                 {
1391ac7ddfbfSEd Maste                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1392ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1393ac7ddfbfSEd Maste                 }
1394ac7ddfbfSEd Maste                 else
1395ac7ddfbfSEd Maste                 {
1396ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1397ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1398ac7ddfbfSEd Maste                 }
1399ac7ddfbfSEd Maste             }
1400ac7ddfbfSEd Maste             return result.Succeeded();
1401ac7ddfbfSEd Maste         }
1402ac7ddfbfSEd Maste 
1403ac7ddfbfSEd Maste         ValueObjectSP return_valobj_sp;
1404ac7ddfbfSEd Maste 
1405ac7ddfbfSEd Maste         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1406ac7ddfbfSEd Maste         uint32_t frame_idx = frame_sp->GetFrameIndex();
1407ac7ddfbfSEd Maste 
1408ac7ddfbfSEd Maste         if (frame_sp->IsInlined())
1409ac7ddfbfSEd Maste         {
1410ac7ddfbfSEd Maste             result.AppendError("Don't know how to return from inlined frames.");
1411ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1412ac7ddfbfSEd Maste             return false;
1413ac7ddfbfSEd Maste         }
1414ac7ddfbfSEd Maste 
1415ac7ddfbfSEd Maste         if (command && command[0] != '\0')
1416ac7ddfbfSEd Maste         {
1417ac7ddfbfSEd Maste             Target *target = m_exe_ctx.GetTargetPtr();
1418ac7ddfbfSEd Maste             EvaluateExpressionOptions options;
1419ac7ddfbfSEd Maste 
1420ac7ddfbfSEd Maste             options.SetUnwindOnError(true);
1421ac7ddfbfSEd Maste             options.SetUseDynamic(eNoDynamicValues);
1422ac7ddfbfSEd Maste 
1423ac7ddfbfSEd Maste             ExecutionResults exe_results = eExecutionSetupError;
1424ac7ddfbfSEd Maste             exe_results = target->EvaluateExpression (command,
1425ac7ddfbfSEd Maste                                                       frame_sp.get(),
1426ac7ddfbfSEd Maste                                                       return_valobj_sp,
1427ac7ddfbfSEd Maste                                                       options);
1428ac7ddfbfSEd Maste             if (exe_results != eExecutionCompleted)
1429ac7ddfbfSEd Maste             {
1430ac7ddfbfSEd Maste                 if (return_valobj_sp)
1431ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1432ac7ddfbfSEd Maste                 else
1433ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1434ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1435ac7ddfbfSEd Maste                 return false;
1436ac7ddfbfSEd Maste 
1437ac7ddfbfSEd Maste             }
1438ac7ddfbfSEd Maste         }
1439ac7ddfbfSEd Maste 
1440ac7ddfbfSEd Maste         Error error;
1441ac7ddfbfSEd Maste         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1442ac7ddfbfSEd Maste         const bool broadcast = true;
1443ac7ddfbfSEd Maste         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1444ac7ddfbfSEd Maste         if (!error.Success())
1445ac7ddfbfSEd Maste         {
1446ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1447ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1448ac7ddfbfSEd Maste             return false;
1449ac7ddfbfSEd Maste         }
1450ac7ddfbfSEd Maste 
1451ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
1452ac7ddfbfSEd Maste         return true;
1453ac7ddfbfSEd Maste     }
1454ac7ddfbfSEd Maste 
1455ac7ddfbfSEd Maste     CommandOptions m_options;
1456ac7ddfbfSEd Maste 
1457ac7ddfbfSEd Maste };
1458ac7ddfbfSEd Maste OptionDefinition
1459ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1460ac7ddfbfSEd Maste {
1461ac7ddfbfSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression",  'x', no_argument, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
1462ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1463ac7ddfbfSEd Maste };
1464ac7ddfbfSEd Maste 
1465ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1466ac7ddfbfSEd Maste // CommandObjectMultiwordThread
1467ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1468ac7ddfbfSEd Maste 
1469ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
1470ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
1471ac7ddfbfSEd Maste                             "thread",
1472ac7ddfbfSEd Maste                             "A set of commands for operating on one or more threads within a running process.",
1473ac7ddfbfSEd Maste                             "thread <subcommand> [<subcommand-options>]")
1474ac7ddfbfSEd Maste {
1475ac7ddfbfSEd Maste     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1476ac7ddfbfSEd Maste     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1477ac7ddfbfSEd Maste     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
1478ac7ddfbfSEd Maste     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
1479ac7ddfbfSEd Maste     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1480ac7ddfbfSEd Maste     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1481ac7ddfbfSEd Maste     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1482ac7ddfbfSEd Maste                                                     interpreter,
1483ac7ddfbfSEd Maste                                                     "thread step-in",
1484ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified).",
1485ac7ddfbfSEd Maste                                                     NULL,
1486ac7ddfbfSEd Maste                                                     eStepTypeInto,
1487ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1488ac7ddfbfSEd Maste 
1489ac7ddfbfSEd Maste     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1490ac7ddfbfSEd Maste                                                     interpreter,
1491ac7ddfbfSEd Maste                                                     "thread step-out",
1492ac7ddfbfSEd Maste                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
1493ac7ddfbfSEd Maste                                                     NULL,
1494ac7ddfbfSEd Maste                                                     eStepTypeOut,
1495ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1496ac7ddfbfSEd Maste 
1497ac7ddfbfSEd Maste     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1498ac7ddfbfSEd Maste                                                     interpreter,
1499ac7ddfbfSEd Maste                                                     "thread step-over",
1500ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
1501ac7ddfbfSEd Maste                                                     NULL,
1502ac7ddfbfSEd Maste                                                     eStepTypeOver,
1503ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1504ac7ddfbfSEd Maste 
1505ac7ddfbfSEd Maste     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1506ac7ddfbfSEd Maste                                                     interpreter,
1507ac7ddfbfSEd Maste                                                     "thread step-inst",
1508ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified).",
1509ac7ddfbfSEd Maste                                                     NULL,
1510ac7ddfbfSEd Maste                                                     eStepTypeTrace,
1511ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
1512ac7ddfbfSEd Maste 
1513ac7ddfbfSEd Maste     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1514ac7ddfbfSEd Maste                                                     interpreter,
1515ac7ddfbfSEd Maste                                                     "thread step-inst-over",
1516ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1517ac7ddfbfSEd Maste                                                     NULL,
1518ac7ddfbfSEd Maste                                                     eStepTypeTraceOver,
1519ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
1520ac7ddfbfSEd Maste }
1521ac7ddfbfSEd Maste 
1522ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1523ac7ddfbfSEd Maste {
1524ac7ddfbfSEd Maste }
1525ac7ddfbfSEd Maste 
1526ac7ddfbfSEd Maste 
1527