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