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 
619f2f44ceSEd Maste     ~CommandObjectIterateOverThreads() override {}
629f2f44ceSEd Maste 
639f2f44ceSEd Maste     bool
649f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
657aa51b79SEd Maste     {
667aa51b79SEd Maste         result.SetStatus (m_success_return);
677aa51b79SEd Maste 
687aa51b79SEd Maste         if (command.GetArgumentCount() == 0)
697aa51b79SEd Maste         {
707aa51b79SEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
717aa51b79SEd Maste             if (!HandleOneThread (*thread, result))
727aa51b79SEd Maste                 return false;
737aa51b79SEd Maste         }
747aa51b79SEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
757aa51b79SEd Maste         {
767aa51b79SEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
777aa51b79SEd Maste             uint32_t idx = 0;
787aa51b79SEd Maste             for (ThreadSP thread_sp : process->Threads())
797aa51b79SEd Maste             {
807aa51b79SEd Maste                 if (idx != 0 && m_add_return)
817aa51b79SEd Maste                     result.AppendMessage("");
827aa51b79SEd Maste 
837aa51b79SEd Maste                 if (!HandleOneThread(*(thread_sp.get()), result))
847aa51b79SEd Maste                     return false;
857aa51b79SEd Maste                 ++idx;
867aa51b79SEd Maste             }
877aa51b79SEd Maste         }
887aa51b79SEd Maste         else
897aa51b79SEd Maste         {
907aa51b79SEd Maste             const size_t num_args = command.GetArgumentCount();
917aa51b79SEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
927aa51b79SEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
937aa51b79SEd Maste             std::vector<ThreadSP> thread_sps;
947aa51b79SEd Maste 
957aa51b79SEd Maste             for (size_t i = 0; i < num_args; i++)
967aa51b79SEd Maste             {
977aa51b79SEd Maste                 bool success;
987aa51b79SEd Maste 
991c3bbb01SEd Maste                 uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
1007aa51b79SEd Maste                 if (!success)
1017aa51b79SEd Maste                 {
1027aa51b79SEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
1037aa51b79SEd Maste                     result.SetStatus (eReturnStatusFailed);
1047aa51b79SEd Maste                     return false;
1057aa51b79SEd Maste                 }
1067aa51b79SEd Maste 
1077aa51b79SEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
1087aa51b79SEd Maste 
1097aa51b79SEd Maste                 if (!thread_sps[i])
1107aa51b79SEd Maste                 {
1117aa51b79SEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
1127aa51b79SEd Maste                     result.SetStatus (eReturnStatusFailed);
1137aa51b79SEd Maste                     return false;
1147aa51b79SEd Maste                 }
1157aa51b79SEd Maste 
1167aa51b79SEd Maste             }
1177aa51b79SEd Maste 
1187aa51b79SEd Maste             for (uint32_t i = 0; i < num_args; i++)
1197aa51b79SEd Maste             {
1207aa51b79SEd Maste                 if (!HandleOneThread (*(thread_sps[i].get()), result))
1217aa51b79SEd Maste                     return false;
1227aa51b79SEd Maste 
1237aa51b79SEd Maste                 if (i < num_args - 1 && m_add_return)
1247aa51b79SEd Maste                     result.AppendMessage("");
1257aa51b79SEd Maste             }
1267aa51b79SEd Maste         }
1277aa51b79SEd Maste         return result.Succeeded();
1287aa51b79SEd Maste     }
1297aa51b79SEd Maste 
1307aa51b79SEd Maste protected:
1317aa51b79SEd Maste 
1327aa51b79SEd Maste     // Override this to do whatever you need to do for one thread.
1337aa51b79SEd Maste     //
1347aa51b79SEd Maste     // If you return false, the iteration will stop, otherwise it will proceed.
1357aa51b79SEd Maste     // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
1367aa51b79SEd Maste     // so you only need to set the return status in HandleOneThread if you want to indicate an error.
1377aa51b79SEd Maste     // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
1387aa51b79SEd Maste 
1397aa51b79SEd Maste     virtual bool
1407aa51b79SEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
1417aa51b79SEd Maste 
1427aa51b79SEd Maste     ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
1437aa51b79SEd Maste     bool m_add_return = true;
1447aa51b79SEd Maste 
1457aa51b79SEd Maste };
1467aa51b79SEd Maste 
1477aa51b79SEd Maste //-------------------------------------------------------------------------
1487aa51b79SEd Maste // CommandObjectThreadBacktrace
1497aa51b79SEd Maste //-------------------------------------------------------------------------
1507aa51b79SEd Maste 
1517aa51b79SEd Maste class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
152ac7ddfbfSEd Maste {
153ac7ddfbfSEd Maste public:
154ac7ddfbfSEd Maste 
155ac7ddfbfSEd Maste     class CommandOptions : public Options
156ac7ddfbfSEd Maste     {
157ac7ddfbfSEd Maste     public:
158ac7ddfbfSEd Maste 
159ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
160ac7ddfbfSEd Maste             Options(interpreter)
161ac7ddfbfSEd Maste         {
162ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
163ac7ddfbfSEd Maste             OptionParsingStarting ();
164ac7ddfbfSEd Maste         }
165ac7ddfbfSEd Maste 
1669f2f44ceSEd Maste         ~CommandOptions () override
167ac7ddfbfSEd Maste         {
168ac7ddfbfSEd Maste         }
169ac7ddfbfSEd Maste 
1709f2f44ceSEd Maste         Error
1719f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
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
2149f2f44ceSEd Maste         OptionParsingStarting () override
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*
2229f2f44ceSEd Maste         GetDefinitions () override
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 
2519f2f44ceSEd Maste     ~CommandObjectThreadBacktrace() override
252ac7ddfbfSEd Maste     {
253ac7ddfbfSEd Maste     }
254ac7ddfbfSEd Maste 
2559f2f44ceSEd Maste     Options *
2569f2f44ceSEd Maste     GetOptions () override
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 
2889f2f44ceSEd Maste     bool
2899f2f44ceSEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result) override
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 
3469f2f44ceSEd Maste         ~CommandOptions () override
347ac7ddfbfSEd Maste         {
348ac7ddfbfSEd Maste         }
349ac7ddfbfSEd Maste 
3509f2f44ceSEd Maste         Error
3519f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
352ac7ddfbfSEd Maste         {
353ac7ddfbfSEd Maste             Error error;
354ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
355ac7ddfbfSEd Maste 
356ac7ddfbfSEd Maste             switch (short_option)
357ac7ddfbfSEd Maste             {
358ac7ddfbfSEd Maste             case 'a':
359ac7ddfbfSEd Maste                 {
360ac7ddfbfSEd Maste                     bool success;
3610127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
362ac7ddfbfSEd Maste                     if (!success)
363ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3640127ef0fSEd Maste                     else
3650127ef0fSEd Maste                     {
3660127ef0fSEd Maste                         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3670127ef0fSEd Maste                     }
368ac7ddfbfSEd Maste                 }
369ac7ddfbfSEd Maste                 break;
370ac7ddfbfSEd Maste 
3710127ef0fSEd Maste             case 'A':
3720127ef0fSEd Maste                 {
3730127ef0fSEd Maste                     bool success;
3740127ef0fSEd Maste                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
3750127ef0fSEd Maste                     if (!success)
3760127ef0fSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
3770127ef0fSEd Maste                     else
3780127ef0fSEd Maste                     {
3790127ef0fSEd Maste                         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
3800127ef0fSEd Maste                     }
3810127ef0fSEd Maste                 }
3820127ef0fSEd Maste                 break;
3830127ef0fSEd Maste 
3840127ef0fSEd Maste             case 'c':
3850127ef0fSEd Maste                 {
3861c3bbb01SEd Maste                     m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
3870127ef0fSEd Maste                     if (m_step_count == UINT32_MAX)
3880127ef0fSEd Maste                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
3890127ef0fSEd Maste                     break;
3900127ef0fSEd Maste                 }
3910127ef0fSEd Maste                 break;
3927aa51b79SEd Maste             case 'C':
3937aa51b79SEd Maste                 {
3947aa51b79SEd Maste                     m_class_name.clear();
3957aa51b79SEd Maste                     m_class_name.assign(option_arg);
3967aa51b79SEd Maste                 }
3977aa51b79SEd Maste                 break;
398ac7ddfbfSEd Maste             case 'm':
399ac7ddfbfSEd Maste                 {
400ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
401ac7ddfbfSEd Maste                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
402ac7ddfbfSEd Maste                 }
403ac7ddfbfSEd Maste                 break;
404ac7ddfbfSEd Maste 
405ac7ddfbfSEd Maste             case 'r':
406ac7ddfbfSEd Maste                 {
407ac7ddfbfSEd Maste                     m_avoid_regexp.clear();
408ac7ddfbfSEd Maste                     m_avoid_regexp.assign(option_arg);
409ac7ddfbfSEd Maste                 }
410ac7ddfbfSEd Maste                 break;
411ac7ddfbfSEd Maste 
412ac7ddfbfSEd Maste             case 't':
413ac7ddfbfSEd Maste                 {
414ac7ddfbfSEd Maste                     m_step_in_target.clear();
415ac7ddfbfSEd Maste                     m_step_in_target.assign(option_arg);
416ac7ddfbfSEd Maste 
417ac7ddfbfSEd Maste                 }
418ac7ddfbfSEd Maste                 break;
419ac7ddfbfSEd Maste             default:
420ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
421ac7ddfbfSEd Maste                 break;
422ac7ddfbfSEd Maste 
423ac7ddfbfSEd Maste             }
424ac7ddfbfSEd Maste             return error;
425ac7ddfbfSEd Maste         }
426ac7ddfbfSEd Maste 
427ac7ddfbfSEd Maste         void
4289f2f44ceSEd Maste         OptionParsingStarting () override
429ac7ddfbfSEd Maste         {
4300127ef0fSEd Maste             m_step_in_avoid_no_debug = eLazyBoolCalculate;
4310127ef0fSEd Maste             m_step_out_avoid_no_debug = eLazyBoolCalculate;
432ac7ddfbfSEd Maste             m_run_mode = eOnlyDuringStepping;
4331c3bbb01SEd Maste 
4341c3bbb01SEd Maste             // Check if we are in Non-Stop mode
4351c3bbb01SEd Maste             lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
4361c3bbb01SEd Maste             if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled())
4371c3bbb01SEd Maste                 m_run_mode = eOnlyThisThread;
4381c3bbb01SEd Maste 
439ac7ddfbfSEd Maste             m_avoid_regexp.clear();
440ac7ddfbfSEd Maste             m_step_in_target.clear();
4417aa51b79SEd Maste             m_class_name.clear();
4420127ef0fSEd Maste             m_step_count = 1;
443ac7ddfbfSEd Maste         }
444ac7ddfbfSEd Maste 
445ac7ddfbfSEd Maste         const OptionDefinition*
4469f2f44ceSEd Maste         GetDefinitions () override
447ac7ddfbfSEd Maste         {
448ac7ddfbfSEd Maste             return g_option_table;
449ac7ddfbfSEd Maste         }
450ac7ddfbfSEd Maste 
451ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
452ac7ddfbfSEd Maste 
453ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
454ac7ddfbfSEd Maste 
455ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
4560127ef0fSEd Maste         LazyBool m_step_in_avoid_no_debug;
4570127ef0fSEd Maste         LazyBool m_step_out_avoid_no_debug;
458ac7ddfbfSEd Maste         RunMode m_run_mode;
459ac7ddfbfSEd Maste         std::string m_avoid_regexp;
460ac7ddfbfSEd Maste         std::string m_step_in_target;
4617aa51b79SEd Maste         std::string m_class_name;
4627aa51b79SEd Maste         uint32_t m_step_count;
463ac7ddfbfSEd Maste     };
464ac7ddfbfSEd Maste 
465ac7ddfbfSEd Maste     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
466ac7ddfbfSEd Maste                                              const char *name,
467ac7ddfbfSEd Maste                                              const char *help,
468ac7ddfbfSEd Maste                                              const char *syntax,
469ac7ddfbfSEd Maste                                              StepType step_type,
470ac7ddfbfSEd Maste                                              StepScope step_scope) :
471ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax,
4721c3bbb01SEd Maste                              eCommandRequiresProcess       |
4731c3bbb01SEd Maste                              eCommandRequiresThread        |
4741c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
4751c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
4761c3bbb01SEd Maste                              eCommandProcessMustBePaused   ),
477ac7ddfbfSEd Maste         m_step_type (step_type),
478ac7ddfbfSEd Maste         m_step_scope (step_scope),
479ac7ddfbfSEd Maste         m_options (interpreter)
480ac7ddfbfSEd Maste     {
481ac7ddfbfSEd Maste         CommandArgumentEntry arg;
482ac7ddfbfSEd Maste         CommandArgumentData thread_id_arg;
483ac7ddfbfSEd Maste 
484ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
485ac7ddfbfSEd Maste         thread_id_arg.arg_type = eArgTypeThreadID;
486ac7ddfbfSEd Maste         thread_id_arg.arg_repetition = eArgRepeatOptional;
487ac7ddfbfSEd Maste 
488ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
489ac7ddfbfSEd Maste         arg.push_back (thread_id_arg);
490ac7ddfbfSEd Maste 
491ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
492ac7ddfbfSEd Maste         m_arguments.push_back (arg);
493ac7ddfbfSEd Maste     }
494ac7ddfbfSEd Maste 
4959f2f44ceSEd Maste     ~CommandObjectThreadStepWithTypeAndScope () override
496ac7ddfbfSEd Maste     {
497ac7ddfbfSEd Maste     }
498ac7ddfbfSEd Maste 
499ac7ddfbfSEd Maste     Options *
5009f2f44ceSEd Maste     GetOptions () override
501ac7ddfbfSEd Maste     {
502ac7ddfbfSEd Maste         return &m_options;
503ac7ddfbfSEd Maste     }
504ac7ddfbfSEd Maste 
505ac7ddfbfSEd Maste protected:
5069f2f44ceSEd Maste     bool
5079f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
508ac7ddfbfSEd Maste     {
509ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
510ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous();
511ac7ddfbfSEd Maste 
512ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
513ac7ddfbfSEd Maste         Thread *thread = NULL;
514ac7ddfbfSEd Maste 
515ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
516ac7ddfbfSEd Maste         {
517ac7ddfbfSEd Maste             thread = process->GetThreadList().GetSelectedThread().get();
518ac7ddfbfSEd Maste             if (thread == NULL)
519ac7ddfbfSEd Maste             {
520ac7ddfbfSEd Maste                 result.AppendError ("no selected thread in process");
521ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
522ac7ddfbfSEd Maste                 return false;
523ac7ddfbfSEd Maste             }
524ac7ddfbfSEd Maste         }
525ac7ddfbfSEd Maste         else
526ac7ddfbfSEd Maste         {
527ac7ddfbfSEd Maste             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
5281c3bbb01SEd Maste             uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
529ac7ddfbfSEd Maste             if (step_thread_idx == LLDB_INVALID_INDEX32)
530ac7ddfbfSEd Maste             {
531ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
532ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
533ac7ddfbfSEd Maste                 return false;
534ac7ddfbfSEd Maste             }
535ac7ddfbfSEd Maste             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
536ac7ddfbfSEd Maste             if (thread == NULL)
537ac7ddfbfSEd Maste             {
538ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
539ac7ddfbfSEd Maste                                               step_thread_idx, num_threads);
540ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
541ac7ddfbfSEd Maste                 return false;
542ac7ddfbfSEd Maste             }
543ac7ddfbfSEd Maste         }
544ac7ddfbfSEd Maste 
5457aa51b79SEd Maste         if (m_step_type == eStepTypeScripted)
5467aa51b79SEd Maste         {
5477aa51b79SEd Maste             if (m_options.m_class_name.empty())
5487aa51b79SEd Maste             {
5497aa51b79SEd Maste                 result.AppendErrorWithFormat ("empty class name for scripted step.");
5507aa51b79SEd Maste                 result.SetStatus(eReturnStatusFailed);
5517aa51b79SEd Maste                 return false;
5527aa51b79SEd Maste             }
5537aa51b79SEd Maste             else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
5547aa51b79SEd Maste             {
5557aa51b79SEd Maste                 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
5567aa51b79SEd Maste                 result.SetStatus(eReturnStatusFailed);
5577aa51b79SEd Maste                 return false;
5587aa51b79SEd Maste             }
5597aa51b79SEd Maste         }
5607aa51b79SEd Maste 
561ac7ddfbfSEd Maste         const bool abort_other_plans = false;
562ac7ddfbfSEd Maste         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
563ac7ddfbfSEd Maste 
564ac7ddfbfSEd Maste         // This is a bit unfortunate, but not all the commands in this command object support
565ac7ddfbfSEd Maste         // only while stepping, so I use the bool for them.
566ac7ddfbfSEd Maste         bool bool_stop_other_threads;
567ac7ddfbfSEd Maste         if (m_options.m_run_mode == eAllThreads)
568ac7ddfbfSEd Maste             bool_stop_other_threads = false;
569ac7ddfbfSEd Maste         else if (m_options.m_run_mode == eOnlyDuringStepping)
570ac7ddfbfSEd Maste         {
5717aa51b79SEd Maste             if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
572ac7ddfbfSEd Maste                 bool_stop_other_threads = false;
573ac7ddfbfSEd Maste             else
574ac7ddfbfSEd Maste                 bool_stop_other_threads = true;
575ac7ddfbfSEd Maste         }
576ac7ddfbfSEd Maste         else
577ac7ddfbfSEd Maste             bool_stop_other_threads = true;
578ac7ddfbfSEd Maste 
579ac7ddfbfSEd Maste         ThreadPlanSP new_plan_sp;
580ac7ddfbfSEd Maste 
581ac7ddfbfSEd Maste         if (m_step_type == eStepTypeInto)
582ac7ddfbfSEd Maste         {
583ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
5841c3bbb01SEd Maste             assert(frame != nullptr);
585ac7ddfbfSEd Maste 
586ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
587ac7ddfbfSEd Maste             {
588ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
5899f2f44ceSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry,
590ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything),
591ac7ddfbfSEd Maste                                                                 m_options.m_step_in_target.c_str(),
592ac7ddfbfSEd Maste                                                                 stop_other_threads,
5930127ef0fSEd Maste                                                                 m_options.m_step_in_avoid_no_debug,
5940127ef0fSEd Maste                                                                 m_options.m_step_out_avoid_no_debug);
5950127ef0fSEd Maste 
596ac7ddfbfSEd Maste                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
597ac7ddfbfSEd Maste                 {
598ac7ddfbfSEd Maste                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
599ac7ddfbfSEd Maste                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
600ac7ddfbfSEd Maste                 }
601ac7ddfbfSEd Maste             }
602ac7ddfbfSEd Maste             else
603ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
604ac7ddfbfSEd Maste 
605ac7ddfbfSEd Maste         }
606ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOver)
607ac7ddfbfSEd Maste         {
608ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste             if (frame->HasDebugInformation())
611ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
6129f2f44ceSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry,
613ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything),
6140127ef0fSEd Maste                                                                     stop_other_threads,
6150127ef0fSEd Maste                                                                     m_options.m_step_out_avoid_no_debug);
616ac7ddfbfSEd Maste             else
617ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
618ac7ddfbfSEd Maste                                                                             abort_other_plans,
619ac7ddfbfSEd Maste                                                                             bool_stop_other_threads);
620ac7ddfbfSEd Maste 
621ac7ddfbfSEd Maste         }
622ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTrace)
623ac7ddfbfSEd Maste         {
624ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
625ac7ddfbfSEd Maste         }
626ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTraceOver)
627ac7ddfbfSEd Maste         {
628ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
629ac7ddfbfSEd Maste         }
630ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOut)
631ac7ddfbfSEd Maste         {
632ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
633ac7ddfbfSEd Maste                                                           NULL,
634ac7ddfbfSEd Maste                                                           false,
635ac7ddfbfSEd Maste                                                           bool_stop_other_threads,
636ac7ddfbfSEd Maste                                                           eVoteYes,
637ac7ddfbfSEd Maste                                                           eVoteNoOpinion,
6380127ef0fSEd Maste                                                           thread->GetSelectedFrameIndex(),
6390127ef0fSEd Maste                                                           m_options.m_step_out_avoid_no_debug);
640ac7ddfbfSEd Maste         }
6417aa51b79SEd Maste         else if (m_step_type == eStepTypeScripted)
6427aa51b79SEd Maste         {
6437aa51b79SEd Maste             new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
6447aa51b79SEd Maste                                                                   m_options.m_class_name.c_str(),
6457aa51b79SEd Maste                                                                   bool_stop_other_threads);
6467aa51b79SEd Maste         }
647ac7ddfbfSEd Maste         else
648ac7ddfbfSEd Maste         {
649ac7ddfbfSEd Maste             result.AppendError ("step type is not supported");
650ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
651ac7ddfbfSEd Maste             return false;
652ac7ddfbfSEd Maste         }
653ac7ddfbfSEd Maste 
654ac7ddfbfSEd Maste         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
655ac7ddfbfSEd Maste         // so that they can be interruptible).  Then resume the process.
656ac7ddfbfSEd Maste 
657ac7ddfbfSEd Maste         if (new_plan_sp)
658ac7ddfbfSEd Maste         {
659ac7ddfbfSEd Maste             new_plan_sp->SetIsMasterPlan (true);
660ac7ddfbfSEd Maste             new_plan_sp->SetOkayToDiscard (false);
661ac7ddfbfSEd Maste 
6620127ef0fSEd Maste             if (m_options.m_step_count > 1)
6630127ef0fSEd Maste             {
6640127ef0fSEd Maste                 if (new_plan_sp->SetIterationCount(m_options.m_step_count))
6650127ef0fSEd Maste                 {
6660127ef0fSEd Maste                     result.AppendWarning ("step operation does not support iteration count.");
6670127ef0fSEd Maste                 }
6680127ef0fSEd Maste             }
6690127ef0fSEd Maste 
6707aa51b79SEd Maste 
671ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
6727aa51b79SEd Maste 
6731c3bbb01SEd Maste             const uint32_t iohandler_id = process->GetIOHandlerID();
6741c3bbb01SEd Maste 
6757aa51b79SEd Maste             StreamString stream;
6767aa51b79SEd Maste             Error error;
6777aa51b79SEd Maste             if (synchronous_execution)
6787aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
6797aa51b79SEd Maste             else
6807aa51b79SEd Maste                 error = process->Resume ();
681ac7ddfbfSEd Maste 
6820127ef0fSEd Maste             // There is a race condition where this thread will return up the call stack to the main command handler
6830127ef0fSEd Maste             // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
6840127ef0fSEd Maste             // a chance to call PushProcessIOHandler().
6851c3bbb01SEd Maste             process->SyncIOHandler(iohandler_id, 2000);
686ac7ddfbfSEd Maste 
687ac7ddfbfSEd Maste             if (synchronous_execution)
688ac7ddfbfSEd Maste             {
6897aa51b79SEd Maste                 // If any state changed events had anything to say, add that to the result
6907aa51b79SEd Maste                 if (stream.GetData())
6917aa51b79SEd Maste                     result.AppendMessage(stream.GetData());
692ac7ddfbfSEd Maste 
693ac7ddfbfSEd Maste                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
694ac7ddfbfSEd Maste                 result.SetDidChangeProcessState (true);
695ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
696ac7ddfbfSEd Maste             }
697ac7ddfbfSEd Maste             else
698ac7ddfbfSEd Maste             {
699ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
700ac7ddfbfSEd Maste             }
701ac7ddfbfSEd Maste         }
702ac7ddfbfSEd Maste         else
703ac7ddfbfSEd Maste         {
704ac7ddfbfSEd Maste             result.AppendError ("Couldn't find thread plan to implement step type.");
705ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
706ac7ddfbfSEd Maste         }
707ac7ddfbfSEd Maste         return result.Succeeded();
708ac7ddfbfSEd Maste     }
709ac7ddfbfSEd Maste 
710ac7ddfbfSEd Maste protected:
711ac7ddfbfSEd Maste     StepType m_step_type;
712ac7ddfbfSEd Maste     StepScope m_step_scope;
713ac7ddfbfSEd Maste     CommandOptions m_options;
714ac7ddfbfSEd Maste };
715ac7ddfbfSEd Maste 
716ac7ddfbfSEd Maste static OptionEnumValueElement
717ac7ddfbfSEd Maste g_tri_running_mode[] =
718ac7ddfbfSEd Maste {
719ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
720ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
721ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
722ac7ddfbfSEd Maste { 0, NULL, NULL }
723ac7ddfbfSEd Maste };
724ac7ddfbfSEd Maste 
725ac7ddfbfSEd Maste static OptionEnumValueElement
726ac7ddfbfSEd Maste g_duo_running_mode[] =
727ac7ddfbfSEd Maste {
728ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
729ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
730ac7ddfbfSEd Maste { 0, NULL, NULL }
731ac7ddfbfSEd Maste };
732ac7ddfbfSEd Maste 
733ac7ddfbfSEd Maste OptionDefinition
734ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
735ac7ddfbfSEd Maste {
7360127ef0fSEd 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."},
7370127ef0fSEd 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."},
7380127ef0fSEd 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."},
7390127ef0fSEd 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."},
7400127ef0fSEd 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."},
7410127ef0fSEd 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."},
7427aa51b79SEd 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."},
7430127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
744ac7ddfbfSEd Maste };
745ac7ddfbfSEd Maste 
746ac7ddfbfSEd Maste 
747ac7ddfbfSEd Maste //-------------------------------------------------------------------------
748ac7ddfbfSEd Maste // CommandObjectThreadContinue
749ac7ddfbfSEd Maste //-------------------------------------------------------------------------
750ac7ddfbfSEd Maste 
751ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed
752ac7ddfbfSEd Maste {
753ac7ddfbfSEd Maste public:
754ac7ddfbfSEd Maste 
755ac7ddfbfSEd Maste     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
756ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
757ac7ddfbfSEd Maste                              "thread continue",
758ac7ddfbfSEd Maste                              "Continue execution of one or more threads in an active process.",
759ac7ddfbfSEd Maste                              NULL,
7601c3bbb01SEd Maste                              eCommandRequiresThread        |
7611c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
7621c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
7631c3bbb01SEd Maste                              eCommandProcessMustBePaused)
764ac7ddfbfSEd Maste     {
765ac7ddfbfSEd Maste         CommandArgumentEntry arg;
766ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
767ac7ddfbfSEd Maste 
768ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
769ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
770ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlus;
771ac7ddfbfSEd Maste 
772ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
773ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
774ac7ddfbfSEd Maste 
775ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
776ac7ddfbfSEd Maste         m_arguments.push_back (arg);
777ac7ddfbfSEd Maste     }
778ac7ddfbfSEd Maste 
779ac7ddfbfSEd Maste 
7809f2f44ceSEd Maste     ~CommandObjectThreadContinue () override
781ac7ddfbfSEd Maste     {
782ac7ddfbfSEd Maste     }
783ac7ddfbfSEd Maste 
7849f2f44ceSEd Maste     bool
7859f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
786ac7ddfbfSEd Maste     {
787ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
788ac7ddfbfSEd Maste 
789ac7ddfbfSEd Maste         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
790ac7ddfbfSEd Maste         {
791ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
792ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
793ac7ddfbfSEd Maste             return false;
794ac7ddfbfSEd Maste         }
795ac7ddfbfSEd Maste 
796ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
797ac7ddfbfSEd Maste         if (process == NULL)
798ac7ddfbfSEd Maste         {
799ac7ddfbfSEd Maste             result.AppendError ("no process exists. Cannot continue");
800ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
801ac7ddfbfSEd Maste             return false;
802ac7ddfbfSEd Maste         }
803ac7ddfbfSEd Maste 
804ac7ddfbfSEd Maste         StateType state = process->GetState();
805ac7ddfbfSEd Maste         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
806ac7ddfbfSEd Maste         {
807ac7ddfbfSEd Maste             const size_t argc = command.GetArgumentCount();
808ac7ddfbfSEd Maste             if (argc > 0)
809ac7ddfbfSEd Maste             {
81035617911SEd Maste                 // These two lines appear at the beginning of both blocks in
81135617911SEd Maste                 // this if..else, but that is because we need to release the
81235617911SEd Maste                 // lock before calling process->Resume below.
81335617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
81435617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
815ac7ddfbfSEd Maste                 std::vector<Thread *> resume_threads;
816ac7ddfbfSEd Maste                 for (uint32_t i=0; i<argc; ++i)
817ac7ddfbfSEd Maste                 {
818ac7ddfbfSEd Maste                     bool success;
819ac7ddfbfSEd Maste                     const int base = 0;
8201c3bbb01SEd Maste                     uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
821ac7ddfbfSEd Maste                     if (success)
822ac7ddfbfSEd Maste                     {
823ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
824ac7ddfbfSEd Maste 
825ac7ddfbfSEd Maste                         if (thread)
826ac7ddfbfSEd Maste                         {
827ac7ddfbfSEd Maste                             resume_threads.push_back(thread);
828ac7ddfbfSEd Maste                         }
829ac7ddfbfSEd Maste                         else
830ac7ddfbfSEd Maste                         {
831ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
832ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
833ac7ddfbfSEd Maste                             return false;
834ac7ddfbfSEd Maste                         }
835ac7ddfbfSEd Maste                     }
836ac7ddfbfSEd Maste                     else
837ac7ddfbfSEd Maste                     {
838ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
839ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
840ac7ddfbfSEd Maste                         return false;
841ac7ddfbfSEd Maste                     }
842ac7ddfbfSEd Maste                 }
843ac7ddfbfSEd Maste 
844ac7ddfbfSEd Maste                 if (resume_threads.empty())
845ac7ddfbfSEd Maste                 {
846ac7ddfbfSEd Maste                     result.AppendError ("no valid thread indexes were specified");
847ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
848ac7ddfbfSEd Maste                     return false;
849ac7ddfbfSEd Maste                 }
850ac7ddfbfSEd Maste                 else
851ac7ddfbfSEd Maste                 {
852ac7ddfbfSEd Maste                     if (resume_threads.size() == 1)
853ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread: ");
854ac7ddfbfSEd Maste                     else
855ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming threads: ");
856ac7ddfbfSEd Maste 
857ac7ddfbfSEd Maste                     for (uint32_t idx=0; idx<num_threads; ++idx)
858ac7ddfbfSEd Maste                     {
859ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
860ac7ddfbfSEd Maste                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
861ac7ddfbfSEd Maste 
862ac7ddfbfSEd Maste                         if (this_thread_pos != resume_threads.end())
863ac7ddfbfSEd Maste                         {
864ac7ddfbfSEd Maste                             resume_threads.erase(this_thread_pos);
865ac7ddfbfSEd Maste                             if (resume_threads.size() > 0)
866ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
867ac7ddfbfSEd Maste                             else
868ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
869ac7ddfbfSEd Maste 
8700127ef0fSEd Maste                             const bool override_suspend = true;
8710127ef0fSEd Maste                             thread->SetResumeState (eStateRunning, override_suspend);
872ac7ddfbfSEd Maste                         }
873ac7ddfbfSEd Maste                         else
874ac7ddfbfSEd Maste                         {
875ac7ddfbfSEd Maste                             thread->SetResumeState (eStateSuspended);
876ac7ddfbfSEd Maste                         }
877ac7ddfbfSEd Maste                     }
878ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
879ac7ddfbfSEd Maste                 }
880ac7ddfbfSEd Maste             }
881ac7ddfbfSEd Maste             else
882ac7ddfbfSEd Maste             {
88335617911SEd Maste                 // These two lines appear at the beginning of both blocks in
88435617911SEd Maste                 // this if..else, but that is because we need to release the
88535617911SEd Maste                 // lock before calling process->Resume below.
88635617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
88735617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
888ac7ddfbfSEd Maste                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
889ac7ddfbfSEd Maste                 if (current_thread == NULL)
890ac7ddfbfSEd Maste                 {
891ac7ddfbfSEd Maste                     result.AppendError ("the process doesn't have a current thread");
892ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
893ac7ddfbfSEd Maste                     return false;
894ac7ddfbfSEd Maste                 }
895ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
896ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
897ac7ddfbfSEd Maste                 {
898ac7ddfbfSEd Maste                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
899ac7ddfbfSEd Maste                     if (thread == current_thread)
900ac7ddfbfSEd Maste                     {
901ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
9020127ef0fSEd Maste                         const bool override_suspend = true;
9030127ef0fSEd Maste                         thread->SetResumeState (eStateRunning, override_suspend);
904ac7ddfbfSEd Maste                     }
905ac7ddfbfSEd Maste                     else
906ac7ddfbfSEd Maste                     {
907ac7ddfbfSEd Maste                         thread->SetResumeState (eStateSuspended);
908ac7ddfbfSEd Maste                     }
909ac7ddfbfSEd Maste                 }
910ac7ddfbfSEd Maste             }
911ac7ddfbfSEd Maste 
9127aa51b79SEd Maste 
9137aa51b79SEd Maste             StreamString stream;
9147aa51b79SEd Maste             Error error;
9157aa51b79SEd Maste             if (synchronous_execution)
9167aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
9177aa51b79SEd Maste             else
9187aa51b79SEd Maste                 error = process->Resume ();
9197aa51b79SEd Maste 
92035617911SEd Maste             // We should not be holding the thread list lock when we do this.
921ac7ddfbfSEd Maste             if (error.Success())
922ac7ddfbfSEd Maste             {
923ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
924ac7ddfbfSEd Maste                 if (synchronous_execution)
925ac7ddfbfSEd Maste                 {
9267aa51b79SEd Maste                     // If any state changed events had anything to say, add that to the result
9277aa51b79SEd Maste                     if (stream.GetData())
9287aa51b79SEd Maste                         result.AppendMessage(stream.GetData());
929ac7ddfbfSEd Maste 
930ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
931ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
932ac7ddfbfSEd Maste                 }
933ac7ddfbfSEd Maste                 else
934ac7ddfbfSEd Maste                 {
935ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
936ac7ddfbfSEd Maste                 }
937ac7ddfbfSEd Maste             }
938ac7ddfbfSEd Maste             else
939ac7ddfbfSEd Maste             {
940ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
941ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
942ac7ddfbfSEd Maste             }
943ac7ddfbfSEd Maste         }
944ac7ddfbfSEd Maste         else
945ac7ddfbfSEd Maste         {
946ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
947ac7ddfbfSEd Maste                                           StateAsCString(state));
948ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
949ac7ddfbfSEd Maste         }
950ac7ddfbfSEd Maste 
951ac7ddfbfSEd Maste         return result.Succeeded();
952ac7ddfbfSEd Maste     }
953ac7ddfbfSEd Maste 
954ac7ddfbfSEd Maste };
955ac7ddfbfSEd Maste 
956ac7ddfbfSEd Maste //-------------------------------------------------------------------------
957ac7ddfbfSEd Maste // CommandObjectThreadUntil
958ac7ddfbfSEd Maste //-------------------------------------------------------------------------
959ac7ddfbfSEd Maste 
960ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed
961ac7ddfbfSEd Maste {
962ac7ddfbfSEd Maste public:
963ac7ddfbfSEd Maste 
964ac7ddfbfSEd Maste     class CommandOptions : public Options
965ac7ddfbfSEd Maste     {
966ac7ddfbfSEd Maste     public:
967ac7ddfbfSEd Maste         uint32_t m_thread_idx;
968ac7ddfbfSEd Maste         uint32_t m_frame_idx;
969ac7ddfbfSEd Maste 
970ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
971ac7ddfbfSEd Maste             Options (interpreter),
972ac7ddfbfSEd Maste             m_thread_idx(LLDB_INVALID_THREAD_ID),
973ac7ddfbfSEd Maste             m_frame_idx(LLDB_INVALID_FRAME_ID)
974ac7ddfbfSEd Maste         {
975ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
976ac7ddfbfSEd Maste             OptionParsingStarting ();
977ac7ddfbfSEd Maste         }
978ac7ddfbfSEd Maste 
9799f2f44ceSEd Maste         ~CommandOptions () override
980ac7ddfbfSEd Maste         {
981ac7ddfbfSEd Maste         }
982ac7ddfbfSEd Maste 
9839f2f44ceSEd Maste         Error
9849f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
985ac7ddfbfSEd Maste         {
986ac7ddfbfSEd Maste             Error error;
987ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
988ac7ddfbfSEd Maste 
989ac7ddfbfSEd Maste             switch (short_option)
990ac7ddfbfSEd Maste             {
9911c3bbb01SEd Maste                 case 'a':
9921c3bbb01SEd Maste                 {
9931c3bbb01SEd Maste                     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
9941c3bbb01SEd Maste                     lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
9951c3bbb01SEd Maste                     if (error.Success())
9961c3bbb01SEd Maste                         m_until_addrs.push_back(tmp_addr);
9971c3bbb01SEd Maste                 }
9981c3bbb01SEd Maste                 break;
999ac7ddfbfSEd Maste                 case 't':
1000ac7ddfbfSEd Maste                 {
10011c3bbb01SEd Maste                     m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32);
1002ac7ddfbfSEd Maste                     if (m_thread_idx == LLDB_INVALID_INDEX32)
1003ac7ddfbfSEd Maste                     {
1004ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
1005ac7ddfbfSEd Maste                     }
1006ac7ddfbfSEd Maste                 }
1007ac7ddfbfSEd Maste                 break;
1008ac7ddfbfSEd Maste                 case 'f':
1009ac7ddfbfSEd Maste                 {
10101c3bbb01SEd Maste                     m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1011ac7ddfbfSEd Maste                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1012ac7ddfbfSEd Maste                     {
1013ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
1014ac7ddfbfSEd Maste                     }
1015ac7ddfbfSEd Maste                 }
1016ac7ddfbfSEd Maste                 break;
1017ac7ddfbfSEd Maste                 case 'm':
1018ac7ddfbfSEd Maste                 {
1019ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1020ac7ddfbfSEd Maste                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
1021ac7ddfbfSEd Maste 
1022ac7ddfbfSEd Maste                     if (error.Success())
1023ac7ddfbfSEd Maste                     {
1024ac7ddfbfSEd Maste                         if (run_mode == eAllThreads)
1025ac7ddfbfSEd Maste                             m_stop_others = false;
1026ac7ddfbfSEd Maste                         else
1027ac7ddfbfSEd Maste                             m_stop_others = true;
1028ac7ddfbfSEd Maste                     }
1029ac7ddfbfSEd Maste                 }
1030ac7ddfbfSEd Maste                 break;
1031ac7ddfbfSEd Maste                 default:
1032ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1033ac7ddfbfSEd Maste                     break;
1034ac7ddfbfSEd Maste 
1035ac7ddfbfSEd Maste             }
1036ac7ddfbfSEd Maste             return error;
1037ac7ddfbfSEd Maste         }
1038ac7ddfbfSEd Maste 
1039ac7ddfbfSEd Maste         void
10409f2f44ceSEd Maste         OptionParsingStarting () override
1041ac7ddfbfSEd Maste         {
1042ac7ddfbfSEd Maste             m_thread_idx = LLDB_INVALID_THREAD_ID;
1043ac7ddfbfSEd Maste             m_frame_idx = 0;
1044ac7ddfbfSEd Maste             m_stop_others = false;
10451c3bbb01SEd Maste             m_until_addrs.clear();
1046ac7ddfbfSEd Maste         }
1047ac7ddfbfSEd Maste 
1048ac7ddfbfSEd Maste         const OptionDefinition*
10499f2f44ceSEd Maste         GetDefinitions () override
1050ac7ddfbfSEd Maste         {
1051ac7ddfbfSEd Maste             return g_option_table;
1052ac7ddfbfSEd Maste         }
1053ac7ddfbfSEd Maste 
1054ac7ddfbfSEd Maste         uint32_t m_step_thread_idx;
1055ac7ddfbfSEd Maste         bool m_stop_others;
10561c3bbb01SEd Maste         std::vector<lldb::addr_t> m_until_addrs;
1057ac7ddfbfSEd Maste 
1058ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1059ac7ddfbfSEd Maste 
1060ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1061ac7ddfbfSEd Maste 
1062ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1063ac7ddfbfSEd Maste     };
1064ac7ddfbfSEd Maste 
1065ac7ddfbfSEd Maste     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1066ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1067ac7ddfbfSEd Maste                              "thread until",
10681c3bbb01SEd Maste                              "Run the current or specified thread until it reaches a given line number or address or leaves the current function.",
1069ac7ddfbfSEd Maste                              NULL,
10701c3bbb01SEd Maste                              eCommandRequiresThread        |
10711c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
10721c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
10731c3bbb01SEd Maste                              eCommandProcessMustBePaused   ),
1074ac7ddfbfSEd Maste         m_options (interpreter)
1075ac7ddfbfSEd Maste     {
1076ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1077ac7ddfbfSEd Maste         CommandArgumentData line_num_arg;
1078ac7ddfbfSEd Maste 
1079ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1080ac7ddfbfSEd Maste         line_num_arg.arg_type = eArgTypeLineNum;
1081ac7ddfbfSEd Maste         line_num_arg.arg_repetition = eArgRepeatPlain;
1082ac7ddfbfSEd Maste 
1083ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1084ac7ddfbfSEd Maste         arg.push_back (line_num_arg);
1085ac7ddfbfSEd Maste 
1086ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1087ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1088ac7ddfbfSEd Maste     }
1089ac7ddfbfSEd Maste 
1090ac7ddfbfSEd Maste 
10919f2f44ceSEd Maste     ~CommandObjectThreadUntil () override
1092ac7ddfbfSEd Maste     {
1093ac7ddfbfSEd Maste     }
1094ac7ddfbfSEd Maste 
1095ac7ddfbfSEd Maste     Options *
10969f2f44ceSEd Maste     GetOptions () override
1097ac7ddfbfSEd Maste     {
1098ac7ddfbfSEd Maste         return &m_options;
1099ac7ddfbfSEd Maste     }
1100ac7ddfbfSEd Maste 
1101ac7ddfbfSEd Maste protected:
11029f2f44ceSEd Maste     bool
11039f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
1104ac7ddfbfSEd Maste     {
1105ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
1106ac7ddfbfSEd Maste 
1107ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1108ac7ddfbfSEd Maste         if (target == NULL)
1109ac7ddfbfSEd Maste         {
1110ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1111ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1112ac7ddfbfSEd Maste             return false;
1113ac7ddfbfSEd Maste         }
1114ac7ddfbfSEd Maste 
1115ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1116ac7ddfbfSEd Maste         if (process == NULL)
1117ac7ddfbfSEd Maste         {
1118ac7ddfbfSEd Maste             result.AppendError ("need a valid process to step");
1119ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1120ac7ddfbfSEd Maste 
1121ac7ddfbfSEd Maste         }
1122ac7ddfbfSEd Maste         else
1123ac7ddfbfSEd Maste         {
1124ac7ddfbfSEd Maste             Thread *thread = NULL;
11251c3bbb01SEd Maste             std::vector<uint32_t> line_numbers;
1126ac7ddfbfSEd Maste 
11271c3bbb01SEd Maste             if (command.GetArgumentCount() >= 1)
1128ac7ddfbfSEd Maste             {
11291c3bbb01SEd Maste                 size_t num_args = command.GetArgumentCount();
11301c3bbb01SEd Maste                 for (size_t i = 0; i < num_args; i++)
11311c3bbb01SEd Maste                 {
11321c3bbb01SEd Maste                     uint32_t line_number;
11331c3bbb01SEd Maste                     line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1134ac7ddfbfSEd Maste                     if (line_number == UINT32_MAX)
1135ac7ddfbfSEd Maste                     {
1136ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1137ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
1138ac7ddfbfSEd Maste                         return false;
1139ac7ddfbfSEd Maste                     }
11401c3bbb01SEd Maste                     else
11411c3bbb01SEd Maste                         line_numbers.push_back(line_number);
11421c3bbb01SEd Maste                 }
11431c3bbb01SEd Maste             }
11441c3bbb01SEd Maste             else if (m_options.m_until_addrs.empty())
11451c3bbb01SEd Maste             {
11461c3bbb01SEd Maste                 result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax());
11471c3bbb01SEd Maste                 result.SetStatus (eReturnStatusFailed);
11481c3bbb01SEd Maste                 return false;
11491c3bbb01SEd Maste             }
11501c3bbb01SEd Maste 
1151ac7ddfbfSEd Maste 
1152ac7ddfbfSEd Maste             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1153ac7ddfbfSEd Maste             {
1154ac7ddfbfSEd Maste                 thread = process->GetThreadList().GetSelectedThread().get();
1155ac7ddfbfSEd Maste             }
1156ac7ddfbfSEd Maste             else
1157ac7ddfbfSEd Maste             {
1158ac7ddfbfSEd Maste                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1159ac7ddfbfSEd Maste             }
1160ac7ddfbfSEd Maste 
1161ac7ddfbfSEd Maste             if (thread == NULL)
1162ac7ddfbfSEd Maste             {
1163ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
1164ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
1165ac7ddfbfSEd Maste                                               m_options.m_thread_idx,
1166ac7ddfbfSEd Maste                                               num_threads);
1167ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1168ac7ddfbfSEd Maste                 return false;
1169ac7ddfbfSEd Maste             }
1170ac7ddfbfSEd Maste 
1171ac7ddfbfSEd Maste             const bool abort_other_plans = false;
1172ac7ddfbfSEd Maste 
1173ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1174ac7ddfbfSEd Maste             if (frame == NULL)
1175ac7ddfbfSEd Maste             {
1176ac7ddfbfSEd Maste 
1177ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
1178ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1179ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1180ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1181ac7ddfbfSEd Maste                 return false;
1182ac7ddfbfSEd Maste             }
1183ac7ddfbfSEd Maste 
1184ac7ddfbfSEd Maste             ThreadPlanSP new_plan_sp;
1185ac7ddfbfSEd Maste 
1186ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
1187ac7ddfbfSEd Maste             {
1188ac7ddfbfSEd Maste                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1189ac7ddfbfSEd Maste                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1190ac7ddfbfSEd Maste                 LineTable *line_table = NULL;
1191ac7ddfbfSEd Maste                 if (sc.comp_unit)
1192ac7ddfbfSEd Maste                     line_table = sc.comp_unit->GetLineTable();
1193ac7ddfbfSEd Maste 
1194ac7ddfbfSEd Maste                 if (line_table == NULL)
1195ac7ddfbfSEd Maste                 {
1196ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1197ac7ddfbfSEd Maste                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1198ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1199ac7ddfbfSEd Maste                     return false;
1200ac7ddfbfSEd Maste                 }
1201ac7ddfbfSEd Maste 
1202ac7ddfbfSEd Maste                 LineEntry function_start;
1203ac7ddfbfSEd Maste                 uint32_t index_ptr = 0, end_ptr;
1204ac7ddfbfSEd Maste                 std::vector<addr_t> address_list;
1205ac7ddfbfSEd Maste 
1206ac7ddfbfSEd Maste                 // Find the beginning & end index of the
1207ac7ddfbfSEd Maste                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1208ac7ddfbfSEd Maste                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1209ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1210ac7ddfbfSEd Maste 
1211ac7ddfbfSEd Maste                 Address fun_end_addr(fun_start_addr.GetSection(),
1212ac7ddfbfSEd Maste                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1213ac7ddfbfSEd Maste 
1214ac7ddfbfSEd Maste                 bool all_in_function = true;
1215ac7ddfbfSEd Maste 
12161c3bbb01SEd Maste                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
12171c3bbb01SEd Maste 
12181c3bbb01SEd Maste                 for (uint32_t line_number : line_numbers)
12191c3bbb01SEd Maste                 {
12201c3bbb01SEd Maste                     uint32_t start_idx_ptr = index_ptr;
12211c3bbb01SEd Maste                     while (start_idx_ptr <= end_ptr)
1222ac7ddfbfSEd Maste                     {
1223ac7ddfbfSEd Maste                         LineEntry line_entry;
1224ac7ddfbfSEd Maste                         const bool exact = false;
12251c3bbb01SEd Maste                         start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry);
12261c3bbb01SEd Maste                         if (start_idx_ptr == UINT32_MAX)
1227ac7ddfbfSEd Maste                             break;
1228ac7ddfbfSEd Maste 
1229ac7ddfbfSEd Maste                         addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1230ac7ddfbfSEd Maste                         if (address != LLDB_INVALID_ADDRESS)
1231ac7ddfbfSEd Maste                         {
1232ac7ddfbfSEd Maste                             if (fun_addr_range.ContainsLoadAddress (address, target))
1233ac7ddfbfSEd Maste                                 address_list.push_back (address);
1234ac7ddfbfSEd Maste                             else
1235ac7ddfbfSEd Maste                                 all_in_function = false;
1236ac7ddfbfSEd Maste                         }
12371c3bbb01SEd Maste                         start_idx_ptr++;
12381c3bbb01SEd Maste                     }
12391c3bbb01SEd Maste                 }
12401c3bbb01SEd Maste 
12411c3bbb01SEd Maste                 for (lldb::addr_t address : m_options.m_until_addrs)
12421c3bbb01SEd Maste                 {
12431c3bbb01SEd Maste                     if (fun_addr_range.ContainsLoadAddress (address, target))
12441c3bbb01SEd Maste                         address_list.push_back (address);
12451c3bbb01SEd Maste                     else
12461c3bbb01SEd Maste                         all_in_function = false;
1247ac7ddfbfSEd Maste                 }
1248ac7ddfbfSEd Maste 
1249ac7ddfbfSEd Maste                 if (address_list.size() == 0)
1250ac7ddfbfSEd Maste                 {
1251ac7ddfbfSEd Maste                     if (all_in_function)
1252ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1253ac7ddfbfSEd Maste                     else
1254ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1255ac7ddfbfSEd Maste 
1256ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1257ac7ddfbfSEd Maste                     return false;
1258ac7ddfbfSEd Maste                 }
1259ac7ddfbfSEd Maste 
1260ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1261ac7ddfbfSEd Maste                                                                 &address_list.front(),
1262ac7ddfbfSEd Maste                                                                 address_list.size(),
1263ac7ddfbfSEd Maste                                                                 m_options.m_stop_others,
1264ac7ddfbfSEd Maste                                                                 m_options.m_frame_idx);
1265ac7ddfbfSEd Maste                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1266ac7ddfbfSEd Maste                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1267ac7ddfbfSEd Maste                 // will resume the original plan.
1268ac7ddfbfSEd Maste                 new_plan_sp->SetIsMasterPlan (true);
1269ac7ddfbfSEd Maste                 new_plan_sp->SetOkayToDiscard(false);
1270ac7ddfbfSEd Maste             }
1271ac7ddfbfSEd Maste             else
1272ac7ddfbfSEd Maste             {
1273ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1274ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1275ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1276ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1277ac7ddfbfSEd Maste                 return false;
1278ac7ddfbfSEd Maste 
1279ac7ddfbfSEd Maste             }
1280ac7ddfbfSEd Maste 
12817aa51b79SEd Maste 
12827aa51b79SEd Maste 
1283ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
12847aa51b79SEd Maste 
12857aa51b79SEd Maste             StreamString stream;
12867aa51b79SEd Maste             Error error;
12877aa51b79SEd Maste             if (synchronous_execution)
12887aa51b79SEd Maste                 error = process->ResumeSynchronous (&stream);
12897aa51b79SEd Maste             else
12907aa51b79SEd Maste                 error = process->Resume ();
12917aa51b79SEd Maste 
1292ac7ddfbfSEd Maste             if (error.Success())
1293ac7ddfbfSEd Maste             {
1294ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1295ac7ddfbfSEd Maste                 if (synchronous_execution)
1296ac7ddfbfSEd Maste                 {
12977aa51b79SEd Maste                     // If any state changed events had anything to say, add that to the result
12987aa51b79SEd Maste                     if (stream.GetData())
12997aa51b79SEd Maste                         result.AppendMessage(stream.GetData());
1300ac7ddfbfSEd Maste 
1301ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
1302ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1303ac7ddfbfSEd Maste                 }
1304ac7ddfbfSEd Maste                 else
1305ac7ddfbfSEd Maste                 {
1306ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1307ac7ddfbfSEd Maste                 }
1308ac7ddfbfSEd Maste             }
1309ac7ddfbfSEd Maste             else
1310ac7ddfbfSEd Maste             {
1311ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1312ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1313ac7ddfbfSEd Maste             }
1314ac7ddfbfSEd Maste 
1315ac7ddfbfSEd Maste         }
1316ac7ddfbfSEd Maste         return result.Succeeded();
1317ac7ddfbfSEd Maste     }
1318ac7ddfbfSEd Maste 
1319ac7ddfbfSEd Maste     CommandOptions m_options;
1320ac7ddfbfSEd Maste 
1321ac7ddfbfSEd Maste };
1322ac7ddfbfSEd Maste 
1323ac7ddfbfSEd Maste OptionDefinition
1324ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1325ac7ddfbfSEd Maste {
13260127ef0fSEd Maste { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
13270127ef0fSEd Maste { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
13280127ef0fSEd 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"},
13291c3bbb01SEd 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."},
13300127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1331ac7ddfbfSEd Maste };
1332ac7ddfbfSEd Maste 
1333ac7ddfbfSEd Maste 
1334ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1335ac7ddfbfSEd Maste // CommandObjectThreadSelect
1336ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1337ac7ddfbfSEd Maste 
1338ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed
1339ac7ddfbfSEd Maste {
1340ac7ddfbfSEd Maste public:
1341ac7ddfbfSEd Maste 
1342ac7ddfbfSEd Maste     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1343ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1344ac7ddfbfSEd Maste                              "thread select",
1345ac7ddfbfSEd Maste                              "Select a thread as the currently active thread.",
1346ac7ddfbfSEd Maste                              NULL,
13471c3bbb01SEd Maste                              eCommandRequiresProcess       |
13481c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
13491c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
13501c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
1351ac7ddfbfSEd Maste     {
1352ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1353ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
1354ac7ddfbfSEd Maste 
1355ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1356ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1357ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1358ac7ddfbfSEd Maste 
1359ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1360ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
1361ac7ddfbfSEd Maste 
1362ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1363ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1364ac7ddfbfSEd Maste     }
1365ac7ddfbfSEd Maste 
1366ac7ddfbfSEd Maste 
13679f2f44ceSEd Maste     ~CommandObjectThreadSelect () override
1368ac7ddfbfSEd Maste     {
1369ac7ddfbfSEd Maste     }
1370ac7ddfbfSEd Maste 
1371ac7ddfbfSEd Maste protected:
13729f2f44ceSEd Maste     bool
13739f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
1374ac7ddfbfSEd Maste     {
1375ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1376ac7ddfbfSEd Maste         if (process == NULL)
1377ac7ddfbfSEd Maste         {
1378ac7ddfbfSEd Maste             result.AppendError ("no process");
1379ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1380ac7ddfbfSEd Maste             return false;
1381ac7ddfbfSEd Maste         }
1382ac7ddfbfSEd Maste         else if (command.GetArgumentCount() != 1)
1383ac7ddfbfSEd Maste         {
1384ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1385ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1386ac7ddfbfSEd Maste             return false;
1387ac7ddfbfSEd Maste         }
1388ac7ddfbfSEd Maste 
13891c3bbb01SEd Maste         uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1390ac7ddfbfSEd Maste 
1391ac7ddfbfSEd Maste         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1392ac7ddfbfSEd Maste         if (new_thread == NULL)
1393ac7ddfbfSEd Maste         {
1394ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1395ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1396ac7ddfbfSEd Maste             return false;
1397ac7ddfbfSEd Maste         }
1398ac7ddfbfSEd Maste 
1399ac7ddfbfSEd Maste         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1400ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1401ac7ddfbfSEd Maste 
1402ac7ddfbfSEd Maste         return result.Succeeded();
1403ac7ddfbfSEd Maste     }
1404ac7ddfbfSEd Maste 
1405ac7ddfbfSEd Maste };
1406ac7ddfbfSEd Maste 
1407ac7ddfbfSEd Maste 
1408ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1409ac7ddfbfSEd Maste // CommandObjectThreadList
1410ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1411ac7ddfbfSEd Maste 
1412ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed
1413ac7ddfbfSEd Maste {
1414ac7ddfbfSEd Maste public:
1415ac7ddfbfSEd Maste 
1416ac7ddfbfSEd Maste 
1417ac7ddfbfSEd Maste     CommandObjectThreadList (CommandInterpreter &interpreter):
1418ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1419ac7ddfbfSEd Maste                              "thread list",
1420ac7ddfbfSEd Maste                              "Show a summary of all current threads in a process.",
1421ac7ddfbfSEd Maste                              "thread list",
14221c3bbb01SEd Maste                              eCommandRequiresProcess       |
14231c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
14241c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
14251c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
1426ac7ddfbfSEd Maste     {
1427ac7ddfbfSEd Maste     }
1428ac7ddfbfSEd Maste 
14299f2f44ceSEd Maste     ~CommandObjectThreadList() override
1430ac7ddfbfSEd Maste     {
1431ac7ddfbfSEd Maste     }
1432ac7ddfbfSEd Maste 
1433ac7ddfbfSEd Maste protected:
1434ac7ddfbfSEd Maste     bool
14359f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
1436ac7ddfbfSEd Maste     {
1437ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1438ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1439ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1440ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = false;
1441ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1442ac7ddfbfSEd Maste         const uint32_t num_frames = 0;
1443ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
1444ac7ddfbfSEd Maste         process->GetStatus(strm);
1445ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1446ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1447ac7ddfbfSEd Maste                                   start_frame,
1448ac7ddfbfSEd Maste                                   num_frames,
1449ac7ddfbfSEd Maste                                   num_frames_with_source);
1450ac7ddfbfSEd Maste         return result.Succeeded();
1451ac7ddfbfSEd Maste     }
1452ac7ddfbfSEd Maste };
1453ac7ddfbfSEd Maste 
1454ac7ddfbfSEd Maste //-------------------------------------------------------------------------
14550127ef0fSEd Maste // CommandObjectThreadInfo
14560127ef0fSEd Maste //-------------------------------------------------------------------------
14570127ef0fSEd Maste 
14587aa51b79SEd Maste class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
14590127ef0fSEd Maste {
14600127ef0fSEd Maste public:
14610127ef0fSEd Maste 
14620127ef0fSEd Maste     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
14637aa51b79SEd Maste         CommandObjectIterateOverThreads (interpreter,
14640127ef0fSEd Maste                                          "thread info",
14650127ef0fSEd Maste                                          "Show an extended summary of information about thread(s) in a process.",
14660127ef0fSEd Maste                                          "thread info",
14671c3bbb01SEd Maste                                          eCommandRequiresProcess       |
14681c3bbb01SEd Maste                                          eCommandTryTargetAPILock      |
14691c3bbb01SEd Maste                                          eCommandProcessMustBeLaunched |
14701c3bbb01SEd Maste                                          eCommandProcessMustBePaused),
14710127ef0fSEd Maste         m_options (interpreter)
14720127ef0fSEd Maste     {
14737aa51b79SEd Maste         m_add_return = false;
14740127ef0fSEd Maste     }
14750127ef0fSEd Maste 
14760127ef0fSEd Maste     class CommandOptions : public Options
14770127ef0fSEd Maste     {
14780127ef0fSEd Maste     public:
14790127ef0fSEd Maste 
14800127ef0fSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
14810127ef0fSEd Maste             Options (interpreter)
14820127ef0fSEd Maste         {
14830127ef0fSEd Maste             OptionParsingStarting ();
14840127ef0fSEd Maste         }
14850127ef0fSEd Maste 
14860127ef0fSEd Maste         void
14879f2f44ceSEd Maste         OptionParsingStarting () override
14880127ef0fSEd Maste         {
14897aa51b79SEd Maste             m_json_thread = false;
14907aa51b79SEd Maste             m_json_stopinfo = false;
14910127ef0fSEd Maste         }
14920127ef0fSEd Maste 
14939f2f44ceSEd Maste         ~CommandOptions () override
14940127ef0fSEd Maste         {
14950127ef0fSEd Maste         }
14960127ef0fSEd Maste 
14979f2f44ceSEd Maste         Error
14989f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
14990127ef0fSEd Maste         {
15000127ef0fSEd Maste             const int short_option = m_getopt_table[option_idx].val;
15010127ef0fSEd Maste             Error error;
15020127ef0fSEd Maste 
15030127ef0fSEd Maste             switch (short_option)
15040127ef0fSEd Maste             {
15050127ef0fSEd Maste                 case 'j':
15067aa51b79SEd Maste                     m_json_thread = true;
15077aa51b79SEd Maste                     break;
15087aa51b79SEd Maste 
15097aa51b79SEd Maste                 case 's':
15107aa51b79SEd Maste                     m_json_stopinfo = true;
15110127ef0fSEd Maste                     break;
15120127ef0fSEd Maste 
15130127ef0fSEd Maste                 default:
15140127ef0fSEd Maste                     return Error("invalid short option character '%c'", short_option);
15150127ef0fSEd Maste 
15160127ef0fSEd Maste             }
15170127ef0fSEd Maste             return error;
15180127ef0fSEd Maste         }
15190127ef0fSEd Maste 
15200127ef0fSEd Maste         const OptionDefinition*
15219f2f44ceSEd Maste         GetDefinitions () override
15220127ef0fSEd Maste         {
15230127ef0fSEd Maste             return g_option_table;
15240127ef0fSEd Maste         }
15250127ef0fSEd Maste 
15267aa51b79SEd Maste         bool m_json_thread;
15277aa51b79SEd Maste         bool m_json_stopinfo;
15280127ef0fSEd Maste 
15290127ef0fSEd Maste         static OptionDefinition g_option_table[];
15300127ef0fSEd Maste     };
15310127ef0fSEd Maste 
15320127ef0fSEd Maste     Options *
15339f2f44ceSEd Maste     GetOptions () override
15340127ef0fSEd Maste     {
15350127ef0fSEd Maste         return &m_options;
15360127ef0fSEd Maste     }
15370127ef0fSEd Maste 
15389f2f44ceSEd Maste     ~CommandObjectThreadInfo () override
15390127ef0fSEd Maste     {
15400127ef0fSEd Maste     }
15410127ef0fSEd Maste 
15429f2f44ceSEd Maste     bool
15439f2f44ceSEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result) override
15440127ef0fSEd Maste     {
15450127ef0fSEd Maste         Stream &strm = result.GetOutputStream();
15467aa51b79SEd Maste         if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
15470127ef0fSEd Maste         {
15487aa51b79SEd Maste             result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
15490127ef0fSEd Maste             result.SetStatus (eReturnStatusFailed);
15500127ef0fSEd Maste             return false;
15510127ef0fSEd Maste         }
15527aa51b79SEd Maste         return true;
15530127ef0fSEd Maste     }
15540127ef0fSEd Maste 
15550127ef0fSEd Maste     CommandOptions m_options;
15560127ef0fSEd Maste 
15570127ef0fSEd Maste };
15580127ef0fSEd Maste 
15590127ef0fSEd Maste OptionDefinition
15600127ef0fSEd Maste CommandObjectThreadInfo::CommandOptions::g_option_table[] =
15610127ef0fSEd Maste {
15620127ef0fSEd Maste     { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
15637aa51b79SEd Maste     { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},
15640127ef0fSEd Maste 
15650127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
15660127ef0fSEd Maste };
15670127ef0fSEd Maste 
15680127ef0fSEd Maste 
15690127ef0fSEd Maste //-------------------------------------------------------------------------
1570ac7ddfbfSEd Maste // CommandObjectThreadReturn
1571ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1572ac7ddfbfSEd Maste 
1573ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw
1574ac7ddfbfSEd Maste {
1575ac7ddfbfSEd Maste public:
1576ac7ddfbfSEd Maste     class CommandOptions : public Options
1577ac7ddfbfSEd Maste     {
1578ac7ddfbfSEd Maste     public:
1579ac7ddfbfSEd Maste 
1580ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1581ac7ddfbfSEd Maste             Options (interpreter),
1582ac7ddfbfSEd Maste             m_from_expression (false)
1583ac7ddfbfSEd Maste         {
1584ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1585ac7ddfbfSEd Maste             OptionParsingStarting ();
1586ac7ddfbfSEd Maste         }
1587ac7ddfbfSEd Maste 
15889f2f44ceSEd Maste         ~CommandOptions () override
1589ac7ddfbfSEd Maste         {
1590ac7ddfbfSEd Maste         }
1591ac7ddfbfSEd Maste 
15929f2f44ceSEd Maste         Error
15939f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
1594ac7ddfbfSEd Maste         {
1595ac7ddfbfSEd Maste             Error error;
1596ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1597ac7ddfbfSEd Maste 
1598ac7ddfbfSEd Maste             switch (short_option)
1599ac7ddfbfSEd Maste             {
1600ac7ddfbfSEd Maste                 case 'x':
1601ac7ddfbfSEd Maste                 {
1602ac7ddfbfSEd Maste                     bool success;
1603ac7ddfbfSEd Maste                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1604ac7ddfbfSEd Maste                     if (success)
1605ac7ddfbfSEd Maste                         m_from_expression = tmp_value;
1606ac7ddfbfSEd Maste                     else
1607ac7ddfbfSEd Maste                     {
1608ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1609ac7ddfbfSEd Maste                     }
1610ac7ddfbfSEd Maste                 }
1611ac7ddfbfSEd Maste                 break;
1612ac7ddfbfSEd Maste                 default:
1613ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1614ac7ddfbfSEd Maste                     break;
1615ac7ddfbfSEd Maste 
1616ac7ddfbfSEd Maste             }
1617ac7ddfbfSEd Maste             return error;
1618ac7ddfbfSEd Maste         }
1619ac7ddfbfSEd Maste 
1620ac7ddfbfSEd Maste         void
16219f2f44ceSEd Maste         OptionParsingStarting () override
1622ac7ddfbfSEd Maste         {
1623ac7ddfbfSEd Maste             m_from_expression = false;
1624ac7ddfbfSEd Maste         }
1625ac7ddfbfSEd Maste 
1626ac7ddfbfSEd Maste         const OptionDefinition*
16279f2f44ceSEd Maste         GetDefinitions () override
1628ac7ddfbfSEd Maste         {
1629ac7ddfbfSEd Maste             return g_option_table;
1630ac7ddfbfSEd Maste         }
1631ac7ddfbfSEd Maste 
1632ac7ddfbfSEd Maste         bool m_from_expression;
1633ac7ddfbfSEd Maste 
1634ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1635ac7ddfbfSEd Maste 
1636ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1637ac7ddfbfSEd Maste 
1638ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1639ac7ddfbfSEd Maste     };
1640ac7ddfbfSEd Maste 
1641ac7ddfbfSEd Maste     Options *
16429f2f44ceSEd Maste     GetOptions () override
1643ac7ddfbfSEd Maste     {
1644ac7ddfbfSEd Maste         return &m_options;
1645ac7ddfbfSEd Maste     }
1646ac7ddfbfSEd Maste 
1647ac7ddfbfSEd Maste     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1648ac7ddfbfSEd Maste         CommandObjectRaw (interpreter,
1649ac7ddfbfSEd Maste                           "thread return",
1650ac7ddfbfSEd Maste                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1651ac7ddfbfSEd Maste                           " or with the -x option from the innermost function evaluation.",
1652ac7ddfbfSEd Maste                           "thread return",
16531c3bbb01SEd Maste                           eCommandRequiresFrame         |
16541c3bbb01SEd Maste                           eCommandTryTargetAPILock      |
16551c3bbb01SEd Maste                           eCommandProcessMustBeLaunched |
16561c3bbb01SEd Maste                           eCommandProcessMustBePaused   ),
1657ac7ddfbfSEd Maste         m_options (interpreter)
1658ac7ddfbfSEd Maste     {
1659ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1660ac7ddfbfSEd Maste         CommandArgumentData expression_arg;
1661ac7ddfbfSEd Maste 
1662ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1663ac7ddfbfSEd Maste         expression_arg.arg_type = eArgTypeExpression;
1664ac7ddfbfSEd Maste         expression_arg.arg_repetition = eArgRepeatOptional;
1665ac7ddfbfSEd Maste 
1666ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1667ac7ddfbfSEd Maste         arg.push_back (expression_arg);
1668ac7ddfbfSEd Maste 
1669ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1670ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1671ac7ddfbfSEd Maste 
1672ac7ddfbfSEd Maste 
1673ac7ddfbfSEd Maste     }
1674ac7ddfbfSEd Maste 
16759f2f44ceSEd Maste     ~CommandObjectThreadReturn() override
1676ac7ddfbfSEd Maste     {
1677ac7ddfbfSEd Maste     }
1678ac7ddfbfSEd Maste 
1679ac7ddfbfSEd Maste protected:
1680ac7ddfbfSEd Maste 
16819f2f44ceSEd Maste     bool
16829f2f44ceSEd Maste     DoExecute (const char *command, CommandReturnObject &result) override
1683ac7ddfbfSEd Maste     {
1684ac7ddfbfSEd Maste         // I am going to handle this by hand, because I don't want you to have to say:
1685ac7ddfbfSEd Maste         // "thread return -- -5".
1686ac7ddfbfSEd Maste         if (command[0] == '-' && command[1] == 'x')
1687ac7ddfbfSEd Maste         {
1688ac7ddfbfSEd Maste             if (command && command[2] != '\0')
1689ac7ddfbfSEd Maste                 result.AppendWarning("Return values ignored when returning from user called expressions");
1690ac7ddfbfSEd Maste 
1691ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
1692ac7ddfbfSEd Maste             Error error;
1693ac7ddfbfSEd Maste             error = thread->UnwindInnermostExpression();
1694ac7ddfbfSEd Maste             if (!error.Success())
1695ac7ddfbfSEd Maste             {
1696ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1697ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1698ac7ddfbfSEd Maste             }
1699ac7ddfbfSEd Maste             else
1700ac7ddfbfSEd Maste             {
1701ac7ddfbfSEd Maste                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1702ac7ddfbfSEd Maste                 if (success)
1703ac7ddfbfSEd Maste                 {
1704ac7ddfbfSEd Maste                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1705ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1706ac7ddfbfSEd Maste                 }
1707ac7ddfbfSEd Maste                 else
1708ac7ddfbfSEd Maste                 {
1709ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1710ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1711ac7ddfbfSEd Maste                 }
1712ac7ddfbfSEd Maste             }
1713ac7ddfbfSEd Maste             return result.Succeeded();
1714ac7ddfbfSEd Maste         }
1715ac7ddfbfSEd Maste 
1716ac7ddfbfSEd Maste         ValueObjectSP return_valobj_sp;
1717ac7ddfbfSEd Maste 
1718ac7ddfbfSEd Maste         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1719ac7ddfbfSEd Maste         uint32_t frame_idx = frame_sp->GetFrameIndex();
1720ac7ddfbfSEd Maste 
1721ac7ddfbfSEd Maste         if (frame_sp->IsInlined())
1722ac7ddfbfSEd Maste         {
1723ac7ddfbfSEd Maste             result.AppendError("Don't know how to return from inlined frames.");
1724ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1725ac7ddfbfSEd Maste             return false;
1726ac7ddfbfSEd Maste         }
1727ac7ddfbfSEd Maste 
1728ac7ddfbfSEd Maste         if (command && command[0] != '\0')
1729ac7ddfbfSEd Maste         {
1730ac7ddfbfSEd Maste             Target *target = m_exe_ctx.GetTargetPtr();
1731ac7ddfbfSEd Maste             EvaluateExpressionOptions options;
1732ac7ddfbfSEd Maste 
1733ac7ddfbfSEd Maste             options.SetUnwindOnError(true);
1734ac7ddfbfSEd Maste             options.SetUseDynamic(eNoDynamicValues);
1735ac7ddfbfSEd Maste 
17360127ef0fSEd Maste             ExpressionResults exe_results = eExpressionSetupError;
1737ac7ddfbfSEd Maste             exe_results = target->EvaluateExpression (command,
1738ac7ddfbfSEd Maste                                                       frame_sp.get(),
1739ac7ddfbfSEd Maste                                                       return_valobj_sp,
1740ac7ddfbfSEd Maste                                                       options);
17410127ef0fSEd Maste             if (exe_results != eExpressionCompleted)
1742ac7ddfbfSEd Maste             {
1743ac7ddfbfSEd Maste                 if (return_valobj_sp)
1744ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1745ac7ddfbfSEd Maste                 else
1746ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1747ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1748ac7ddfbfSEd Maste                 return false;
1749ac7ddfbfSEd Maste 
1750ac7ddfbfSEd Maste             }
1751ac7ddfbfSEd Maste         }
1752ac7ddfbfSEd Maste 
1753ac7ddfbfSEd Maste         Error error;
1754ac7ddfbfSEd Maste         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1755ac7ddfbfSEd Maste         const bool broadcast = true;
1756ac7ddfbfSEd Maste         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1757ac7ddfbfSEd Maste         if (!error.Success())
1758ac7ddfbfSEd Maste         {
1759ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1760ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1761ac7ddfbfSEd Maste             return false;
1762ac7ddfbfSEd Maste         }
1763ac7ddfbfSEd Maste 
1764ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
1765ac7ddfbfSEd Maste         return true;
1766ac7ddfbfSEd Maste     }
1767ac7ddfbfSEd Maste 
1768ac7ddfbfSEd Maste     CommandOptions m_options;
1769ac7ddfbfSEd Maste 
1770ac7ddfbfSEd Maste };
1771ac7ddfbfSEd Maste OptionDefinition
1772ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1773ac7ddfbfSEd Maste {
17740127ef0fSEd Maste { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
17750127ef0fSEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
177635617911SEd Maste };
177735617911SEd Maste 
177835617911SEd Maste //-------------------------------------------------------------------------
177935617911SEd Maste // CommandObjectThreadJump
178035617911SEd Maste //-------------------------------------------------------------------------
178135617911SEd Maste 
178235617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed
178335617911SEd Maste {
178435617911SEd Maste public:
178535617911SEd Maste     class CommandOptions : public Options
178635617911SEd Maste     {
178735617911SEd Maste     public:
178835617911SEd Maste 
178935617911SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
179035617911SEd Maste             Options (interpreter)
179135617911SEd Maste         {
179235617911SEd Maste             OptionParsingStarting ();
179335617911SEd Maste         }
179435617911SEd Maste 
179535617911SEd Maste         void
17969f2f44ceSEd Maste         OptionParsingStarting () override
179735617911SEd Maste         {
179835617911SEd Maste             m_filenames.Clear();
179935617911SEd Maste             m_line_num = 0;
180035617911SEd Maste             m_line_offset = 0;
180135617911SEd Maste             m_load_addr = LLDB_INVALID_ADDRESS;
180235617911SEd Maste             m_force = false;
180335617911SEd Maste         }
180435617911SEd Maste 
18059f2f44ceSEd Maste         ~CommandOptions () override
180635617911SEd Maste         {
180735617911SEd Maste         }
180835617911SEd Maste 
18099f2f44ceSEd Maste         Error
18109f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
181135617911SEd Maste         {
181235617911SEd Maste             bool success;
181335617911SEd Maste             const int short_option = m_getopt_table[option_idx].val;
181435617911SEd Maste             Error error;
181535617911SEd Maste 
181635617911SEd Maste             switch (short_option)
181735617911SEd Maste             {
181835617911SEd Maste                 case 'f':
181935617911SEd Maste                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
182035617911SEd Maste                     if (m_filenames.GetSize() > 1)
182135617911SEd Maste                         return Error("only one source file expected.");
182235617911SEd Maste                     break;
182335617911SEd Maste                 case 'l':
18241c3bbb01SEd Maste                     m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
182535617911SEd Maste                     if (!success || m_line_num == 0)
182635617911SEd Maste                         return Error("invalid line number: '%s'.", option_arg);
182735617911SEd Maste                     break;
182835617911SEd Maste                 case 'b':
18291c3bbb01SEd Maste                     m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success);
183035617911SEd Maste                     if (!success)
183135617911SEd Maste                         return Error("invalid line offset: '%s'.", option_arg);
183235617911SEd Maste                     break;
183335617911SEd Maste                 case 'a':
183435617911SEd Maste                     {
183535617911SEd Maste                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
183635617911SEd Maste                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
183735617911SEd Maste                     }
183835617911SEd Maste                     break;
183935617911SEd Maste                 case 'r':
184035617911SEd Maste                     m_force = true;
184135617911SEd Maste                     break;
184235617911SEd Maste 
184335617911SEd Maste                  default:
184435617911SEd Maste                     return Error("invalid short option character '%c'", short_option);
184535617911SEd Maste 
184635617911SEd Maste             }
184735617911SEd Maste             return error;
184835617911SEd Maste         }
184935617911SEd Maste 
185035617911SEd Maste         const OptionDefinition*
18519f2f44ceSEd Maste         GetDefinitions () override
185235617911SEd Maste         {
185335617911SEd Maste             return g_option_table;
185435617911SEd Maste         }
185535617911SEd Maste 
185635617911SEd Maste         FileSpecList m_filenames;
185735617911SEd Maste         uint32_t m_line_num;
185835617911SEd Maste         int32_t m_line_offset;
185935617911SEd Maste         lldb::addr_t m_load_addr;
186035617911SEd Maste         bool m_force;
186135617911SEd Maste 
186235617911SEd Maste         static OptionDefinition g_option_table[];
186335617911SEd Maste     };
186435617911SEd Maste 
186535617911SEd Maste     Options *
18669f2f44ceSEd Maste     GetOptions () override
186735617911SEd Maste     {
186835617911SEd Maste         return &m_options;
186935617911SEd Maste     }
187035617911SEd Maste 
187135617911SEd Maste     CommandObjectThreadJump (CommandInterpreter &interpreter) :
187235617911SEd Maste         CommandObjectParsed (interpreter,
187335617911SEd Maste                           "thread jump",
187435617911SEd Maste                           "Sets the program counter to a new address.",
187535617911SEd Maste                           "thread jump",
18761c3bbb01SEd Maste                           eCommandRequiresFrame         |
18771c3bbb01SEd Maste                           eCommandTryTargetAPILock      |
18781c3bbb01SEd Maste                           eCommandProcessMustBeLaunched |
18791c3bbb01SEd Maste                           eCommandProcessMustBePaused   ),
188035617911SEd Maste         m_options (interpreter)
188135617911SEd Maste     {
188235617911SEd Maste     }
188335617911SEd Maste 
18849f2f44ceSEd Maste     ~CommandObjectThreadJump() override
188535617911SEd Maste     {
188635617911SEd Maste     }
188735617911SEd Maste 
188835617911SEd Maste protected:
188935617911SEd Maste 
18909f2f44ceSEd Maste     bool DoExecute (Args& args, CommandReturnObject &result) override
189135617911SEd Maste     {
189235617911SEd Maste         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
189335617911SEd Maste         StackFrame *frame = m_exe_ctx.GetFramePtr();
189435617911SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
189535617911SEd Maste         Target *target = m_exe_ctx.GetTargetPtr();
189635617911SEd Maste         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
189735617911SEd Maste 
189835617911SEd Maste         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
189935617911SEd Maste         {
190035617911SEd Maste             // Use this address directly.
190135617911SEd Maste             Address dest = Address(m_options.m_load_addr);
190235617911SEd Maste 
190335617911SEd Maste             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
190435617911SEd Maste             if (callAddr == LLDB_INVALID_ADDRESS)
190535617911SEd Maste             {
190635617911SEd Maste                 result.AppendErrorWithFormat ("Invalid destination address.");
190735617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
190835617911SEd Maste                 return false;
190935617911SEd Maste             }
191035617911SEd Maste 
191135617911SEd Maste             if (!reg_ctx->SetPC (callAddr))
191235617911SEd Maste             {
191335617911SEd Maste                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
191435617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
191535617911SEd Maste                 return false;
191635617911SEd Maste             }
191735617911SEd Maste         }
191835617911SEd Maste         else
191935617911SEd Maste         {
192035617911SEd Maste             // Pick either the absolute line, or work out a relative one.
192135617911SEd Maste             int32_t line = (int32_t)m_options.m_line_num;
192235617911SEd Maste             if (line == 0)
192335617911SEd Maste                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
192435617911SEd Maste 
192535617911SEd Maste             // Try the current file, but override if asked.
192635617911SEd Maste             FileSpec file = sym_ctx.line_entry.file;
192735617911SEd Maste             if (m_options.m_filenames.GetSize() == 1)
192835617911SEd Maste                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
192935617911SEd Maste 
193035617911SEd Maste             if (!file)
193135617911SEd Maste             {
193235617911SEd Maste                 result.AppendErrorWithFormat ("No source file available for the current location.");
193335617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
193435617911SEd Maste                 return false;
193535617911SEd Maste             }
193635617911SEd Maste 
193735617911SEd Maste             std::string warnings;
193835617911SEd Maste             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
193935617911SEd Maste 
194035617911SEd Maste             if (err.Fail())
194135617911SEd Maste             {
194235617911SEd Maste                 result.SetError (err);
194335617911SEd Maste                 return false;
194435617911SEd Maste             }
194535617911SEd Maste 
194635617911SEd Maste             if (!warnings.empty())
194735617911SEd Maste                 result.AppendWarning (warnings.c_str());
194835617911SEd Maste         }
194935617911SEd Maste 
195035617911SEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
195135617911SEd Maste         return true;
195235617911SEd Maste     }
195335617911SEd Maste 
195435617911SEd Maste     CommandOptions m_options;
195535617911SEd Maste };
195635617911SEd Maste OptionDefinition
195735617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] =
195835617911SEd Maste {
19590127ef0fSEd Maste     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
196035617911SEd Maste         "Specifies the source file to jump to."},
196135617911SEd Maste 
19620127ef0fSEd Maste     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
196335617911SEd Maste         "Specifies the line number to jump to."},
196435617911SEd Maste 
19650127ef0fSEd Maste     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
196635617911SEd Maste         "Jumps by a relative line offset from the current line."},
196735617911SEd Maste 
19680127ef0fSEd Maste     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
196935617911SEd Maste         "Jumps to a specific address."},
197035617911SEd Maste 
197135617911SEd Maste     { LLDB_OPT_SET_1|
197235617911SEd Maste       LLDB_OPT_SET_2|
19730127ef0fSEd Maste       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
197435617911SEd Maste 
19750127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1976ac7ddfbfSEd Maste };
1977ac7ddfbfSEd Maste 
1978ac7ddfbfSEd Maste //-------------------------------------------------------------------------
19797aa51b79SEd Maste // Next are the subcommands of CommandObjectMultiwordThreadPlan
19807aa51b79SEd Maste //-------------------------------------------------------------------------
19817aa51b79SEd Maste 
19827aa51b79SEd Maste 
19837aa51b79SEd Maste //-------------------------------------------------------------------------
19847aa51b79SEd Maste // CommandObjectThreadPlanList
19857aa51b79SEd Maste //-------------------------------------------------------------------------
19867aa51b79SEd Maste class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
19877aa51b79SEd Maste {
19887aa51b79SEd Maste public:
19897aa51b79SEd Maste 
19907aa51b79SEd Maste     class CommandOptions : public Options
19917aa51b79SEd Maste     {
19927aa51b79SEd Maste     public:
19937aa51b79SEd Maste 
19947aa51b79SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
19957aa51b79SEd Maste             Options(interpreter)
19967aa51b79SEd Maste         {
19977aa51b79SEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
19987aa51b79SEd Maste             OptionParsingStarting ();
19997aa51b79SEd Maste         }
20007aa51b79SEd Maste 
20019f2f44ceSEd Maste         ~CommandOptions () override
20027aa51b79SEd Maste         {
20037aa51b79SEd Maste         }
20047aa51b79SEd Maste 
20059f2f44ceSEd Maste         Error
20069f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
20077aa51b79SEd Maste         {
20087aa51b79SEd Maste             Error error;
20097aa51b79SEd Maste             const int short_option = m_getopt_table[option_idx].val;
20107aa51b79SEd Maste 
20117aa51b79SEd Maste             switch (short_option)
20127aa51b79SEd Maste             {
20137aa51b79SEd Maste                 case 'i':
20147aa51b79SEd Maste                 {
20157aa51b79SEd Maste                     m_internal = true;
20167aa51b79SEd Maste                 }
20177aa51b79SEd Maste                 break;
20187aa51b79SEd Maste                 case 'v':
20197aa51b79SEd Maste                 {
20207aa51b79SEd Maste                     m_verbose = true;
20217aa51b79SEd Maste                 }
20227aa51b79SEd Maste                 break;
20237aa51b79SEd Maste                 default:
20247aa51b79SEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
20257aa51b79SEd Maste                     break;
20267aa51b79SEd Maste 
20277aa51b79SEd Maste             }
20287aa51b79SEd Maste             return error;
20297aa51b79SEd Maste         }
20307aa51b79SEd Maste 
20317aa51b79SEd Maste         void
20329f2f44ceSEd Maste         OptionParsingStarting () override
20337aa51b79SEd Maste         {
20347aa51b79SEd Maste             m_verbose = false;
20357aa51b79SEd Maste             m_internal = false;
20367aa51b79SEd Maste         }
20377aa51b79SEd Maste 
20387aa51b79SEd Maste         const OptionDefinition*
20399f2f44ceSEd Maste         GetDefinitions () override
20407aa51b79SEd Maste         {
20417aa51b79SEd Maste             return g_option_table;
20427aa51b79SEd Maste         }
20437aa51b79SEd Maste 
20447aa51b79SEd Maste         // Options table: Required for subclasses of Options.
20457aa51b79SEd Maste 
20467aa51b79SEd Maste         static OptionDefinition g_option_table[];
20477aa51b79SEd Maste 
20487aa51b79SEd Maste         // Instance variables to hold the values for command options.
20497aa51b79SEd Maste         bool m_verbose;
20507aa51b79SEd Maste         bool m_internal;
20517aa51b79SEd Maste     };
20527aa51b79SEd Maste 
20537aa51b79SEd Maste     CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
20547aa51b79SEd Maste         CommandObjectIterateOverThreads (interpreter,
20557aa51b79SEd Maste                                          "thread plan list",
20567aa51b79SEd Maste                                          "Show thread plans for one or more threads.  If no threads are specified, show the "
20577aa51b79SEd Maste                                          "currently selected thread.  Use the thread-index \"all\" to see all threads.",
20587aa51b79SEd Maste                                          NULL,
20591c3bbb01SEd Maste                                          eCommandRequiresProcess       |
20601c3bbb01SEd Maste                                          eCommandRequiresThread        |
20611c3bbb01SEd Maste                                          eCommandTryTargetAPILock      |
20621c3bbb01SEd Maste                                          eCommandProcessMustBeLaunched |
20631c3bbb01SEd Maste                                          eCommandProcessMustBePaused   ),
20647aa51b79SEd Maste         m_options(interpreter)
20657aa51b79SEd Maste     {
20667aa51b79SEd Maste     }
20677aa51b79SEd Maste 
20689f2f44ceSEd Maste     ~CommandObjectThreadPlanList () override
20697aa51b79SEd Maste     {
20707aa51b79SEd Maste     }
20717aa51b79SEd Maste 
20729f2f44ceSEd Maste     Options *
20739f2f44ceSEd Maste     GetOptions () override
20747aa51b79SEd Maste     {
20757aa51b79SEd Maste         return &m_options;
20767aa51b79SEd Maste     }
20777aa51b79SEd Maste 
20787aa51b79SEd Maste protected:
20799f2f44ceSEd Maste     bool
20809f2f44ceSEd Maste     HandleOneThread (Thread &thread, CommandReturnObject &result) override
20817aa51b79SEd Maste     {
20827aa51b79SEd Maste         Stream &strm = result.GetOutputStream();
20837aa51b79SEd Maste         DescriptionLevel desc_level = eDescriptionLevelFull;
20847aa51b79SEd Maste         if (m_options.m_verbose)
20857aa51b79SEd Maste             desc_level = eDescriptionLevelVerbose;
20867aa51b79SEd Maste 
20877aa51b79SEd Maste         thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
20887aa51b79SEd Maste         return true;
20897aa51b79SEd Maste     }
20907aa51b79SEd Maste     CommandOptions m_options;
20917aa51b79SEd Maste };
20927aa51b79SEd Maste 
20937aa51b79SEd Maste OptionDefinition
20947aa51b79SEd Maste CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
20957aa51b79SEd Maste {
20967aa51b79SEd Maste { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
20977aa51b79SEd Maste { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
20987aa51b79SEd Maste { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
20997aa51b79SEd Maste };
21007aa51b79SEd Maste 
21017aa51b79SEd Maste class CommandObjectThreadPlanDiscard : public CommandObjectParsed
21027aa51b79SEd Maste {
21037aa51b79SEd Maste public:
21047aa51b79SEd Maste     CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
21057aa51b79SEd Maste         CommandObjectParsed (interpreter,
21067aa51b79SEd Maste                              "thread plan discard",
21077aa51b79SEd Maste                              "Discards thread plans up to and including the plan passed as the command argument."
21087aa51b79SEd Maste                              "Only user visible plans can be discarded, use the index from \"thread plan list\""
21097aa51b79SEd Maste                              " without the \"-i\" argument.",
21107aa51b79SEd Maste                              NULL,
21111c3bbb01SEd Maste                              eCommandRequiresProcess       |
21121c3bbb01SEd Maste                              eCommandRequiresThread        |
21131c3bbb01SEd Maste                              eCommandTryTargetAPILock      |
21141c3bbb01SEd Maste                              eCommandProcessMustBeLaunched |
21151c3bbb01SEd Maste                              eCommandProcessMustBePaused   )
21167aa51b79SEd Maste     {
21177aa51b79SEd Maste         CommandArgumentEntry arg;
21187aa51b79SEd Maste         CommandArgumentData plan_index_arg;
21197aa51b79SEd Maste 
21207aa51b79SEd Maste         // Define the first (and only) variant of this arg.
21217aa51b79SEd Maste         plan_index_arg.arg_type = eArgTypeUnsignedInteger;
21227aa51b79SEd Maste         plan_index_arg.arg_repetition = eArgRepeatPlain;
21237aa51b79SEd Maste 
21247aa51b79SEd Maste         // There is only one variant this argument could be; put it into the argument entry.
21257aa51b79SEd Maste         arg.push_back (plan_index_arg);
21267aa51b79SEd Maste 
21277aa51b79SEd Maste         // Push the data for the first argument into the m_arguments vector.
21287aa51b79SEd Maste         m_arguments.push_back (arg);
21297aa51b79SEd Maste     }
21307aa51b79SEd Maste 
21319f2f44ceSEd Maste     ~CommandObjectThreadPlanDiscard () override {}
21327aa51b79SEd Maste 
21337aa51b79SEd Maste     bool
21349f2f44ceSEd Maste     DoExecute (Args& args, CommandReturnObject &result) override
21357aa51b79SEd Maste     {
21367aa51b79SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
21377aa51b79SEd Maste         if (args.GetArgumentCount() != 1)
21387aa51b79SEd Maste         {
21397aa51b79SEd Maste             result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
21407aa51b79SEd Maste                                          args.GetArgumentCount());
21417aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21427aa51b79SEd Maste             return false;
21437aa51b79SEd Maste         }
21447aa51b79SEd Maste 
21457aa51b79SEd Maste         bool success;
21461c3bbb01SEd Maste         uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
21477aa51b79SEd Maste         if (!success)
21487aa51b79SEd Maste         {
21497aa51b79SEd Maste             result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
21507aa51b79SEd Maste                                          args.GetArgumentAtIndex(0));
21517aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21527aa51b79SEd Maste             return false;
21537aa51b79SEd Maste         }
21547aa51b79SEd Maste 
21557aa51b79SEd Maste         if (thread_plan_idx == 0)
21567aa51b79SEd Maste         {
21577aa51b79SEd Maste             result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
21587aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21597aa51b79SEd Maste             return false;
21607aa51b79SEd Maste         }
21617aa51b79SEd Maste 
21627aa51b79SEd Maste         if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
21637aa51b79SEd Maste         {
21647aa51b79SEd Maste             result.SetStatus(eReturnStatusSuccessFinishNoResult);
21657aa51b79SEd Maste             return true;
21667aa51b79SEd Maste         }
21677aa51b79SEd Maste         else
21687aa51b79SEd Maste         {
21697aa51b79SEd Maste             result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
21707aa51b79SEd Maste                                          args.GetArgumentAtIndex(0));
21717aa51b79SEd Maste             result.SetStatus (eReturnStatusFailed);
21727aa51b79SEd Maste             return false;
21737aa51b79SEd Maste         }
21747aa51b79SEd Maste     }
21757aa51b79SEd Maste };
21767aa51b79SEd Maste 
21777aa51b79SEd Maste //-------------------------------------------------------------------------
21787aa51b79SEd Maste // CommandObjectMultiwordThreadPlan
21797aa51b79SEd Maste //-------------------------------------------------------------------------
21807aa51b79SEd Maste 
21817aa51b79SEd Maste class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
21827aa51b79SEd Maste {
21837aa51b79SEd Maste public:
21847aa51b79SEd Maste     CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
21857aa51b79SEd Maste         CommandObjectMultiword (interpreter,
21867aa51b79SEd Maste                                 "plan",
21877aa51b79SEd Maste                                 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
21887aa51b79SEd Maste                                 "thread plan <subcommand> [<subcommand objects]")
21897aa51b79SEd Maste     {
21907aa51b79SEd Maste         LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
21917aa51b79SEd Maste         LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
21927aa51b79SEd Maste     }
21937aa51b79SEd Maste 
21949f2f44ceSEd Maste     ~CommandObjectMultiwordThreadPlan () override {}
21957aa51b79SEd Maste 
21967aa51b79SEd Maste 
21977aa51b79SEd Maste };
21987aa51b79SEd Maste 
21997aa51b79SEd Maste //-------------------------------------------------------------------------
2200ac7ddfbfSEd Maste // CommandObjectMultiwordThread
2201ac7ddfbfSEd Maste //-------------------------------------------------------------------------
2202ac7ddfbfSEd Maste 
2203ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
2204ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
2205ac7ddfbfSEd Maste                             "thread",
2206ac7ddfbfSEd Maste                             "A set of commands for operating on one or more threads within a running process.",
2207ac7ddfbfSEd Maste                             "thread <subcommand> [<subcommand-options>]")
2208ac7ddfbfSEd Maste {
2209ac7ddfbfSEd Maste     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
2210ac7ddfbfSEd Maste     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
2211ac7ddfbfSEd Maste     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
2212ac7ddfbfSEd Maste     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
221335617911SEd Maste     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
2214ac7ddfbfSEd Maste     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
2215ac7ddfbfSEd Maste     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
22160127ef0fSEd Maste     LoadSubCommand ("info",       CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
2217ac7ddfbfSEd Maste     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2218ac7ddfbfSEd Maste                                                     interpreter,
2219ac7ddfbfSEd Maste                                                     "thread step-in",
2220ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified).",
2221ac7ddfbfSEd Maste                                                     NULL,
2222ac7ddfbfSEd Maste                                                     eStepTypeInto,
2223ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2224ac7ddfbfSEd Maste 
2225ac7ddfbfSEd Maste     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2226ac7ddfbfSEd Maste                                                     interpreter,
2227ac7ddfbfSEd Maste                                                     "thread step-out",
2228ac7ddfbfSEd Maste                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
2229ac7ddfbfSEd Maste                                                     NULL,
2230ac7ddfbfSEd Maste                                                     eStepTypeOut,
2231ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2232ac7ddfbfSEd Maste 
2233ac7ddfbfSEd Maste     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2234ac7ddfbfSEd Maste                                                     interpreter,
2235ac7ddfbfSEd Maste                                                     "thread step-over",
2236ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
2237ac7ddfbfSEd Maste                                                     NULL,
2238ac7ddfbfSEd Maste                                                     eStepTypeOver,
2239ac7ddfbfSEd Maste                                                     eStepScopeSource)));
2240ac7ddfbfSEd Maste 
2241ac7ddfbfSEd Maste     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2242ac7ddfbfSEd Maste                                                     interpreter,
2243ac7ddfbfSEd Maste                                                     "thread step-inst",
2244ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified).",
2245ac7ddfbfSEd Maste                                                     NULL,
2246ac7ddfbfSEd Maste                                                     eStepTypeTrace,
2247ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
2248ac7ddfbfSEd Maste 
2249ac7ddfbfSEd Maste     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2250ac7ddfbfSEd Maste                                                     interpreter,
2251ac7ddfbfSEd Maste                                                     "thread step-inst-over",
2252ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
2253ac7ddfbfSEd Maste                                                     NULL,
2254ac7ddfbfSEd Maste                                                     eStepTypeTraceOver,
2255ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
22567aa51b79SEd Maste 
22577aa51b79SEd Maste     LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
22587aa51b79SEd Maste                                                     interpreter,
22597aa51b79SEd Maste                                                     "thread step-scripted",
22607aa51b79SEd Maste                                                     "Step as instructed by the script class passed in the -C option.",
22617aa51b79SEd Maste                                                     NULL,
22627aa51b79SEd Maste                                                     eStepTypeScripted,
22637aa51b79SEd Maste                                                     eStepScopeSource)));
22647aa51b79SEd Maste 
22657aa51b79SEd Maste     LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
2266ac7ddfbfSEd Maste }
2267ac7ddfbfSEd Maste 
2268ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
2269ac7ddfbfSEd Maste {
2270ac7ddfbfSEd Maste }
2271ac7ddfbfSEd Maste 
2272ac7ddfbfSEd Maste 
2273