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"
31b952cd58SEd Maste #include "lldb/Target/SystemRuntime.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
33ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
34ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h"
35ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
36ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
37ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
38ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInRange.h"
39ac7ddfbfSEd Maste 
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste using namespace lldb;
42ac7ddfbfSEd Maste using namespace lldb_private;
43ac7ddfbfSEd Maste 
44ac7ddfbfSEd Maste 
45ac7ddfbfSEd Maste //-------------------------------------------------------------------------
46ac7ddfbfSEd Maste // CommandObjectThreadBacktrace
47ac7ddfbfSEd Maste //-------------------------------------------------------------------------
48ac7ddfbfSEd Maste 
49ac7ddfbfSEd Maste class CommandObjectThreadBacktrace : public CommandObjectParsed
50ac7ddfbfSEd Maste {
51ac7ddfbfSEd Maste public:
52ac7ddfbfSEd Maste 
53ac7ddfbfSEd Maste     class CommandOptions : public Options
54ac7ddfbfSEd Maste     {
55ac7ddfbfSEd Maste     public:
56ac7ddfbfSEd Maste 
57ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
58ac7ddfbfSEd Maste             Options(interpreter)
59ac7ddfbfSEd Maste         {
60ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
61ac7ddfbfSEd Maste             OptionParsingStarting ();
62ac7ddfbfSEd Maste         }
63ac7ddfbfSEd Maste 
64ac7ddfbfSEd Maste         virtual
65ac7ddfbfSEd Maste         ~CommandOptions ()
66ac7ddfbfSEd Maste         {
67ac7ddfbfSEd Maste         }
68ac7ddfbfSEd Maste 
69ac7ddfbfSEd Maste         virtual Error
70ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
71ac7ddfbfSEd Maste         {
72ac7ddfbfSEd Maste             Error error;
73ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
74ac7ddfbfSEd Maste 
75ac7ddfbfSEd Maste             switch (short_option)
76ac7ddfbfSEd Maste             {
77ac7ddfbfSEd Maste                 case 'c':
78ac7ddfbfSEd Maste                 {
79ac7ddfbfSEd Maste                     bool success;
80ac7ddfbfSEd Maste                     int32_t input_count =  Args::StringToSInt32 (option_arg, -1, 0, &success);
81ac7ddfbfSEd Maste                     if (!success)
82ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
83ac7ddfbfSEd Maste                     if (input_count < -1)
84ac7ddfbfSEd Maste                         m_count = UINT32_MAX;
85ac7ddfbfSEd Maste                     else
86ac7ddfbfSEd Maste                         m_count = input_count;
87ac7ddfbfSEd Maste                 }
88ac7ddfbfSEd Maste                 break;
89ac7ddfbfSEd Maste                 case 's':
90ac7ddfbfSEd Maste                 {
91ac7ddfbfSEd Maste                     bool success;
92ac7ddfbfSEd Maste                     m_start =  Args::StringToUInt32 (option_arg, 0, 0, &success);
93ac7ddfbfSEd Maste                     if (!success)
94ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
95ac7ddfbfSEd Maste                 }
96b952cd58SEd Maste                 case 'e':
97b952cd58SEd Maste                 {
98b952cd58SEd Maste                     bool success;
99b952cd58SEd Maste                     m_extended_backtrace =  Args::StringToBoolean (option_arg, false, &success);
100b952cd58SEd Maste                     if (!success)
101b952cd58SEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
102b952cd58SEd Maste                 }
103ac7ddfbfSEd Maste                 break;
104ac7ddfbfSEd Maste                 default:
105ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
106ac7ddfbfSEd Maste                     break;
107ac7ddfbfSEd Maste 
108ac7ddfbfSEd Maste             }
109ac7ddfbfSEd Maste             return error;
110ac7ddfbfSEd Maste         }
111ac7ddfbfSEd Maste 
112ac7ddfbfSEd Maste         void
113ac7ddfbfSEd Maste         OptionParsingStarting ()
114ac7ddfbfSEd Maste         {
115ac7ddfbfSEd Maste             m_count = UINT32_MAX;
116ac7ddfbfSEd Maste             m_start = 0;
117b952cd58SEd Maste             m_extended_backtrace = false;
118ac7ddfbfSEd Maste         }
119ac7ddfbfSEd Maste 
120ac7ddfbfSEd Maste         const OptionDefinition*
121ac7ddfbfSEd Maste         GetDefinitions ()
122ac7ddfbfSEd Maste         {
123ac7ddfbfSEd Maste             return g_option_table;
124ac7ddfbfSEd Maste         }
125ac7ddfbfSEd Maste 
126ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
127ac7ddfbfSEd Maste 
128ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
129ac7ddfbfSEd Maste 
130ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
131ac7ddfbfSEd Maste         uint32_t m_count;
132ac7ddfbfSEd Maste         uint32_t m_start;
133b952cd58SEd Maste         bool     m_extended_backtrace;
134ac7ddfbfSEd Maste     };
135ac7ddfbfSEd Maste 
136ac7ddfbfSEd Maste     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
137ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
138ac7ddfbfSEd Maste                              "thread backtrace",
139ac7ddfbfSEd 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.",
140ac7ddfbfSEd Maste                              NULL,
141ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
142ac7ddfbfSEd Maste                              eFlagRequiresThread        |
143ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
144ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
145ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
146ac7ddfbfSEd Maste         m_options(interpreter)
147ac7ddfbfSEd Maste     {
148ac7ddfbfSEd Maste         CommandArgumentEntry arg;
149ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
150ac7ddfbfSEd Maste 
151ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
152ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
153ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatStar;
154ac7ddfbfSEd Maste 
155ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
156ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
157ac7ddfbfSEd Maste 
158ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
159ac7ddfbfSEd Maste         m_arguments.push_back (arg);
160ac7ddfbfSEd Maste     }
161ac7ddfbfSEd Maste 
162ac7ddfbfSEd Maste     ~CommandObjectThreadBacktrace()
163ac7ddfbfSEd Maste     {
164ac7ddfbfSEd Maste     }
165ac7ddfbfSEd Maste 
166ac7ddfbfSEd Maste     virtual Options *
167ac7ddfbfSEd Maste     GetOptions ()
168ac7ddfbfSEd Maste     {
169ac7ddfbfSEd Maste         return &m_options;
170ac7ddfbfSEd Maste     }
171ac7ddfbfSEd Maste 
172ac7ddfbfSEd Maste protected:
173b952cd58SEd Maste     void
174b952cd58SEd Maste     DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
175b952cd58SEd Maste     {
176b952cd58SEd Maste         SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
177b952cd58SEd Maste         if (runtime)
178b952cd58SEd Maste         {
179b952cd58SEd Maste             Stream &strm = result.GetOutputStream();
180b952cd58SEd Maste             const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
181b952cd58SEd Maste             for (auto type : types)
182b952cd58SEd Maste             {
183b952cd58SEd Maste                 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
184b952cd58SEd Maste                 if (ext_thread_sp && ext_thread_sp->IsValid ())
185b952cd58SEd Maste                 {
186b952cd58SEd Maste                     const uint32_t num_frames_with_source = 0;
187b952cd58SEd Maste                     if (ext_thread_sp->GetStatus (strm,
188b952cd58SEd Maste                         m_options.m_start,
189b952cd58SEd Maste                         m_options.m_count,
190b952cd58SEd Maste                         num_frames_with_source))
191b952cd58SEd Maste                     {
192b952cd58SEd Maste                         DoExtendedBacktrace (ext_thread_sp.get(), result);
193b952cd58SEd Maste                     }
194b952cd58SEd Maste                 }
195b952cd58SEd Maste             }
196b952cd58SEd Maste         }
197b952cd58SEd Maste     }
198b952cd58SEd Maste 
199ac7ddfbfSEd Maste     virtual bool
200ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
201ac7ddfbfSEd Maste     {
202ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
203ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
204ac7ddfbfSEd Maste 
205ac7ddfbfSEd Maste         // Don't show source context when doing backtraces.
206ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
207ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
208ac7ddfbfSEd Maste         {
209ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
210ac7ddfbfSEd Maste             // Thread::GetStatus() returns the number of frames shown.
211ac7ddfbfSEd Maste             if (thread->GetStatus (strm,
212ac7ddfbfSEd Maste                                    m_options.m_start,
213ac7ddfbfSEd Maste                                    m_options.m_count,
214ac7ddfbfSEd Maste                                    num_frames_with_source))
215ac7ddfbfSEd Maste             {
216ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
217b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
218b952cd58SEd Maste                 {
219b952cd58SEd Maste                     DoExtendedBacktrace (thread, result);
220b952cd58SEd Maste                 }
221ac7ddfbfSEd Maste             }
222ac7ddfbfSEd Maste         }
223ac7ddfbfSEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
224ac7ddfbfSEd Maste         {
225ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
226b952cd58SEd Maste             uint32_t idx = 0;
227b952cd58SEd Maste             for (ThreadSP thread_sp : process->Threads())
228ac7ddfbfSEd Maste             {
229b952cd58SEd Maste                 if (idx != 0)
230b952cd58SEd Maste                     result.AppendMessage("");
231b952cd58SEd Maste 
232ac7ddfbfSEd Maste                 if (!thread_sp->GetStatus (strm,
233ac7ddfbfSEd Maste                                            m_options.m_start,
234ac7ddfbfSEd Maste                                            m_options.m_count,
235ac7ddfbfSEd Maste                                            num_frames_with_source))
236ac7ddfbfSEd Maste                 {
237b952cd58SEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
238ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
239ac7ddfbfSEd Maste                     return false;
240ac7ddfbfSEd Maste                 }
241b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
242b952cd58SEd Maste                 {
243b952cd58SEd Maste                     DoExtendedBacktrace (thread_sp.get(), result);
244b952cd58SEd Maste                 }
245ac7ddfbfSEd Maste 
246b952cd58SEd Maste                 ++idx;
247ac7ddfbfSEd Maste             }
248ac7ddfbfSEd Maste         }
249ac7ddfbfSEd Maste         else
250ac7ddfbfSEd Maste         {
251ac7ddfbfSEd Maste             const size_t num_args = command.GetArgumentCount();
252ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
253ac7ddfbfSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
254ac7ddfbfSEd Maste             std::vector<ThreadSP> thread_sps;
255ac7ddfbfSEd Maste 
256ac7ddfbfSEd Maste             for (size_t i = 0; i < num_args; i++)
257ac7ddfbfSEd Maste             {
258ac7ddfbfSEd Maste                 bool success;
259ac7ddfbfSEd Maste 
260ac7ddfbfSEd Maste                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
261ac7ddfbfSEd Maste                 if (!success)
262ac7ddfbfSEd Maste                 {
263ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
264ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
265ac7ddfbfSEd Maste                     return false;
266ac7ddfbfSEd Maste                 }
267ac7ddfbfSEd Maste 
268ac7ddfbfSEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
269ac7ddfbfSEd Maste 
270ac7ddfbfSEd Maste                 if (!thread_sps[i])
271ac7ddfbfSEd Maste                 {
272ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
273ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
274ac7ddfbfSEd Maste                     return false;
275ac7ddfbfSEd Maste                 }
276ac7ddfbfSEd Maste 
277ac7ddfbfSEd Maste             }
278ac7ddfbfSEd Maste 
279ac7ddfbfSEd Maste             for (uint32_t i = 0; i < num_args; i++)
280ac7ddfbfSEd Maste             {
281ac7ddfbfSEd Maste                 if (!thread_sps[i]->GetStatus (strm,
282ac7ddfbfSEd Maste                                                m_options.m_start,
283ac7ddfbfSEd Maste                                                m_options.m_count,
284ac7ddfbfSEd Maste                                                num_frames_with_source))
285ac7ddfbfSEd Maste                 {
286ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
287ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
288ac7ddfbfSEd Maste                     return false;
289ac7ddfbfSEd Maste                 }
290b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
291b952cd58SEd Maste                 {
292b952cd58SEd Maste                     DoExtendedBacktrace (thread_sps[i].get(), result);
293b952cd58SEd Maste                 }
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste                 if (i < num_args - 1)
296ac7ddfbfSEd Maste                     result.AppendMessage("");
297ac7ddfbfSEd Maste             }
298ac7ddfbfSEd Maste         }
299ac7ddfbfSEd Maste         return result.Succeeded();
300ac7ddfbfSEd Maste     }
301ac7ddfbfSEd Maste 
302ac7ddfbfSEd Maste     CommandOptions m_options;
303ac7ddfbfSEd Maste };
304ac7ddfbfSEd Maste 
305ac7ddfbfSEd Maste OptionDefinition
306ac7ddfbfSEd Maste CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
307ac7ddfbfSEd Maste {
3080127ef0fSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
3090127ef0fSEd Maste { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
3100127ef0fSEd Maste { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
3110127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
312ac7ddfbfSEd Maste };
313ac7ddfbfSEd Maste 
314ac7ddfbfSEd Maste enum StepScope
315ac7ddfbfSEd Maste {
316ac7ddfbfSEd Maste     eStepScopeSource,
317ac7ddfbfSEd Maste     eStepScopeInstruction
318ac7ddfbfSEd Maste };
319ac7ddfbfSEd Maste 
320ac7ddfbfSEd Maste class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
321ac7ddfbfSEd Maste {
322ac7ddfbfSEd Maste public:
323ac7ddfbfSEd Maste 
324ac7ddfbfSEd Maste     class CommandOptions : public Options
325ac7ddfbfSEd Maste     {
326ac7ddfbfSEd Maste     public:
327ac7ddfbfSEd Maste 
328ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
329ac7ddfbfSEd Maste             Options (interpreter)
330ac7ddfbfSEd Maste         {
331ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
332ac7ddfbfSEd Maste             OptionParsingStarting ();
333ac7ddfbfSEd Maste         }
334ac7ddfbfSEd Maste 
335ac7ddfbfSEd Maste         virtual
336ac7ddfbfSEd Maste         ~CommandOptions ()
337ac7ddfbfSEd Maste         {
338ac7ddfbfSEd Maste         }
339ac7ddfbfSEd Maste 
340ac7ddfbfSEd Maste         virtual Error
341ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
342ac7ddfbfSEd Maste         {
343ac7ddfbfSEd Maste             Error error;
344ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
345ac7ddfbfSEd Maste 
346ac7ddfbfSEd Maste             switch (short_option)
347ac7ddfbfSEd Maste             {
348ac7ddfbfSEd Maste             case 'a':
349ac7ddfbfSEd Maste                 {
350ac7ddfbfSEd Maste                     bool success;
3510127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
352ac7ddfbfSEd Maste                     if (!success)
353ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3540127ef0fSEd Maste                     else
3550127ef0fSEd Maste                     {
3560127ef0fSEd Maste                         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3570127ef0fSEd Maste                     }
358ac7ddfbfSEd Maste                 }
359ac7ddfbfSEd Maste                 break;
360ac7ddfbfSEd Maste 
3610127ef0fSEd Maste             case 'A':
3620127ef0fSEd Maste                 {
3630127ef0fSEd Maste                     bool success;
3640127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
3650127ef0fSEd Maste                     if (!success)
3660127ef0fSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3670127ef0fSEd Maste                     else
3680127ef0fSEd Maste                     {
3690127ef0fSEd Maste                         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3700127ef0fSEd Maste                     }
3710127ef0fSEd Maste                 }
3720127ef0fSEd Maste                 break;
3730127ef0fSEd Maste 
3740127ef0fSEd Maste             case 'c':
3750127ef0fSEd Maste                 {
3760127ef0fSEd Maste                     m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
3770127ef0fSEd Maste                     if (m_step_count == UINT32_MAX)
3780127ef0fSEd Maste                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
3790127ef0fSEd Maste                     break;
3800127ef0fSEd Maste                 }
3810127ef0fSEd Maste                 break;
382ac7ddfbfSEd Maste             case 'm':
383ac7ddfbfSEd Maste                 {
384ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
385ac7ddfbfSEd Maste                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
386ac7ddfbfSEd Maste                 }
387ac7ddfbfSEd Maste                 break;
388ac7ddfbfSEd Maste 
389ac7ddfbfSEd Maste             case 'r':
390ac7ddfbfSEd Maste                 {
391ac7ddfbfSEd Maste                     m_avoid_regexp.clear();
392ac7ddfbfSEd Maste                     m_avoid_regexp.assign(option_arg);
393ac7ddfbfSEd Maste                 }
394ac7ddfbfSEd Maste                 break;
395ac7ddfbfSEd Maste 
396ac7ddfbfSEd Maste             case 't':
397ac7ddfbfSEd Maste                 {
398ac7ddfbfSEd Maste                     m_step_in_target.clear();
399ac7ddfbfSEd Maste                     m_step_in_target.assign(option_arg);
400ac7ddfbfSEd Maste 
401ac7ddfbfSEd Maste                 }
402ac7ddfbfSEd Maste                 break;
403ac7ddfbfSEd Maste             default:
404ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
405ac7ddfbfSEd Maste                 break;
406ac7ddfbfSEd Maste 
407ac7ddfbfSEd Maste             }
408ac7ddfbfSEd Maste             return error;
409ac7ddfbfSEd Maste         }
410ac7ddfbfSEd Maste 
411ac7ddfbfSEd Maste         void
412ac7ddfbfSEd Maste         OptionParsingStarting ()
413ac7ddfbfSEd Maste         {
4140127ef0fSEd Maste             m_step_in_avoid_no_debug = eLazyBoolCalculate;
4150127ef0fSEd Maste             m_step_out_avoid_no_debug = eLazyBoolCalculate;
416ac7ddfbfSEd Maste             m_run_mode = eOnlyDuringStepping;
417ac7ddfbfSEd Maste             m_avoid_regexp.clear();
418ac7ddfbfSEd Maste             m_step_in_target.clear();
4190127ef0fSEd Maste             m_step_count = 1;
420ac7ddfbfSEd Maste         }
421ac7ddfbfSEd Maste 
422ac7ddfbfSEd Maste         const OptionDefinition*
423ac7ddfbfSEd Maste         GetDefinitions ()
424ac7ddfbfSEd Maste         {
425ac7ddfbfSEd Maste             return g_option_table;
426ac7ddfbfSEd Maste         }
427ac7ddfbfSEd Maste 
428ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
429ac7ddfbfSEd Maste 
430ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
431ac7ddfbfSEd Maste 
432ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
4330127ef0fSEd Maste         LazyBool m_step_in_avoid_no_debug;
4340127ef0fSEd Maste         LazyBool m_step_out_avoid_no_debug;
435ac7ddfbfSEd Maste         RunMode m_run_mode;
436ac7ddfbfSEd Maste         std::string m_avoid_regexp;
437ac7ddfbfSEd Maste         std::string m_step_in_target;
4380127ef0fSEd Maste         int32_t m_step_count;
439ac7ddfbfSEd Maste     };
440ac7ddfbfSEd Maste 
441ac7ddfbfSEd Maste     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
442ac7ddfbfSEd Maste                                              const char *name,
443ac7ddfbfSEd Maste                                              const char *help,
444ac7ddfbfSEd Maste                                              const char *syntax,
445ac7ddfbfSEd Maste                                              StepType step_type,
446ac7ddfbfSEd Maste                                              StepScope step_scope) :
447ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax,
448ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
449ac7ddfbfSEd Maste                              eFlagRequiresThread        |
450ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
451ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
452ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
453ac7ddfbfSEd Maste         m_step_type (step_type),
454ac7ddfbfSEd Maste         m_step_scope (step_scope),
455ac7ddfbfSEd Maste         m_options (interpreter)
456ac7ddfbfSEd Maste     {
457ac7ddfbfSEd Maste         CommandArgumentEntry arg;
458ac7ddfbfSEd Maste         CommandArgumentData thread_id_arg;
459ac7ddfbfSEd Maste 
460ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
461ac7ddfbfSEd Maste         thread_id_arg.arg_type = eArgTypeThreadID;
462ac7ddfbfSEd Maste         thread_id_arg.arg_repetition = eArgRepeatOptional;
463ac7ddfbfSEd Maste 
464ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
465ac7ddfbfSEd Maste         arg.push_back (thread_id_arg);
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
468ac7ddfbfSEd Maste         m_arguments.push_back (arg);
469ac7ddfbfSEd Maste     }
470ac7ddfbfSEd Maste 
471ac7ddfbfSEd Maste     virtual
472ac7ddfbfSEd Maste     ~CommandObjectThreadStepWithTypeAndScope ()
473ac7ddfbfSEd Maste     {
474ac7ddfbfSEd Maste     }
475ac7ddfbfSEd Maste 
476ac7ddfbfSEd Maste     virtual
477ac7ddfbfSEd Maste     Options *
478ac7ddfbfSEd Maste     GetOptions ()
479ac7ddfbfSEd Maste     {
480ac7ddfbfSEd Maste         return &m_options;
481ac7ddfbfSEd Maste     }
482ac7ddfbfSEd Maste 
483ac7ddfbfSEd Maste protected:
484ac7ddfbfSEd Maste     virtual bool
485ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
486ac7ddfbfSEd Maste     {
487ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
488ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous();
489ac7ddfbfSEd Maste 
490ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
491ac7ddfbfSEd Maste         Thread *thread = NULL;
492ac7ddfbfSEd Maste 
493ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
494ac7ddfbfSEd Maste         {
495ac7ddfbfSEd Maste             thread = process->GetThreadList().GetSelectedThread().get();
496ac7ddfbfSEd Maste             if (thread == NULL)
497ac7ddfbfSEd Maste             {
498ac7ddfbfSEd Maste                 result.AppendError ("no selected thread in process");
499ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
500ac7ddfbfSEd Maste                 return false;
501ac7ddfbfSEd Maste             }
502ac7ddfbfSEd Maste         }
503ac7ddfbfSEd Maste         else
504ac7ddfbfSEd Maste         {
505ac7ddfbfSEd Maste             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
506ac7ddfbfSEd Maste             uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
507ac7ddfbfSEd Maste             if (step_thread_idx == LLDB_INVALID_INDEX32)
508ac7ddfbfSEd Maste             {
509ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
510ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
511ac7ddfbfSEd Maste                 return false;
512ac7ddfbfSEd Maste             }
513ac7ddfbfSEd Maste             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
514ac7ddfbfSEd Maste             if (thread == NULL)
515ac7ddfbfSEd Maste             {
516ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
517ac7ddfbfSEd Maste                                               step_thread_idx, num_threads);
518ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
519ac7ddfbfSEd Maste                 return false;
520ac7ddfbfSEd Maste             }
521ac7ddfbfSEd Maste         }
522ac7ddfbfSEd Maste 
523ac7ddfbfSEd Maste         const bool abort_other_plans = false;
524ac7ddfbfSEd Maste         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
525ac7ddfbfSEd Maste 
526ac7ddfbfSEd Maste         // This is a bit unfortunate, but not all the commands in this command object support
527ac7ddfbfSEd Maste         // only while stepping, so I use the bool for them.
528ac7ddfbfSEd Maste         bool bool_stop_other_threads;
529ac7ddfbfSEd Maste         if (m_options.m_run_mode == eAllThreads)
530ac7ddfbfSEd Maste             bool_stop_other_threads = false;
531ac7ddfbfSEd Maste         else if (m_options.m_run_mode == eOnlyDuringStepping)
532ac7ddfbfSEd Maste         {
533ac7ddfbfSEd Maste             if (m_step_type == eStepTypeOut)
534ac7ddfbfSEd Maste                 bool_stop_other_threads = false;
535ac7ddfbfSEd Maste             else
536ac7ddfbfSEd Maste                 bool_stop_other_threads = true;
537ac7ddfbfSEd Maste         }
538ac7ddfbfSEd Maste         else
539ac7ddfbfSEd Maste             bool_stop_other_threads = true;
540ac7ddfbfSEd Maste 
541ac7ddfbfSEd Maste         ThreadPlanSP new_plan_sp;
542ac7ddfbfSEd Maste 
543ac7ddfbfSEd Maste         if (m_step_type == eStepTypeInto)
544ac7ddfbfSEd Maste         {
545ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
546ac7ddfbfSEd Maste 
547ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
548ac7ddfbfSEd Maste             {
549ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
550ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
551ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything),
552ac7ddfbfSEd Maste                                                                 m_options.m_step_in_target.c_str(),
553ac7ddfbfSEd Maste                                                                 stop_other_threads,
5540127ef0fSEd Maste                                                                 m_options.m_step_in_avoid_no_debug,
5550127ef0fSEd Maste                                                                 m_options.m_step_out_avoid_no_debug);
5560127ef0fSEd Maste 
557ac7ddfbfSEd Maste                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
558ac7ddfbfSEd Maste                 {
559ac7ddfbfSEd Maste                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
560ac7ddfbfSEd Maste                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
561ac7ddfbfSEd Maste                 }
562ac7ddfbfSEd Maste             }
563ac7ddfbfSEd Maste             else
564ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
565ac7ddfbfSEd Maste 
566ac7ddfbfSEd Maste         }
567ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOver)
568ac7ddfbfSEd Maste         {
569ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
570ac7ddfbfSEd Maste 
571ac7ddfbfSEd Maste             if (frame->HasDebugInformation())
572ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
573ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
574ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything),
5750127ef0fSEd Maste                                                                     stop_other_threads,
5760127ef0fSEd Maste                                                                     m_options.m_step_out_avoid_no_debug);
577ac7ddfbfSEd Maste             else
578ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
579ac7ddfbfSEd Maste                                                                             abort_other_plans,
580ac7ddfbfSEd Maste                                                                             bool_stop_other_threads);
581ac7ddfbfSEd Maste 
582ac7ddfbfSEd Maste         }
583ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTrace)
584ac7ddfbfSEd Maste         {
585ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
586ac7ddfbfSEd Maste         }
587ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTraceOver)
588ac7ddfbfSEd Maste         {
589ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
590ac7ddfbfSEd Maste         }
591ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOut)
592ac7ddfbfSEd Maste         {
593ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
594ac7ddfbfSEd Maste                                                           NULL,
595ac7ddfbfSEd Maste                                                           false,
596ac7ddfbfSEd Maste                                                           bool_stop_other_threads,
597ac7ddfbfSEd Maste                                                           eVoteYes,
598ac7ddfbfSEd Maste                                                           eVoteNoOpinion,
5990127ef0fSEd Maste                                                           thread->GetSelectedFrameIndex(),
6000127ef0fSEd Maste                                                           m_options.m_step_out_avoid_no_debug);
601ac7ddfbfSEd Maste         }
602ac7ddfbfSEd Maste         else
603ac7ddfbfSEd Maste         {
604ac7ddfbfSEd Maste             result.AppendError ("step type is not supported");
605ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
606ac7ddfbfSEd Maste             return false;
607ac7ddfbfSEd Maste         }
608ac7ddfbfSEd Maste 
609ac7ddfbfSEd Maste         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
610ac7ddfbfSEd Maste         // so that they can be interruptible).  Then resume the process.
611ac7ddfbfSEd Maste 
612ac7ddfbfSEd Maste         if (new_plan_sp)
613ac7ddfbfSEd Maste         {
614ac7ddfbfSEd Maste             new_plan_sp->SetIsMasterPlan (true);
615ac7ddfbfSEd Maste             new_plan_sp->SetOkayToDiscard (false);
616ac7ddfbfSEd Maste 
6170127ef0fSEd Maste             if (m_options.m_step_count > 1)
6180127ef0fSEd Maste             {
6190127ef0fSEd Maste                 if (new_plan_sp->SetIterationCount(m_options.m_step_count))
6200127ef0fSEd Maste                 {
6210127ef0fSEd Maste                     result.AppendWarning ("step operation does not support iteration count.");
6220127ef0fSEd Maste                 }
6230127ef0fSEd Maste             }
6240127ef0fSEd Maste 
625ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
626ac7ddfbfSEd Maste             process->Resume ();
627ac7ddfbfSEd Maste 
6280127ef0fSEd Maste             // There is a race condition where this thread will return up the call stack to the main command handler
6290127ef0fSEd Maste             // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
6300127ef0fSEd Maste             // a chance to call PushProcessIOHandler().
6310127ef0fSEd Maste             process->SyncIOHandler(2000);
632ac7ddfbfSEd Maste 
633ac7ddfbfSEd Maste             if (synchronous_execution)
634ac7ddfbfSEd Maste             {
635ac7ddfbfSEd Maste                 StateType state = process->WaitForProcessToStop (NULL);
636ac7ddfbfSEd Maste 
637ac7ddfbfSEd Maste                 //EventSP event_sp;
638ac7ddfbfSEd Maste                 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
639ac7ddfbfSEd Maste                 //while (! StateIsStoppedState (state))
640ac7ddfbfSEd Maste                 //  {
641ac7ddfbfSEd Maste                 //    state = process->WaitForStateChangedEvents (NULL, event_sp);
642ac7ddfbfSEd Maste                 //  }
643ac7ddfbfSEd Maste                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
644ac7ddfbfSEd Maste                 result.SetDidChangeProcessState (true);
645ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
646ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
647ac7ddfbfSEd Maste             }
648ac7ddfbfSEd Maste             else
649ac7ddfbfSEd Maste             {
650ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
651ac7ddfbfSEd Maste             }
652ac7ddfbfSEd Maste         }
653ac7ddfbfSEd Maste         else
654ac7ddfbfSEd Maste         {
655ac7ddfbfSEd Maste             result.AppendError ("Couldn't find thread plan to implement step type.");
656ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
657ac7ddfbfSEd Maste         }
658ac7ddfbfSEd Maste         return result.Succeeded();
659ac7ddfbfSEd Maste     }
660ac7ddfbfSEd Maste 
661ac7ddfbfSEd Maste protected:
662ac7ddfbfSEd Maste     StepType m_step_type;
663ac7ddfbfSEd Maste     StepScope m_step_scope;
664ac7ddfbfSEd Maste     CommandOptions m_options;
665ac7ddfbfSEd Maste };
666ac7ddfbfSEd Maste 
667ac7ddfbfSEd Maste static OptionEnumValueElement
668ac7ddfbfSEd Maste g_tri_running_mode[] =
669ac7ddfbfSEd Maste {
670ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
671ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
672ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
673ac7ddfbfSEd Maste { 0, NULL, NULL }
674ac7ddfbfSEd Maste };
675ac7ddfbfSEd Maste 
676ac7ddfbfSEd Maste static OptionEnumValueElement
677ac7ddfbfSEd Maste g_duo_running_mode[] =
678ac7ddfbfSEd Maste {
679ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
680ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
681ac7ddfbfSEd Maste { 0, NULL, NULL }
682ac7ddfbfSEd Maste };
683ac7ddfbfSEd Maste 
684ac7ddfbfSEd Maste OptionDefinition
685ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
686ac7ddfbfSEd Maste {
6870127ef0fSEd Maste { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug",   'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether stepping into functions will step over functions with no debug information."},
6880127ef0fSEd Maste { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug",  'A', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeBoolean,     "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."},
6890127ef0fSEd Maste { LLDB_OPT_SET_1, false, "count",           'c', OptionParser::eRequiredArgument, NULL, NULL,               1, eArgTypeCount,     "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."},
6900127ef0fSEd Maste { LLDB_OPT_SET_1, false, "run-mode",        'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
6910127ef0fSEd Maste { LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
6920127ef0fSEd Maste { LLDB_OPT_SET_1, false, "step-in-target",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
6930127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
694ac7ddfbfSEd Maste };
695ac7ddfbfSEd Maste 
696ac7ddfbfSEd Maste 
697ac7ddfbfSEd Maste //-------------------------------------------------------------------------
698ac7ddfbfSEd Maste // CommandObjectThreadContinue
699ac7ddfbfSEd Maste //-------------------------------------------------------------------------
700ac7ddfbfSEd Maste 
701ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed
702ac7ddfbfSEd Maste {
703ac7ddfbfSEd Maste public:
704ac7ddfbfSEd Maste 
705ac7ddfbfSEd Maste     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
706ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
707ac7ddfbfSEd Maste                              "thread continue",
708ac7ddfbfSEd Maste                              "Continue execution of one or more threads in an active process.",
709ac7ddfbfSEd Maste                              NULL,
710ac7ddfbfSEd Maste                              eFlagRequiresThread        |
711ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
712ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
713ac7ddfbfSEd Maste                              eFlagProcessMustBePaused)
714ac7ddfbfSEd Maste     {
715ac7ddfbfSEd Maste         CommandArgumentEntry arg;
716ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
717ac7ddfbfSEd Maste 
718ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
719ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
720ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlus;
721ac7ddfbfSEd Maste 
722ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
723ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
724ac7ddfbfSEd Maste 
725ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
726ac7ddfbfSEd Maste         m_arguments.push_back (arg);
727ac7ddfbfSEd Maste     }
728ac7ddfbfSEd Maste 
729ac7ddfbfSEd Maste 
730ac7ddfbfSEd Maste     virtual
731ac7ddfbfSEd Maste     ~CommandObjectThreadContinue ()
732ac7ddfbfSEd Maste     {
733ac7ddfbfSEd Maste     }
734ac7ddfbfSEd Maste 
735ac7ddfbfSEd Maste     virtual bool
736ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
737ac7ddfbfSEd Maste     {
738ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
739ac7ddfbfSEd Maste 
740ac7ddfbfSEd Maste         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
741ac7ddfbfSEd Maste         {
742ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
743ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
744ac7ddfbfSEd Maste             return false;
745ac7ddfbfSEd Maste         }
746ac7ddfbfSEd Maste 
747ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
748ac7ddfbfSEd Maste         if (process == NULL)
749ac7ddfbfSEd Maste         {
750ac7ddfbfSEd Maste             result.AppendError ("no process exists. Cannot continue");
751ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
752ac7ddfbfSEd Maste             return false;
753ac7ddfbfSEd Maste         }
754ac7ddfbfSEd Maste 
755ac7ddfbfSEd Maste         StateType state = process->GetState();
756ac7ddfbfSEd Maste         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
757ac7ddfbfSEd Maste         {
758ac7ddfbfSEd Maste             const size_t argc = command.GetArgumentCount();
759ac7ddfbfSEd Maste             if (argc > 0)
760ac7ddfbfSEd Maste             {
76135617911SEd Maste                 // These two lines appear at the beginning of both blocks in
76235617911SEd Maste                 // this if..else, but that is because we need to release the
76335617911SEd Maste                 // lock before calling process->Resume below.
76435617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
76535617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
766ac7ddfbfSEd Maste                 std::vector<Thread *> resume_threads;
767ac7ddfbfSEd Maste                 for (uint32_t i=0; i<argc; ++i)
768ac7ddfbfSEd Maste                 {
769ac7ddfbfSEd Maste                     bool success;
770ac7ddfbfSEd Maste                     const int base = 0;
771ac7ddfbfSEd Maste                     uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
772ac7ddfbfSEd Maste                     if (success)
773ac7ddfbfSEd Maste                     {
774ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
775ac7ddfbfSEd Maste 
776ac7ddfbfSEd Maste                         if (thread)
777ac7ddfbfSEd Maste                         {
778ac7ddfbfSEd Maste                             resume_threads.push_back(thread);
779ac7ddfbfSEd Maste                         }
780ac7ddfbfSEd Maste                         else
781ac7ddfbfSEd Maste                         {
782ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
783ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
784ac7ddfbfSEd Maste                             return false;
785ac7ddfbfSEd Maste                         }
786ac7ddfbfSEd Maste                     }
787ac7ddfbfSEd Maste                     else
788ac7ddfbfSEd Maste                     {
789ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
790ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
791ac7ddfbfSEd Maste                         return false;
792ac7ddfbfSEd Maste                     }
793ac7ddfbfSEd Maste                 }
794ac7ddfbfSEd Maste 
795ac7ddfbfSEd Maste                 if (resume_threads.empty())
796ac7ddfbfSEd Maste                 {
797ac7ddfbfSEd Maste                     result.AppendError ("no valid thread indexes were specified");
798ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
799ac7ddfbfSEd Maste                     return false;
800ac7ddfbfSEd Maste                 }
801ac7ddfbfSEd Maste                 else
802ac7ddfbfSEd Maste                 {
803ac7ddfbfSEd Maste                     if (resume_threads.size() == 1)
804ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread: ");
805ac7ddfbfSEd Maste                     else
806ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming threads: ");
807ac7ddfbfSEd Maste 
808ac7ddfbfSEd Maste                     for (uint32_t idx=0; idx<num_threads; ++idx)
809ac7ddfbfSEd Maste                     {
810ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
811ac7ddfbfSEd Maste                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
812ac7ddfbfSEd Maste 
813ac7ddfbfSEd Maste                         if (this_thread_pos != resume_threads.end())
814ac7ddfbfSEd Maste                         {
815ac7ddfbfSEd Maste                             resume_threads.erase(this_thread_pos);
816ac7ddfbfSEd Maste                             if (resume_threads.size() > 0)
817ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
818ac7ddfbfSEd Maste                             else
819ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
820ac7ddfbfSEd Maste 
8210127ef0fSEd Maste                             const bool override_suspend = true;
8220127ef0fSEd Maste                             thread->SetResumeState (eStateRunning, override_suspend);
823ac7ddfbfSEd Maste                         }
824ac7ddfbfSEd Maste                         else
825ac7ddfbfSEd Maste                         {
826ac7ddfbfSEd Maste                             thread->SetResumeState (eStateSuspended);
827ac7ddfbfSEd Maste                         }
828ac7ddfbfSEd Maste                     }
829ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
830ac7ddfbfSEd Maste                 }
831ac7ddfbfSEd Maste             }
832ac7ddfbfSEd Maste             else
833ac7ddfbfSEd Maste             {
83435617911SEd Maste                 // These two lines appear at the beginning of both blocks in
83535617911SEd Maste                 // this if..else, but that is because we need to release the
83635617911SEd Maste                 // lock before calling process->Resume below.
83735617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
83835617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
839ac7ddfbfSEd Maste                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
840ac7ddfbfSEd Maste                 if (current_thread == NULL)
841ac7ddfbfSEd Maste                 {
842ac7ddfbfSEd Maste                     result.AppendError ("the process doesn't have a current thread");
843ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
844ac7ddfbfSEd Maste                     return false;
845ac7ddfbfSEd Maste                 }
846ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
847ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
848ac7ddfbfSEd Maste                 {
849ac7ddfbfSEd Maste                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
850ac7ddfbfSEd Maste                     if (thread == current_thread)
851ac7ddfbfSEd Maste                     {
852ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
8530127ef0fSEd Maste                         const bool override_suspend = true;
8540127ef0fSEd Maste                         thread->SetResumeState (eStateRunning, override_suspend);
855ac7ddfbfSEd Maste                     }
856ac7ddfbfSEd Maste                     else
857ac7ddfbfSEd Maste                     {
858ac7ddfbfSEd Maste                         thread->SetResumeState (eStateSuspended);
859ac7ddfbfSEd Maste                     }
860ac7ddfbfSEd Maste                 }
861ac7ddfbfSEd Maste             }
862ac7ddfbfSEd Maste 
86335617911SEd Maste             // We should not be holding the thread list lock when we do this.
864ac7ddfbfSEd Maste             Error error (process->Resume());
865ac7ddfbfSEd Maste             if (error.Success())
866ac7ddfbfSEd Maste             {
867ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
868ac7ddfbfSEd Maste                 if (synchronous_execution)
869ac7ddfbfSEd Maste                 {
870ac7ddfbfSEd Maste                     state = process->WaitForProcessToStop (NULL);
871ac7ddfbfSEd Maste 
872ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
873ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
874ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
875ac7ddfbfSEd Maste                 }
876ac7ddfbfSEd Maste                 else
877ac7ddfbfSEd Maste                 {
878ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
879ac7ddfbfSEd Maste                 }
880ac7ddfbfSEd Maste             }
881ac7ddfbfSEd Maste             else
882ac7ddfbfSEd Maste             {
883ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
884ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
885ac7ddfbfSEd Maste             }
886ac7ddfbfSEd Maste         }
887ac7ddfbfSEd Maste         else
888ac7ddfbfSEd Maste         {
889ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
890ac7ddfbfSEd Maste                                           StateAsCString(state));
891ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
892ac7ddfbfSEd Maste         }
893ac7ddfbfSEd Maste 
894ac7ddfbfSEd Maste         return result.Succeeded();
895ac7ddfbfSEd Maste     }
896ac7ddfbfSEd Maste 
897ac7ddfbfSEd Maste };
898ac7ddfbfSEd Maste 
899ac7ddfbfSEd Maste //-------------------------------------------------------------------------
900ac7ddfbfSEd Maste // CommandObjectThreadUntil
901ac7ddfbfSEd Maste //-------------------------------------------------------------------------
902ac7ddfbfSEd Maste 
903ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed
904ac7ddfbfSEd Maste {
905ac7ddfbfSEd Maste public:
906ac7ddfbfSEd Maste 
907ac7ddfbfSEd Maste     class CommandOptions : public Options
908ac7ddfbfSEd Maste     {
909ac7ddfbfSEd Maste     public:
910ac7ddfbfSEd Maste         uint32_t m_thread_idx;
911ac7ddfbfSEd Maste         uint32_t m_frame_idx;
912ac7ddfbfSEd Maste 
913ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
914ac7ddfbfSEd Maste             Options (interpreter),
915ac7ddfbfSEd Maste             m_thread_idx(LLDB_INVALID_THREAD_ID),
916ac7ddfbfSEd Maste             m_frame_idx(LLDB_INVALID_FRAME_ID)
917ac7ddfbfSEd Maste         {
918ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
919ac7ddfbfSEd Maste             OptionParsingStarting ();
920ac7ddfbfSEd Maste         }
921ac7ddfbfSEd Maste 
922ac7ddfbfSEd Maste         virtual
923ac7ddfbfSEd Maste         ~CommandOptions ()
924ac7ddfbfSEd Maste         {
925ac7ddfbfSEd Maste         }
926ac7ddfbfSEd Maste 
927ac7ddfbfSEd Maste         virtual Error
928ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
929ac7ddfbfSEd Maste         {
930ac7ddfbfSEd Maste             Error error;
931ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
932ac7ddfbfSEd Maste 
933ac7ddfbfSEd Maste             switch (short_option)
934ac7ddfbfSEd Maste             {
935ac7ddfbfSEd Maste                 case 't':
936ac7ddfbfSEd Maste                 {
937ac7ddfbfSEd Maste                     m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
938ac7ddfbfSEd Maste                     if (m_thread_idx == LLDB_INVALID_INDEX32)
939ac7ddfbfSEd Maste                     {
940ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
941ac7ddfbfSEd Maste                     }
942ac7ddfbfSEd Maste                 }
943ac7ddfbfSEd Maste                 break;
944ac7ddfbfSEd Maste                 case 'f':
945ac7ddfbfSEd Maste                 {
946ac7ddfbfSEd Maste                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
947ac7ddfbfSEd Maste                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
948ac7ddfbfSEd Maste                     {
949ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
950ac7ddfbfSEd Maste                     }
951ac7ddfbfSEd Maste                 }
952ac7ddfbfSEd Maste                 break;
953ac7ddfbfSEd Maste                 case 'm':
954ac7ddfbfSEd Maste                 {
955ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
956ac7ddfbfSEd Maste                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
957ac7ddfbfSEd Maste 
958ac7ddfbfSEd Maste                     if (error.Success())
959ac7ddfbfSEd Maste                     {
960ac7ddfbfSEd Maste                         if (run_mode == eAllThreads)
961ac7ddfbfSEd Maste                             m_stop_others = false;
962ac7ddfbfSEd Maste                         else
963ac7ddfbfSEd Maste                             m_stop_others = true;
964ac7ddfbfSEd Maste                     }
965ac7ddfbfSEd Maste                 }
966ac7ddfbfSEd Maste                 break;
967ac7ddfbfSEd Maste                 default:
968ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
969ac7ddfbfSEd Maste                     break;
970ac7ddfbfSEd Maste 
971ac7ddfbfSEd Maste             }
972ac7ddfbfSEd Maste             return error;
973ac7ddfbfSEd Maste         }
974ac7ddfbfSEd Maste 
975ac7ddfbfSEd Maste         void
976ac7ddfbfSEd Maste         OptionParsingStarting ()
977ac7ddfbfSEd Maste         {
978ac7ddfbfSEd Maste             m_thread_idx = LLDB_INVALID_THREAD_ID;
979ac7ddfbfSEd Maste             m_frame_idx = 0;
980ac7ddfbfSEd Maste             m_stop_others = false;
981ac7ddfbfSEd Maste         }
982ac7ddfbfSEd Maste 
983ac7ddfbfSEd Maste         const OptionDefinition*
984ac7ddfbfSEd Maste         GetDefinitions ()
985ac7ddfbfSEd Maste         {
986ac7ddfbfSEd Maste             return g_option_table;
987ac7ddfbfSEd Maste         }
988ac7ddfbfSEd Maste 
989ac7ddfbfSEd Maste         uint32_t m_step_thread_idx;
990ac7ddfbfSEd Maste         bool m_stop_others;
991ac7ddfbfSEd Maste 
992ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
993ac7ddfbfSEd Maste 
994ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
995ac7ddfbfSEd Maste 
996ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
997ac7ddfbfSEd Maste     };
998ac7ddfbfSEd Maste 
999ac7ddfbfSEd Maste     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1000ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1001ac7ddfbfSEd Maste                              "thread until",
1002ac7ddfbfSEd Maste                              "Run the current or specified thread until it reaches a given line number or leaves the current function.",
1003ac7ddfbfSEd Maste                              NULL,
1004ac7ddfbfSEd Maste                              eFlagRequiresThread        |
1005ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1006ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1007ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
1008ac7ddfbfSEd Maste         m_options (interpreter)
1009ac7ddfbfSEd Maste     {
1010ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1011ac7ddfbfSEd Maste         CommandArgumentData line_num_arg;
1012ac7ddfbfSEd Maste 
1013ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1014ac7ddfbfSEd Maste         line_num_arg.arg_type = eArgTypeLineNum;
1015ac7ddfbfSEd Maste         line_num_arg.arg_repetition = eArgRepeatPlain;
1016ac7ddfbfSEd Maste 
1017ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1018ac7ddfbfSEd Maste         arg.push_back (line_num_arg);
1019ac7ddfbfSEd Maste 
1020ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1021ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1022ac7ddfbfSEd Maste     }
1023ac7ddfbfSEd Maste 
1024ac7ddfbfSEd Maste 
1025ac7ddfbfSEd Maste     virtual
1026ac7ddfbfSEd Maste     ~CommandObjectThreadUntil ()
1027ac7ddfbfSEd Maste     {
1028ac7ddfbfSEd Maste     }
1029ac7ddfbfSEd Maste 
1030ac7ddfbfSEd Maste     virtual
1031ac7ddfbfSEd Maste     Options *
1032ac7ddfbfSEd Maste     GetOptions ()
1033ac7ddfbfSEd Maste     {
1034ac7ddfbfSEd Maste         return &m_options;
1035ac7ddfbfSEd Maste     }
1036ac7ddfbfSEd Maste 
1037ac7ddfbfSEd Maste protected:
1038ac7ddfbfSEd Maste     virtual bool
1039ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1040ac7ddfbfSEd Maste     {
1041ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
1042ac7ddfbfSEd Maste 
1043ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1044ac7ddfbfSEd Maste         if (target == NULL)
1045ac7ddfbfSEd Maste         {
1046ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1047ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1048ac7ddfbfSEd Maste             return false;
1049ac7ddfbfSEd Maste         }
1050ac7ddfbfSEd Maste 
1051ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1052ac7ddfbfSEd Maste         if (process == NULL)
1053ac7ddfbfSEd Maste         {
1054ac7ddfbfSEd Maste             result.AppendError ("need a valid process to step");
1055ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1056ac7ddfbfSEd Maste 
1057ac7ddfbfSEd Maste         }
1058ac7ddfbfSEd Maste         else
1059ac7ddfbfSEd Maste         {
1060ac7ddfbfSEd Maste             Thread *thread = NULL;
1061ac7ddfbfSEd Maste             uint32_t line_number;
1062ac7ddfbfSEd Maste 
1063ac7ddfbfSEd Maste             if (command.GetArgumentCount() != 1)
1064ac7ddfbfSEd Maste             {
1065ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1066ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1067ac7ddfbfSEd Maste                 return false;
1068ac7ddfbfSEd Maste             }
1069ac7ddfbfSEd Maste 
1070ac7ddfbfSEd Maste             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1071ac7ddfbfSEd Maste             if (line_number == UINT32_MAX)
1072ac7ddfbfSEd Maste             {
1073ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1074ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1075ac7ddfbfSEd Maste                 return false;
1076ac7ddfbfSEd Maste             }
1077ac7ddfbfSEd Maste 
1078ac7ddfbfSEd Maste             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1079ac7ddfbfSEd Maste             {
1080ac7ddfbfSEd Maste                 thread = process->GetThreadList().GetSelectedThread().get();
1081ac7ddfbfSEd Maste             }
1082ac7ddfbfSEd Maste             else
1083ac7ddfbfSEd Maste             {
1084ac7ddfbfSEd Maste                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1085ac7ddfbfSEd Maste             }
1086ac7ddfbfSEd Maste 
1087ac7ddfbfSEd Maste             if (thread == NULL)
1088ac7ddfbfSEd Maste             {
1089ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
1090ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
1091ac7ddfbfSEd Maste                                               m_options.m_thread_idx,
1092ac7ddfbfSEd Maste                                               num_threads);
1093ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1094ac7ddfbfSEd Maste                 return false;
1095ac7ddfbfSEd Maste             }
1096ac7ddfbfSEd Maste 
1097ac7ddfbfSEd Maste             const bool abort_other_plans = false;
1098ac7ddfbfSEd Maste 
1099ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1100ac7ddfbfSEd Maste             if (frame == NULL)
1101ac7ddfbfSEd Maste             {
1102ac7ddfbfSEd Maste 
1103ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
1104ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1105ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1106ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1107ac7ddfbfSEd Maste                 return false;
1108ac7ddfbfSEd Maste             }
1109ac7ddfbfSEd Maste 
1110ac7ddfbfSEd Maste             ThreadPlanSP new_plan_sp;
1111ac7ddfbfSEd Maste 
1112ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
1113ac7ddfbfSEd Maste             {
1114ac7ddfbfSEd Maste                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1115ac7ddfbfSEd Maste                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1116ac7ddfbfSEd Maste                 LineTable *line_table = NULL;
1117ac7ddfbfSEd Maste                 if (sc.comp_unit)
1118ac7ddfbfSEd Maste                     line_table = sc.comp_unit->GetLineTable();
1119ac7ddfbfSEd Maste 
1120ac7ddfbfSEd Maste                 if (line_table == NULL)
1121ac7ddfbfSEd Maste                 {
1122ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1123ac7ddfbfSEd Maste                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1124ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1125ac7ddfbfSEd Maste                     return false;
1126ac7ddfbfSEd Maste                 }
1127ac7ddfbfSEd Maste 
1128ac7ddfbfSEd Maste                 LineEntry function_start;
1129ac7ddfbfSEd Maste                 uint32_t index_ptr = 0, end_ptr;
1130ac7ddfbfSEd Maste                 std::vector<addr_t> address_list;
1131ac7ddfbfSEd Maste 
1132ac7ddfbfSEd Maste                 // Find the beginning & end index of the
1133ac7ddfbfSEd Maste                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1134ac7ddfbfSEd Maste                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1135ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1136ac7ddfbfSEd Maste 
1137ac7ddfbfSEd Maste                 Address fun_end_addr(fun_start_addr.GetSection(),
1138ac7ddfbfSEd Maste                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1139ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1140ac7ddfbfSEd Maste 
1141ac7ddfbfSEd Maste                 bool all_in_function = true;
1142ac7ddfbfSEd Maste 
1143ac7ddfbfSEd Maste                 while (index_ptr <= end_ptr)
1144ac7ddfbfSEd Maste                 {
1145ac7ddfbfSEd Maste                     LineEntry line_entry;
1146ac7ddfbfSEd Maste                     const bool exact = false;
1147ac7ddfbfSEd Maste                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
1148ac7ddfbfSEd Maste                     if (index_ptr == UINT32_MAX)
1149ac7ddfbfSEd Maste                         break;
1150ac7ddfbfSEd Maste 
1151ac7ddfbfSEd Maste                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1152ac7ddfbfSEd Maste                     if (address != LLDB_INVALID_ADDRESS)
1153ac7ddfbfSEd Maste                     {
1154ac7ddfbfSEd Maste                         if (fun_addr_range.ContainsLoadAddress (address, target))
1155ac7ddfbfSEd Maste                             address_list.push_back (address);
1156ac7ddfbfSEd Maste                         else
1157ac7ddfbfSEd Maste                             all_in_function = false;
1158ac7ddfbfSEd Maste                     }
1159ac7ddfbfSEd Maste                     index_ptr++;
1160ac7ddfbfSEd Maste                 }
1161ac7ddfbfSEd Maste 
1162ac7ddfbfSEd Maste                 if (address_list.size() == 0)
1163ac7ddfbfSEd Maste                 {
1164ac7ddfbfSEd Maste                     if (all_in_function)
1165ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1166ac7ddfbfSEd Maste                     else
1167ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1168ac7ddfbfSEd Maste 
1169ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1170ac7ddfbfSEd Maste                     return false;
1171ac7ddfbfSEd Maste                 }
1172ac7ddfbfSEd Maste 
1173ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1174ac7ddfbfSEd Maste                                                                 &address_list.front(),
1175ac7ddfbfSEd Maste                                                                 address_list.size(),
1176ac7ddfbfSEd Maste                                                                 m_options.m_stop_others,
1177ac7ddfbfSEd Maste                                                                 m_options.m_frame_idx);
1178ac7ddfbfSEd Maste                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1179ac7ddfbfSEd Maste                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1180ac7ddfbfSEd Maste                 // will resume the original plan.
1181ac7ddfbfSEd Maste                 new_plan_sp->SetIsMasterPlan (true);
1182ac7ddfbfSEd Maste                 new_plan_sp->SetOkayToDiscard(false);
1183ac7ddfbfSEd Maste             }
1184ac7ddfbfSEd Maste             else
1185ac7ddfbfSEd Maste             {
1186ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1187ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1188ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1189ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1190ac7ddfbfSEd Maste                 return false;
1191ac7ddfbfSEd Maste 
1192ac7ddfbfSEd Maste             }
1193ac7ddfbfSEd Maste 
1194ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
1195ac7ddfbfSEd Maste             Error error (process->Resume ());
1196ac7ddfbfSEd Maste             if (error.Success())
1197ac7ddfbfSEd Maste             {
1198ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1199ac7ddfbfSEd Maste                 if (synchronous_execution)
1200ac7ddfbfSEd Maste                 {
1201ac7ddfbfSEd Maste                     StateType state = process->WaitForProcessToStop (NULL);
1202ac7ddfbfSEd Maste 
1203ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
1204ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
1205ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1206ac7ddfbfSEd Maste                 }
1207ac7ddfbfSEd Maste                 else
1208ac7ddfbfSEd Maste                 {
1209ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1210ac7ddfbfSEd Maste                 }
1211ac7ddfbfSEd Maste             }
1212ac7ddfbfSEd Maste             else
1213ac7ddfbfSEd Maste             {
1214ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1215ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1216ac7ddfbfSEd Maste             }
1217ac7ddfbfSEd Maste 
1218ac7ddfbfSEd Maste         }
1219ac7ddfbfSEd Maste         return result.Succeeded();
1220ac7ddfbfSEd Maste     }
1221ac7ddfbfSEd Maste 
1222ac7ddfbfSEd Maste     CommandOptions m_options;
1223ac7ddfbfSEd Maste 
1224ac7ddfbfSEd Maste };
1225ac7ddfbfSEd Maste 
1226ac7ddfbfSEd Maste OptionDefinition
1227ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1228ac7ddfbfSEd Maste {
12290127ef0fSEd Maste { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
12300127ef0fSEd Maste { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
12310127ef0fSEd Maste { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
12320127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1233ac7ddfbfSEd Maste };
1234ac7ddfbfSEd Maste 
1235ac7ddfbfSEd Maste 
1236ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1237ac7ddfbfSEd Maste // CommandObjectThreadSelect
1238ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1239ac7ddfbfSEd Maste 
1240ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed
1241ac7ddfbfSEd Maste {
1242ac7ddfbfSEd Maste public:
1243ac7ddfbfSEd Maste 
1244ac7ddfbfSEd Maste     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1245ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1246ac7ddfbfSEd Maste                              "thread select",
1247ac7ddfbfSEd Maste                              "Select a thread as the currently active thread.",
1248ac7ddfbfSEd Maste                              NULL,
1249ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1250ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1251ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1252ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1253ac7ddfbfSEd Maste     {
1254ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1255ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
1256ac7ddfbfSEd Maste 
1257ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1258ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1259ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1260ac7ddfbfSEd Maste 
1261ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1262ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
1263ac7ddfbfSEd Maste 
1264ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1265ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1266ac7ddfbfSEd Maste     }
1267ac7ddfbfSEd Maste 
1268ac7ddfbfSEd Maste 
1269ac7ddfbfSEd Maste     virtual
1270ac7ddfbfSEd Maste     ~CommandObjectThreadSelect ()
1271ac7ddfbfSEd Maste     {
1272ac7ddfbfSEd Maste     }
1273ac7ddfbfSEd Maste 
1274ac7ddfbfSEd Maste protected:
1275ac7ddfbfSEd Maste     virtual bool
1276ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1277ac7ddfbfSEd Maste     {
1278ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1279ac7ddfbfSEd Maste         if (process == NULL)
1280ac7ddfbfSEd Maste         {
1281ac7ddfbfSEd Maste             result.AppendError ("no process");
1282ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1283ac7ddfbfSEd Maste             return false;
1284ac7ddfbfSEd Maste         }
1285ac7ddfbfSEd Maste         else if (command.GetArgumentCount() != 1)
1286ac7ddfbfSEd Maste         {
1287ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1288ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1289ac7ddfbfSEd Maste             return false;
1290ac7ddfbfSEd Maste         }
1291ac7ddfbfSEd Maste 
1292ac7ddfbfSEd Maste         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1293ac7ddfbfSEd Maste 
1294ac7ddfbfSEd Maste         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1295ac7ddfbfSEd Maste         if (new_thread == NULL)
1296ac7ddfbfSEd Maste         {
1297ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1298ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1299ac7ddfbfSEd Maste             return false;
1300ac7ddfbfSEd Maste         }
1301ac7ddfbfSEd Maste 
1302ac7ddfbfSEd Maste         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1303ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1304ac7ddfbfSEd Maste 
1305ac7ddfbfSEd Maste         return result.Succeeded();
1306ac7ddfbfSEd Maste     }
1307ac7ddfbfSEd Maste 
1308ac7ddfbfSEd Maste };
1309ac7ddfbfSEd Maste 
1310ac7ddfbfSEd Maste 
1311ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1312ac7ddfbfSEd Maste // CommandObjectThreadList
1313ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1314ac7ddfbfSEd Maste 
1315ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed
1316ac7ddfbfSEd Maste {
1317ac7ddfbfSEd Maste public:
1318ac7ddfbfSEd Maste 
1319ac7ddfbfSEd Maste 
1320ac7ddfbfSEd Maste     CommandObjectThreadList (CommandInterpreter &interpreter):
1321ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1322ac7ddfbfSEd Maste                              "thread list",
1323ac7ddfbfSEd Maste                              "Show a summary of all current threads in a process.",
1324ac7ddfbfSEd Maste                              "thread list",
1325ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1326ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1327ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1328ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1329ac7ddfbfSEd Maste     {
1330ac7ddfbfSEd Maste     }
1331ac7ddfbfSEd Maste 
1332ac7ddfbfSEd Maste     ~CommandObjectThreadList()
1333ac7ddfbfSEd Maste     {
1334ac7ddfbfSEd Maste     }
1335ac7ddfbfSEd Maste 
1336ac7ddfbfSEd Maste protected:
1337ac7ddfbfSEd Maste     bool
1338ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1339ac7ddfbfSEd Maste     {
1340ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1341ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1342ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1343ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = false;
1344ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1345ac7ddfbfSEd Maste         const uint32_t num_frames = 0;
1346ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
1347ac7ddfbfSEd Maste         process->GetStatus(strm);
1348ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1349ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1350ac7ddfbfSEd Maste                                   start_frame,
1351ac7ddfbfSEd Maste                                   num_frames,
1352ac7ddfbfSEd Maste                                   num_frames_with_source);
1353ac7ddfbfSEd Maste         return result.Succeeded();
1354ac7ddfbfSEd Maste     }
1355ac7ddfbfSEd Maste };
1356ac7ddfbfSEd Maste 
1357ac7ddfbfSEd Maste //-------------------------------------------------------------------------
13580127ef0fSEd Maste // CommandObjectThreadInfo
13590127ef0fSEd Maste //-------------------------------------------------------------------------
13600127ef0fSEd Maste 
13610127ef0fSEd Maste class CommandObjectThreadInfo : public CommandObjectParsed
13620127ef0fSEd Maste {
13630127ef0fSEd Maste public:
13640127ef0fSEd Maste 
13650127ef0fSEd Maste     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
13660127ef0fSEd Maste         CommandObjectParsed (interpreter,
13670127ef0fSEd Maste                              "thread info",
13680127ef0fSEd Maste                              "Show an extended summary of information about thread(s) in a process.",
13690127ef0fSEd Maste                              "thread info",
13700127ef0fSEd Maste                              eFlagRequiresProcess       |
13710127ef0fSEd Maste                              eFlagTryTargetAPILock      |
13720127ef0fSEd Maste                              eFlagProcessMustBeLaunched |
13730127ef0fSEd Maste                              eFlagProcessMustBePaused),
13740127ef0fSEd Maste         m_options (interpreter)
13750127ef0fSEd Maste     {
13760127ef0fSEd Maste         CommandArgumentEntry arg;
13770127ef0fSEd Maste         CommandArgumentData thread_idx_arg;
13780127ef0fSEd Maste 
13790127ef0fSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
13800127ef0fSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatStar;
13810127ef0fSEd Maste 
13820127ef0fSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
13830127ef0fSEd Maste         arg.push_back (thread_idx_arg);
13840127ef0fSEd Maste 
13850127ef0fSEd Maste         // Push the data for the first argument into the m_arguments vector.
13860127ef0fSEd Maste         m_arguments.push_back (arg);
13870127ef0fSEd Maste     }
13880127ef0fSEd Maste 
13890127ef0fSEd Maste     class CommandOptions : public Options
13900127ef0fSEd Maste     {
13910127ef0fSEd Maste     public:
13920127ef0fSEd Maste 
13930127ef0fSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
13940127ef0fSEd Maste             Options (interpreter)
13950127ef0fSEd Maste         {
13960127ef0fSEd Maste             OptionParsingStarting ();
13970127ef0fSEd Maste         }
13980127ef0fSEd Maste 
13990127ef0fSEd Maste         void
14000127ef0fSEd Maste         OptionParsingStarting ()
14010127ef0fSEd Maste         {
14020127ef0fSEd Maste             m_json = false;
14030127ef0fSEd Maste         }
14040127ef0fSEd Maste 
14050127ef0fSEd Maste         virtual
14060127ef0fSEd Maste         ~CommandOptions ()
14070127ef0fSEd Maste         {
14080127ef0fSEd Maste         }
14090127ef0fSEd Maste 
14100127ef0fSEd Maste         virtual Error
14110127ef0fSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
14120127ef0fSEd Maste         {
14130127ef0fSEd Maste             const int short_option = m_getopt_table[option_idx].val;
14140127ef0fSEd Maste             Error error;
14150127ef0fSEd Maste 
14160127ef0fSEd Maste             switch (short_option)
14170127ef0fSEd Maste             {
14180127ef0fSEd Maste                 case 'j':
14190127ef0fSEd Maste                     m_json = true;
14200127ef0fSEd Maste                     break;
14210127ef0fSEd Maste 
14220127ef0fSEd Maste                  default:
14230127ef0fSEd Maste                     return Error("invalid short option character '%c'", short_option);
14240127ef0fSEd Maste 
14250127ef0fSEd Maste             }
14260127ef0fSEd Maste             return error;
14270127ef0fSEd Maste         }
14280127ef0fSEd Maste 
14290127ef0fSEd Maste         const OptionDefinition*
14300127ef0fSEd Maste         GetDefinitions ()
14310127ef0fSEd Maste         {
14320127ef0fSEd Maste             return g_option_table;
14330127ef0fSEd Maste         }
14340127ef0fSEd Maste 
14350127ef0fSEd Maste         bool m_json;
14360127ef0fSEd Maste 
14370127ef0fSEd Maste         static OptionDefinition g_option_table[];
14380127ef0fSEd Maste     };
14390127ef0fSEd Maste 
14400127ef0fSEd Maste     virtual
14410127ef0fSEd Maste     Options *
14420127ef0fSEd Maste     GetOptions ()
14430127ef0fSEd Maste     {
14440127ef0fSEd Maste         return &m_options;
14450127ef0fSEd Maste     }
14460127ef0fSEd Maste 
14470127ef0fSEd Maste 
14480127ef0fSEd Maste     virtual
14490127ef0fSEd Maste     ~CommandObjectThreadInfo ()
14500127ef0fSEd Maste     {
14510127ef0fSEd Maste     }
14520127ef0fSEd Maste 
14530127ef0fSEd Maste     virtual bool
14540127ef0fSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
14550127ef0fSEd Maste     {
14560127ef0fSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
14570127ef0fSEd Maste         Stream &strm = result.GetOutputStream();
14580127ef0fSEd Maste 
14590127ef0fSEd Maste         if (command.GetArgumentCount() == 0)
14600127ef0fSEd Maste         {
14610127ef0fSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
14620127ef0fSEd Maste             if (thread->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
14630127ef0fSEd Maste             {
14640127ef0fSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
14650127ef0fSEd Maste             }
14660127ef0fSEd Maste         }
14670127ef0fSEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
14680127ef0fSEd Maste         {
14690127ef0fSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
14700127ef0fSEd Maste             uint32_t idx = 0;
14710127ef0fSEd Maste             for (ThreadSP thread_sp : process->Threads())
14720127ef0fSEd Maste             {
14730127ef0fSEd Maste                 if (idx != 0)
14740127ef0fSEd Maste                     result.AppendMessage("");
14750127ef0fSEd Maste                 if (!thread_sp->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
14760127ef0fSEd Maste                 {
14770127ef0fSEd Maste                     result.AppendErrorWithFormat ("error displaying info for thread: \"0x%4.4x\"\n", idx);
14780127ef0fSEd Maste                     result.SetStatus (eReturnStatusFailed);
14790127ef0fSEd Maste                     return false;
14800127ef0fSEd Maste                 }
14810127ef0fSEd Maste                 ++idx;
14820127ef0fSEd Maste             }
14830127ef0fSEd Maste         }
14840127ef0fSEd Maste         else
14850127ef0fSEd Maste         {
14860127ef0fSEd Maste             const size_t num_args = command.GetArgumentCount();
14870127ef0fSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
14880127ef0fSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
14890127ef0fSEd Maste             std::vector<ThreadSP> thread_sps;
14900127ef0fSEd Maste 
14910127ef0fSEd Maste             for (size_t i = 0; i < num_args; i++)
14920127ef0fSEd Maste             {
14930127ef0fSEd Maste                 bool success;
14940127ef0fSEd Maste 
14950127ef0fSEd Maste                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
14960127ef0fSEd Maste                 if (!success)
14970127ef0fSEd Maste                 {
14980127ef0fSEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
14990127ef0fSEd Maste                     result.SetStatus (eReturnStatusFailed);
15000127ef0fSEd Maste                     return false;
15010127ef0fSEd Maste                 }
15020127ef0fSEd Maste 
15030127ef0fSEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
15040127ef0fSEd Maste 
15050127ef0fSEd Maste                 if (!thread_sps[i])
15060127ef0fSEd Maste                 {
15070127ef0fSEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
15080127ef0fSEd Maste                     result.SetStatus (eReturnStatusFailed);
15090127ef0fSEd Maste                     return false;
15100127ef0fSEd Maste                 }
15110127ef0fSEd Maste 
15120127ef0fSEd Maste             }
15130127ef0fSEd Maste 
15140127ef0fSEd Maste             for (uint32_t i = 0; i < num_args; i++)
15150127ef0fSEd Maste             {
15160127ef0fSEd Maste                 if (!thread_sps[i]->GetDescription (strm, eDescriptionLevelFull, m_options.m_json))
15170127ef0fSEd Maste                 {
15180127ef0fSEd Maste                     result.AppendErrorWithFormat ("error displaying info for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
15190127ef0fSEd Maste                     result.SetStatus (eReturnStatusFailed);
15200127ef0fSEd Maste                     return false;
15210127ef0fSEd Maste                 }
15220127ef0fSEd Maste 
15230127ef0fSEd Maste                 if (i < num_args - 1)
15240127ef0fSEd Maste                     result.AppendMessage("");
15250127ef0fSEd Maste             }
15260127ef0fSEd Maste 
15270127ef0fSEd Maste         }
15280127ef0fSEd Maste         return result.Succeeded();
15290127ef0fSEd Maste     }
15300127ef0fSEd Maste 
15310127ef0fSEd Maste     CommandOptions m_options;
15320127ef0fSEd Maste 
15330127ef0fSEd Maste };
15340127ef0fSEd Maste 
15350127ef0fSEd Maste OptionDefinition
15360127ef0fSEd Maste CommandObjectThreadInfo::CommandOptions::g_option_table[] =
15370127ef0fSEd Maste {
15380127ef0fSEd Maste     { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
15390127ef0fSEd Maste 
15400127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
15410127ef0fSEd Maste };
15420127ef0fSEd Maste 
15430127ef0fSEd Maste 
15440127ef0fSEd Maste //-------------------------------------------------------------------------
1545ac7ddfbfSEd Maste // CommandObjectThreadReturn
1546ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1547ac7ddfbfSEd Maste 
1548ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw
1549ac7ddfbfSEd Maste {
1550ac7ddfbfSEd Maste public:
1551ac7ddfbfSEd Maste     class CommandOptions : public Options
1552ac7ddfbfSEd Maste     {
1553ac7ddfbfSEd Maste     public:
1554ac7ddfbfSEd Maste 
1555ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1556ac7ddfbfSEd Maste             Options (interpreter),
1557ac7ddfbfSEd Maste             m_from_expression (false)
1558ac7ddfbfSEd Maste         {
1559ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1560ac7ddfbfSEd Maste             OptionParsingStarting ();
1561ac7ddfbfSEd Maste         }
1562ac7ddfbfSEd Maste 
1563ac7ddfbfSEd Maste         virtual
1564ac7ddfbfSEd Maste         ~CommandOptions ()
1565ac7ddfbfSEd Maste         {
1566ac7ddfbfSEd Maste         }
1567ac7ddfbfSEd Maste 
1568ac7ddfbfSEd Maste         virtual Error
1569ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1570ac7ddfbfSEd Maste         {
1571ac7ddfbfSEd Maste             Error error;
1572ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1573ac7ddfbfSEd Maste 
1574ac7ddfbfSEd Maste             switch (short_option)
1575ac7ddfbfSEd Maste             {
1576ac7ddfbfSEd Maste                 case 'x':
1577ac7ddfbfSEd Maste                 {
1578ac7ddfbfSEd Maste                     bool success;
1579ac7ddfbfSEd Maste                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1580ac7ddfbfSEd Maste                     if (success)
1581ac7ddfbfSEd Maste                         m_from_expression = tmp_value;
1582ac7ddfbfSEd Maste                     else
1583ac7ddfbfSEd Maste                     {
1584ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1585ac7ddfbfSEd Maste                     }
1586ac7ddfbfSEd Maste                 }
1587ac7ddfbfSEd Maste                 break;
1588ac7ddfbfSEd Maste                 default:
1589ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1590ac7ddfbfSEd Maste                     break;
1591ac7ddfbfSEd Maste 
1592ac7ddfbfSEd Maste             }
1593ac7ddfbfSEd Maste             return error;
1594ac7ddfbfSEd Maste         }
1595ac7ddfbfSEd Maste 
1596ac7ddfbfSEd Maste         void
1597ac7ddfbfSEd Maste         OptionParsingStarting ()
1598ac7ddfbfSEd Maste         {
1599ac7ddfbfSEd Maste             m_from_expression = false;
1600ac7ddfbfSEd Maste         }
1601ac7ddfbfSEd Maste 
1602ac7ddfbfSEd Maste         const OptionDefinition*
1603ac7ddfbfSEd Maste         GetDefinitions ()
1604ac7ddfbfSEd Maste         {
1605ac7ddfbfSEd Maste             return g_option_table;
1606ac7ddfbfSEd Maste         }
1607ac7ddfbfSEd Maste 
1608ac7ddfbfSEd Maste         bool m_from_expression;
1609ac7ddfbfSEd Maste 
1610ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1611ac7ddfbfSEd Maste 
1612ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1613ac7ddfbfSEd Maste 
1614ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1615ac7ddfbfSEd Maste     };
1616ac7ddfbfSEd Maste 
1617ac7ddfbfSEd Maste     virtual
1618ac7ddfbfSEd Maste     Options *
1619ac7ddfbfSEd Maste     GetOptions ()
1620ac7ddfbfSEd Maste     {
1621ac7ddfbfSEd Maste         return &m_options;
1622ac7ddfbfSEd Maste     }
1623ac7ddfbfSEd Maste 
1624ac7ddfbfSEd Maste     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1625ac7ddfbfSEd Maste         CommandObjectRaw (interpreter,
1626ac7ddfbfSEd Maste                           "thread return",
1627ac7ddfbfSEd Maste                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1628ac7ddfbfSEd Maste                           " or with the -x option from the innermost function evaluation.",
1629ac7ddfbfSEd Maste                           "thread return",
1630ac7ddfbfSEd Maste                           eFlagRequiresFrame         |
1631ac7ddfbfSEd Maste                           eFlagTryTargetAPILock      |
1632ac7ddfbfSEd Maste                           eFlagProcessMustBeLaunched |
1633ac7ddfbfSEd Maste                           eFlagProcessMustBePaused   ),
1634ac7ddfbfSEd Maste         m_options (interpreter)
1635ac7ddfbfSEd Maste     {
1636ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1637ac7ddfbfSEd Maste         CommandArgumentData expression_arg;
1638ac7ddfbfSEd Maste 
1639ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1640ac7ddfbfSEd Maste         expression_arg.arg_type = eArgTypeExpression;
1641ac7ddfbfSEd Maste         expression_arg.arg_repetition = eArgRepeatOptional;
1642ac7ddfbfSEd Maste 
1643ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1644ac7ddfbfSEd Maste         arg.push_back (expression_arg);
1645ac7ddfbfSEd Maste 
1646ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1647ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1648ac7ddfbfSEd Maste 
1649ac7ddfbfSEd Maste 
1650ac7ddfbfSEd Maste     }
1651ac7ddfbfSEd Maste 
1652ac7ddfbfSEd Maste     ~CommandObjectThreadReturn()
1653ac7ddfbfSEd Maste     {
1654ac7ddfbfSEd Maste     }
1655ac7ddfbfSEd Maste 
1656ac7ddfbfSEd Maste protected:
1657ac7ddfbfSEd Maste 
1658ac7ddfbfSEd Maste     bool DoExecute
1659ac7ddfbfSEd Maste     (
1660ac7ddfbfSEd Maste         const char *command,
1661ac7ddfbfSEd Maste         CommandReturnObject &result
1662ac7ddfbfSEd Maste     )
1663ac7ddfbfSEd Maste     {
1664ac7ddfbfSEd Maste         // I am going to handle this by hand, because I don't want you to have to say:
1665ac7ddfbfSEd Maste         // "thread return -- -5".
1666ac7ddfbfSEd Maste         if (command[0] == '-' && command[1] == 'x')
1667ac7ddfbfSEd Maste         {
1668ac7ddfbfSEd Maste             if (command && command[2] != '\0')
1669ac7ddfbfSEd Maste                 result.AppendWarning("Return values ignored when returning from user called expressions");
1670ac7ddfbfSEd Maste 
1671ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
1672ac7ddfbfSEd Maste             Error error;
1673ac7ddfbfSEd Maste             error = thread->UnwindInnermostExpression();
1674ac7ddfbfSEd Maste             if (!error.Success())
1675ac7ddfbfSEd Maste             {
1676ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1677ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1678ac7ddfbfSEd Maste             }
1679ac7ddfbfSEd Maste             else
1680ac7ddfbfSEd Maste             {
1681ac7ddfbfSEd Maste                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1682ac7ddfbfSEd Maste                 if (success)
1683ac7ddfbfSEd Maste                 {
1684ac7ddfbfSEd Maste                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1685ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1686ac7ddfbfSEd Maste                 }
1687ac7ddfbfSEd Maste                 else
1688ac7ddfbfSEd Maste                 {
1689ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1690ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1691ac7ddfbfSEd Maste                 }
1692ac7ddfbfSEd Maste             }
1693ac7ddfbfSEd Maste             return result.Succeeded();
1694ac7ddfbfSEd Maste         }
1695ac7ddfbfSEd Maste 
1696ac7ddfbfSEd Maste         ValueObjectSP return_valobj_sp;
1697ac7ddfbfSEd Maste 
1698ac7ddfbfSEd Maste         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1699ac7ddfbfSEd Maste         uint32_t frame_idx = frame_sp->GetFrameIndex();
1700ac7ddfbfSEd Maste 
1701ac7ddfbfSEd Maste         if (frame_sp->IsInlined())
1702ac7ddfbfSEd Maste         {
1703ac7ddfbfSEd Maste             result.AppendError("Don't know how to return from inlined frames.");
1704ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1705ac7ddfbfSEd Maste             return false;
1706ac7ddfbfSEd Maste         }
1707ac7ddfbfSEd Maste 
1708ac7ddfbfSEd Maste         if (command && command[0] != '\0')
1709ac7ddfbfSEd Maste         {
1710ac7ddfbfSEd Maste             Target *target = m_exe_ctx.GetTargetPtr();
1711ac7ddfbfSEd Maste             EvaluateExpressionOptions options;
1712ac7ddfbfSEd Maste 
1713ac7ddfbfSEd Maste             options.SetUnwindOnError(true);
1714ac7ddfbfSEd Maste             options.SetUseDynamic(eNoDynamicValues);
1715ac7ddfbfSEd Maste 
17160127ef0fSEd Maste             ExpressionResults exe_results = eExpressionSetupError;
1717ac7ddfbfSEd Maste             exe_results = target->EvaluateExpression (command,
1718ac7ddfbfSEd Maste                                                       frame_sp.get(),
1719ac7ddfbfSEd Maste                                                       return_valobj_sp,
1720ac7ddfbfSEd Maste                                                       options);
17210127ef0fSEd Maste             if (exe_results != eExpressionCompleted)
1722ac7ddfbfSEd Maste             {
1723ac7ddfbfSEd Maste                 if (return_valobj_sp)
1724ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1725ac7ddfbfSEd Maste                 else
1726ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1727ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1728ac7ddfbfSEd Maste                 return false;
1729ac7ddfbfSEd Maste 
1730ac7ddfbfSEd Maste             }
1731ac7ddfbfSEd Maste         }
1732ac7ddfbfSEd Maste 
1733ac7ddfbfSEd Maste         Error error;
1734ac7ddfbfSEd Maste         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1735ac7ddfbfSEd Maste         const bool broadcast = true;
1736ac7ddfbfSEd Maste         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1737ac7ddfbfSEd Maste         if (!error.Success())
1738ac7ddfbfSEd Maste         {
1739ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1740ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1741ac7ddfbfSEd Maste             return false;
1742ac7ddfbfSEd Maste         }
1743ac7ddfbfSEd Maste 
1744ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
1745ac7ddfbfSEd Maste         return true;
1746ac7ddfbfSEd Maste     }
1747ac7ddfbfSEd Maste 
1748ac7ddfbfSEd Maste     CommandOptions m_options;
1749ac7ddfbfSEd Maste 
1750ac7ddfbfSEd Maste };
1751ac7ddfbfSEd Maste OptionDefinition
1752ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1753ac7ddfbfSEd Maste {
17540127ef0fSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
17550127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
175635617911SEd Maste };
175735617911SEd Maste 
175835617911SEd Maste //-------------------------------------------------------------------------
175935617911SEd Maste // CommandObjectThreadJump
176035617911SEd Maste //-------------------------------------------------------------------------
176135617911SEd Maste 
176235617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed
176335617911SEd Maste {
176435617911SEd Maste public:
176535617911SEd Maste     class CommandOptions : public Options
176635617911SEd Maste     {
176735617911SEd Maste     public:
176835617911SEd Maste 
176935617911SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
177035617911SEd Maste             Options (interpreter)
177135617911SEd Maste         {
177235617911SEd Maste             OptionParsingStarting ();
177335617911SEd Maste         }
177435617911SEd Maste 
177535617911SEd Maste         void
177635617911SEd Maste         OptionParsingStarting ()
177735617911SEd Maste         {
177835617911SEd Maste             m_filenames.Clear();
177935617911SEd Maste             m_line_num = 0;
178035617911SEd Maste             m_line_offset = 0;
178135617911SEd Maste             m_load_addr = LLDB_INVALID_ADDRESS;
178235617911SEd Maste             m_force = false;
178335617911SEd Maste         }
178435617911SEd Maste 
178535617911SEd Maste         virtual
178635617911SEd Maste         ~CommandOptions ()
178735617911SEd Maste         {
178835617911SEd Maste         }
178935617911SEd Maste 
179035617911SEd Maste         virtual Error
179135617911SEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
179235617911SEd Maste         {
179335617911SEd Maste             bool success;
179435617911SEd Maste             const int short_option = m_getopt_table[option_idx].val;
179535617911SEd Maste             Error error;
179635617911SEd Maste 
179735617911SEd Maste             switch (short_option)
179835617911SEd Maste             {
179935617911SEd Maste                 case 'f':
180035617911SEd Maste                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
180135617911SEd Maste                     if (m_filenames.GetSize() > 1)
180235617911SEd Maste                         return Error("only one source file expected.");
180335617911SEd Maste                     break;
180435617911SEd Maste                 case 'l':
180535617911SEd Maste                     m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success);
180635617911SEd Maste                     if (!success || m_line_num == 0)
180735617911SEd Maste                         return Error("invalid line number: '%s'.", option_arg);
180835617911SEd Maste                     break;
180935617911SEd Maste                 case 'b':
181035617911SEd Maste                     m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success);
181135617911SEd Maste                     if (!success)
181235617911SEd Maste                         return Error("invalid line offset: '%s'.", option_arg);
181335617911SEd Maste                     break;
181435617911SEd Maste                 case 'a':
181535617911SEd Maste                     {
181635617911SEd Maste                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
181735617911SEd Maste                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
181835617911SEd Maste                     }
181935617911SEd Maste                     break;
182035617911SEd Maste                 case 'r':
182135617911SEd Maste                     m_force = true;
182235617911SEd Maste                     break;
182335617911SEd Maste 
182435617911SEd Maste                  default:
182535617911SEd Maste                     return Error("invalid short option character '%c'", short_option);
182635617911SEd Maste 
182735617911SEd Maste             }
182835617911SEd Maste             return error;
182935617911SEd Maste         }
183035617911SEd Maste 
183135617911SEd Maste         const OptionDefinition*
183235617911SEd Maste         GetDefinitions ()
183335617911SEd Maste         {
183435617911SEd Maste             return g_option_table;
183535617911SEd Maste         }
183635617911SEd Maste 
183735617911SEd Maste         FileSpecList m_filenames;
183835617911SEd Maste         uint32_t m_line_num;
183935617911SEd Maste         int32_t m_line_offset;
184035617911SEd Maste         lldb::addr_t m_load_addr;
184135617911SEd Maste         bool m_force;
184235617911SEd Maste 
184335617911SEd Maste         static OptionDefinition g_option_table[];
184435617911SEd Maste     };
184535617911SEd Maste 
184635617911SEd Maste     virtual
184735617911SEd Maste     Options *
184835617911SEd Maste     GetOptions ()
184935617911SEd Maste     {
185035617911SEd Maste         return &m_options;
185135617911SEd Maste     }
185235617911SEd Maste 
185335617911SEd Maste     CommandObjectThreadJump (CommandInterpreter &interpreter) :
185435617911SEd Maste         CommandObjectParsed (interpreter,
185535617911SEd Maste                           "thread jump",
185635617911SEd Maste                           "Sets the program counter to a new address.",
185735617911SEd Maste                           "thread jump",
185835617911SEd Maste                           eFlagRequiresFrame         |
185935617911SEd Maste                           eFlagTryTargetAPILock      |
186035617911SEd Maste                           eFlagProcessMustBeLaunched |
186135617911SEd Maste                           eFlagProcessMustBePaused   ),
186235617911SEd Maste         m_options (interpreter)
186335617911SEd Maste     {
186435617911SEd Maste     }
186535617911SEd Maste 
186635617911SEd Maste     ~CommandObjectThreadJump()
186735617911SEd Maste     {
186835617911SEd Maste     }
186935617911SEd Maste 
187035617911SEd Maste protected:
187135617911SEd Maste 
187235617911SEd Maste     bool DoExecute (Args& args, CommandReturnObject &result)
187335617911SEd Maste     {
187435617911SEd Maste         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
187535617911SEd Maste         StackFrame *frame = m_exe_ctx.GetFramePtr();
187635617911SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
187735617911SEd Maste         Target *target = m_exe_ctx.GetTargetPtr();
187835617911SEd Maste         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
187935617911SEd Maste 
188035617911SEd Maste         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
188135617911SEd Maste         {
188235617911SEd Maste             // Use this address directly.
188335617911SEd Maste             Address dest = Address(m_options.m_load_addr);
188435617911SEd Maste 
188535617911SEd Maste             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
188635617911SEd Maste             if (callAddr == LLDB_INVALID_ADDRESS)
188735617911SEd Maste             {
188835617911SEd Maste                 result.AppendErrorWithFormat ("Invalid destination address.");
188935617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
189035617911SEd Maste                 return false;
189135617911SEd Maste             }
189235617911SEd Maste 
189335617911SEd Maste             if (!reg_ctx->SetPC (callAddr))
189435617911SEd Maste             {
189535617911SEd Maste                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
189635617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
189735617911SEd Maste                 return false;
189835617911SEd Maste             }
189935617911SEd Maste         }
190035617911SEd Maste         else
190135617911SEd Maste         {
190235617911SEd Maste             // Pick either the absolute line, or work out a relative one.
190335617911SEd Maste             int32_t line = (int32_t)m_options.m_line_num;
190435617911SEd Maste             if (line == 0)
190535617911SEd Maste                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
190635617911SEd Maste 
190735617911SEd Maste             // Try the current file, but override if asked.
190835617911SEd Maste             FileSpec file = sym_ctx.line_entry.file;
190935617911SEd Maste             if (m_options.m_filenames.GetSize() == 1)
191035617911SEd Maste                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
191135617911SEd Maste 
191235617911SEd Maste             if (!file)
191335617911SEd Maste             {
191435617911SEd Maste                 result.AppendErrorWithFormat ("No source file available for the current location.");
191535617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
191635617911SEd Maste                 return false;
191735617911SEd Maste             }
191835617911SEd Maste 
191935617911SEd Maste             std::string warnings;
192035617911SEd Maste             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
192135617911SEd Maste 
192235617911SEd Maste             if (err.Fail())
192335617911SEd Maste             {
192435617911SEd Maste                 result.SetError (err);
192535617911SEd Maste                 return false;
192635617911SEd Maste             }
192735617911SEd Maste 
192835617911SEd Maste             if (!warnings.empty())
192935617911SEd Maste                 result.AppendWarning (warnings.c_str());
193035617911SEd Maste         }
193135617911SEd Maste 
193235617911SEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
193335617911SEd Maste         return true;
193435617911SEd Maste     }
193535617911SEd Maste 
193635617911SEd Maste     CommandOptions m_options;
193735617911SEd Maste };
193835617911SEd Maste OptionDefinition
193935617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] =
194035617911SEd Maste {
19410127ef0fSEd Maste     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
194235617911SEd Maste         "Specifies the source file to jump to."},
194335617911SEd Maste 
19440127ef0fSEd Maste     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
194535617911SEd Maste         "Specifies the line number to jump to."},
194635617911SEd Maste 
19470127ef0fSEd Maste     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
194835617911SEd Maste         "Jumps by a relative line offset from the current line."},
194935617911SEd Maste 
19500127ef0fSEd Maste     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
195135617911SEd Maste         "Jumps to a specific address."},
195235617911SEd Maste 
195335617911SEd Maste     { LLDB_OPT_SET_1|
195435617911SEd Maste       LLDB_OPT_SET_2|
19550127ef0fSEd Maste       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
195635617911SEd Maste 
19570127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1958ac7ddfbfSEd Maste };
1959ac7ddfbfSEd Maste 
1960ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1961ac7ddfbfSEd Maste // CommandObjectMultiwordThread
1962ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1963ac7ddfbfSEd Maste 
1964ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
1965ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
1966ac7ddfbfSEd Maste                             "thread",
1967ac7ddfbfSEd Maste                             "A set of commands for operating on one or more threads within a running process.",
1968ac7ddfbfSEd Maste                             "thread <subcommand> [<subcommand-options>]")
1969ac7ddfbfSEd Maste {
1970ac7ddfbfSEd Maste     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1971ac7ddfbfSEd Maste     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1972ac7ddfbfSEd Maste     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
1973ac7ddfbfSEd Maste     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
197435617911SEd Maste     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
1975ac7ddfbfSEd Maste     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1976ac7ddfbfSEd Maste     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
19770127ef0fSEd Maste     LoadSubCommand ("info",       CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
1978ac7ddfbfSEd Maste     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1979ac7ddfbfSEd Maste                                                     interpreter,
1980ac7ddfbfSEd Maste                                                     "thread step-in",
1981ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified).",
1982ac7ddfbfSEd Maste                                                     NULL,
1983ac7ddfbfSEd Maste                                                     eStepTypeInto,
1984ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1985ac7ddfbfSEd Maste 
1986ac7ddfbfSEd Maste     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1987ac7ddfbfSEd Maste                                                     interpreter,
1988ac7ddfbfSEd Maste                                                     "thread step-out",
1989ac7ddfbfSEd Maste                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
1990ac7ddfbfSEd Maste                                                     NULL,
1991ac7ddfbfSEd Maste                                                     eStepTypeOut,
1992ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1993ac7ddfbfSEd Maste 
1994ac7ddfbfSEd Maste     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1995ac7ddfbfSEd Maste                                                     interpreter,
1996ac7ddfbfSEd Maste                                                     "thread step-over",
1997ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
1998ac7ddfbfSEd Maste                                                     NULL,
1999ac7ddfbfSEd Maste                                                     eStepTypeOver,
2000ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2001ac7ddfbfSEd Maste 
2002ac7ddfbfSEd Maste     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2003ac7ddfbfSEd Maste                                                     interpreter,
2004ac7ddfbfSEd Maste                                                     "thread step-inst",
2005ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified).",
2006ac7ddfbfSEd Maste                                                     NULL,
2007ac7ddfbfSEd Maste                                                     eStepTypeTrace,
2008ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
2009ac7ddfbfSEd Maste 
2010ac7ddfbfSEd Maste     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2011ac7ddfbfSEd Maste                                                     interpreter,
2012ac7ddfbfSEd Maste                                                     "thread step-inst-over",
2013ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
2014ac7ddfbfSEd Maste                                                     NULL,
2015ac7ddfbfSEd Maste                                                     eStepTypeTraceOver,
2016ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
2017ac7ddfbfSEd Maste }
2018ac7ddfbfSEd Maste 
2019ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
2020ac7ddfbfSEd Maste {
2021ac7ddfbfSEd Maste }
2022ac7ddfbfSEd Maste 
2023ac7ddfbfSEd Maste 
2024