]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectThread.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Commands / CommandObjectThread.cpp
1 //===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 #include "CommandObjectThread.h"
13
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-private.h"
19 #include "lldb/Core/State.h"
20 #include "lldb/Core/SourceManager.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/CompileUnit.h"
26 #include "lldb/Symbol/Function.h"
27 #include "lldb/Symbol/LineTable.h"
28 #include "lldb/Symbol/LineEntry.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/RegisterContext.h"
31 #include "lldb/Target/SystemRuntime.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Target/Thread.h"
34 #include "lldb/Target/ThreadPlan.h"
35 #include "lldb/Target/ThreadPlanStepInstruction.h"
36 #include "lldb/Target/ThreadPlanStepOut.h"
37 #include "lldb/Target/ThreadPlanStepRange.h"
38 #include "lldb/Target/ThreadPlanStepInRange.h"
39
40
41 using namespace lldb;
42 using namespace lldb_private;
43
44
45 //-------------------------------------------------------------------------
46 // CommandObjectThreadBacktrace
47 //-------------------------------------------------------------------------
48
49 class CommandObjectIterateOverThreads : public CommandObjectParsed
50 {
51 public:
52     CommandObjectIterateOverThreads (CommandInterpreter &interpreter,
53                          const char *name,
54                          const char *help,
55                          const char *syntax,
56                          uint32_t flags) :
57         CommandObjectParsed (interpreter, name, help, syntax, flags)
58     {
59     }
60
61     virtual ~CommandObjectIterateOverThreads() {}
62     virtual bool
63     DoExecute (Args& command, CommandReturnObject &result)
64     {        
65         result.SetStatus (m_success_return);
66
67         if (command.GetArgumentCount() == 0)
68         {
69             Thread *thread = m_exe_ctx.GetThreadPtr();
70             if (!HandleOneThread (*thread, result))
71                 return false;
72         }
73         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
74         {
75             Process *process = m_exe_ctx.GetProcessPtr();
76             uint32_t idx = 0;
77             for (ThreadSP thread_sp : process->Threads())
78             {
79                 if (idx != 0 && m_add_return)
80                     result.AppendMessage("");
81
82                 if (!HandleOneThread(*(thread_sp.get()), result))
83                     return false;
84                 ++idx;
85             }
86         }
87         else
88         {
89             const size_t num_args = command.GetArgumentCount();
90             Process *process = m_exe_ctx.GetProcessPtr();
91             Mutex::Locker locker (process->GetThreadList().GetMutex());
92             std::vector<ThreadSP> thread_sps;
93
94             for (size_t i = 0; i < num_args; i++)
95             {
96                 bool success;
97                 
98                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
99                 if (!success)
100                 {
101                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
102                     result.SetStatus (eReturnStatusFailed);
103                     return false;
104                 }
105                 
106                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
107                 
108                 if (!thread_sps[i])
109                 {
110                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
111                     result.SetStatus (eReturnStatusFailed);
112                     return false;
113                 }
114                 
115             }
116             
117             for (uint32_t i = 0; i < num_args; i++)
118             {
119                 if (!HandleOneThread (*(thread_sps[i].get()), result))
120                     return false;
121
122                 if (i < num_args - 1 && m_add_return)
123                     result.AppendMessage("");
124             }
125         }
126         return result.Succeeded();
127     }
128
129 protected:
130
131     // Override this to do whatever you need to do for one thread.
132     //
133     // If you return false, the iteration will stop, otherwise it will proceed.
134     // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration,
135     // so you only need to set the return status in HandleOneThread if you want to indicate an error.
136     // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.)
137
138     virtual bool
139     HandleOneThread (Thread &thread, CommandReturnObject &result) = 0;
140
141     ReturnStatus m_success_return = eReturnStatusSuccessFinishResult;
142     bool m_add_return = true;
143
144 };
145
146 //-------------------------------------------------------------------------
147 // CommandObjectThreadBacktrace
148 //-------------------------------------------------------------------------
149
150 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads
151 {
152 public:
153
154     class CommandOptions : public Options
155     {
156     public:
157
158         CommandOptions (CommandInterpreter &interpreter) :
159             Options(interpreter)
160         {
161             // Keep default values of all options in one place: OptionParsingStarting ()
162             OptionParsingStarting ();
163         }
164
165         virtual
166         ~CommandOptions ()
167         {
168         }
169
170         virtual Error
171         SetOptionValue (uint32_t option_idx, const char *option_arg)
172         {
173             Error error;
174             const int short_option = m_getopt_table[option_idx].val;
175
176             switch (short_option)
177             {
178                 case 'c':
179                 {
180                     bool success;
181                     int32_t input_count =  Args::StringToSInt32 (option_arg, -1, 0, &success);
182                     if (!success)
183                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
184                     if (input_count < -1)
185                         m_count = UINT32_MAX;
186                     else
187                         m_count = input_count;
188                 }
189                 break;
190                 case 's':
191                 {
192                     bool success;
193                     m_start =  Args::StringToUInt32 (option_arg, 0, 0, &success);
194                     if (!success)
195                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
196                 }
197                 case 'e':
198                 {
199                     bool success;
200                     m_extended_backtrace =  Args::StringToBoolean (option_arg, false, &success);
201                     if (!success)
202                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
203                 }
204                 break;
205                 default:
206                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
207                     break;
208
209             }
210             return error;
211         }
212
213         void
214         OptionParsingStarting ()
215         {
216             m_count = UINT32_MAX;
217             m_start = 0;
218             m_extended_backtrace = false;
219         }
220
221         const OptionDefinition*
222         GetDefinitions ()
223         {
224             return g_option_table;
225         }
226
227         // Options table: Required for subclasses of Options.
228
229         static OptionDefinition g_option_table[];
230
231         // Instance variables to hold the values for command options.
232         uint32_t m_count;
233         uint32_t m_start;
234         bool     m_extended_backtrace;
235     };
236
237     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
238         CommandObjectIterateOverThreads (interpreter,
239                              "thread backtrace",
240                              "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.",
241                              NULL,
242                              eFlagRequiresProcess       |
243                              eFlagRequiresThread        |
244                              eFlagTryTargetAPILock      |
245                              eFlagProcessMustBeLaunched |
246                              eFlagProcessMustBePaused   ),
247         m_options(interpreter)
248     {
249     }
250
251     ~CommandObjectThreadBacktrace()
252     {
253     }
254
255     virtual Options *
256     GetOptions ()
257     {
258         return &m_options;
259     }
260
261 protected:
262     void
263     DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
264     {
265         SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
266         if (runtime)
267         {
268             Stream &strm = result.GetOutputStream();
269             const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
270             for (auto type : types)
271             {
272                 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
273                 if (ext_thread_sp && ext_thread_sp->IsValid ())
274                 {
275                     const uint32_t num_frames_with_source = 0;
276                     if (ext_thread_sp->GetStatus (strm, 
277                         m_options.m_start, 
278                         m_options.m_count, 
279                         num_frames_with_source))
280                     {
281                         DoExtendedBacktrace (ext_thread_sp.get(), result);
282                     }
283                 }
284             }
285         }
286     }
287
288     virtual bool
289     HandleOneThread (Thread &thread, CommandReturnObject &result)
290     {
291         Stream &strm = result.GetOutputStream();
292
293         // Don't show source context when doing backtraces.
294         const uint32_t num_frames_with_source = 0;
295
296         if (!thread.GetStatus (strm,
297                                    m_options.m_start,
298                                    m_options.m_count,
299                                    num_frames_with_source))
300         {
301             result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID());
302             result.SetStatus (eReturnStatusFailed);
303             return false;
304         }
305         if (m_options.m_extended_backtrace)
306         {
307             DoExtendedBacktrace (&thread, result);
308         }
309
310         return true;
311     }
312
313     CommandOptions m_options;
314 };
315
316 OptionDefinition
317 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
318 {
319 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
320 { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
321 { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
322 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
323 };
324
325 enum StepScope
326 {
327     eStepScopeSource,
328     eStepScopeInstruction
329 };
330
331 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
332 {
333 public:
334
335     class CommandOptions : public Options
336     {
337     public:
338
339         CommandOptions (CommandInterpreter &interpreter) :
340             Options (interpreter)
341         {
342             // Keep default values of all options in one place: OptionParsingStarting ()
343             OptionParsingStarting ();
344         }
345
346         virtual
347         ~CommandOptions ()
348         {
349         }
350
351         virtual Error
352         SetOptionValue (uint32_t option_idx, const char *option_arg)
353         {
354             Error error;
355             const int short_option = m_getopt_table[option_idx].val;
356
357             switch (short_option)
358             {
359             case 'a':
360                 {
361                     bool success;
362                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
363                     if (!success)
364                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
365                     else
366                     {
367                         m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
368                     }
369                 }
370                 break;
371             
372             case 'A':
373                 {
374                     bool success;
375                     bool avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
376                     if (!success)
377                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
378                     else
379                     {
380                         m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo;
381                     }
382                 }
383                 break;
384             
385             case 'c':
386                 {
387                     m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
388                     if (m_step_count == UINT32_MAX)
389                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
390                     break;
391                 }
392                 break;
393             case 'C':
394                 {
395                     m_class_name.clear();
396                     m_class_name.assign(option_arg);
397                 }
398                 break;
399             case 'm':
400                 {
401                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
402                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
403                 }
404                 break;
405             
406             case 'r':
407                 {
408                     m_avoid_regexp.clear();
409                     m_avoid_regexp.assign(option_arg);
410                 }
411                 break;
412
413             case 't':
414                 {
415                     m_step_in_target.clear();
416                     m_step_in_target.assign(option_arg);
417
418                 }
419                 break;
420             default:
421                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
422                 break;
423
424             }
425             return error;
426         }
427
428         void
429         OptionParsingStarting ()
430         {
431             m_step_in_avoid_no_debug = eLazyBoolCalculate;
432             m_step_out_avoid_no_debug = eLazyBoolCalculate;
433             m_run_mode = eOnlyDuringStepping;
434             m_avoid_regexp.clear();
435             m_step_in_target.clear();
436             m_class_name.clear();
437             m_step_count = 1;
438         }
439
440         const OptionDefinition*
441         GetDefinitions ()
442         {
443             return g_option_table;
444         }
445
446         // Options table: Required for subclasses of Options.
447
448         static OptionDefinition g_option_table[];
449
450         // Instance variables to hold the values for command options.
451         LazyBool m_step_in_avoid_no_debug;
452         LazyBool m_step_out_avoid_no_debug;
453         RunMode m_run_mode;
454         std::string m_avoid_regexp;
455         std::string m_step_in_target;
456         std::string m_class_name;
457         uint32_t m_step_count;
458     };
459
460     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
461                                              const char *name,
462                                              const char *help,
463                                              const char *syntax,
464                                              StepType step_type,
465                                              StepScope step_scope) :
466         CommandObjectParsed (interpreter, name, help, syntax,
467                              eFlagRequiresProcess       |
468                              eFlagRequiresThread        |
469                              eFlagTryTargetAPILock      |
470                              eFlagProcessMustBeLaunched |
471                              eFlagProcessMustBePaused   ),
472         m_step_type (step_type),
473         m_step_scope (step_scope),
474         m_options (interpreter)
475     {
476         CommandArgumentEntry arg;
477         CommandArgumentData thread_id_arg;
478         
479         // Define the first (and only) variant of this arg.
480         thread_id_arg.arg_type = eArgTypeThreadID;
481         thread_id_arg.arg_repetition = eArgRepeatOptional;
482         
483         // There is only one variant this argument could be; put it into the argument entry.
484         arg.push_back (thread_id_arg);
485         
486         // Push the data for the first argument into the m_arguments vector.
487         m_arguments.push_back (arg);
488     }
489
490     virtual
491     ~CommandObjectThreadStepWithTypeAndScope ()
492     {
493     }
494
495     virtual
496     Options *
497     GetOptions ()
498     {
499         return &m_options;
500     }
501
502 protected:
503     virtual bool
504     DoExecute (Args& command, CommandReturnObject &result)
505     {
506         Process *process = m_exe_ctx.GetProcessPtr();
507         bool synchronous_execution = m_interpreter.GetSynchronous();
508
509         const uint32_t num_threads = process->GetThreadList().GetSize();
510         Thread *thread = NULL;
511
512         if (command.GetArgumentCount() == 0)
513         {
514             thread = process->GetThreadList().GetSelectedThread().get();
515             if (thread == NULL)
516             {
517                 result.AppendError ("no selected thread in process");
518                 result.SetStatus (eReturnStatusFailed);
519                 return false;
520             }
521         }
522         else
523         {
524             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
525             uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
526             if (step_thread_idx == LLDB_INVALID_INDEX32)
527             {
528                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
529                 result.SetStatus (eReturnStatusFailed);
530                 return false;
531             }
532             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
533             if (thread == NULL)
534             {
535                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 
536                                               step_thread_idx, num_threads);
537                 result.SetStatus (eReturnStatusFailed);
538                 return false;
539             }
540         }
541
542         if (m_step_type == eStepTypeScripted)
543         {
544             if (m_options.m_class_name.empty())
545             {
546                 result.AppendErrorWithFormat ("empty class name for scripted step.");
547                 result.SetStatus(eReturnStatusFailed);
548                 return false;
549             }
550             else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str()))
551             {
552                 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str());
553                 result.SetStatus(eReturnStatusFailed);
554                 return false;
555             }
556         }
557
558         const bool abort_other_plans = false;
559         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
560         
561         // This is a bit unfortunate, but not all the commands in this command object support
562         // only while stepping, so I use the bool for them.
563         bool bool_stop_other_threads;
564         if (m_options.m_run_mode == eAllThreads)
565             bool_stop_other_threads = false;
566         else if (m_options.m_run_mode == eOnlyDuringStepping)
567         {
568             if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted)
569                 bool_stop_other_threads = false;
570             else
571                 bool_stop_other_threads = true;
572         }
573         else
574             bool_stop_other_threads = true;
575
576         ThreadPlanSP new_plan_sp;
577         
578         if (m_step_type == eStepTypeInto)
579         {
580             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
581
582             if (frame->HasDebugInformation ())
583             {
584                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
585                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
586                                                                 frame->GetSymbolContext(eSymbolContextEverything),
587                                                                 m_options.m_step_in_target.c_str(),
588                                                                 stop_other_threads,
589                                                                 m_options.m_step_in_avoid_no_debug,
590                                                                 m_options.m_step_out_avoid_no_debug);
591                 
592                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
593                 {
594                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
595                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
596                 }
597             }
598             else
599                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
600                 
601         }
602         else if (m_step_type == eStepTypeOver)
603         {
604             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
605
606             if (frame->HasDebugInformation())
607                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
608                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 
609                                                                     frame->GetSymbolContext(eSymbolContextEverything), 
610                                                                     stop_other_threads,
611                                                                     m_options.m_step_out_avoid_no_debug);
612             else
613                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
614                                                                             abort_other_plans, 
615                                                                             bool_stop_other_threads);
616
617         }
618         else if (m_step_type == eStepTypeTrace)
619         {
620             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
621         }
622         else if (m_step_type == eStepTypeTraceOver)
623         {
624             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
625         }
626         else if (m_step_type == eStepTypeOut)
627         {
628             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
629                                                           NULL, 
630                                                           false, 
631                                                           bool_stop_other_threads, 
632                                                           eVoteYes, 
633                                                           eVoteNoOpinion, 
634                                                           thread->GetSelectedFrameIndex(),
635                                                           m_options.m_step_out_avoid_no_debug);
636         }
637         else if (m_step_type == eStepTypeScripted)
638         {
639             new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans,
640                                                                   m_options.m_class_name.c_str(),
641                                                                   bool_stop_other_threads);
642         }
643         else
644         {
645             result.AppendError ("step type is not supported");
646             result.SetStatus (eReturnStatusFailed);
647             return false;
648         }
649         
650         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
651         // so that they can be interruptible).  Then resume the process.
652         
653         if (new_plan_sp)
654         {
655             new_plan_sp->SetIsMasterPlan (true);
656             new_plan_sp->SetOkayToDiscard (false);
657             
658             if (m_options.m_step_count > 1)
659             {
660                 if (new_plan_sp->SetIterationCount(m_options.m_step_count))
661                 {
662                     result.AppendWarning ("step operation does not support iteration count.");
663                 }
664             }
665
666
667             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
668
669             StreamString stream;
670             Error error;
671             if (synchronous_execution)
672                 error = process->ResumeSynchronous (&stream);
673             else
674                 error = process->Resume ();
675
676             // There is a race condition where this thread will return up the call stack to the main command handler
677             // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has
678             // a chance to call PushProcessIOHandler().
679             process->SyncIOHandler(2000);
680
681             if (synchronous_execution)
682             {
683                 // If any state changed events had anything to say, add that to the result
684                 if (stream.GetData())
685                     result.AppendMessage(stream.GetData());
686
687                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
688                 result.SetDidChangeProcessState (true);
689                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
690             }
691             else
692             {
693                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
694             }
695         }
696         else
697         {
698             result.AppendError ("Couldn't find thread plan to implement step type.");
699             result.SetStatus (eReturnStatusFailed);
700         }
701         return result.Succeeded();
702     }
703
704 protected:
705     StepType m_step_type;
706     StepScope m_step_scope;
707     CommandOptions m_options;
708 };
709
710 static OptionEnumValueElement
711 g_tri_running_mode[] =
712 {
713 { eOnlyThisThread,     "this-thread",    "Run only this thread"},
714 { eAllThreads,         "all-threads",    "Run all threads"},
715 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
716 { 0, NULL, NULL }
717 };
718
719 static OptionEnumValueElement
720 g_duo_running_mode[] =
721 {
722 { eOnlyThisThread,     "this-thread",    "Run only this thread"},
723 { eAllThreads,         "all-threads",    "Run all threads"},
724 { 0, NULL, NULL }
725 };
726
727 OptionDefinition
728 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
729 {
730 { 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."},
731 { 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."},
732 { 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."},
733 { 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."},
734 { 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."},
735 { 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."},
736 { 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."},
737 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
738 };
739
740
741 //-------------------------------------------------------------------------
742 // CommandObjectThreadContinue
743 //-------------------------------------------------------------------------
744
745 class CommandObjectThreadContinue : public CommandObjectParsed
746 {
747 public:
748
749     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
750         CommandObjectParsed (interpreter, 
751                              "thread continue",
752                              "Continue execution of one or more threads in an active process.",
753                              NULL,
754                              eFlagRequiresThread        |
755                              eFlagTryTargetAPILock      |
756                              eFlagProcessMustBeLaunched |
757                              eFlagProcessMustBePaused)
758     {
759         CommandArgumentEntry arg;
760         CommandArgumentData thread_idx_arg;
761         
762         // Define the first (and only) variant of this arg.
763         thread_idx_arg.arg_type = eArgTypeThreadIndex;
764         thread_idx_arg.arg_repetition = eArgRepeatPlus;
765         
766         // There is only one variant this argument could be; put it into the argument entry.
767         arg.push_back (thread_idx_arg);
768         
769         // Push the data for the first argument into the m_arguments vector.
770         m_arguments.push_back (arg);
771     }
772
773
774     virtual
775     ~CommandObjectThreadContinue ()
776     {
777     }
778
779     virtual bool
780     DoExecute (Args& command, CommandReturnObject &result)
781     {
782         bool synchronous_execution = m_interpreter.GetSynchronous ();
783
784         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
785         {
786             result.AppendError ("invalid target, create a debug target using the 'target create' command");
787             result.SetStatus (eReturnStatusFailed);
788             return false;
789         }
790
791         Process *process = m_exe_ctx.GetProcessPtr();
792         if (process == NULL)
793         {
794             result.AppendError ("no process exists. Cannot continue");
795             result.SetStatus (eReturnStatusFailed);
796             return false;
797         }
798
799         StateType state = process->GetState();
800         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
801         {
802             const size_t argc = command.GetArgumentCount();
803             if (argc > 0)
804             {
805                 // These two lines appear at the beginning of both blocks in
806                 // this if..else, but that is because we need to release the
807                 // lock before calling process->Resume below.
808                 Mutex::Locker locker (process->GetThreadList().GetMutex());
809                 const uint32_t num_threads = process->GetThreadList().GetSize();
810                 std::vector<Thread *> resume_threads;
811                 for (uint32_t i=0; i<argc; ++i)
812                 {
813                     bool success;
814                     const int base = 0;
815                     uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
816                     if (success)
817                     {
818                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
819
820                         if (thread)
821                         {
822                             resume_threads.push_back(thread);
823                         }
824                         else
825                         {
826                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
827                             result.SetStatus (eReturnStatusFailed);
828                             return false;
829                         }
830                     }
831                     else
832                     {
833                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
834                         result.SetStatus (eReturnStatusFailed);
835                         return false;
836                     }
837                 }
838
839                 if (resume_threads.empty())
840                 {
841                     result.AppendError ("no valid thread indexes were specified");
842                     result.SetStatus (eReturnStatusFailed);
843                     return false;
844                 }
845                 else
846                 {
847                     if (resume_threads.size() == 1)
848                         result.AppendMessageWithFormat ("Resuming thread: ");
849                     else
850                         result.AppendMessageWithFormat ("Resuming threads: ");
851
852                     for (uint32_t idx=0; idx<num_threads; ++idx)
853                     {
854                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
855                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
856
857                         if (this_thread_pos != resume_threads.end())
858                         {
859                             resume_threads.erase(this_thread_pos);
860                             if (resume_threads.size() > 0)
861                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
862                             else
863                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
864                             
865                             const bool override_suspend = true;
866                             thread->SetResumeState (eStateRunning, override_suspend);
867                         }
868                         else
869                         {
870                             thread->SetResumeState (eStateSuspended);
871                         }
872                     }
873                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
874                 }
875             }
876             else
877             {
878                 // These two lines appear at the beginning of both blocks in
879                 // this if..else, but that is because we need to release the
880                 // lock before calling process->Resume below.
881                 Mutex::Locker locker (process->GetThreadList().GetMutex());
882                 const uint32_t num_threads = process->GetThreadList().GetSize();
883                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
884                 if (current_thread == NULL)
885                 {
886                     result.AppendError ("the process doesn't have a current thread");
887                     result.SetStatus (eReturnStatusFailed);
888                     return false;
889                 }
890                 // Set the actions that the threads should each take when resuming
891                 for (uint32_t idx=0; idx<num_threads; ++idx)
892                 {
893                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
894                     if (thread == current_thread)
895                     {
896                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
897                         const bool override_suspend = true;
898                         thread->SetResumeState (eStateRunning, override_suspend);
899                     }
900                     else
901                     {
902                         thread->SetResumeState (eStateSuspended);
903                     }
904                 }
905             }
906
907
908             StreamString stream;
909             Error error;
910             if (synchronous_execution)
911                 error = process->ResumeSynchronous (&stream);
912             else
913                 error = process->Resume ();
914
915             // We should not be holding the thread list lock when we do this.
916             if (error.Success())
917             {
918                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
919                 if (synchronous_execution)
920                 {
921                     // If any state changed events had anything to say, add that to the result
922                     if (stream.GetData())
923                         result.AppendMessage(stream.GetData());
924
925                     result.SetDidChangeProcessState (true);
926                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
927                 }
928                 else
929                 {
930                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
931                 }
932             }
933             else
934             {
935                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
936                 result.SetStatus (eReturnStatusFailed);
937             }
938         }
939         else
940         {
941             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
942                                           StateAsCString(state));
943             result.SetStatus (eReturnStatusFailed);
944         }
945
946         return result.Succeeded();
947     }
948
949 };
950
951 //-------------------------------------------------------------------------
952 // CommandObjectThreadUntil
953 //-------------------------------------------------------------------------
954
955 class CommandObjectThreadUntil : public CommandObjectParsed
956 {
957 public:
958
959     class CommandOptions : public Options
960     {
961     public:
962         uint32_t m_thread_idx;
963         uint32_t m_frame_idx;
964
965         CommandOptions (CommandInterpreter &interpreter) :
966             Options (interpreter),
967             m_thread_idx(LLDB_INVALID_THREAD_ID),
968             m_frame_idx(LLDB_INVALID_FRAME_ID)
969         {
970             // Keep default values of all options in one place: OptionParsingStarting ()
971             OptionParsingStarting ();
972         }
973
974         virtual
975         ~CommandOptions ()
976         {
977         }
978
979         virtual Error
980         SetOptionValue (uint32_t option_idx, const char *option_arg)
981         {
982             Error error;
983             const int short_option = m_getopt_table[option_idx].val;
984
985             switch (short_option)
986             {
987                 case 't':
988                 {
989                     m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
990                     if (m_thread_idx == LLDB_INVALID_INDEX32)
991                     {
992                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
993                     }
994                 }
995                 break;
996                 case 'f':
997                 {
998                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
999                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1000                     {
1001                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
1002                     }
1003                 }
1004                 break;
1005                 case 'm':
1006                 {
1007                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 
1008                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
1009
1010                     if (error.Success())
1011                     {
1012                         if (run_mode == eAllThreads)
1013                             m_stop_others = false;
1014                         else
1015                             m_stop_others = true;
1016                     }
1017                 }
1018                 break;
1019                 default:
1020                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1021                     break;
1022
1023             }
1024             return error;
1025         }
1026
1027         void
1028         OptionParsingStarting ()
1029         {
1030             m_thread_idx = LLDB_INVALID_THREAD_ID;
1031             m_frame_idx = 0;
1032             m_stop_others = false;
1033         }
1034
1035         const OptionDefinition*
1036         GetDefinitions ()
1037         {
1038             return g_option_table;
1039         }
1040
1041         uint32_t m_step_thread_idx;
1042         bool m_stop_others;
1043
1044         // Options table: Required for subclasses of Options.
1045
1046         static OptionDefinition g_option_table[];
1047
1048         // Instance variables to hold the values for command options.
1049     };
1050
1051     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1052         CommandObjectParsed (interpreter, 
1053                              "thread until",
1054                              "Run the current or specified thread until it reaches a given line number or leaves the current function.",
1055                              NULL,
1056                              eFlagRequiresThread        |
1057                              eFlagTryTargetAPILock      |
1058                              eFlagProcessMustBeLaunched |
1059                              eFlagProcessMustBePaused   ),
1060         m_options (interpreter)
1061     {
1062         CommandArgumentEntry arg;
1063         CommandArgumentData line_num_arg;
1064         
1065         // Define the first (and only) variant of this arg.
1066         line_num_arg.arg_type = eArgTypeLineNum;
1067         line_num_arg.arg_repetition = eArgRepeatPlain;
1068         
1069         // There is only one variant this argument could be; put it into the argument entry.
1070         arg.push_back (line_num_arg);
1071         
1072         // Push the data for the first argument into the m_arguments vector.
1073         m_arguments.push_back (arg);
1074     }
1075
1076
1077     virtual
1078     ~CommandObjectThreadUntil ()
1079     {
1080     }
1081
1082     virtual
1083     Options *
1084     GetOptions ()
1085     {
1086         return &m_options;
1087     }
1088
1089 protected:
1090     virtual bool
1091     DoExecute (Args& command, CommandReturnObject &result)
1092     {
1093         bool synchronous_execution = m_interpreter.GetSynchronous ();
1094
1095         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1096         if (target == NULL)
1097         {
1098             result.AppendError ("invalid target, create a debug target using the 'target create' command");
1099             result.SetStatus (eReturnStatusFailed);
1100             return false;
1101         }
1102
1103         Process *process = m_exe_ctx.GetProcessPtr();
1104         if (process == NULL)
1105         {
1106             result.AppendError ("need a valid process to step");
1107             result.SetStatus (eReturnStatusFailed);
1108
1109         }
1110         else
1111         {
1112             Thread *thread = NULL;
1113             uint32_t line_number;
1114
1115             if (command.GetArgumentCount() != 1)
1116             {
1117                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1118                 result.SetStatus (eReturnStatusFailed);
1119                 return false;
1120             }
1121
1122             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1123             if (line_number == UINT32_MAX)
1124             {
1125                 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1126                 result.SetStatus (eReturnStatusFailed);
1127                 return false;
1128             }
1129
1130             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1131             {
1132                 thread = process->GetThreadList().GetSelectedThread().get();
1133             }
1134             else
1135             {
1136                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1137             }
1138
1139             if (thread == NULL)
1140             {
1141                 const uint32_t num_threads = process->GetThreadList().GetSize();
1142                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 
1143                                               m_options.m_thread_idx, 
1144                                               num_threads);
1145                 result.SetStatus (eReturnStatusFailed);
1146                 return false;
1147             }
1148
1149             const bool abort_other_plans = false;
1150
1151             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1152             if (frame == NULL)
1153             {
1154
1155                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 
1156                                               m_options.m_frame_idx, 
1157                                               m_options.m_thread_idx);
1158                 result.SetStatus (eReturnStatusFailed);
1159                 return false;
1160             }
1161
1162             ThreadPlanSP new_plan_sp;
1163
1164             if (frame->HasDebugInformation ())
1165             {
1166                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1167                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1168                 LineTable *line_table = NULL;
1169                 if (sc.comp_unit)
1170                     line_table = sc.comp_unit->GetLineTable();
1171
1172                 if (line_table == NULL)
1173                 {
1174                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1175                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1176                     result.SetStatus (eReturnStatusFailed);
1177                     return false;
1178                 }
1179
1180                 LineEntry function_start;
1181                 uint32_t index_ptr = 0, end_ptr;
1182                 std::vector<addr_t> address_list;
1183
1184                 // Find the beginning & end index of the
1185                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1186                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1187                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1188
1189                 Address fun_end_addr(fun_start_addr.GetSection(), 
1190                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1191                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1192
1193                 bool all_in_function = true;
1194                 
1195                 while (index_ptr <= end_ptr)
1196                 {
1197                     LineEntry line_entry;
1198                     const bool exact = false;
1199                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
1200                     if (index_ptr == UINT32_MAX)
1201                         break;
1202
1203                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1204                     if (address != LLDB_INVALID_ADDRESS)
1205                     {
1206                         if (fun_addr_range.ContainsLoadAddress (address, target))
1207                             address_list.push_back (address);
1208                         else
1209                             all_in_function = false;
1210                     }
1211                     index_ptr++;
1212                 }
1213
1214                 if (address_list.size() == 0)
1215                 {
1216                     if (all_in_function)
1217                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1218                     else
1219                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1220                         
1221                     result.SetStatus (eReturnStatusFailed);
1222                     return false;
1223                 }
1224                 
1225                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1226                                                                 &address_list.front(), 
1227                                                                 address_list.size(), 
1228                                                                 m_options.m_stop_others, 
1229                                                                 m_options.m_frame_idx);
1230                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1231                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1232                 // will resume the original plan.
1233                 new_plan_sp->SetIsMasterPlan (true);
1234                 new_plan_sp->SetOkayToDiscard(false);
1235             }
1236             else
1237             {
1238                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 
1239                                               m_options.m_frame_idx, 
1240                                               m_options.m_thread_idx);
1241                 result.SetStatus (eReturnStatusFailed);
1242                 return false;
1243
1244             }
1245
1246
1247
1248             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
1249
1250             StreamString stream;
1251             Error error;
1252             if (synchronous_execution)
1253                 error = process->ResumeSynchronous (&stream);
1254             else
1255                 error = process->Resume ();
1256
1257             if (error.Success())
1258             {
1259                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1260                 if (synchronous_execution)
1261                 {
1262                     // If any state changed events had anything to say, add that to the result
1263                     if (stream.GetData())
1264                         result.AppendMessage(stream.GetData());
1265
1266                     result.SetDidChangeProcessState (true);
1267                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1268                 }
1269                 else
1270                 {
1271                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1272                 }
1273             }
1274             else
1275             {
1276                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1277                 result.SetStatus (eReturnStatusFailed);
1278             }
1279
1280         }
1281         return result.Succeeded();
1282     }
1283
1284     CommandOptions m_options;
1285
1286 };
1287
1288 OptionDefinition
1289 CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1290 {
1291 { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
1292 { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
1293 { 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"},
1294 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1295 };
1296
1297
1298 //-------------------------------------------------------------------------
1299 // CommandObjectThreadSelect
1300 //-------------------------------------------------------------------------
1301
1302 class CommandObjectThreadSelect : public CommandObjectParsed
1303 {
1304 public:
1305
1306     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1307         CommandObjectParsed (interpreter,
1308                              "thread select",
1309                              "Select a thread as the currently active thread.",
1310                              NULL,
1311                              eFlagRequiresProcess       |
1312                              eFlagTryTargetAPILock      |
1313                              eFlagProcessMustBeLaunched |
1314                              eFlagProcessMustBePaused   )
1315     {
1316         CommandArgumentEntry arg;
1317         CommandArgumentData thread_idx_arg;
1318         
1319         // Define the first (and only) variant of this arg.
1320         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1321         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1322         
1323         // There is only one variant this argument could be; put it into the argument entry.
1324         arg.push_back (thread_idx_arg);
1325         
1326         // Push the data for the first argument into the m_arguments vector.
1327         m_arguments.push_back (arg);
1328     }
1329
1330
1331     virtual
1332     ~CommandObjectThreadSelect ()
1333     {
1334     }
1335
1336 protected:
1337     virtual bool
1338     DoExecute (Args& command, CommandReturnObject &result)
1339     {
1340         Process *process = m_exe_ctx.GetProcessPtr();
1341         if (process == NULL)
1342         {
1343             result.AppendError ("no process");
1344             result.SetStatus (eReturnStatusFailed);
1345             return false;
1346         }
1347         else if (command.GetArgumentCount() != 1)
1348         {
1349             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1350             result.SetStatus (eReturnStatusFailed);
1351             return false;
1352         }
1353
1354         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1355
1356         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1357         if (new_thread == NULL)
1358         {
1359             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1360             result.SetStatus (eReturnStatusFailed);
1361             return false;
1362         }
1363
1364         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1365         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1366         
1367         return result.Succeeded();
1368     }
1369
1370 };
1371
1372
1373 //-------------------------------------------------------------------------
1374 // CommandObjectThreadList
1375 //-------------------------------------------------------------------------
1376
1377 class CommandObjectThreadList : public CommandObjectParsed
1378 {
1379 public:
1380
1381
1382     CommandObjectThreadList (CommandInterpreter &interpreter):
1383         CommandObjectParsed (interpreter,
1384                              "thread list",
1385                              "Show a summary of all current threads in a process.",
1386                              "thread list",
1387                              eFlagRequiresProcess       |
1388                              eFlagTryTargetAPILock      |
1389                              eFlagProcessMustBeLaunched |
1390                              eFlagProcessMustBePaused   )
1391     {
1392     }
1393
1394     ~CommandObjectThreadList()
1395     {
1396     }
1397
1398 protected:
1399     bool
1400     DoExecute (Args& command, CommandReturnObject &result)
1401     {
1402         Stream &strm = result.GetOutputStream();
1403         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1404         Process *process = m_exe_ctx.GetProcessPtr();
1405         const bool only_threads_with_stop_reason = false;
1406         const uint32_t start_frame = 0;
1407         const uint32_t num_frames = 0;
1408         const uint32_t num_frames_with_source = 0;
1409         process->GetStatus(strm);
1410         process->GetThreadStatus (strm, 
1411                                   only_threads_with_stop_reason, 
1412                                   start_frame,
1413                                   num_frames,
1414                                   num_frames_with_source);            
1415         return result.Succeeded();
1416     }
1417 };
1418
1419 //-------------------------------------------------------------------------
1420 // CommandObjectThreadInfo
1421 //-------------------------------------------------------------------------
1422
1423 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads
1424 {
1425 public:
1426
1427     CommandObjectThreadInfo (CommandInterpreter &interpreter) :
1428         CommandObjectIterateOverThreads (interpreter,
1429                                          "thread info",
1430                                          "Show an extended summary of information about thread(s) in a process.",
1431                                          "thread info",
1432                                          eFlagRequiresProcess       |
1433                                          eFlagTryTargetAPILock      |
1434                                          eFlagProcessMustBeLaunched |
1435                                          eFlagProcessMustBePaused),
1436         m_options (interpreter)
1437     {
1438         m_add_return = false;
1439     }
1440
1441     class CommandOptions : public Options
1442     {
1443     public:
1444
1445         CommandOptions (CommandInterpreter &interpreter) :
1446             Options (interpreter)
1447         {
1448             OptionParsingStarting ();
1449         }
1450
1451         void
1452         OptionParsingStarting ()
1453         {
1454             m_json_thread = false;
1455             m_json_stopinfo = false;
1456         }
1457
1458         virtual
1459         ~CommandOptions ()
1460         {
1461         }
1462
1463         virtual Error
1464         SetOptionValue (uint32_t option_idx, const char *option_arg)
1465         {
1466             const int short_option = m_getopt_table[option_idx].val;
1467             Error error;
1468
1469             switch (short_option)
1470             {
1471                 case 'j':
1472                     m_json_thread = true;
1473                     break;
1474                     
1475                 case 's':
1476                     m_json_stopinfo = true;
1477                     break;
1478
1479                 default:
1480                     return Error("invalid short option character '%c'", short_option);
1481
1482             }
1483             return error;
1484         }
1485
1486         const OptionDefinition*
1487         GetDefinitions ()
1488         {
1489             return g_option_table;
1490         }
1491
1492         bool m_json_thread;
1493         bool m_json_stopinfo;
1494
1495         static OptionDefinition g_option_table[];
1496     };
1497
1498     virtual
1499     Options *
1500     GetOptions ()
1501     {
1502         return &m_options;
1503     }
1504
1505
1506     virtual
1507     ~CommandObjectThreadInfo ()
1508     {
1509     }
1510
1511     virtual bool
1512     HandleOneThread (Thread &thread, CommandReturnObject &result)
1513     {
1514         Stream &strm = result.GetOutputStream();
1515         if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo))
1516         {
1517             result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID());
1518             result.SetStatus (eReturnStatusFailed);
1519             return false;
1520         }
1521         return true;
1522     }
1523
1524     CommandOptions m_options;
1525
1526 };
1527
1528 OptionDefinition
1529 CommandObjectThreadInfo::CommandOptions::g_option_table[] =
1530 {
1531     { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."},
1532     { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."},
1533
1534     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1535 };
1536
1537
1538 //-------------------------------------------------------------------------
1539 // CommandObjectThreadReturn
1540 //-------------------------------------------------------------------------
1541
1542 class CommandObjectThreadReturn : public CommandObjectRaw
1543 {
1544 public:
1545     class CommandOptions : public Options
1546     {
1547     public:
1548
1549         CommandOptions (CommandInterpreter &interpreter) :
1550             Options (interpreter),
1551             m_from_expression (false)
1552         {
1553             // Keep default values of all options in one place: OptionParsingStarting ()
1554             OptionParsingStarting ();
1555         }
1556
1557         virtual
1558         ~CommandOptions ()
1559         {
1560         }
1561
1562         virtual Error
1563         SetOptionValue (uint32_t option_idx, const char *option_arg)
1564         {
1565             Error error;
1566             const int short_option = m_getopt_table[option_idx].val;
1567
1568             switch (short_option)
1569             {
1570                 case 'x':
1571                 {
1572                     bool success;
1573                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1574                     if (success)
1575                         m_from_expression = tmp_value;
1576                     else
1577                     {
1578                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1579                     }
1580                 }
1581                 break;
1582                 default:
1583                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1584                     break;
1585
1586             }
1587             return error;
1588         }
1589
1590         void
1591         OptionParsingStarting ()
1592         {
1593             m_from_expression = false;
1594         }
1595
1596         const OptionDefinition*
1597         GetDefinitions ()
1598         {
1599             return g_option_table;
1600         }
1601
1602         bool m_from_expression;
1603
1604         // Options table: Required for subclasses of Options.
1605
1606         static OptionDefinition g_option_table[];
1607
1608         // Instance variables to hold the values for command options.
1609     };
1610
1611     virtual
1612     Options *
1613     GetOptions ()
1614     {
1615         return &m_options;
1616     }
1617
1618     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1619         CommandObjectRaw (interpreter,
1620                           "thread return",
1621                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1622                           " or with the -x option from the innermost function evaluation.",
1623                           "thread return",
1624                           eFlagRequiresFrame         |
1625                           eFlagTryTargetAPILock      |
1626                           eFlagProcessMustBeLaunched |
1627                           eFlagProcessMustBePaused   ),
1628         m_options (interpreter)
1629     {
1630         CommandArgumentEntry arg;
1631         CommandArgumentData expression_arg;
1632
1633         // Define the first (and only) variant of this arg.
1634         expression_arg.arg_type = eArgTypeExpression;
1635         expression_arg.arg_repetition = eArgRepeatOptional;
1636
1637         // There is only one variant this argument could be; put it into the argument entry.
1638         arg.push_back (expression_arg);
1639
1640         // Push the data for the first argument into the m_arguments vector.
1641         m_arguments.push_back (arg);
1642         
1643         
1644     }
1645     
1646     ~CommandObjectThreadReturn()
1647     {
1648     }
1649     
1650 protected:
1651
1652     bool DoExecute
1653     (
1654         const char *command,
1655         CommandReturnObject &result
1656     )
1657     {
1658         // I am going to handle this by hand, because I don't want you to have to say:
1659         // "thread return -- -5".
1660         if (command[0] == '-' && command[1] == 'x')
1661         {
1662             if (command && command[2] != '\0')
1663                 result.AppendWarning("Return values ignored when returning from user called expressions");
1664             
1665             Thread *thread = m_exe_ctx.GetThreadPtr();
1666             Error error;
1667             error = thread->UnwindInnermostExpression();
1668             if (!error.Success())
1669             {
1670                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1671                 result.SetStatus (eReturnStatusFailed);
1672             }
1673             else
1674             {
1675                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1676                 if (success)
1677                 {
1678                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1679                     result.SetStatus (eReturnStatusSuccessFinishResult);
1680                 }
1681                 else
1682                 {
1683                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1684                     result.SetStatus (eReturnStatusFailed);
1685                 }
1686             }
1687             return result.Succeeded();
1688         }
1689         
1690         ValueObjectSP return_valobj_sp;
1691         
1692         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1693         uint32_t frame_idx = frame_sp->GetFrameIndex();
1694         
1695         if (frame_sp->IsInlined())
1696         {
1697             result.AppendError("Don't know how to return from inlined frames.");
1698             result.SetStatus (eReturnStatusFailed);
1699             return false;
1700         }
1701         
1702         if (command && command[0] != '\0')
1703         {
1704             Target *target = m_exe_ctx.GetTargetPtr();
1705             EvaluateExpressionOptions options;
1706
1707             options.SetUnwindOnError(true);
1708             options.SetUseDynamic(eNoDynamicValues);
1709             
1710             ExpressionResults exe_results = eExpressionSetupError;
1711             exe_results = target->EvaluateExpression (command,
1712                                                       frame_sp.get(),
1713                                                       return_valobj_sp,
1714                                                       options);
1715             if (exe_results != eExpressionCompleted)
1716             {
1717                 if (return_valobj_sp)
1718                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1719                 else
1720                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1721                 result.SetStatus (eReturnStatusFailed);
1722                 return false;
1723             
1724             }
1725         }
1726                 
1727         Error error;
1728         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1729         const bool broadcast = true;
1730         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1731         if (!error.Success())
1732         {
1733             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1734             result.SetStatus (eReturnStatusFailed);
1735             return false;
1736         }
1737
1738         result.SetStatus (eReturnStatusSuccessFinishResult);
1739         return true;
1740     }
1741     
1742     CommandOptions m_options;
1743
1744 };
1745 OptionDefinition
1746 CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1747 {
1748 { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
1749 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1750 };
1751
1752 //-------------------------------------------------------------------------
1753 // CommandObjectThreadJump
1754 //-------------------------------------------------------------------------
1755
1756 class CommandObjectThreadJump : public CommandObjectParsed
1757 {
1758 public:
1759     class CommandOptions : public Options
1760     {
1761     public:
1762
1763         CommandOptions (CommandInterpreter &interpreter) :
1764             Options (interpreter)
1765         {
1766             OptionParsingStarting ();
1767         }
1768
1769         void
1770         OptionParsingStarting ()
1771         {
1772             m_filenames.Clear();
1773             m_line_num = 0;
1774             m_line_offset = 0;
1775             m_load_addr = LLDB_INVALID_ADDRESS;
1776             m_force = false;
1777         }
1778
1779         virtual
1780         ~CommandOptions ()
1781         {
1782         }
1783
1784         virtual Error
1785         SetOptionValue (uint32_t option_idx, const char *option_arg)
1786         {
1787             bool success;
1788             const int short_option = m_getopt_table[option_idx].val;
1789             Error error;
1790
1791             switch (short_option)
1792             {
1793                 case 'f':
1794                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
1795                     if (m_filenames.GetSize() > 1)
1796                         return Error("only one source file expected.");
1797                     break;
1798                 case 'l':
1799                     m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success);
1800                     if (!success || m_line_num == 0)
1801                         return Error("invalid line number: '%s'.", option_arg);
1802                     break;
1803                 case 'b':
1804                     m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success);
1805                     if (!success)
1806                         return Error("invalid line offset: '%s'.", option_arg);
1807                     break;
1808                 case 'a':
1809                     {
1810                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
1811                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
1812                     }
1813                     break;
1814                 case 'r':
1815                     m_force = true;
1816                     break;
1817
1818                  default:
1819                     return Error("invalid short option character '%c'", short_option);
1820
1821             }
1822             return error;
1823         }
1824
1825         const OptionDefinition*
1826         GetDefinitions ()
1827         {
1828             return g_option_table;
1829         }
1830
1831         FileSpecList m_filenames;
1832         uint32_t m_line_num;
1833         int32_t m_line_offset;
1834         lldb::addr_t m_load_addr;
1835         bool m_force;
1836
1837         static OptionDefinition g_option_table[];
1838     };
1839
1840     virtual
1841     Options *
1842     GetOptions ()
1843     {
1844         return &m_options;
1845     }
1846
1847     CommandObjectThreadJump (CommandInterpreter &interpreter) :
1848         CommandObjectParsed (interpreter,
1849                           "thread jump",
1850                           "Sets the program counter to a new address.",
1851                           "thread jump",
1852                           eFlagRequiresFrame         |
1853                           eFlagTryTargetAPILock      |
1854                           eFlagProcessMustBeLaunched |
1855                           eFlagProcessMustBePaused   ),
1856         m_options (interpreter)
1857     {
1858     }
1859
1860     ~CommandObjectThreadJump()
1861     {
1862     }
1863
1864 protected:
1865
1866     bool DoExecute (Args& args, CommandReturnObject &result)
1867     {
1868         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
1869         StackFrame *frame = m_exe_ctx.GetFramePtr();
1870         Thread *thread = m_exe_ctx.GetThreadPtr();
1871         Target *target = m_exe_ctx.GetTargetPtr();
1872         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
1873
1874         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
1875         {
1876             // Use this address directly.
1877             Address dest = Address(m_options.m_load_addr);
1878
1879             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
1880             if (callAddr == LLDB_INVALID_ADDRESS)
1881             {
1882                 result.AppendErrorWithFormat ("Invalid destination address.");
1883                 result.SetStatus (eReturnStatusFailed);
1884                 return false;
1885             }
1886
1887             if (!reg_ctx->SetPC (callAddr))
1888             {
1889                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
1890                 result.SetStatus (eReturnStatusFailed);
1891                 return false;
1892             }
1893         }
1894         else
1895         {
1896             // Pick either the absolute line, or work out a relative one.
1897             int32_t line = (int32_t)m_options.m_line_num;
1898             if (line == 0)
1899                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
1900
1901             // Try the current file, but override if asked.
1902             FileSpec file = sym_ctx.line_entry.file;
1903             if (m_options.m_filenames.GetSize() == 1)
1904                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
1905
1906             if (!file)
1907             {
1908                 result.AppendErrorWithFormat ("No source file available for the current location.");
1909                 result.SetStatus (eReturnStatusFailed);
1910                 return false;
1911             }
1912
1913             std::string warnings;
1914             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
1915
1916             if (err.Fail())
1917             {
1918                 result.SetError (err);
1919                 return false;
1920             }
1921
1922             if (!warnings.empty())
1923                 result.AppendWarning (warnings.c_str());
1924         }
1925
1926         result.SetStatus (eReturnStatusSuccessFinishResult);
1927         return true;
1928     }
1929
1930     CommandOptions m_options;
1931 };
1932 OptionDefinition
1933 CommandObjectThreadJump::CommandOptions::g_option_table[] =
1934 {
1935     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
1936         "Specifies the source file to jump to."},
1937
1938     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum,
1939         "Specifies the line number to jump to."},
1940
1941     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset,
1942         "Jumps by a relative line offset from the current line."},
1943
1944     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression,
1945         "Jumps to a specific address."},
1946
1947     { LLDB_OPT_SET_1|
1948       LLDB_OPT_SET_2|
1949       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
1950
1951     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1952 };
1953
1954 //-------------------------------------------------------------------------
1955 // Next are the subcommands of CommandObjectMultiwordThreadPlan
1956 //-------------------------------------------------------------------------
1957
1958
1959 //-------------------------------------------------------------------------
1960 // CommandObjectThreadPlanList
1961 //-------------------------------------------------------------------------
1962 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads
1963 {
1964 public:
1965
1966     class CommandOptions : public Options
1967     {
1968     public:
1969
1970         CommandOptions (CommandInterpreter &interpreter) :
1971             Options(interpreter)
1972         {
1973             // Keep default values of all options in one place: OptionParsingStarting ()
1974             OptionParsingStarting ();
1975         }
1976
1977         virtual
1978         ~CommandOptions ()
1979         {
1980         }
1981
1982         virtual Error
1983         SetOptionValue (uint32_t option_idx, const char *option_arg)
1984         {
1985             Error error;
1986             const int short_option = m_getopt_table[option_idx].val;
1987
1988             switch (short_option)
1989             {
1990                 case 'i':
1991                 {
1992                     m_internal = true;
1993                 }
1994                 break;
1995                 case 'v':
1996                 {
1997                     m_verbose = true;
1998                 }
1999                 break;
2000                 default:
2001                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
2002                     break;
2003
2004             }
2005             return error;
2006         }
2007
2008         void
2009         OptionParsingStarting ()
2010         {
2011             m_verbose = false;
2012             m_internal = false;
2013         }
2014
2015         const OptionDefinition*
2016         GetDefinitions ()
2017         {
2018             return g_option_table;
2019         }
2020
2021         // Options table: Required for subclasses of Options.
2022
2023         static OptionDefinition g_option_table[];
2024
2025         // Instance variables to hold the values for command options.
2026         bool m_verbose;
2027         bool m_internal;
2028     };
2029
2030     CommandObjectThreadPlanList (CommandInterpreter &interpreter) :
2031         CommandObjectIterateOverThreads (interpreter,
2032                                          "thread plan list",
2033                                          "Show thread plans for one or more threads.  If no threads are specified, show the "
2034                                          "currently selected thread.  Use the thread-index \"all\" to see all threads.",
2035                                          NULL,
2036                                          eFlagRequiresProcess       |
2037                                          eFlagRequiresThread        |
2038                                          eFlagTryTargetAPILock      |
2039                                          eFlagProcessMustBeLaunched |
2040                                          eFlagProcessMustBePaused   ),
2041         m_options(interpreter)
2042     {
2043     }
2044
2045     ~CommandObjectThreadPlanList ()
2046     {
2047     }
2048
2049     virtual Options *
2050     GetOptions ()
2051     {
2052         return &m_options;
2053     }
2054
2055 protected:
2056     virtual bool
2057     HandleOneThread (Thread &thread, CommandReturnObject &result)
2058     {
2059         Stream &strm = result.GetOutputStream();
2060         DescriptionLevel desc_level = eDescriptionLevelFull;
2061         if (m_options.m_verbose)
2062             desc_level = eDescriptionLevelVerbose;
2063
2064         thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true);
2065         return true;
2066     }
2067     CommandOptions m_options;
2068 };
2069
2070 OptionDefinition
2071 CommandObjectThreadPlanList::CommandOptions::g_option_table[] =
2072 {
2073 { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"},
2074 { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"},
2075 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2076 };
2077
2078 class CommandObjectThreadPlanDiscard : public CommandObjectParsed
2079 {
2080 public:
2081     CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) :
2082         CommandObjectParsed (interpreter,
2083                              "thread plan discard",
2084                              "Discards thread plans up to and including the plan passed as the command argument."
2085                              "Only user visible plans can be discarded, use the index from \"thread plan list\""
2086                              " without the \"-i\" argument.",
2087                              NULL,
2088                              eFlagRequiresProcess       |
2089                              eFlagRequiresThread        |
2090                              eFlagTryTargetAPILock      |
2091                              eFlagProcessMustBeLaunched |
2092                              eFlagProcessMustBePaused   )
2093     {
2094         CommandArgumentEntry arg;
2095         CommandArgumentData plan_index_arg;
2096
2097         // Define the first (and only) variant of this arg.
2098         plan_index_arg.arg_type = eArgTypeUnsignedInteger;
2099         plan_index_arg.arg_repetition = eArgRepeatPlain;
2100
2101         // There is only one variant this argument could be; put it into the argument entry.
2102         arg.push_back (plan_index_arg);
2103
2104         // Push the data for the first argument into the m_arguments vector.
2105         m_arguments.push_back (arg);
2106     }
2107
2108     virtual ~CommandObjectThreadPlanDiscard () {}
2109
2110     bool
2111     DoExecute (Args& args, CommandReturnObject &result)
2112     {
2113         Thread *thread = m_exe_ctx.GetThreadPtr();
2114         if (args.GetArgumentCount() != 1)
2115         {
2116             result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.",
2117                                          args.GetArgumentCount());
2118             result.SetStatus (eReturnStatusFailed);
2119             return false;
2120         }
2121
2122         bool success;
2123         uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success);
2124         if (!success)
2125         {
2126             result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.",
2127                                          args.GetArgumentAtIndex(0));
2128             result.SetStatus (eReturnStatusFailed);
2129             return false;
2130         }
2131
2132         if (thread_plan_idx == 0)
2133         {
2134             result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan.");
2135             result.SetStatus (eReturnStatusFailed);
2136             return false;
2137         }
2138
2139         if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx))
2140         {
2141             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2142             return true;
2143         }
2144         else
2145         {
2146             result.AppendErrorWithFormat("Could not find User thread plan with index %s.",
2147                                          args.GetArgumentAtIndex(0));
2148             result.SetStatus (eReturnStatusFailed);
2149             return false;
2150         }
2151     }
2152 };
2153
2154 //-------------------------------------------------------------------------
2155 // CommandObjectMultiwordThreadPlan
2156 //-------------------------------------------------------------------------
2157
2158 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword
2159 {
2160 public:
2161     CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) :
2162         CommandObjectMultiword (interpreter,
2163                                 "plan",
2164                                 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.",
2165                                 "thread plan <subcommand> [<subcommand objects]")
2166     {
2167         LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter)));
2168         LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter)));
2169     }
2170
2171     virtual ~CommandObjectMultiwordThreadPlan () {}
2172
2173
2174 };
2175
2176 //-------------------------------------------------------------------------
2177 // CommandObjectMultiwordThread
2178 //-------------------------------------------------------------------------
2179
2180 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
2181     CommandObjectMultiword (interpreter,
2182                             "thread",
2183                             "A set of commands for operating on one or more threads within a running process.",
2184                             "thread <subcommand> [<subcommand-options>]")
2185 {
2186     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
2187     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
2188     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
2189     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
2190     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
2191     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
2192     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
2193     LoadSubCommand ("info",       CommandObjectSP (new CommandObjectThreadInfo (interpreter)));
2194     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2195                                                     interpreter,
2196                                                     "thread step-in",
2197                                                     "Source level single step in specified thread (current thread, if none specified).",
2198                                                     NULL,
2199                                                     eStepTypeInto,
2200                                                     eStepScopeSource)));
2201     
2202     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2203                                                     interpreter,
2204                                                     "thread step-out",
2205                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
2206                                                     NULL,
2207                                                     eStepTypeOut,
2208                                                     eStepScopeSource)));
2209
2210     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2211                                                     interpreter,
2212                                                     "thread step-over",
2213                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
2214                                                     NULL,
2215                                                     eStepTypeOver,
2216                                                     eStepScopeSource)));
2217
2218     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2219                                                     interpreter,
2220                                                     "thread step-inst",
2221                                                     "Single step one instruction in specified thread (current thread, if none specified).",
2222                                                     NULL,
2223                                                     eStepTypeTrace,
2224                                                     eStepScopeInstruction)));
2225
2226     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2227                                                     interpreter,
2228                                                     "thread step-inst-over",
2229                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
2230                                                     NULL,
2231                                                     eStepTypeTraceOver,
2232                                                     eStepScopeInstruction)));
2233
2234     LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
2235                                                     interpreter,
2236                                                     "thread step-scripted",
2237                                                     "Step as instructed by the script class passed in the -C option.",
2238                                                     NULL,
2239                                                     eStepTypeScripted,
2240                                                     eStepScopeSource)));
2241
2242     LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter)));
2243 }
2244
2245 CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
2246 {
2247 }
2248
2249