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 "CommandObjectThread.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste // C Includes
13ac7ddfbfSEd Maste // C++ Includes
14ac7ddfbfSEd Maste // Other libraries and framework includes
15ac7ddfbfSEd Maste // Project includes
16ac7ddfbfSEd Maste #include "lldb/lldb-private.h"
17ac7ddfbfSEd Maste #include "lldb/Core/State.h"
18ac7ddfbfSEd Maste #include "lldb/Core/SourceManager.h"
191c3bbb01SEd Maste #include "lldb/Core/ValueObject.h"
20ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
211c3bbb01SEd Maste #include "lldb/Host/StringConvert.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 
497aa51b79SEd Maste class CommandObjectIterateOverThreads : public CommandObjectParsed
507aa51b79SEd Maste {
517aa51b79SEd Maste public:
527aa51b79SEd Maste     CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
537aa51b79SEd Maste                          const char *name,
547aa51b79SEd Maste                          const char *help,
557aa51b79SEd Maste                          const char *syntax,
567aa51b79SEd Maste                          uint32_t flags) :
577aa51b79SEd Maste         CommandObjectParsed (interpreter, name, help, syntax, flags)
587aa51b79SEd Maste     {
597aa51b79SEd Maste     }
607aa51b79SEd Maste 
617aa51b79SEd Maste     virtual ~CommandObjectIterateOverThreads() {}
627aa51b79SEd Maste     virtual bool
637aa51b79SEd Maste     DoExecute (Args& command, CommandReturnObject &result)
647aa51b79SEd Maste     {
657aa51b79SEd Maste         result.SetStatus (m_success_return);
667aa51b79SEd Maste 
677aa51b79SEd Maste         if (command.GetArgumentCount() == 0)
687aa51b79SEd Maste         {
697aa51b79SEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
707aa51b79SEd Maste             if (!HandleOneThread (*thread, result))
717aa51b79SEd Maste                 return false;
727aa51b79SEd Maste         }
737aa51b79SEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
747aa51b79SEd Maste         {
757aa51b79SEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
767aa51b79SEd Maste             uint32_t idx = 0;
777aa51b79SEd Maste             for (ThreadSP thread_sp : process->Threads())
787aa51b79SEd Maste             {
797aa51b79SEd Maste                 if (idx != 0 && m_add_return)
807aa51b79SEd Maste                     result.AppendMessage("");
817aa51b79SEd Maste 
827aa51b79SEd Maste                 if (!HandleOneThread(*(thread_sp.get()), result))
837aa51b79SEd Maste                     return false;
847aa51b79SEd Maste                 ++idx;
857aa51b79SEd Maste             }
867aa51b79SEd Maste         }
877aa51b79SEd Maste         else
887aa51b79SEd Maste         {
897aa51b79SEd Maste             const size_t num_args = command.GetArgumentCount();
907aa51b79SEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
917aa51b79SEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
927aa51b79SEd Maste             std::vector<ThreadSP> thread_sps;
937aa51b79SEd Maste 
947aa51b79SEd Maste             for (size_t i = 0; i < num_args; i++)
957aa51b79SEd Maste             {
967aa51b79SEd Maste                 bool success;
977aa51b79SEd Maste 
981c3bbb01SEd Maste                 uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
997aa51b79SEd Maste                 if (!success)
1007aa51b79SEd Maste                 {
1017aa51b79SEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
1027aa51b79SEd Maste                     result.SetStatus (eReturnStatusFailed);
1037aa51b79SEd Maste                     return false;
1047aa51b79SEd Maste                 }
1057aa51b79SEd Maste 
1067aa51b79SEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
1077aa51b79SEd Maste 
1087aa51b79SEd Maste                 if (!thread_sps[i])
1097aa51b79SEd Maste                 {
1107aa51b79SEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
1117aa51b79SEd Maste                     result.SetStatus (eReturnStatusFailed);
1127aa51b79SEd Maste                     return false;
1137aa51b79SEd Maste                 }
1147aa51b79SEd Maste 
1157aa51b79SEd Maste             }
1167aa51b79SEd Maste 
1177aa51b79SEd Maste             for (uint32_t i = 0; i < num_args; i++)
1187aa51b79SEd Maste             {
1197aa51b79SEd Maste                 if (!HandleOneThread (*(thread_sps[i].get()), result))
1207aa51b79SEd Maste                     return false;
1217aa51b79SEd Maste 
1227aa51b79SEd Maste                 if (i < num_args - 1 && m_add_return)
1237aa51b79SEd Maste                     result.AppendMessage("");
1247aa51b79SEd Maste             }
1257aa51b79SEd Maste         }
1267aa51b79SEd Maste         return result.Succeeded();
1277aa51b79SEd Maste     }
1287aa51b79SEd Maste 
1297aa51b79SEd Maste protected:
1307aa51b79SEd Maste 
1317aa51b79SEd Maste     // Override this to do whatever you need to do for one thread.
1327aa51b79SEd Maste     //
1337aa51b79SEd Maste     // If you return false, the iteration will stop, otherwise it will proceed.
1347aa51b79SEd Maste     // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
1357aa51b79SEd Maste     // so you only need to set the return status in HandleOneThread if you want to indicate an error.
1367aa51b79SEd Maste     // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
1377aa51b79SEd Maste 
1387aa51b79SEd Maste     virtual bool
1397aa51b79SEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
1407aa51b79SEd Maste 
1417aa51b79SEd Maste     ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
1427aa51b79SEd Maste     bool m_add_return = true;
1437aa51b79SEd Maste 
1447aa51b79SEd Maste };
1457aa51b79SEd Maste 
1467aa51b79SEd Maste //-------------------------------------------------------------------------
1477aa51b79SEd Maste // CommandObjectThreadBacktrace
1487aa51b79SEd Maste //-------------------------------------------------------------------------
1497aa51b79SEd Maste 
1507aa51b79SEd Maste class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
151ac7ddfbfSEd Maste {
152ac7ddfbfSEd Maste public:
153ac7ddfbfSEd Maste 
154ac7ddfbfSEd Maste     class CommandOptions : public Options
155ac7ddfbfSEd Maste     {
156ac7ddfbfSEd Maste     public:
157ac7ddfbfSEd Maste 
158ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
159ac7ddfbfSEd Maste             Options(interpreter)
160ac7ddfbfSEd Maste         {
161ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
162ac7ddfbfSEd Maste             OptionParsingStarting ();
163ac7ddfbfSEd Maste         }
164ac7ddfbfSEd Maste 
165ac7ddfbfSEd Maste         virtual
166ac7ddfbfSEd Maste         ~CommandOptions ()
167ac7ddfbfSEd Maste         {
168ac7ddfbfSEd Maste         }
169ac7ddfbfSEd Maste 
170ac7ddfbfSEd Maste         virtual Error
171ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
172ac7ddfbfSEd Maste         {
173ac7ddfbfSEd Maste             Error error;
174ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
175ac7ddfbfSEd Maste 
176ac7ddfbfSEd Maste             switch (short_option)
177ac7ddfbfSEd Maste             {
178ac7ddfbfSEd Maste                 case 'c':
179ac7ddfbfSEd Maste                 {
180ac7ddfbfSEd Maste                     bool success;
1811c3bbb01SEd Maste                     int32_t input_count =  StringConvert::ToSInt32 (option_arg, -1, 0, &success);
182ac7ddfbfSEd Maste                     if (!success)
183ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
184ac7ddfbfSEd Maste                     if (input_count < -1)
185ac7ddfbfSEd Maste                         m_count = UINT32_MAX;
186ac7ddfbfSEd Maste                     else
187ac7ddfbfSEd Maste                         m_count = input_count;
188ac7ddfbfSEd Maste                 }
189ac7ddfbfSEd Maste                 break;
190ac7ddfbfSEd Maste                 case 's':
191ac7ddfbfSEd Maste                 {
192ac7ddfbfSEd Maste                     bool success;
1931c3bbb01SEd Maste                     m_start =  StringConvert::ToUInt32 (option_arg, 0, 0, &success);
194ac7ddfbfSEd Maste                     if (!success)
195ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
196ac7ddfbfSEd Maste                 }
197b952cd58SEd Maste                 case 'e':
198b952cd58SEd Maste                 {
199b952cd58SEd Maste                     bool success;
200b952cd58SEd Maste                     m_extended_backtrace =  Args::StringToBoolean (option_arg, false, &success);
201b952cd58SEd Maste                     if (!success)
202b952cd58SEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
203b952cd58SEd Maste                 }
204ac7ddfbfSEd Maste                 break;
205ac7ddfbfSEd Maste                 default:
206ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
207ac7ddfbfSEd Maste                     break;
208ac7ddfbfSEd Maste 
209ac7ddfbfSEd Maste             }
210ac7ddfbfSEd Maste             return error;
211ac7ddfbfSEd Maste         }
212ac7ddfbfSEd Maste 
213ac7ddfbfSEd Maste         void
214ac7ddfbfSEd Maste         OptionParsingStarting ()
215ac7ddfbfSEd Maste         {
216ac7ddfbfSEd Maste             m_count = UINT32_MAX;
217ac7ddfbfSEd Maste             m_start = 0;
218b952cd58SEd Maste             m_extended_backtrace = false;
219ac7ddfbfSEd Maste         }
220ac7ddfbfSEd Maste 
221ac7ddfbfSEd Maste         const OptionDefinition*
222ac7ddfbfSEd Maste         GetDefinitions ()
223ac7ddfbfSEd Maste         {
224ac7ddfbfSEd Maste             return g_option_table;
225ac7ddfbfSEd Maste         }
226ac7ddfbfSEd Maste 
227ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
228ac7ddfbfSEd Maste 
229ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
230ac7ddfbfSEd Maste 
231ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
232ac7ddfbfSEd Maste         uint32_t m_count;
233ac7ddfbfSEd Maste         uint32_t m_start;
234b952cd58SEd Maste         bool     m_extended_backtrace;
235ac7ddfbfSEd Maste     };
236ac7ddfbfSEd Maste 
237ac7ddfbfSEd Maste     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
2387aa51b79SEd Maste         CommandObjectIterateOverThreads (interpreter,
239ac7ddfbfSEd Maste                              "thread backtrace",
240ac7ddfbfSEd 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.",
241ac7ddfbfSEd Maste                              NULL,
2421c3bbb01SEd Maste                              eCommandRequiresProcess       |
2431c3bbb01SEd Maste                              eCommandRequiresThread        |
2441c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
2451c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
2461c3bbb01SEd Maste                              eCommandProcessMustBePaused   ),
247ac7ddfbfSEd Maste         m_options(interpreter)
248ac7ddfbfSEd Maste     {
249ac7ddfbfSEd Maste     }
250ac7ddfbfSEd Maste 
251ac7ddfbfSEd Maste     ~CommandObjectThreadBacktrace()
252ac7ddfbfSEd Maste     {
253ac7ddfbfSEd Maste     }
254ac7ddfbfSEd Maste 
255ac7ddfbfSEd Maste     virtual Options *
256ac7ddfbfSEd Maste     GetOptions ()
257ac7ddfbfSEd Maste     {
258ac7ddfbfSEd Maste         return &m_options;
259ac7ddfbfSEd Maste     }
260ac7ddfbfSEd Maste 
261ac7ddfbfSEd Maste protected:
262b952cd58SEd Maste     void
263b952cd58SEd Maste     DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
264b952cd58SEd Maste     {
265b952cd58SEd Maste         SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
266b952cd58SEd Maste         if (runtime)
267b952cd58SEd Maste         {
268b952cd58SEd Maste             Stream &strm = result.GetOutputStream();
269b952cd58SEd Maste             const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
270b952cd58SEd Maste             for (auto type : types)
271b952cd58SEd Maste             {
272b952cd58SEd Maste                 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
273b952cd58SEd Maste                 if (ext_thread_sp && ext_thread_sp->IsValid ())
274b952cd58SEd Maste                 {
275b952cd58SEd Maste                     const uint32_t num_frames_with_source = 0;
276b952cd58SEd Maste                     if (ext_thread_sp->GetStatus (strm,
277b952cd58SEd Maste                         m_options.m_start,
278b952cd58SEd Maste                         m_options.m_count,
279b952cd58SEd Maste                         num_frames_with_source))
280b952cd58SEd Maste                     {
281b952cd58SEd Maste                         DoExtendedBacktrace (ext_thread_sp.get(), result);
282b952cd58SEd Maste                     }
283b952cd58SEd Maste                 }
284b952cd58SEd Maste             }
285b952cd58SEd Maste         }
286b952cd58SEd Maste     }
287b952cd58SEd Maste 
288ac7ddfbfSEd Maste     virtual bool
2897aa51b79SEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result)
290ac7ddfbfSEd Maste     {
291ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
292ac7ddfbfSEd Maste 
293ac7ddfbfSEd Maste         // Don't show source context when doing backtraces.
294ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
295b952cd58SEd Maste 
2967aa51b79SEd Maste         if (!thread.GetStatus (strm,
297ac7ddfbfSEd Maste                                    m_options.m_start,
298ac7ddfbfSEd Maste                                    m_options.m_count,
299ac7ddfbfSEd Maste                                    num_frames_with_source))
300ac7ddfbfSEd Maste         {
3017aa51b79SEd Maste             result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
302ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
303ac7ddfbfSEd Maste             return false;
304ac7ddfbfSEd Maste         }
305b952cd58SEd Maste         if (m_options.m_extended_backtrace)
306b952cd58SEd Maste         {
3077aa51b79SEd Maste             DoExtendedBacktrace (&thread, result);
308b952cd58SEd Maste         }
309ac7ddfbfSEd Maste 
3107aa51b79SEd Maste         return true;
311ac7ddfbfSEd Maste     }
312ac7ddfbfSEd Maste 
313ac7ddfbfSEd Maste     CommandOptions m_options;
314ac7ddfbfSEd Maste };
315ac7ddfbfSEd Maste 
316ac7ddfbfSEd Maste OptionDefinition
317ac7ddfbfSEd Maste CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
318ac7ddfbfSEd Maste {
3190127ef0fSEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
3200127ef0fSEd Maste { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
3210127ef0fSEd Maste { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
3220127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
323ac7ddfbfSEd Maste };
324ac7ddfbfSEd Maste 
325ac7ddfbfSEd Maste enum StepScope
326ac7ddfbfSEd Maste {
327ac7ddfbfSEd Maste     eStepScopeSource,
328ac7ddfbfSEd Maste     eStepScopeInstruction
329ac7ddfbfSEd Maste };
330ac7ddfbfSEd Maste 
331ac7ddfbfSEd Maste class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
332ac7ddfbfSEd Maste {
333ac7ddfbfSEd Maste public:
334ac7ddfbfSEd Maste 
335ac7ddfbfSEd Maste     class CommandOptions : public Options
336ac7ddfbfSEd Maste     {
337ac7ddfbfSEd Maste     public:
338ac7ddfbfSEd Maste 
339ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
340ac7ddfbfSEd Maste             Options (interpreter)
341ac7ddfbfSEd Maste         {
342ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
343ac7ddfbfSEd Maste             OptionParsingStarting ();
344ac7ddfbfSEd Maste         }
345ac7ddfbfSEd Maste 
346ac7ddfbfSEd Maste         virtual
347ac7ddfbfSEd Maste         ~CommandOptions ()
348ac7ddfbfSEd Maste         {
349ac7ddfbfSEd Maste         }
350ac7ddfbfSEd Maste 
351ac7ddfbfSEd Maste         virtual Error
352ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
353ac7ddfbfSEd Maste         {
354ac7ddfbfSEd Maste             Error error;
355ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste             switch (short_option)
358ac7ddfbfSEd Maste             {
359ac7ddfbfSEd Maste             case 'a':
360ac7ddfbfSEd Maste                 {
361ac7ddfbfSEd Maste                     bool success;
3620127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
363ac7ddfbfSEd Maste                     if (!success)
364ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3650127ef0fSEd Maste                     else
3660127ef0fSEd Maste                     {
3670127ef0fSEd Maste                         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3680127ef0fSEd Maste                     }
369ac7ddfbfSEd Maste                 }
370ac7ddfbfSEd Maste                 break;
371ac7ddfbfSEd Maste 
3720127ef0fSEd Maste             case 'A':
3730127ef0fSEd Maste                 {
3740127ef0fSEd Maste                     bool success;
3750127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
3760127ef0fSEd Maste                     if (!success)
3770127ef0fSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3780127ef0fSEd Maste                     else
3790127ef0fSEd Maste                     {
3800127ef0fSEd Maste                         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3810127ef0fSEd Maste                     }
3820127ef0fSEd Maste                 }
3830127ef0fSEd Maste                 break;
3840127ef0fSEd Maste 
3850127ef0fSEd Maste             case 'c':
3860127ef0fSEd Maste                 {
3871c3bbb01SEd Maste                     m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
3880127ef0fSEd Maste                     if (m_step_count == UINT32_MAX)
3890127ef0fSEd Maste                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
3900127ef0fSEd Maste                     break;
3910127ef0fSEd Maste                 }
3920127ef0fSEd Maste                 break;
3937aa51b79SEd Maste             case 'C':
3947aa51b79SEd Maste                 {
3957aa51b79SEd Maste                     m_class_name.clear();
3967aa51b79SEd Maste                     m_class_name.assign(option_arg);
3977aa51b79SEd Maste                 }
3987aa51b79SEd Maste                 break;
399ac7ddfbfSEd Maste             case 'm':
400ac7ddfbfSEd Maste                 {
401ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
402ac7ddfbfSEd Maste                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
403ac7ddfbfSEd Maste                 }
404ac7ddfbfSEd Maste                 break;
405ac7ddfbfSEd Maste 
406ac7ddfbfSEd Maste             case 'r':
407ac7ddfbfSEd Maste                 {
408ac7ddfbfSEd Maste                     m_avoid_regexp.clear();
409ac7ddfbfSEd Maste                     m_avoid_regexp.assign(option_arg);
410ac7ddfbfSEd Maste                 }
411ac7ddfbfSEd Maste                 break;
412ac7ddfbfSEd Maste 
413ac7ddfbfSEd Maste             case 't':
414ac7ddfbfSEd Maste                 {
415ac7ddfbfSEd Maste                     m_step_in_target.clear();
416ac7ddfbfSEd Maste                     m_step_in_target.assign(option_arg);
417ac7ddfbfSEd Maste 
418ac7ddfbfSEd Maste                 }
419ac7ddfbfSEd Maste                 break;
420ac7ddfbfSEd Maste             default:
421ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
422ac7ddfbfSEd Maste                 break;
423ac7ddfbfSEd Maste 
424ac7ddfbfSEd Maste             }
425ac7ddfbfSEd Maste             return error;
426ac7ddfbfSEd Maste         }
427ac7ddfbfSEd Maste 
428ac7ddfbfSEd Maste         void
429ac7ddfbfSEd Maste         OptionParsingStarting ()
430ac7ddfbfSEd Maste         {
4310127ef0fSEd Maste             m_step_in_avoid_no_debug = eLazyBoolCalculate;
4320127ef0fSEd Maste             m_step_out_avoid_no_debug = eLazyBoolCalculate;
433ac7ddfbfSEd Maste             m_run_mode = eOnlyDuringStepping;
4341c3bbb01SEd Maste 
4351c3bbb01SEd Maste             // Check if we are in Non-Stop mode
4361c3bbb01SEd Maste             lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
4371c3bbb01SEd Maste             if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled())
4381c3bbb01SEd Maste                 m_run_mode = eOnlyThisThread;
4391c3bbb01SEd Maste 
440ac7ddfbfSEd Maste             m_avoid_regexp.clear();
441ac7ddfbfSEd Maste             m_step_in_target.clear();
4427aa51b79SEd Maste             m_class_name.clear();
4430127ef0fSEd Maste             m_step_count = 1;
444ac7ddfbfSEd Maste         }
445ac7ddfbfSEd Maste 
446ac7ddfbfSEd Maste         const OptionDefinition*
447ac7ddfbfSEd Maste         GetDefinitions ()
448ac7ddfbfSEd Maste         {
449ac7ddfbfSEd Maste             return g_option_table;
450ac7ddfbfSEd Maste         }
451ac7ddfbfSEd Maste 
452ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
453ac7ddfbfSEd Maste 
454ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
455ac7ddfbfSEd Maste 
456ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
4570127ef0fSEd Maste         LazyBool m_step_in_avoid_no_debug;
4580127ef0fSEd Maste         LazyBool m_step_out_avoid_no_debug;
459ac7ddfbfSEd Maste         RunMode m_run_mode;
460ac7ddfbfSEd Maste         std::string m_avoid_regexp;
461ac7ddfbfSEd Maste         std::string m_step_in_target;
4627aa51b79SEd Maste         std::string m_class_name;
4637aa51b79SEd Maste         uint32_t m_step_count;
464ac7ddfbfSEd Maste     };
465ac7ddfbfSEd Maste 
466ac7ddfbfSEd Maste     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
467ac7ddfbfSEd Maste                                              const char *name,
468ac7ddfbfSEd Maste                                              const char *help,
469ac7ddfbfSEd Maste                                              const char *syntax,
470ac7ddfbfSEd Maste                                              StepType step_type,
471ac7ddfbfSEd Maste                                              StepScope step_scope) :
472ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax,
4731c3bbb01SEd Maste                              eCommandRequiresProcess       |
4741c3bbb01SEd Maste                              eCommandRequiresThread        |
4751c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
4761c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
4771c3bbb01SEd Maste                              eCommandProcessMustBePaused   ),
478ac7ddfbfSEd Maste         m_step_type (step_type),
479ac7ddfbfSEd Maste         m_step_scope (step_scope),
480ac7ddfbfSEd Maste         m_options (interpreter)
481ac7ddfbfSEd Maste     {
482ac7ddfbfSEd Maste         CommandArgumentEntry arg;
483ac7ddfbfSEd Maste         CommandArgumentData thread_id_arg;
484ac7ddfbfSEd Maste 
485ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
486ac7ddfbfSEd Maste         thread_id_arg.arg_type = eArgTypeThreadID;
487ac7ddfbfSEd Maste         thread_id_arg.arg_repetition = eArgRepeatOptional;
488ac7ddfbfSEd Maste 
489ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
490ac7ddfbfSEd Maste         arg.push_back (thread_id_arg);
491ac7ddfbfSEd Maste 
492ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
493ac7ddfbfSEd Maste         m_arguments.push_back (arg);
494ac7ddfbfSEd Maste     }
495ac7ddfbfSEd Maste 
496ac7ddfbfSEd Maste     virtual
497ac7ddfbfSEd Maste     ~CommandObjectThreadStepWithTypeAndScope ()
498ac7ddfbfSEd Maste     {
499ac7ddfbfSEd Maste     }
500ac7ddfbfSEd Maste 
501ac7ddfbfSEd Maste     virtual
502ac7ddfbfSEd Maste     Options *
503ac7ddfbfSEd Maste     GetOptions ()
504ac7ddfbfSEd Maste     {
505ac7ddfbfSEd Maste         return &m_options;
506ac7ddfbfSEd Maste     }
507ac7ddfbfSEd Maste 
508ac7ddfbfSEd Maste protected:
509ac7ddfbfSEd Maste     virtual bool
510ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
511ac7ddfbfSEd Maste     {
512ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
513ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous();
514ac7ddfbfSEd Maste 
515ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
516ac7ddfbfSEd Maste         Thread *thread = NULL;
517ac7ddfbfSEd Maste 
518ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
519ac7ddfbfSEd Maste         {
520ac7ddfbfSEd Maste             thread = process->GetThreadList().GetSelectedThread().get();
521ac7ddfbfSEd Maste             if (thread == NULL)
522ac7ddfbfSEd Maste             {
523ac7ddfbfSEd Maste                 result.AppendError ("no selected thread in process");
524ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
525ac7ddfbfSEd Maste                 return false;
526ac7ddfbfSEd Maste             }
527ac7ddfbfSEd Maste         }
528ac7ddfbfSEd Maste         else
529ac7ddfbfSEd Maste         {
530ac7ddfbfSEd Maste             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
5311c3bbb01SEd Maste             uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
532ac7ddfbfSEd Maste             if (step_thread_idx == LLDB_INVALID_INDEX32)
533ac7ddfbfSEd Maste             {
534ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
535ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
536ac7ddfbfSEd Maste                 return false;
537ac7ddfbfSEd Maste             }
538ac7ddfbfSEd Maste             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
539ac7ddfbfSEd Maste             if (thread == NULL)
540ac7ddfbfSEd Maste             {
541ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
542ac7ddfbfSEd Maste                                               step_thread_idx, num_threads);
543ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
544ac7ddfbfSEd Maste                 return false;
545ac7ddfbfSEd Maste             }
546ac7ddfbfSEd Maste         }
547ac7ddfbfSEd Maste 
5487aa51b79SEd Maste         if (m_step_type == eStepTypeScripted)
5497aa51b79SEd Maste         {
5507aa51b79SEd Maste             if (m_options.m_class_name.empty())
5517aa51b79SEd Maste             {
5527aa51b79SEd Maste                 result.AppendErrorWithFormat ("empty class name for scripted step.");
5537aa51b79SEd Maste                 result.SetStatus(eReturnStatusFailed);
5547aa51b79SEd Maste                 return false;
5557aa51b79SEd Maste             }
5567aa51b79SEd Maste             else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
5577aa51b79SEd Maste             {
5587aa51b79SEd Maste                 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
5597aa51b79SEd Maste                 result.SetStatus(eReturnStatusFailed);
5607aa51b79SEd Maste                 return false;
5617aa51b79SEd Maste             }
5627aa51b79SEd Maste         }
5637aa51b79SEd Maste 
564ac7ddfbfSEd Maste         const bool abort_other_plans = false;
565ac7ddfbfSEd Maste         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
566ac7ddfbfSEd Maste 
567ac7ddfbfSEd Maste         // This is a bit unfortunate, but not all the commands in this command object support
568ac7ddfbfSEd Maste         // only while stepping, so I use the bool for them.
569ac7ddfbfSEd Maste         bool bool_stop_other_threads;
570ac7ddfbfSEd Maste         if (m_options.m_run_mode == eAllThreads)
571ac7ddfbfSEd Maste             bool_stop_other_threads = false;
572ac7ddfbfSEd Maste         else if (m_options.m_run_mode == eOnlyDuringStepping)
573ac7ddfbfSEd Maste         {
5747aa51b79SEd Maste             if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
575ac7ddfbfSEd Maste                 bool_stop_other_threads = false;
576ac7ddfbfSEd Maste             else
577ac7ddfbfSEd Maste                 bool_stop_other_threads = true;
578ac7ddfbfSEd Maste         }
579ac7ddfbfSEd Maste         else
580ac7ddfbfSEd Maste             bool_stop_other_threads = true;
581ac7ddfbfSEd Maste 
582ac7ddfbfSEd Maste         ThreadPlanSP new_plan_sp;
583ac7ddfbfSEd Maste 
584ac7ddfbfSEd Maste         if (m_step_type == eStepTypeInto)
585ac7ddfbfSEd Maste         {
586ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
5871c3bbb01SEd Maste             assert(frame != nullptr);
588ac7ddfbfSEd Maste 
589ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
590ac7ddfbfSEd Maste             {
591ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
592ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
593ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything),
594ac7ddfbfSEd Maste                                                                 m_options.m_step_in_target.c_str(),
595ac7ddfbfSEd Maste                                                                 stop_other_threads,
5960127ef0fSEd Maste                                                                 m_options.m_step_in_avoid_no_debug,
5970127ef0fSEd Maste                                                                 m_options.m_step_out_avoid_no_debug);
5980127ef0fSEd Maste 
599ac7ddfbfSEd Maste                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
600ac7ddfbfSEd Maste                 {
601ac7ddfbfSEd Maste                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
602ac7ddfbfSEd Maste                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
603ac7ddfbfSEd Maste                 }
604ac7ddfbfSEd Maste             }
605ac7ddfbfSEd Maste             else
606ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
607ac7ddfbfSEd Maste 
608ac7ddfbfSEd Maste         }
609ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOver)
610ac7ddfbfSEd Maste         {
611ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
612ac7ddfbfSEd Maste 
613ac7ddfbfSEd Maste             if (frame->HasDebugInformation())
614ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
615ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
616ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything),
6170127ef0fSEd Maste                                                                     stop_other_threads,
6180127ef0fSEd Maste                                                                     m_options.m_step_out_avoid_no_debug);
619ac7ddfbfSEd Maste             else
620ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
621ac7ddfbfSEd Maste                                                                             abort_other_plans,
622ac7ddfbfSEd Maste                                                                             bool_stop_other_threads);
623ac7ddfbfSEd Maste 
624ac7ddfbfSEd Maste         }
625ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTrace)
626ac7ddfbfSEd Maste         {
627ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
628ac7ddfbfSEd Maste         }
629ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTraceOver)
630ac7ddfbfSEd Maste         {
631ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
632ac7ddfbfSEd Maste         }
633ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOut)
634ac7ddfbfSEd Maste         {
635ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
636ac7ddfbfSEd Maste                                                           NULL,
637ac7ddfbfSEd Maste                                                           false,
638ac7ddfbfSEd Maste                                                           bool_stop_other_threads,
639ac7ddfbfSEd Maste                                                           eVoteYes,
640ac7ddfbfSEd Maste                                                           eVoteNoOpinion,
6410127ef0fSEd Maste                                                           thread->GetSelectedFrameIndex(),
6420127ef0fSEd Maste                                                           m_options.m_step_out_avoid_no_debug);
643ac7ddfbfSEd Maste         }
6447aa51b79SEd Maste         else if (m_step_type == eStepTypeScripted)
6457aa51b79SEd Maste         {
6467aa51b79SEd Maste             new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
6477aa51b79SEd Maste                                                                   m_options.m_class_name.c_str(),
6487aa51b79SEd Maste                                                                   bool_stop_other_threads);
6497aa51b79SEd Maste         }
650ac7ddfbfSEd Maste         else
651ac7ddfbfSEd Maste         {
652ac7ddfbfSEd Maste             result.AppendError ("step type is not supported");
653ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
654ac7ddfbfSEd Maste             return false;
655ac7ddfbfSEd Maste         }
656ac7ddfbfSEd Maste 
657ac7ddfbfSEd Maste         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
658ac7ddfbfSEd Maste         // so that they can be interruptible).  Then resume the process.
659ac7ddfbfSEd Maste 
660ac7ddfbfSEd Maste         if (new_plan_sp)
661ac7ddfbfSEd Maste         {
662ac7ddfbfSEd Maste             new_plan_sp->SetIsMasterPlan (true);
663ac7ddfbfSEd Maste             new_plan_sp->SetOkayToDiscard (false);
664ac7ddfbfSEd Maste 
6650127ef0fSEd Maste             if (m_options.m_step_count > 1)
6660127ef0fSEd Maste             {
6670127ef0fSEd Maste                 if (new_plan_sp->SetIterationCount(m_options.m_step_count))
6680127ef0fSEd Maste                 {
6690127ef0fSEd Maste                     result.AppendWarning ("step operation does not support iteration count.");
6700127ef0fSEd Maste                 }
6710127ef0fSEd Maste             }
6720127ef0fSEd Maste 
6737aa51b79SEd Maste 
674ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
6757aa51b79SEd Maste 
6761c3bbb01SEd Maste             const uint32_t iohandler_id = process->GetIOHandlerID();
6771c3bbb01SEd Maste 
6787aa51b79SEd Maste             StreamString stream;
6797aa51b79SEd Maste             Error error;
6807aa51b79SEd Maste             if (synchronous_execution)
6817aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
6827aa51b79SEd Maste             else
6837aa51b79SEd Maste                 error = process->Resume ();
684ac7ddfbfSEd Maste 
6850127ef0fSEd Maste             // There is a race condition where this thread will return up the call stack to the main command handler
6860127ef0fSEd Maste             // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
6870127ef0fSEd Maste             // a chance to call PushProcessIOHandler().
6881c3bbb01SEd Maste             process->SyncIOHandler(iohandler_id, 2000);
689ac7ddfbfSEd Maste 
690ac7ddfbfSEd Maste             if (synchronous_execution)
691ac7ddfbfSEd Maste             {
6927aa51b79SEd Maste                 // If any state changed events had anything to say, add that to the result
6937aa51b79SEd Maste                 if (stream.GetData())
6947aa51b79SEd Maste                     result.AppendMessage(stream.GetData());
695ac7ddfbfSEd Maste 
696ac7ddfbfSEd Maste                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
697ac7ddfbfSEd Maste                 result.SetDidChangeProcessState (true);
698ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
699ac7ddfbfSEd Maste             }
700ac7ddfbfSEd Maste             else
701ac7ddfbfSEd Maste             {
702ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
703ac7ddfbfSEd Maste             }
704ac7ddfbfSEd Maste         }
705ac7ddfbfSEd Maste         else
706ac7ddfbfSEd Maste         {
707ac7ddfbfSEd Maste             result.AppendError ("Couldn't find thread plan to implement step type.");
708ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
709ac7ddfbfSEd Maste         }
710ac7ddfbfSEd Maste         return result.Succeeded();
711ac7ddfbfSEd Maste     }
712ac7ddfbfSEd Maste 
713ac7ddfbfSEd Maste protected:
714ac7ddfbfSEd Maste     StepType m_step_type;
715ac7ddfbfSEd Maste     StepScope m_step_scope;
716ac7ddfbfSEd Maste     CommandOptions m_options;
717ac7ddfbfSEd Maste };
718ac7ddfbfSEd Maste 
719ac7ddfbfSEd Maste static OptionEnumValueElement
720ac7ddfbfSEd Maste g_tri_running_mode[] =
721ac7ddfbfSEd Maste {
722ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
723ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
724ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
725ac7ddfbfSEd Maste { 0, NULL, NULL }
726ac7ddfbfSEd Maste };
727ac7ddfbfSEd Maste 
728ac7ddfbfSEd Maste static OptionEnumValueElement
729ac7ddfbfSEd Maste g_duo_running_mode[] =
730ac7ddfbfSEd Maste {
731ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
732ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
733ac7ddfbfSEd Maste { 0, NULL, NULL }
734ac7ddfbfSEd Maste };
735ac7ddfbfSEd Maste 
736ac7ddfbfSEd Maste OptionDefinition
737ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
738ac7ddfbfSEd Maste {
7390127ef0fSEd 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."},
7400127ef0fSEd 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."},
7410127ef0fSEd 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."},
7420127ef0fSEd 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."},
7430127ef0fSEd 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."},
7440127ef0fSEd 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."},
7457aa51b79SEd Maste { LLDB_OPT_SET_2, false, "python-class",              'C', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."},
7460127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
747ac7ddfbfSEd Maste };
748ac7ddfbfSEd Maste 
749ac7ddfbfSEd Maste 
750ac7ddfbfSEd Maste //-------------------------------------------------------------------------
751ac7ddfbfSEd Maste // CommandObjectThreadContinue
752ac7ddfbfSEd Maste //-------------------------------------------------------------------------
753ac7ddfbfSEd Maste 
754ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed
755ac7ddfbfSEd Maste {
756ac7ddfbfSEd Maste public:
757ac7ddfbfSEd Maste 
758ac7ddfbfSEd Maste     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
759ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
760ac7ddfbfSEd Maste                              "thread continue",
761ac7ddfbfSEd Maste                              "Continue execution of one or more threads in an active process.",
762ac7ddfbfSEd Maste                              NULL,
7631c3bbb01SEd Maste                              eCommandRequiresThread        |
7641c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
7651c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
7661c3bbb01SEd Maste                              eCommandProcessMustBePaused)
767ac7ddfbfSEd Maste     {
768ac7ddfbfSEd Maste         CommandArgumentEntry arg;
769ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
770ac7ddfbfSEd Maste 
771ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
772ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
773ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlus;
774ac7ddfbfSEd Maste 
775ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
776ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
777ac7ddfbfSEd Maste 
778ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
779ac7ddfbfSEd Maste         m_arguments.push_back (arg);
780ac7ddfbfSEd Maste     }
781ac7ddfbfSEd Maste 
782ac7ddfbfSEd Maste 
783ac7ddfbfSEd Maste     virtual
784ac7ddfbfSEd Maste     ~CommandObjectThreadContinue ()
785ac7ddfbfSEd Maste     {
786ac7ddfbfSEd Maste     }
787ac7ddfbfSEd Maste 
788ac7ddfbfSEd Maste     virtual bool
789ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
790ac7ddfbfSEd Maste     {
791ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
792ac7ddfbfSEd Maste 
793ac7ddfbfSEd Maste         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
794ac7ddfbfSEd Maste         {
795ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
796ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
797ac7ddfbfSEd Maste             return false;
798ac7ddfbfSEd Maste         }
799ac7ddfbfSEd Maste 
800ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
801ac7ddfbfSEd Maste         if (process == NULL)
802ac7ddfbfSEd Maste         {
803ac7ddfbfSEd Maste             result.AppendError ("no process exists. Cannot continue");
804ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
805ac7ddfbfSEd Maste             return false;
806ac7ddfbfSEd Maste         }
807ac7ddfbfSEd Maste 
808ac7ddfbfSEd Maste         StateType state = process->GetState();
809ac7ddfbfSEd Maste         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
810ac7ddfbfSEd Maste         {
811ac7ddfbfSEd Maste             const size_t argc = command.GetArgumentCount();
812ac7ddfbfSEd Maste             if (argc > 0)
813ac7ddfbfSEd Maste             {
81435617911SEd Maste                 // These two lines appear at the beginning of both blocks in
81535617911SEd Maste                 // this if..else, but that is because we need to release the
81635617911SEd Maste                 // lock before calling process->Resume below.
81735617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
81835617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
819ac7ddfbfSEd Maste                 std::vector<Thread *> resume_threads;
820ac7ddfbfSEd Maste                 for (uint32_t i=0; i<argc; ++i)
821ac7ddfbfSEd Maste                 {
822ac7ddfbfSEd Maste                     bool success;
823ac7ddfbfSEd Maste                     const int base = 0;
8241c3bbb01SEd Maste                     uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
825ac7ddfbfSEd Maste                     if (success)
826ac7ddfbfSEd Maste                     {
827ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
828ac7ddfbfSEd Maste 
829ac7ddfbfSEd Maste                         if (thread)
830ac7ddfbfSEd Maste                         {
831ac7ddfbfSEd Maste                             resume_threads.push_back(thread);
832ac7ddfbfSEd Maste                         }
833ac7ddfbfSEd Maste                         else
834ac7ddfbfSEd Maste                         {
835ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
836ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
837ac7ddfbfSEd Maste                             return false;
838ac7ddfbfSEd Maste                         }
839ac7ddfbfSEd Maste                     }
840ac7ddfbfSEd Maste                     else
841ac7ddfbfSEd Maste                     {
842ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
843ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
844ac7ddfbfSEd Maste                         return false;
845ac7ddfbfSEd Maste                     }
846ac7ddfbfSEd Maste                 }
847ac7ddfbfSEd Maste 
848ac7ddfbfSEd Maste                 if (resume_threads.empty())
849ac7ddfbfSEd Maste                 {
850ac7ddfbfSEd Maste                     result.AppendError ("no valid thread indexes were specified");
851ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
852ac7ddfbfSEd Maste                     return false;
853ac7ddfbfSEd Maste                 }
854ac7ddfbfSEd Maste                 else
855ac7ddfbfSEd Maste                 {
856ac7ddfbfSEd Maste                     if (resume_threads.size() == 1)
857ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread: ");
858ac7ddfbfSEd Maste                     else
859ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming threads: ");
860ac7ddfbfSEd Maste 
861ac7ddfbfSEd Maste                     for (uint32_t idx=0; idx<num_threads; ++idx)
862ac7ddfbfSEd Maste                     {
863ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
864ac7ddfbfSEd Maste                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
865ac7ddfbfSEd Maste 
866ac7ddfbfSEd Maste                         if (this_thread_pos != resume_threads.end())
867ac7ddfbfSEd Maste                         {
868ac7ddfbfSEd Maste                             resume_threads.erase(this_thread_pos);
869ac7ddfbfSEd Maste                             if (resume_threads.size() > 0)
870ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
871ac7ddfbfSEd Maste                             else
872ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
873ac7ddfbfSEd Maste 
8740127ef0fSEd Maste                             const bool override_suspend = true;
8750127ef0fSEd Maste                             thread->SetResumeState (eStateRunning, override_suspend);
876ac7ddfbfSEd Maste                         }
877ac7ddfbfSEd Maste                         else
878ac7ddfbfSEd Maste                         {
879ac7ddfbfSEd Maste                             thread->SetResumeState (eStateSuspended);
880ac7ddfbfSEd Maste                         }
881ac7ddfbfSEd Maste                     }
882ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
883ac7ddfbfSEd Maste                 }
884ac7ddfbfSEd Maste             }
885ac7ddfbfSEd Maste             else
886ac7ddfbfSEd Maste             {
88735617911SEd Maste                 // These two lines appear at the beginning of both blocks in
88835617911SEd Maste                 // this if..else, but that is because we need to release the
88935617911SEd Maste                 // lock before calling process->Resume below.
89035617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
89135617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
892ac7ddfbfSEd Maste                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
893ac7ddfbfSEd Maste                 if (current_thread == NULL)
894ac7ddfbfSEd Maste                 {
895ac7ddfbfSEd Maste                     result.AppendError ("the process doesn't have a current thread");
896ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
897ac7ddfbfSEd Maste                     return false;
898ac7ddfbfSEd Maste                 }
899ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
900ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
901ac7ddfbfSEd Maste                 {
902ac7ddfbfSEd Maste                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
903ac7ddfbfSEd Maste                     if (thread == current_thread)
904ac7ddfbfSEd Maste                     {
905ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
9060127ef0fSEd Maste                         const bool override_suspend = true;
9070127ef0fSEd Maste                         thread->SetResumeState (eStateRunning, override_suspend);
908ac7ddfbfSEd Maste                     }
909ac7ddfbfSEd Maste                     else
910ac7ddfbfSEd Maste                     {
911ac7ddfbfSEd Maste                         thread->SetResumeState (eStateSuspended);
912ac7ddfbfSEd Maste                     }
913ac7ddfbfSEd Maste                 }
914ac7ddfbfSEd Maste             }
915ac7ddfbfSEd Maste 
9167aa51b79SEd Maste 
9177aa51b79SEd Maste             StreamString stream;
9187aa51b79SEd Maste             Error error;
9197aa51b79SEd Maste             if (synchronous_execution)
9207aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
9217aa51b79SEd Maste             else
9227aa51b79SEd Maste                 error = process->Resume ();
9237aa51b79SEd Maste 
92435617911SEd Maste             // We should not be holding the thread list lock when we do this.
925ac7ddfbfSEd Maste             if (error.Success())
926ac7ddfbfSEd Maste             {
927ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
928ac7ddfbfSEd Maste                 if (synchronous_execution)
929ac7ddfbfSEd Maste                 {
9307aa51b79SEd Maste                     // If any state changed events had anything to say, add that to the result
9317aa51b79SEd Maste                     if (stream.GetData())
9327aa51b79SEd Maste                         result.AppendMessage(stream.GetData());
933ac7ddfbfSEd Maste 
934ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
935ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
936ac7ddfbfSEd Maste                 }
937ac7ddfbfSEd Maste                 else
938ac7ddfbfSEd Maste                 {
939ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
940ac7ddfbfSEd Maste                 }
941ac7ddfbfSEd Maste             }
942ac7ddfbfSEd Maste             else
943ac7ddfbfSEd Maste             {
944ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
945ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
946ac7ddfbfSEd Maste             }
947ac7ddfbfSEd Maste         }
948ac7ddfbfSEd Maste         else
949ac7ddfbfSEd Maste         {
950ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
951ac7ddfbfSEd Maste                                           StateAsCString(state));
952ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
953ac7ddfbfSEd Maste         }
954ac7ddfbfSEd Maste 
955ac7ddfbfSEd Maste         return result.Succeeded();
956ac7ddfbfSEd Maste     }
957ac7ddfbfSEd Maste 
958ac7ddfbfSEd Maste };
959ac7ddfbfSEd Maste 
960ac7ddfbfSEd Maste //-------------------------------------------------------------------------
961ac7ddfbfSEd Maste // CommandObjectThreadUntil
962ac7ddfbfSEd Maste //-------------------------------------------------------------------------
963ac7ddfbfSEd Maste 
964ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed
965ac7ddfbfSEd Maste {
966ac7ddfbfSEd Maste public:
967ac7ddfbfSEd Maste 
968ac7ddfbfSEd Maste     class CommandOptions : public Options
969ac7ddfbfSEd Maste     {
970ac7ddfbfSEd Maste     public:
971ac7ddfbfSEd Maste         uint32_t m_thread_idx;
972ac7ddfbfSEd Maste         uint32_t m_frame_idx;
973ac7ddfbfSEd Maste 
974ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
975ac7ddfbfSEd Maste             Options (interpreter),
976ac7ddfbfSEd Maste             m_thread_idx(LLDB_INVALID_THREAD_ID),
977ac7ddfbfSEd Maste             m_frame_idx(LLDB_INVALID_FRAME_ID)
978ac7ddfbfSEd Maste         {
979ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
980ac7ddfbfSEd Maste             OptionParsingStarting ();
981ac7ddfbfSEd Maste         }
982ac7ddfbfSEd Maste 
983ac7ddfbfSEd Maste         virtual
984ac7ddfbfSEd Maste         ~CommandOptions ()
985ac7ddfbfSEd Maste         {
986ac7ddfbfSEd Maste         }
987ac7ddfbfSEd Maste 
988ac7ddfbfSEd Maste         virtual Error
989ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
990ac7ddfbfSEd Maste         {
991ac7ddfbfSEd Maste             Error error;
992ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
993ac7ddfbfSEd Maste 
994ac7ddfbfSEd Maste             switch (short_option)
995ac7ddfbfSEd Maste             {
9961c3bbb01SEd Maste                 case 'a':
9971c3bbb01SEd Maste                 {
9981c3bbb01SEd Maste                     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
9991c3bbb01SEd Maste                     lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
10001c3bbb01SEd Maste                     if (error.Success())
10011c3bbb01SEd Maste                         m_until_addrs.push_back(tmp_addr);
10021c3bbb01SEd Maste                 }
10031c3bbb01SEd Maste                 break;
1004ac7ddfbfSEd Maste                 case 't':
1005ac7ddfbfSEd Maste                 {
10061c3bbb01SEd Maste                     m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32);
1007ac7ddfbfSEd Maste                     if (m_thread_idx == LLDB_INVALID_INDEX32)
1008ac7ddfbfSEd Maste                     {
1009ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
1010ac7ddfbfSEd Maste                     }
1011ac7ddfbfSEd Maste                 }
1012ac7ddfbfSEd Maste                 break;
1013ac7ddfbfSEd Maste                 case 'f':
1014ac7ddfbfSEd Maste                 {
10151c3bbb01SEd Maste                     m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1016ac7ddfbfSEd Maste                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1017ac7ddfbfSEd Maste                     {
1018ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
1019ac7ddfbfSEd Maste                     }
1020ac7ddfbfSEd Maste                 }
1021ac7ddfbfSEd Maste                 break;
1022ac7ddfbfSEd Maste                 case 'm':
1023ac7ddfbfSEd Maste                 {
1024ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1025ac7ddfbfSEd Maste                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
1026ac7ddfbfSEd Maste 
1027ac7ddfbfSEd Maste                     if (error.Success())
1028ac7ddfbfSEd Maste                     {
1029ac7ddfbfSEd Maste                         if (run_mode == eAllThreads)
1030ac7ddfbfSEd Maste                             m_stop_others = false;
1031ac7ddfbfSEd Maste                         else
1032ac7ddfbfSEd Maste                             m_stop_others = true;
1033ac7ddfbfSEd Maste                     }
1034ac7ddfbfSEd Maste                 }
1035ac7ddfbfSEd Maste                 break;
1036ac7ddfbfSEd Maste                 default:
1037ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1038ac7ddfbfSEd Maste                     break;
1039ac7ddfbfSEd Maste 
1040ac7ddfbfSEd Maste             }
1041ac7ddfbfSEd Maste             return error;
1042ac7ddfbfSEd Maste         }
1043ac7ddfbfSEd Maste 
1044ac7ddfbfSEd Maste         void
1045ac7ddfbfSEd Maste         OptionParsingStarting ()
1046ac7ddfbfSEd Maste         {
1047ac7ddfbfSEd Maste             m_thread_idx = LLDB_INVALID_THREAD_ID;
1048ac7ddfbfSEd Maste             m_frame_idx = 0;
1049ac7ddfbfSEd Maste             m_stop_others = false;
10501c3bbb01SEd Maste             m_until_addrs.clear();
1051ac7ddfbfSEd Maste         }
1052ac7ddfbfSEd Maste 
1053ac7ddfbfSEd Maste         const OptionDefinition*
1054ac7ddfbfSEd Maste         GetDefinitions ()
1055ac7ddfbfSEd Maste         {
1056ac7ddfbfSEd Maste             return g_option_table;
1057ac7ddfbfSEd Maste         }
1058ac7ddfbfSEd Maste 
1059ac7ddfbfSEd Maste         uint32_t m_step_thread_idx;
1060ac7ddfbfSEd Maste         bool m_stop_others;
10611c3bbb01SEd Maste         std::vector<lldb::addr_t> m_until_addrs;
1062ac7ddfbfSEd Maste 
1063ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1064ac7ddfbfSEd Maste 
1065ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1066ac7ddfbfSEd Maste 
1067ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1068ac7ddfbfSEd Maste     };
1069ac7ddfbfSEd Maste 
1070ac7ddfbfSEd Maste     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1071ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1072ac7ddfbfSEd Maste                              "thread until",
10731c3bbb01SEd Maste                              "Run the current or specified thread until it reaches a given line number or address or leaves the current function.",
1074ac7ddfbfSEd Maste                              NULL,
10751c3bbb01SEd Maste                              eCommandRequiresThread        |
10761c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
10771c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
10781c3bbb01SEd Maste                              eCommandProcessMustBePaused   ),
1079ac7ddfbfSEd Maste         m_options (interpreter)
1080ac7ddfbfSEd Maste     {
1081ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1082ac7ddfbfSEd Maste         CommandArgumentData line_num_arg;
1083ac7ddfbfSEd Maste 
1084ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1085ac7ddfbfSEd Maste         line_num_arg.arg_type = eArgTypeLineNum;
1086ac7ddfbfSEd Maste         line_num_arg.arg_repetition = eArgRepeatPlain;
1087ac7ddfbfSEd Maste 
1088ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1089ac7ddfbfSEd Maste         arg.push_back (line_num_arg);
1090ac7ddfbfSEd Maste 
1091ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1092ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1093ac7ddfbfSEd Maste     }
1094ac7ddfbfSEd Maste 
1095ac7ddfbfSEd Maste 
1096ac7ddfbfSEd Maste     virtual
1097ac7ddfbfSEd Maste     ~CommandObjectThreadUntil ()
1098ac7ddfbfSEd Maste     {
1099ac7ddfbfSEd Maste     }
1100ac7ddfbfSEd Maste 
1101ac7ddfbfSEd Maste     virtual
1102ac7ddfbfSEd Maste     Options *
1103ac7ddfbfSEd Maste     GetOptions ()
1104ac7ddfbfSEd Maste     {
1105ac7ddfbfSEd Maste         return &m_options;
1106ac7ddfbfSEd Maste     }
1107ac7ddfbfSEd Maste 
1108ac7ddfbfSEd Maste protected:
1109ac7ddfbfSEd Maste     virtual bool
1110ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1111ac7ddfbfSEd Maste     {
1112ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
1113ac7ddfbfSEd Maste 
1114ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1115ac7ddfbfSEd Maste         if (target == NULL)
1116ac7ddfbfSEd Maste         {
1117ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1118ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1119ac7ddfbfSEd Maste             return false;
1120ac7ddfbfSEd Maste         }
1121ac7ddfbfSEd Maste 
1122ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1123ac7ddfbfSEd Maste         if (process == NULL)
1124ac7ddfbfSEd Maste         {
1125ac7ddfbfSEd Maste             result.AppendError ("need a valid process to step");
1126ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1127ac7ddfbfSEd Maste 
1128ac7ddfbfSEd Maste         }
1129ac7ddfbfSEd Maste         else
1130ac7ddfbfSEd Maste         {
1131ac7ddfbfSEd Maste             Thread *thread = NULL;
11321c3bbb01SEd Maste             std::vector<uint32_t> line_numbers;
1133ac7ddfbfSEd Maste 
11341c3bbb01SEd Maste             if (command.GetArgumentCount() >= 1)
1135ac7ddfbfSEd Maste             {
11361c3bbb01SEd Maste                 size_t num_args = command.GetArgumentCount();
11371c3bbb01SEd Maste                 for (size_t i = 0; i < num_args; i++)
11381c3bbb01SEd Maste                 {
11391c3bbb01SEd Maste                     uint32_t line_number;
11401c3bbb01SEd Maste                     line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1141ac7ddfbfSEd Maste                     if (line_number == UINT32_MAX)
1142ac7ddfbfSEd Maste                     {
1143ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1144ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
1145ac7ddfbfSEd Maste                         return false;
1146ac7ddfbfSEd Maste                     }
11471c3bbb01SEd Maste                     else
11481c3bbb01SEd Maste                         line_numbers.push_back(line_number);
11491c3bbb01SEd Maste                 }
11501c3bbb01SEd Maste             }
11511c3bbb01SEd Maste             else if (m_options.m_until_addrs.empty())
11521c3bbb01SEd Maste             {
11531c3bbb01SEd Maste                 result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax());
11541c3bbb01SEd Maste                 result.SetStatus (eReturnStatusFailed);
11551c3bbb01SEd Maste                 return false;
11561c3bbb01SEd Maste             }
11571c3bbb01SEd Maste 
1158ac7ddfbfSEd Maste 
1159ac7ddfbfSEd Maste             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1160ac7ddfbfSEd Maste             {
1161ac7ddfbfSEd Maste                 thread = process->GetThreadList().GetSelectedThread().get();
1162ac7ddfbfSEd Maste             }
1163ac7ddfbfSEd Maste             else
1164ac7ddfbfSEd Maste             {
1165ac7ddfbfSEd Maste                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1166ac7ddfbfSEd Maste             }
1167ac7ddfbfSEd Maste 
1168ac7ddfbfSEd Maste             if (thread == NULL)
1169ac7ddfbfSEd Maste             {
1170ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
1171ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
1172ac7ddfbfSEd Maste                                               m_options.m_thread_idx,
1173ac7ddfbfSEd Maste                                               num_threads);
1174ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1175ac7ddfbfSEd Maste                 return false;
1176ac7ddfbfSEd Maste             }
1177ac7ddfbfSEd Maste 
1178ac7ddfbfSEd Maste             const bool abort_other_plans = false;
1179ac7ddfbfSEd Maste 
1180ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1181ac7ddfbfSEd Maste             if (frame == NULL)
1182ac7ddfbfSEd Maste             {
1183ac7ddfbfSEd Maste 
1184ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
1185ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1186ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1187ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1188ac7ddfbfSEd Maste                 return false;
1189ac7ddfbfSEd Maste             }
1190ac7ddfbfSEd Maste 
1191ac7ddfbfSEd Maste             ThreadPlanSP new_plan_sp;
1192ac7ddfbfSEd Maste 
1193ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
1194ac7ddfbfSEd Maste             {
1195ac7ddfbfSEd Maste                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1196ac7ddfbfSEd Maste                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1197ac7ddfbfSEd Maste                 LineTable *line_table = NULL;
1198ac7ddfbfSEd Maste                 if (sc.comp_unit)
1199ac7ddfbfSEd Maste                     line_table = sc.comp_unit->GetLineTable();
1200ac7ddfbfSEd Maste 
1201ac7ddfbfSEd Maste                 if (line_table == NULL)
1202ac7ddfbfSEd Maste                 {
1203ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1204ac7ddfbfSEd Maste                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1205ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1206ac7ddfbfSEd Maste                     return false;
1207ac7ddfbfSEd Maste                 }
1208ac7ddfbfSEd Maste 
1209ac7ddfbfSEd Maste                 LineEntry function_start;
1210ac7ddfbfSEd Maste                 uint32_t index_ptr = 0, end_ptr;
1211ac7ddfbfSEd Maste                 std::vector<addr_t> address_list;
1212ac7ddfbfSEd Maste 
1213ac7ddfbfSEd Maste                 // Find the beginning & end index of the
1214ac7ddfbfSEd Maste                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1215ac7ddfbfSEd Maste                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1216ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1217ac7ddfbfSEd Maste 
1218ac7ddfbfSEd Maste                 Address fun_end_addr(fun_start_addr.GetSection(),
1219ac7ddfbfSEd Maste                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1220ac7ddfbfSEd Maste 
1221ac7ddfbfSEd Maste                 bool all_in_function = true;
1222ac7ddfbfSEd Maste 
12231c3bbb01SEd Maste                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
12241c3bbb01SEd Maste 
12251c3bbb01SEd Maste                 for (uint32_t line_number : line_numbers)
12261c3bbb01SEd Maste                 {
12271c3bbb01SEd Maste                     uint32_t start_idx_ptr = index_ptr;
12281c3bbb01SEd Maste                     while (start_idx_ptr <= end_ptr)
1229ac7ddfbfSEd Maste                     {
1230ac7ddfbfSEd Maste                         LineEntry line_entry;
1231ac7ddfbfSEd Maste                         const bool exact = false;
12321c3bbb01SEd Maste                         start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry);
12331c3bbb01SEd Maste                         if (start_idx_ptr == UINT32_MAX)
1234ac7ddfbfSEd Maste                             break;
1235ac7ddfbfSEd Maste 
1236ac7ddfbfSEd Maste                         addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1237ac7ddfbfSEd Maste                         if (address != LLDB_INVALID_ADDRESS)
1238ac7ddfbfSEd Maste                         {
1239ac7ddfbfSEd Maste                             if (fun_addr_range.ContainsLoadAddress (address, target))
1240ac7ddfbfSEd Maste                                 address_list.push_back (address);
1241ac7ddfbfSEd Maste                             else
1242ac7ddfbfSEd Maste                                 all_in_function = false;
1243ac7ddfbfSEd Maste                         }
12441c3bbb01SEd Maste                         start_idx_ptr++;
12451c3bbb01SEd Maste                     }
12461c3bbb01SEd Maste                 }
12471c3bbb01SEd Maste 
12481c3bbb01SEd Maste                 for (lldb::addr_t address : m_options.m_until_addrs)
12491c3bbb01SEd Maste                 {
12501c3bbb01SEd Maste                     if (fun_addr_range.ContainsLoadAddress (address, target))
12511c3bbb01SEd Maste                         address_list.push_back (address);
12521c3bbb01SEd Maste                     else
12531c3bbb01SEd Maste                         all_in_function = false;
1254ac7ddfbfSEd Maste                 }
1255ac7ddfbfSEd Maste 
1256ac7ddfbfSEd Maste                 if (address_list.size() == 0)
1257ac7ddfbfSEd Maste                 {
1258ac7ddfbfSEd Maste                     if (all_in_function)
1259ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1260ac7ddfbfSEd Maste                     else
1261ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1262ac7ddfbfSEd Maste 
1263ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1264ac7ddfbfSEd Maste                     return false;
1265ac7ddfbfSEd Maste                 }
1266ac7ddfbfSEd Maste 
1267ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1268ac7ddfbfSEd Maste                                                                 &address_list.front(),
1269ac7ddfbfSEd Maste                                                                 address_list.size(),
1270ac7ddfbfSEd Maste                                                                 m_options.m_stop_others,
1271ac7ddfbfSEd Maste                                                                 m_options.m_frame_idx);
1272ac7ddfbfSEd Maste                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1273ac7ddfbfSEd Maste                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1274ac7ddfbfSEd Maste                 // will resume the original plan.
1275ac7ddfbfSEd Maste                 new_plan_sp->SetIsMasterPlan (true);
1276ac7ddfbfSEd Maste                 new_plan_sp->SetOkayToDiscard(false);
1277ac7ddfbfSEd Maste             }
1278ac7ddfbfSEd Maste             else
1279ac7ddfbfSEd Maste             {
1280ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1281ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1282ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1283ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1284ac7ddfbfSEd Maste                 return false;
1285ac7ddfbfSEd Maste 
1286ac7ddfbfSEd Maste             }
1287ac7ddfbfSEd Maste 
12887aa51b79SEd Maste 
12897aa51b79SEd Maste 
1290ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
12917aa51b79SEd Maste 
12927aa51b79SEd Maste             StreamString stream;
12937aa51b79SEd Maste             Error error;
12947aa51b79SEd Maste             if (synchronous_execution)
12957aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
12967aa51b79SEd Maste             else
12977aa51b79SEd Maste                 error = process->Resume ();
12987aa51b79SEd Maste 
1299ac7ddfbfSEd Maste             if (error.Success())
1300ac7ddfbfSEd Maste             {
1301ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1302ac7ddfbfSEd Maste                 if (synchronous_execution)
1303ac7ddfbfSEd Maste                 {
13047aa51b79SEd Maste                     // If any state changed events had anything to say, add that to the result
13057aa51b79SEd Maste                     if (stream.GetData())
13067aa51b79SEd Maste                         result.AppendMessage(stream.GetData());
1307ac7ddfbfSEd Maste 
1308ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
1309ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1310ac7ddfbfSEd Maste                 }
1311ac7ddfbfSEd Maste                 else
1312ac7ddfbfSEd Maste                 {
1313ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1314ac7ddfbfSEd Maste                 }
1315ac7ddfbfSEd Maste             }
1316ac7ddfbfSEd Maste             else
1317ac7ddfbfSEd Maste             {
1318ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1319ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1320ac7ddfbfSEd Maste             }
1321ac7ddfbfSEd Maste 
1322ac7ddfbfSEd Maste         }
1323ac7ddfbfSEd Maste         return result.Succeeded();
1324ac7ddfbfSEd Maste     }
1325ac7ddfbfSEd Maste 
1326ac7ddfbfSEd Maste     CommandOptions m_options;
1327ac7ddfbfSEd Maste 
1328ac7ddfbfSEd Maste };
1329ac7ddfbfSEd Maste 
1330ac7ddfbfSEd Maste OptionDefinition
1331ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1332ac7ddfbfSEd Maste {
13330127ef0fSEd Maste { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
13340127ef0fSEd Maste { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
13350127ef0fSEd 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"},
13361c3bbb01SEd Maste { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."},
13370127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1338ac7ddfbfSEd Maste };
1339ac7ddfbfSEd Maste 
1340ac7ddfbfSEd Maste 
1341ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1342ac7ddfbfSEd Maste // CommandObjectThreadSelect
1343ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1344ac7ddfbfSEd Maste 
1345ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed
1346ac7ddfbfSEd Maste {
1347ac7ddfbfSEd Maste public:
1348ac7ddfbfSEd Maste 
1349ac7ddfbfSEd Maste     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1350ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1351ac7ddfbfSEd Maste                              "thread select",
1352ac7ddfbfSEd Maste                              "Select a thread as the currently active thread.",
1353ac7ddfbfSEd Maste                              NULL,
13541c3bbb01SEd Maste                              eCommandRequiresProcess       |
13551c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
13561c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
13571c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
1358ac7ddfbfSEd Maste     {
1359ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1360ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
1361ac7ddfbfSEd Maste 
1362ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1363ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1364ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1365ac7ddfbfSEd Maste 
1366ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1367ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
1368ac7ddfbfSEd Maste 
1369ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1370ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1371ac7ddfbfSEd Maste     }
1372ac7ddfbfSEd Maste 
1373ac7ddfbfSEd Maste 
1374ac7ddfbfSEd Maste     virtual
1375ac7ddfbfSEd Maste     ~CommandObjectThreadSelect ()
1376ac7ddfbfSEd Maste     {
1377ac7ddfbfSEd Maste     }
1378ac7ddfbfSEd Maste 
1379ac7ddfbfSEd Maste protected:
1380ac7ddfbfSEd Maste     virtual bool
1381ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1382ac7ddfbfSEd Maste     {
1383ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1384ac7ddfbfSEd Maste         if (process == NULL)
1385ac7ddfbfSEd Maste         {
1386ac7ddfbfSEd Maste             result.AppendError ("no process");
1387ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1388ac7ddfbfSEd Maste             return false;
1389ac7ddfbfSEd Maste         }
1390ac7ddfbfSEd Maste         else if (command.GetArgumentCount() != 1)
1391ac7ddfbfSEd Maste         {
1392ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1393ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1394ac7ddfbfSEd Maste             return false;
1395ac7ddfbfSEd Maste         }
1396ac7ddfbfSEd Maste 
13971c3bbb01SEd Maste         uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1398ac7ddfbfSEd Maste 
1399ac7ddfbfSEd Maste         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1400ac7ddfbfSEd Maste         if (new_thread == NULL)
1401ac7ddfbfSEd Maste         {
1402ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1403ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1404ac7ddfbfSEd Maste             return false;
1405ac7ddfbfSEd Maste         }
1406ac7ddfbfSEd Maste 
1407ac7ddfbfSEd Maste         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1408ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1409ac7ddfbfSEd Maste 
1410ac7ddfbfSEd Maste         return result.Succeeded();
1411ac7ddfbfSEd Maste     }
1412ac7ddfbfSEd Maste 
1413ac7ddfbfSEd Maste };
1414ac7ddfbfSEd Maste 
1415ac7ddfbfSEd Maste 
1416ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1417ac7ddfbfSEd Maste // CommandObjectThreadList
1418ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1419ac7ddfbfSEd Maste 
1420ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed
1421ac7ddfbfSEd Maste {
1422ac7ddfbfSEd Maste public:
1423ac7ddfbfSEd Maste 
1424ac7ddfbfSEd Maste 
1425ac7ddfbfSEd Maste     CommandObjectThreadList (CommandInterpreter &interpreter):
1426ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1427ac7ddfbfSEd Maste                              "thread list",
1428ac7ddfbfSEd Maste                              "Show a summary of all current threads in a process.",
1429ac7ddfbfSEd Maste                              "thread list",
14301c3bbb01SEd Maste                              eCommandRequiresProcess       |
14311c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
14321c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
14331c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
1434ac7ddfbfSEd Maste     {
1435ac7ddfbfSEd Maste     }
1436ac7ddfbfSEd Maste 
1437ac7ddfbfSEd Maste     ~CommandObjectThreadList()
1438ac7ddfbfSEd Maste     {
1439ac7ddfbfSEd Maste     }
1440ac7ddfbfSEd Maste 
1441ac7ddfbfSEd Maste protected:
1442ac7ddfbfSEd Maste     bool
1443ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1444ac7ddfbfSEd Maste     {
1445ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1446ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1447ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1448ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = false;
1449ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1450ac7ddfbfSEd Maste         const uint32_t num_frames = 0;
1451ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
1452ac7ddfbfSEd Maste         process->GetStatus(strm);
1453ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1454ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1455ac7ddfbfSEd Maste                                   start_frame,
1456ac7ddfbfSEd Maste                                   num_frames,
1457ac7ddfbfSEd Maste                                   num_frames_with_source);
1458ac7ddfbfSEd Maste         return result.Succeeded();
1459ac7ddfbfSEd Maste     }
1460ac7ddfbfSEd Maste };
1461ac7ddfbfSEd Maste 
1462ac7ddfbfSEd Maste //-------------------------------------------------------------------------
14630127ef0fSEd Maste // CommandObjectThreadInfo
14640127ef0fSEd Maste //-------------------------------------------------------------------------
14650127ef0fSEd Maste 
14667aa51b79SEd Maste class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
14670127ef0fSEd Maste {
14680127ef0fSEd Maste public:
14690127ef0fSEd Maste 
14700127ef0fSEd Maste     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
14717aa51b79SEd Maste         CommandObjectIterateOverThreads (interpreter,
14720127ef0fSEd Maste                                          "thread info",
14730127ef0fSEd Maste                                          "Show an extended summary of information about thread(s) in a process.",
14740127ef0fSEd Maste                                          "thread info",
14751c3bbb01SEd Maste                                          eCommandRequiresProcess       |
14761c3bbb01SEd Maste                                          eCommandTryTargetAPILock      |
14771c3bbb01SEd Maste                                          eCommandProcessMustBeLaunched |
14781c3bbb01SEd Maste                                          eCommandProcessMustBePaused),
14790127ef0fSEd Maste         m_options (interpreter)
14800127ef0fSEd Maste     {
14817aa51b79SEd Maste         m_add_return = false;
14820127ef0fSEd Maste     }
14830127ef0fSEd Maste 
14840127ef0fSEd Maste     class CommandOptions : public Options
14850127ef0fSEd Maste     {
14860127ef0fSEd Maste     public:
14870127ef0fSEd Maste 
14880127ef0fSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
14890127ef0fSEd Maste             Options (interpreter)
14900127ef0fSEd Maste         {
14910127ef0fSEd Maste             OptionParsingStarting ();
14920127ef0fSEd Maste         }
14930127ef0fSEd Maste 
14940127ef0fSEd Maste         void
14950127ef0fSEd Maste         OptionParsingStarting ()
14960127ef0fSEd Maste         {
14977aa51b79SEd Maste             m_json_thread = false;
14987aa51b79SEd Maste             m_json_stopinfo = false;
14990127ef0fSEd Maste         }
15000127ef0fSEd Maste 
15010127ef0fSEd Maste         virtual
15020127ef0fSEd Maste         ~CommandOptions ()
15030127ef0fSEd Maste         {
15040127ef0fSEd Maste         }
15050127ef0fSEd Maste 
15060127ef0fSEd Maste         virtual Error
15070127ef0fSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
15080127ef0fSEd Maste         {
15090127ef0fSEd Maste             const int short_option = m_getopt_table[option_idx].val;
15100127ef0fSEd Maste             Error error;
15110127ef0fSEd Maste 
15120127ef0fSEd Maste             switch (short_option)
15130127ef0fSEd Maste             {
15140127ef0fSEd Maste                 case 'j':
15157aa51b79SEd Maste                     m_json_thread = true;
15167aa51b79SEd Maste                     break;
15177aa51b79SEd Maste 
15187aa51b79SEd Maste                 case 's':
15197aa51b79SEd Maste                     m_json_stopinfo = true;
15200127ef0fSEd Maste                     break;
15210127ef0fSEd Maste 
15220127ef0fSEd Maste                 default:
15230127ef0fSEd Maste                     return Error("invalid short option character '%c'", short_option);
15240127ef0fSEd Maste 
15250127ef0fSEd Maste             }
15260127ef0fSEd Maste             return error;
15270127ef0fSEd Maste         }
15280127ef0fSEd Maste 
15290127ef0fSEd Maste         const OptionDefinition*
15300127ef0fSEd Maste         GetDefinitions ()
15310127ef0fSEd Maste         {
15320127ef0fSEd Maste             return g_option_table;
15330127ef0fSEd Maste         }
15340127ef0fSEd Maste 
15357aa51b79SEd Maste         bool m_json_thread;
15367aa51b79SEd Maste         bool m_json_stopinfo;
15370127ef0fSEd Maste 
15380127ef0fSEd Maste         static OptionDefinition g_option_table[];
15390127ef0fSEd Maste     };
15400127ef0fSEd Maste 
15410127ef0fSEd Maste     virtual
15420127ef0fSEd Maste     Options *
15430127ef0fSEd Maste     GetOptions ()
15440127ef0fSEd Maste     {
15450127ef0fSEd Maste         return &m_options;
15460127ef0fSEd Maste     }
15470127ef0fSEd Maste 
15480127ef0fSEd Maste 
15490127ef0fSEd Maste     virtual
15500127ef0fSEd Maste     ~CommandObjectThreadInfo ()
15510127ef0fSEd Maste     {
15520127ef0fSEd Maste     }
15530127ef0fSEd Maste 
15540127ef0fSEd Maste     virtual bool
15557aa51b79SEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result)
15560127ef0fSEd Maste     {
15570127ef0fSEd Maste         Stream &strm = result.GetOutputStream();
15587aa51b79SEd Maste         if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
15590127ef0fSEd Maste         {
15607aa51b79SEd Maste             result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
15610127ef0fSEd Maste             result.SetStatus (eReturnStatusFailed);
15620127ef0fSEd Maste             return false;
15630127ef0fSEd Maste         }
15647aa51b79SEd Maste         return true;
15650127ef0fSEd Maste     }
15660127ef0fSEd Maste 
15670127ef0fSEd Maste     CommandOptions m_options;
15680127ef0fSEd Maste 
15690127ef0fSEd Maste };
15700127ef0fSEd Maste 
15710127ef0fSEd Maste OptionDefinition
15720127ef0fSEd Maste CommandObjectThreadInfo::CommandOptions::g_option_table[] =
15730127ef0fSEd Maste {
15740127ef0fSEd Maste     { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
15757aa51b79SEd Maste     { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},
15760127ef0fSEd Maste 
15770127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
15780127ef0fSEd Maste };
15790127ef0fSEd Maste 
15800127ef0fSEd Maste 
15810127ef0fSEd Maste //-------------------------------------------------------------------------
1582ac7ddfbfSEd Maste // CommandObjectThreadReturn
1583ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1584ac7ddfbfSEd Maste 
1585ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw
1586ac7ddfbfSEd Maste {
1587ac7ddfbfSEd Maste public:
1588ac7ddfbfSEd Maste     class CommandOptions : public Options
1589ac7ddfbfSEd Maste     {
1590ac7ddfbfSEd Maste     public:
1591ac7ddfbfSEd Maste 
1592ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1593ac7ddfbfSEd Maste             Options (interpreter),
1594ac7ddfbfSEd Maste             m_from_expression (false)
1595ac7ddfbfSEd Maste         {
1596ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1597ac7ddfbfSEd Maste             OptionParsingStarting ();
1598ac7ddfbfSEd Maste         }
1599ac7ddfbfSEd Maste 
1600ac7ddfbfSEd Maste         virtual
1601ac7ddfbfSEd Maste         ~CommandOptions ()
1602ac7ddfbfSEd Maste         {
1603ac7ddfbfSEd Maste         }
1604ac7ddfbfSEd Maste 
1605ac7ddfbfSEd Maste         virtual Error
1606ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1607ac7ddfbfSEd Maste         {
1608ac7ddfbfSEd Maste             Error error;
1609ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1610ac7ddfbfSEd Maste 
1611ac7ddfbfSEd Maste             switch (short_option)
1612ac7ddfbfSEd Maste             {
1613ac7ddfbfSEd Maste                 case 'x':
1614ac7ddfbfSEd Maste                 {
1615ac7ddfbfSEd Maste                     bool success;
1616ac7ddfbfSEd Maste                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1617ac7ddfbfSEd Maste                     if (success)
1618ac7ddfbfSEd Maste                         m_from_expression = tmp_value;
1619ac7ddfbfSEd Maste                     else
1620ac7ddfbfSEd Maste                     {
1621ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1622ac7ddfbfSEd Maste                     }
1623ac7ddfbfSEd Maste                 }
1624ac7ddfbfSEd Maste                 break;
1625ac7ddfbfSEd Maste                 default:
1626ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1627ac7ddfbfSEd Maste                     break;
1628ac7ddfbfSEd Maste 
1629ac7ddfbfSEd Maste             }
1630ac7ddfbfSEd Maste             return error;
1631ac7ddfbfSEd Maste         }
1632ac7ddfbfSEd Maste 
1633ac7ddfbfSEd Maste         void
1634ac7ddfbfSEd Maste         OptionParsingStarting ()
1635ac7ddfbfSEd Maste         {
1636ac7ddfbfSEd Maste             m_from_expression = false;
1637ac7ddfbfSEd Maste         }
1638ac7ddfbfSEd Maste 
1639ac7ddfbfSEd Maste         const OptionDefinition*
1640ac7ddfbfSEd Maste         GetDefinitions ()
1641ac7ddfbfSEd Maste         {
1642ac7ddfbfSEd Maste             return g_option_table;
1643ac7ddfbfSEd Maste         }
1644ac7ddfbfSEd Maste 
1645ac7ddfbfSEd Maste         bool m_from_expression;
1646ac7ddfbfSEd Maste 
1647ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1648ac7ddfbfSEd Maste 
1649ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1650ac7ddfbfSEd Maste 
1651ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1652ac7ddfbfSEd Maste     };
1653ac7ddfbfSEd Maste 
1654ac7ddfbfSEd Maste     virtual
1655ac7ddfbfSEd Maste     Options *
1656ac7ddfbfSEd Maste     GetOptions ()
1657ac7ddfbfSEd Maste     {
1658ac7ddfbfSEd Maste         return &m_options;
1659ac7ddfbfSEd Maste     }
1660ac7ddfbfSEd Maste 
1661ac7ddfbfSEd Maste     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1662ac7ddfbfSEd Maste         CommandObjectRaw (interpreter,
1663ac7ddfbfSEd Maste                           "thread return",
1664ac7ddfbfSEd Maste                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1665ac7ddfbfSEd Maste                           " or with the -x option from the innermost function evaluation.",
1666ac7ddfbfSEd Maste                           "thread return",
16671c3bbb01SEd Maste                           eCommandRequiresFrame         |
16681c3bbb01SEd Maste                           eCommandTryTargetAPILock      |
16691c3bbb01SEd Maste                           eCommandProcessMustBeLaunched |
16701c3bbb01SEd Maste                           eCommandProcessMustBePaused   ),
1671ac7ddfbfSEd Maste         m_options (interpreter)
1672ac7ddfbfSEd Maste     {
1673ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1674ac7ddfbfSEd Maste         CommandArgumentData expression_arg;
1675ac7ddfbfSEd Maste 
1676ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1677ac7ddfbfSEd Maste         expression_arg.arg_type = eArgTypeExpression;
1678ac7ddfbfSEd Maste         expression_arg.arg_repetition = eArgRepeatOptional;
1679ac7ddfbfSEd Maste 
1680ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1681ac7ddfbfSEd Maste         arg.push_back (expression_arg);
1682ac7ddfbfSEd Maste 
1683ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1684ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1685ac7ddfbfSEd Maste 
1686ac7ddfbfSEd Maste 
1687ac7ddfbfSEd Maste     }
1688ac7ddfbfSEd Maste 
1689ac7ddfbfSEd Maste     ~CommandObjectThreadReturn()
1690ac7ddfbfSEd Maste     {
1691ac7ddfbfSEd Maste     }
1692ac7ddfbfSEd Maste 
1693ac7ddfbfSEd Maste protected:
1694ac7ddfbfSEd Maste 
1695ac7ddfbfSEd Maste     bool DoExecute
1696ac7ddfbfSEd Maste     (
1697ac7ddfbfSEd Maste         const char *command,
1698ac7ddfbfSEd Maste         CommandReturnObject &result
1699ac7ddfbfSEd Maste     )
1700ac7ddfbfSEd Maste     {
1701ac7ddfbfSEd Maste         // I am going to handle this by hand, because I don't want you to have to say:
1702ac7ddfbfSEd Maste         // "thread return -- -5".
1703ac7ddfbfSEd Maste         if (command[0] == '-' && command[1] == 'x')
1704ac7ddfbfSEd Maste         {
1705ac7ddfbfSEd Maste             if (command && command[2] != '\0')
1706ac7ddfbfSEd Maste                 result.AppendWarning("Return values ignored when returning from user called expressions");
1707ac7ddfbfSEd Maste 
1708ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
1709ac7ddfbfSEd Maste             Error error;
1710ac7ddfbfSEd Maste             error = thread->UnwindInnermostExpression();
1711ac7ddfbfSEd Maste             if (!error.Success())
1712ac7ddfbfSEd Maste             {
1713ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1714ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1715ac7ddfbfSEd Maste             }
1716ac7ddfbfSEd Maste             else
1717ac7ddfbfSEd Maste             {
1718ac7ddfbfSEd Maste                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1719ac7ddfbfSEd Maste                 if (success)
1720ac7ddfbfSEd Maste                 {
1721ac7ddfbfSEd Maste                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1722ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1723ac7ddfbfSEd Maste                 }
1724ac7ddfbfSEd Maste                 else
1725ac7ddfbfSEd Maste                 {
1726ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1727ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1728ac7ddfbfSEd Maste                 }
1729ac7ddfbfSEd Maste             }
1730ac7ddfbfSEd Maste             return result.Succeeded();
1731ac7ddfbfSEd Maste         }
1732ac7ddfbfSEd Maste 
1733ac7ddfbfSEd Maste         ValueObjectSP return_valobj_sp;
1734ac7ddfbfSEd Maste 
1735ac7ddfbfSEd Maste         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1736ac7ddfbfSEd Maste         uint32_t frame_idx = frame_sp->GetFrameIndex();
1737ac7ddfbfSEd Maste 
1738ac7ddfbfSEd Maste         if (frame_sp->IsInlined())
1739ac7ddfbfSEd Maste         {
1740ac7ddfbfSEd Maste             result.AppendError("Don't know how to return from inlined frames.");
1741ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1742ac7ddfbfSEd Maste             return false;
1743ac7ddfbfSEd Maste         }
1744ac7ddfbfSEd Maste 
1745ac7ddfbfSEd Maste         if (command && command[0] != '\0')
1746ac7ddfbfSEd Maste         {
1747ac7ddfbfSEd Maste             Target *target = m_exe_ctx.GetTargetPtr();
1748ac7ddfbfSEd Maste             EvaluateExpressionOptions options;
1749ac7ddfbfSEd Maste 
1750ac7ddfbfSEd Maste             options.SetUnwindOnError(true);
1751ac7ddfbfSEd Maste             options.SetUseDynamic(eNoDynamicValues);
1752ac7ddfbfSEd Maste 
17530127ef0fSEd Maste             ExpressionResults exe_results = eExpressionSetupError;
1754ac7ddfbfSEd Maste             exe_results = target->EvaluateExpression (command,
1755ac7ddfbfSEd Maste                                                       frame_sp.get(),
1756ac7ddfbfSEd Maste                                                       return_valobj_sp,
1757ac7ddfbfSEd Maste                                                       options);
17580127ef0fSEd Maste             if (exe_results != eExpressionCompleted)
1759ac7ddfbfSEd Maste             {
1760ac7ddfbfSEd Maste                 if (return_valobj_sp)
1761ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1762ac7ddfbfSEd Maste                 else
1763ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1764ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1765ac7ddfbfSEd Maste                 return false;
1766ac7ddfbfSEd Maste 
1767ac7ddfbfSEd Maste             }
1768ac7ddfbfSEd Maste         }
1769ac7ddfbfSEd Maste 
1770ac7ddfbfSEd Maste         Error error;
1771ac7ddfbfSEd Maste         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1772ac7ddfbfSEd Maste         const bool broadcast = true;
1773ac7ddfbfSEd Maste         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1774ac7ddfbfSEd Maste         if (!error.Success())
1775ac7ddfbfSEd Maste         {
1776ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1777ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1778ac7ddfbfSEd Maste             return false;
1779ac7ddfbfSEd Maste         }
1780ac7ddfbfSEd Maste 
1781ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
1782ac7ddfbfSEd Maste         return true;
1783ac7ddfbfSEd Maste     }
1784ac7ddfbfSEd Maste 
1785ac7ddfbfSEd Maste     CommandOptions m_options;
1786ac7ddfbfSEd Maste 
1787ac7ddfbfSEd Maste };
1788ac7ddfbfSEd Maste OptionDefinition
1789ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1790ac7ddfbfSEd Maste {
17910127ef0fSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
17920127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
179335617911SEd Maste };
179435617911SEd Maste 
179535617911SEd Maste //-------------------------------------------------------------------------
179635617911SEd Maste // CommandObjectThreadJump
179735617911SEd Maste //-------------------------------------------------------------------------
179835617911SEd Maste 
179935617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed
180035617911SEd Maste {
180135617911SEd Maste public:
180235617911SEd Maste     class CommandOptions : public Options
180335617911SEd Maste     {
180435617911SEd Maste     public:
180535617911SEd Maste 
180635617911SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
180735617911SEd Maste             Options (interpreter)
180835617911SEd Maste         {
180935617911SEd Maste             OptionParsingStarting ();
181035617911SEd Maste         }
181135617911SEd Maste 
181235617911SEd Maste         void
181335617911SEd Maste         OptionParsingStarting ()
181435617911SEd Maste         {
181535617911SEd Maste             m_filenames.Clear();
181635617911SEd Maste             m_line_num = 0;
181735617911SEd Maste             m_line_offset = 0;
181835617911SEd Maste             m_load_addr = LLDB_INVALID_ADDRESS;
181935617911SEd Maste             m_force = false;
182035617911SEd Maste         }
182135617911SEd Maste 
182235617911SEd Maste         virtual
182335617911SEd Maste         ~CommandOptions ()
182435617911SEd Maste         {
182535617911SEd Maste         }
182635617911SEd Maste 
182735617911SEd Maste         virtual Error
182835617911SEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
182935617911SEd Maste         {
183035617911SEd Maste             bool success;
183135617911SEd Maste             const int short_option = m_getopt_table[option_idx].val;
183235617911SEd Maste             Error error;
183335617911SEd Maste 
183435617911SEd Maste             switch (short_option)
183535617911SEd Maste             {
183635617911SEd Maste                 case 'f':
183735617911SEd Maste                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
183835617911SEd Maste                     if (m_filenames.GetSize() > 1)
183935617911SEd Maste                         return Error("only one source file expected.");
184035617911SEd Maste                     break;
184135617911SEd Maste                 case 'l':
18421c3bbb01SEd Maste                     m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
184335617911SEd Maste                     if (!success || m_line_num == 0)
184435617911SEd Maste                         return Error("invalid line number: '%s'.", option_arg);
184535617911SEd Maste                     break;
184635617911SEd Maste                 case 'b':
18471c3bbb01SEd Maste                     m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success);
184835617911SEd Maste                     if (!success)
184935617911SEd Maste                         return Error("invalid line offset: '%s'.", option_arg);
185035617911SEd Maste                     break;
185135617911SEd Maste                 case 'a':
185235617911SEd Maste                     {
185335617911SEd Maste                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
185435617911SEd Maste                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
185535617911SEd Maste                     }
185635617911SEd Maste                     break;
185735617911SEd Maste                 case 'r':
185835617911SEd Maste                     m_force = true;
185935617911SEd Maste                     break;
186035617911SEd Maste 
186135617911SEd Maste                  default:
186235617911SEd Maste                     return Error("invalid short option character '%c'", short_option);
186335617911SEd Maste 
186435617911SEd Maste             }
186535617911SEd Maste             return error;
186635617911SEd Maste         }
186735617911SEd Maste 
186835617911SEd Maste         const OptionDefinition*
186935617911SEd Maste         GetDefinitions ()
187035617911SEd Maste         {
187135617911SEd Maste             return g_option_table;
187235617911SEd Maste         }
187335617911SEd Maste 
187435617911SEd Maste         FileSpecList m_filenames;
187535617911SEd Maste         uint32_t m_line_num;
187635617911SEd Maste         int32_t m_line_offset;
187735617911SEd Maste         lldb::addr_t m_load_addr;
187835617911SEd Maste         bool m_force;
187935617911SEd Maste 
188035617911SEd Maste         static OptionDefinition g_option_table[];
188135617911SEd Maste     };
188235617911SEd Maste 
188335617911SEd Maste     virtual
188435617911SEd Maste     Options *
188535617911SEd Maste     GetOptions ()
188635617911SEd Maste     {
188735617911SEd Maste         return &m_options;
188835617911SEd Maste     }
188935617911SEd Maste 
189035617911SEd Maste     CommandObjectThreadJump (CommandInterpreter &interpreter) :
189135617911SEd Maste         CommandObjectParsed (interpreter,
189235617911SEd Maste                           "thread jump",
189335617911SEd Maste                           "Sets the program counter to a new address.",
189435617911SEd Maste                           "thread jump",
18951c3bbb01SEd Maste                           eCommandRequiresFrame         |
18961c3bbb01SEd Maste                           eCommandTryTargetAPILock      |
18971c3bbb01SEd Maste                           eCommandProcessMustBeLaunched |
18981c3bbb01SEd Maste                           eCommandProcessMustBePaused   ),
189935617911SEd Maste         m_options (interpreter)
190035617911SEd Maste     {
190135617911SEd Maste     }
190235617911SEd Maste 
190335617911SEd Maste     ~CommandObjectThreadJump()
190435617911SEd Maste     {
190535617911SEd Maste     }
190635617911SEd Maste 
190735617911SEd Maste protected:
190835617911SEd Maste 
190935617911SEd Maste     bool DoExecute (Args& args, CommandReturnObject &result)
191035617911SEd Maste     {
191135617911SEd Maste         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
191235617911SEd Maste         StackFrame *frame = m_exe_ctx.GetFramePtr();
191335617911SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
191435617911SEd Maste         Target *target = m_exe_ctx.GetTargetPtr();
191535617911SEd Maste         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
191635617911SEd Maste 
191735617911SEd Maste         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
191835617911SEd Maste         {
191935617911SEd Maste             // Use this address directly.
192035617911SEd Maste             Address dest = Address(m_options.m_load_addr);
192135617911SEd Maste 
192235617911SEd Maste             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
192335617911SEd Maste             if (callAddr == LLDB_INVALID_ADDRESS)
192435617911SEd Maste             {
192535617911SEd Maste                 result.AppendErrorWithFormat ("Invalid destination address.");
192635617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
192735617911SEd Maste                 return false;
192835617911SEd Maste             }
192935617911SEd Maste 
193035617911SEd Maste             if (!reg_ctx->SetPC (callAddr))
193135617911SEd Maste             {
193235617911SEd Maste                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
193335617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
193435617911SEd Maste                 return false;
193535617911SEd Maste             }
193635617911SEd Maste         }
193735617911SEd Maste         else
193835617911SEd Maste         {
193935617911SEd Maste             // Pick either the absolute line, or work out a relative one.
194035617911SEd Maste             int32_t line = (int32_t)m_options.m_line_num;
194135617911SEd Maste             if (line == 0)
194235617911SEd Maste                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
194335617911SEd Maste 
194435617911SEd Maste             // Try the current file, but override if asked.
194535617911SEd Maste             FileSpec file = sym_ctx.line_entry.file;
194635617911SEd Maste             if (m_options.m_filenames.GetSize() == 1)
194735617911SEd Maste                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
194835617911SEd Maste 
194935617911SEd Maste             if (!file)
195035617911SEd Maste             {
195135617911SEd Maste                 result.AppendErrorWithFormat ("No source file available for the current location.");
195235617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
195335617911SEd Maste                 return false;
195435617911SEd Maste             }
195535617911SEd Maste 
195635617911SEd Maste             std::string warnings;
195735617911SEd Maste             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
195835617911SEd Maste 
195935617911SEd Maste             if (err.Fail())
196035617911SEd Maste             {
196135617911SEd Maste                 result.SetError (err);
196235617911SEd Maste                 return false;
196335617911SEd Maste             }
196435617911SEd Maste 
196535617911SEd Maste             if (!warnings.empty())
196635617911SEd Maste                 result.AppendWarning (warnings.c_str());
196735617911SEd Maste         }
196835617911SEd Maste 
196935617911SEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
197035617911SEd Maste         return true;
197135617911SEd Maste     }
197235617911SEd Maste 
197335617911SEd Maste     CommandOptions m_options;
197435617911SEd Maste };
197535617911SEd Maste OptionDefinition
197635617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] =
197735617911SEd Maste {
19780127ef0fSEd Maste     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
197935617911SEd Maste         "Specifies the source file to jump to."},
198035617911SEd Maste 
19810127ef0fSEd Maste     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
198235617911SEd Maste         "Specifies the line number to jump to."},
198335617911SEd Maste 
19840127ef0fSEd Maste     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
198535617911SEd Maste         "Jumps by a relative line offset from the current line."},
198635617911SEd Maste 
19870127ef0fSEd Maste     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
198835617911SEd Maste         "Jumps to a specific address."},
198935617911SEd Maste 
199035617911SEd Maste     { LLDB_OPT_SET_1|
199135617911SEd Maste       LLDB_OPT_SET_2|
19920127ef0fSEd Maste       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
199335617911SEd Maste 
19940127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1995ac7ddfbfSEd Maste };
1996ac7ddfbfSEd Maste 
1997ac7ddfbfSEd Maste //-------------------------------------------------------------------------
19987aa51b79SEd Maste // Next are the subcommands of CommandObjectMultiwordThreadPlan
19997aa51b79SEd Maste //-------------------------------------------------------------------------
20007aa51b79SEd Maste 
20017aa51b79SEd Maste 
20027aa51b79SEd Maste //-------------------------------------------------------------------------
20037aa51b79SEd Maste // CommandObjectThreadPlanList
20047aa51b79SEd Maste //-------------------------------------------------------------------------
20057aa51b79SEd Maste class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
20067aa51b79SEd Maste {
20077aa51b79SEd Maste public:
20087aa51b79SEd Maste 
20097aa51b79SEd Maste     class CommandOptions : public Options
20107aa51b79SEd Maste     {
20117aa51b79SEd Maste     public:
20127aa51b79SEd Maste 
20137aa51b79SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
20147aa51b79SEd Maste             Options(interpreter)
20157aa51b79SEd Maste         {
20167aa51b79SEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
20177aa51b79SEd Maste             OptionParsingStarting ();
20187aa51b79SEd Maste         }
20197aa51b79SEd Maste 
20207aa51b79SEd Maste         virtual
20217aa51b79SEd Maste         ~CommandOptions ()
20227aa51b79SEd Maste         {
20237aa51b79SEd Maste         }
20247aa51b79SEd Maste 
20257aa51b79SEd Maste         virtual Error
20267aa51b79SEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
20277aa51b79SEd Maste         {
20287aa51b79SEd Maste             Error error;
20297aa51b79SEd Maste             const int short_option = m_getopt_table[option_idx].val;
20307aa51b79SEd Maste 
20317aa51b79SEd Maste             switch (short_option)
20327aa51b79SEd Maste             {
20337aa51b79SEd Maste                 case 'i':
20347aa51b79SEd Maste                 {
20357aa51b79SEd Maste                     m_internal = true;
20367aa51b79SEd Maste                 }
20377aa51b79SEd Maste                 break;
20387aa51b79SEd Maste                 case 'v':
20397aa51b79SEd Maste                 {
20407aa51b79SEd Maste                     m_verbose = true;
20417aa51b79SEd Maste                 }
20427aa51b79SEd Maste                 break;
20437aa51b79SEd Maste                 default:
20447aa51b79SEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
20457aa51b79SEd Maste                     break;
20467aa51b79SEd Maste 
20477aa51b79SEd Maste             }
20487aa51b79SEd Maste             return error;
20497aa51b79SEd Maste         }
20507aa51b79SEd Maste 
20517aa51b79SEd Maste         void
20527aa51b79SEd Maste         OptionParsingStarting ()
20537aa51b79SEd Maste         {
20547aa51b79SEd Maste             m_verbose = false;
20557aa51b79SEd Maste             m_internal = false;
20567aa51b79SEd Maste         }
20577aa51b79SEd Maste 
20587aa51b79SEd Maste         const OptionDefinition*
20597aa51b79SEd Maste         GetDefinitions ()
20607aa51b79SEd Maste         {
20617aa51b79SEd Maste             return g_option_table;
20627aa51b79SEd Maste         }
20637aa51b79SEd Maste 
20647aa51b79SEd Maste         // Options table: Required for subclasses of Options.
20657aa51b79SEd Maste 
20667aa51b79SEd Maste         static OptionDefinition g_option_table[];
20677aa51b79SEd Maste 
20687aa51b79SEd Maste         // Instance variables to hold the values for command options.
20697aa51b79SEd Maste         bool m_verbose;
20707aa51b79SEd Maste         bool m_internal;
20717aa51b79SEd Maste     };
20727aa51b79SEd Maste 
20737aa51b79SEd Maste     CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
20747aa51b79SEd Maste         CommandObjectIterateOverThreads (interpreter,
20757aa51b79SEd Maste                                          "thread plan list",
20767aa51b79SEd Maste                                          "Show thread plans for one or more threads.  If no threads are specified, show the "
20777aa51b79SEd Maste                                          "currently selected thread.  Use the thread-index \"all\" to see all threads.",
20787aa51b79SEd Maste                                          NULL,
20791c3bbb01SEd Maste                                          eCommandRequiresProcess       |
20801c3bbb01SEd Maste                                          eCommandRequiresThread        |
20811c3bbb01SEd Maste                                          eCommandTryTargetAPILock      |
20821c3bbb01SEd Maste                                          eCommandProcessMustBeLaunched |
20831c3bbb01SEd Maste                                          eCommandProcessMustBePaused   ),
20847aa51b79SEd Maste         m_options(interpreter)
20857aa51b79SEd Maste     {
20867aa51b79SEd Maste     }
20877aa51b79SEd Maste 
20887aa51b79SEd Maste     ~CommandObjectThreadPlanList ()
20897aa51b79SEd Maste     {
20907aa51b79SEd Maste     }
20917aa51b79SEd Maste 
20927aa51b79SEd Maste     virtual Options *
20937aa51b79SEd Maste     GetOptions ()
20947aa51b79SEd Maste     {
20957aa51b79SEd Maste         return &m_options;
20967aa51b79SEd Maste     }
20977aa51b79SEd Maste 
20987aa51b79SEd Maste protected:
20997aa51b79SEd Maste     virtual bool
21007aa51b79SEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result)
21017aa51b79SEd Maste     {
21027aa51b79SEd Maste         Stream &strm = result.GetOutputStream();
21037aa51b79SEd Maste         DescriptionLevel desc_level = eDescriptionLevelFull;
21047aa51b79SEd Maste         if (m_options.m_verbose)
21057aa51b79SEd Maste             desc_level = eDescriptionLevelVerbose;
21067aa51b79SEd Maste 
21077aa51b79SEd Maste         thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
21087aa51b79SEd Maste         return true;
21097aa51b79SEd Maste     }
21107aa51b79SEd Maste     CommandOptions m_options;
21117aa51b79SEd Maste };
21127aa51b79SEd Maste 
21137aa51b79SEd Maste OptionDefinition
21147aa51b79SEd Maste CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
21157aa51b79SEd Maste {
21167aa51b79SEd Maste { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
21177aa51b79SEd Maste { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
21187aa51b79SEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
21197aa51b79SEd Maste };
21207aa51b79SEd Maste 
21217aa51b79SEd Maste class CommandObjectThreadPlanDiscard : public CommandObjectParsed
21227aa51b79SEd Maste {
21237aa51b79SEd Maste public:
21247aa51b79SEd Maste     CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
21257aa51b79SEd Maste         CommandObjectParsed (interpreter,
21267aa51b79SEd Maste                              "thread plan discard",
21277aa51b79SEd Maste                              "Discards thread plans up to and including the plan passed as the command argument."
21287aa51b79SEd Maste                              "Only user visible plans can be discarded, use the index from \"thread plan list\""
21297aa51b79SEd Maste                              " without the \"-i\" argument.",
21307aa51b79SEd Maste                              NULL,
21311c3bbb01SEd Maste                              eCommandRequiresProcess       |
21321c3bbb01SEd Maste                              eCommandRequiresThread        |
21331c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
21341c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
21351c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
21367aa51b79SEd Maste     {
21377aa51b79SEd Maste         CommandArgumentEntry arg;
21387aa51b79SEd Maste         CommandArgumentData plan_index_arg;
21397aa51b79SEd Maste 
21407aa51b79SEd Maste         // Define the first (and only) variant of this arg.
21417aa51b79SEd Maste         plan_index_arg.arg_type = eArgTypeUnsignedInteger;
21427aa51b79SEd Maste         plan_index_arg.arg_repetition = eArgRepeatPlain;
21437aa51b79SEd Maste 
21447aa51b79SEd Maste         // There is only one variant this argument could be; put it into the argument entry.
21457aa51b79SEd Maste         arg.push_back (plan_index_arg);
21467aa51b79SEd Maste 
21477aa51b79SEd Maste         // Push the data for the first argument into the m_arguments vector.
21487aa51b79SEd Maste         m_arguments.push_back (arg);
21497aa51b79SEd Maste     }
21507aa51b79SEd Maste 
21517aa51b79SEd Maste     virtual ~CommandObjectThreadPlanDiscard () {}
21527aa51b79SEd Maste 
21537aa51b79SEd Maste     bool
21547aa51b79SEd Maste     DoExecute (Args& args, CommandReturnObject &result)
21557aa51b79SEd Maste     {
21567aa51b79SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
21577aa51b79SEd Maste         if (args.GetArgumentCount() != 1)
21587aa51b79SEd Maste         {
21597aa51b79SEd Maste             result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
21607aa51b79SEd Maste                                          args.GetArgumentCount());
21617aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21627aa51b79SEd Maste             return false;
21637aa51b79SEd Maste         }
21647aa51b79SEd Maste 
21657aa51b79SEd Maste         bool success;
21661c3bbb01SEd Maste         uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
21677aa51b79SEd Maste         if (!success)
21687aa51b79SEd Maste         {
21697aa51b79SEd Maste             result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
21707aa51b79SEd Maste                                          args.GetArgumentAtIndex(0));
21717aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21727aa51b79SEd Maste             return false;
21737aa51b79SEd Maste         }
21747aa51b79SEd Maste 
21757aa51b79SEd Maste         if (thread_plan_idx == 0)
21767aa51b79SEd Maste         {
21777aa51b79SEd Maste             result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
21787aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21797aa51b79SEd Maste             return false;
21807aa51b79SEd Maste         }
21817aa51b79SEd Maste 
21827aa51b79SEd Maste         if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
21837aa51b79SEd Maste         {
21847aa51b79SEd Maste             result.SetStatus(eReturnStatusSuccessFinishNoResult);
21857aa51b79SEd Maste             return true;
21867aa51b79SEd Maste         }
21877aa51b79SEd Maste         else
21887aa51b79SEd Maste         {
21897aa51b79SEd Maste             result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
21907aa51b79SEd Maste                                          args.GetArgumentAtIndex(0));
21917aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21927aa51b79SEd Maste             return false;
21937aa51b79SEd Maste         }
21947aa51b79SEd Maste     }
21957aa51b79SEd Maste };
21967aa51b79SEd Maste 
21977aa51b79SEd Maste //-------------------------------------------------------------------------
21987aa51b79SEd Maste // CommandObjectMultiwordThreadPlan
21997aa51b79SEd Maste //-------------------------------------------------------------------------
22007aa51b79SEd Maste 
22017aa51b79SEd Maste class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
22027aa51b79SEd Maste {
22037aa51b79SEd Maste public:
22047aa51b79SEd Maste     CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
22057aa51b79SEd Maste         CommandObjectMultiword (interpreter,
22067aa51b79SEd Maste                                 "plan",
22077aa51b79SEd Maste                                 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
22087aa51b79SEd Maste                                 "thread plan <subcommand> [<subcommand objects]")
22097aa51b79SEd Maste     {
22107aa51b79SEd Maste         LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
22117aa51b79SEd Maste         LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
22127aa51b79SEd Maste     }
22137aa51b79SEd Maste 
22147aa51b79SEd Maste     virtual ~CommandObjectMultiwordThreadPlan () {}
22157aa51b79SEd Maste 
22167aa51b79SEd Maste 
22177aa51b79SEd Maste };
22187aa51b79SEd Maste 
22197aa51b79SEd Maste //-------------------------------------------------------------------------
2220ac7ddfbfSEd Maste // CommandObjectMultiwordThread
2221ac7ddfbfSEd Maste //-------------------------------------------------------------------------
2222ac7ddfbfSEd Maste 
2223ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
2224ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
2225ac7ddfbfSEd Maste                             "thread",
2226ac7ddfbfSEd Maste                             "A set of commands for operating on one or more threads within a running process.",
2227ac7ddfbfSEd Maste                             "thread <subcommand> [<subcommand-options>]")
2228ac7ddfbfSEd Maste {
2229ac7ddfbfSEd Maste     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
2230ac7ddfbfSEd Maste     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
2231ac7ddfbfSEd Maste     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
2232ac7ddfbfSEd Maste     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
223335617911SEd Maste     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
2234ac7ddfbfSEd Maste     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
2235ac7ddfbfSEd Maste     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
22360127ef0fSEd Maste     LoadSubCommand ("info",       CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
2237ac7ddfbfSEd Maste     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2238ac7ddfbfSEd Maste                                                     interpreter,
2239ac7ddfbfSEd Maste                                                     "thread step-in",
2240ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified).",
2241ac7ddfbfSEd Maste                                                     NULL,
2242ac7ddfbfSEd Maste                                                     eStepTypeInto,
2243ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2244ac7ddfbfSEd Maste 
2245ac7ddfbfSEd Maste     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2246ac7ddfbfSEd Maste                                                     interpreter,
2247ac7ddfbfSEd Maste                                                     "thread step-out",
2248ac7ddfbfSEd Maste                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
2249ac7ddfbfSEd Maste                                                     NULL,
2250ac7ddfbfSEd Maste                                                     eStepTypeOut,
2251ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2252ac7ddfbfSEd Maste 
2253ac7ddfbfSEd Maste     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2254ac7ddfbfSEd Maste                                                     interpreter,
2255ac7ddfbfSEd Maste                                                     "thread step-over",
2256ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
2257ac7ddfbfSEd Maste                                                     NULL,
2258ac7ddfbfSEd Maste                                                     eStepTypeOver,
2259ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2260ac7ddfbfSEd Maste 
2261ac7ddfbfSEd Maste     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2262ac7ddfbfSEd Maste                                                     interpreter,
2263ac7ddfbfSEd Maste                                                     "thread step-inst",
2264ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified).",
2265ac7ddfbfSEd Maste                                                     NULL,
2266ac7ddfbfSEd Maste                                                     eStepTypeTrace,
2267ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
2268ac7ddfbfSEd Maste 
2269ac7ddfbfSEd Maste     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2270ac7ddfbfSEd Maste                                                     interpreter,
2271ac7ddfbfSEd Maste                                                     "thread step-inst-over",
2272ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
2273ac7ddfbfSEd Maste                                                     NULL,
2274ac7ddfbfSEd Maste                                                     eStepTypeTraceOver,
2275ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
22767aa51b79SEd Maste 
22777aa51b79SEd Maste     LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
22787aa51b79SEd Maste                                                     interpreter,
22797aa51b79SEd Maste                                                     "thread step-scripted",
22807aa51b79SEd Maste                                                     "Step as instructed by the script class passed in the -C option.",
22817aa51b79SEd Maste                                                     NULL,
22827aa51b79SEd Maste                                                     eStepTypeScripted,
22837aa51b79SEd Maste                                                     eStepScopeSource)));
22847aa51b79SEd Maste 
22857aa51b79SEd Maste     LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
2286ac7ddfbfSEd Maste }
2287ac7ddfbfSEd Maste 
2288ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
2289ac7ddfbfSEd Maste {
2290ac7ddfbfSEd Maste }
2291ac7ddfbfSEd Maste 
2292ac7ddfbfSEd Maste 
2293