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