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