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     int 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->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     bool
289     Execute
290     (
291         Args& command,
292         CommandContext *context,
293         CommandInterpreter *interpreter,
294         CommandReturnObject &result
295     )
296     {
297         if (command.GetArgumentCount() == 0)
298         {
299             ExecutionContext exe_ctx(context->GetExecutionContext());
300             if (exe_ctx.thread)
301             {
302                 bool show_frame_info = true;
303                 uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing
304                 if (DisplayFramesForExecutionContext (exe_ctx.thread,
305                                                       interpreter,
306                                                       result.GetOutputStream(),
307                                                       m_ascending,
308                                                       0,
309                                                       UINT32_MAX,
310                                                       show_frame_info,
311                                                       num_frames_with_source,
312                                                       3,
313                                                       3))
314                 {
315                     result.SetStatus (eReturnStatusSuccessFinishResult);
316                 }
317             }
318             else
319             {
320                 result.AppendError ("invalid thread");
321                 result.SetStatus (eReturnStatusFailed);
322             }
323         }
324         else
325         {
326             result.AppendError ("backtrace doesn't take arguments (for now)");
327             result.SetStatus (eReturnStatusFailed);
328         }
329         return result.Succeeded();
330     }
331 protected:
332     bool m_ascending;
333 };
334 
335 
336 typedef enum StepScope
337 {
338     eStepScopeSource,
339     eStepScopeInstruction
340 };
341 
342 class CommandObjectThreadStepWithTypeAndScope : public CommandObject
343 {
344 public:
345 
346     class CommandOptions : public Options
347     {
348     public:
349 
350         CommandOptions () :
351             Options()
352         {
353             // Keep default values of all options in one place: ResetOptionValues ()
354             ResetOptionValues ();
355         }
356 
357         virtual
358         ~CommandOptions ()
359         {
360         }
361 
362         virtual Error
363         SetOptionValue (int option_idx, const char *option_arg)
364         {
365             Error error;
366             char short_option = (char) m_getopt_table[option_idx].val;
367 
368             switch (short_option)
369             {
370                 case 'a':
371                 {
372                     bool success;
373                     m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
374                     if (!success)
375                         error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
376                 }
377                 break;
378                 case 'm':
379                 {
380                     bool found_one = false;
381                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
382                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
383                     if (!found_one)
384                         error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
385                 }
386                 break;
387                 default:
388                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
389                     break;
390 
391             }
392             return error;
393         }
394 
395         void
396         ResetOptionValues ()
397         {
398             Options::ResetOptionValues();
399             m_avoid_no_debug = true;
400             m_run_mode = eOnlyDuringStepping;
401         }
402 
403         const lldb::OptionDefinition*
404         GetDefinitions ()
405         {
406             return g_option_table;
407         }
408 
409         // Options table: Required for subclasses of Options.
410 
411         static lldb::OptionDefinition g_option_table[];
412 
413         // Instance variables to hold the values for command options.
414         bool m_avoid_no_debug;
415         RunMode m_run_mode;
416     };
417 
418     CommandObjectThreadStepWithTypeAndScope (const char *name,
419                          const char *help,
420                          const char *syntax,
421                          uint32_t flags,
422                          StepType step_type,
423                          StepScope step_scope) :
424         CommandObject (name, help, syntax, flags),
425         m_step_type (step_type),
426         m_step_scope (step_scope),
427         m_options ()
428     {
429     }
430 
431     virtual
432     ~CommandObjectThreadStepWithTypeAndScope ()
433     {
434     }
435 
436     virtual
437     Options *
438     GetOptions ()
439     {
440         return &m_options;
441     }
442 
443     virtual bool
444     Execute (Args& command,
445              CommandContext *context,
446              CommandInterpreter *interpreter,
447              CommandReturnObject &result)
448     {
449         Process *process = context->GetExecutionContext().process;
450         bool synchronous_execution = interpreter->GetSynchronous();
451 
452         if (process == NULL)
453         {
454             result.AppendError ("need a valid process to step");
455             result.SetStatus (eReturnStatusFailed);
456 
457         }
458         else
459         {
460             const uint32_t num_threads = process->GetThreadList().GetSize();
461             Thread *thread = NULL;
462 
463             if (command.GetArgumentCount() == 0)
464             {
465                 thread = process->GetThreadList().GetCurrentThread().get();
466                 if (thread == NULL)
467                 {
468                     result.AppendError ("no current thread in process");
469                     result.SetStatus (eReturnStatusFailed);
470                     return false;
471                 }
472             }
473             else
474             {
475                 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
476                 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
477                 if (step_thread_idx == LLDB_INVALID_INDEX32)
478                 {
479                     result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
480                     result.SetStatus (eReturnStatusFailed);
481                     return false;
482                 }
483                 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
484                 if (thread == NULL)
485                 {
486                     result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
487                                                   step_thread_idx, 0, num_threads);
488                     result.SetStatus (eReturnStatusFailed);
489                     return false;
490                 }
491             }
492 
493             const bool abort_other_plans = false;
494             const lldb::RunMode stop_other_threads = m_options.m_run_mode;
495 
496             // This is a bit unfortunate, but not all the commands in this command object support
497             // only while stepping, so I use the bool for them.
498             bool bool_stop_other_threads;
499             if (m_options.m_run_mode == eAllThreads)
500                 bool_stop_other_threads = false;
501             else
502                 bool_stop_other_threads = true;
503 
504             if (m_step_type == eStepTypeInto)
505             {
506                 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
507                 ThreadPlan *new_plan;
508 
509                 if (frame->HasDebugInformation ())
510                 {
511                     new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
512                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
513                                                                     frame->GetSymbolContext(eSymbolContextEverything),
514                                                                     stop_other_threads,
515                                                                     m_options.m_avoid_no_debug);
516                 }
517                 else
518                     new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
519 
520                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
521                 process->Resume ();
522             }
523             else if (m_step_type == eStepTypeOver)
524             {
525                 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
526                 ThreadPlan *new_plan;
527 
528                 if (frame->HasDebugInformation())
529                     new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
530                                                                     m_step_type,
531                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
532                                                                     frame->GetSymbolContext(eSymbolContextEverything),
533                                                                     stop_other_threads,
534                                                                     false);
535                 else
536                     new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
537                                                                                 abort_other_plans,
538                                                                                 bool_stop_other_threads);
539 
540                 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
541                 // Maybe there should be a parameter to control this.
542                 new_plan->SetOkayToDiscard(false);
543 
544                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
545                 process->Resume ();
546             }
547             else if (m_step_type == eStepTypeTrace)
548             {
549                 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
550                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
551                 process->Resume ();
552             }
553             else if (m_step_type == eStepTypeTraceOver)
554             {
555                 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
556                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
557                 process->Resume ();
558             }
559             else if (m_step_type == eStepTypeOut)
560             {
561                 ThreadPlan *new_plan;
562 
563                 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
564                 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
565                 // Maybe there should be a parameter to control this.
566                 new_plan->SetOkayToDiscard(false);
567 
568                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
569                 process->Resume ();
570             }
571             else
572             {
573                 result.AppendError ("step type is not supported");
574                 result.SetStatus (eReturnStatusFailed);
575             }
576             if (synchronous_execution)
577             {
578                 StateType state = process->WaitForProcessToStop (NULL);
579 
580                 //EventSP event_sp;
581                 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
582                 //while (! StateIsStoppedState (state))
583                 //  {
584                 //    state = process->WaitForStateChangedEvents (NULL, event_sp);
585                 //  }
586                 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
587                 result.SetDidChangeProcessState (true);
588                 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
589                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
590             }
591         }
592         return result.Succeeded();
593     }
594 
595 protected:
596     StepType m_step_type;
597     StepScope m_step_scope;
598     CommandOptions m_options;
599 };
600 
601 static lldb::OptionEnumValueElement
602 g_tri_running_mode[] =
603 {
604 { eOnlyThisThread,     "thisThread",    "Run only this thread"},
605 { eAllThreads,         "allThreads",    "Run all threads"},
606 { eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
607 { 0, NULL, NULL }
608 };
609 
610 static lldb::OptionEnumValueElement
611 g_duo_running_mode[] =
612 {
613 { eOnlyThisThread,     "thisThread",    "Run only this thread"},
614 { eAllThreads,         "allThreads",    "Run all threads"},
615 { 0, NULL, NULL }
616 };
617 
618 lldb::OptionDefinition
619 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
620 {
621 { LLDB_OPT_SET_1, true, "avoid_no_debug", 'a', required_argument,       NULL, 0, "<avoid_no_debug>",        "Should step-in step over functions with no debug information"},
622 { LLDB_OPT_SET_1, true, "run_mode", 'm', required_argument,       g_tri_running_mode, 0, "<run_mode>",        "Determine how to run other threads while stepping this one"},
623 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
624 };
625 
626 
627 //-------------------------------------------------------------------------
628 // CommandObjectThreadContinue
629 //-------------------------------------------------------------------------
630 
631 class CommandObjectThreadContinue : public CommandObject
632 {
633 public:
634 
635     CommandObjectThreadContinue () :
636         CommandObject ("thread continue",
637                        "Continues execution of one or more threads in an active process.",
638                        "thread continue <thread-index> [<thread-index> ...]",
639                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
640     {
641     }
642 
643 
644     virtual
645     ~CommandObjectThreadContinue ()
646     {
647     }
648 
649     virtual bool
650     Execute (Args& command,
651              CommandContext *context,
652              CommandInterpreter *interpreter,
653              CommandReturnObject &result)
654     {
655         bool synchronous_execution = interpreter->GetSynchronous ();
656 
657         if (!context->GetTarget())
658         {
659             result.AppendError ("invalid target, set executable file using 'file' command");
660             result.SetStatus (eReturnStatusFailed);
661             return false;
662         }
663 
664         Process *process = context->GetExecutionContext().process;
665         if (process == NULL)
666         {
667             result.AppendError ("no process exists. Cannot continue");
668             result.SetStatus (eReturnStatusFailed);
669             return false;
670         }
671 
672         StateType state = process->GetState();
673         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
674         {
675             const uint32_t num_threads = process->GetThreadList().GetSize();
676             uint32_t idx;
677             const size_t argc = command.GetArgumentCount();
678             if (argc > 0)
679             {
680                 std::vector<uint32_t> resume_thread_indexes;
681                 for (uint32_t i=0; i<argc; ++i)
682                 {
683                     idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
684                     if (idx < num_threads)
685                         resume_thread_indexes.push_back(idx);
686                     else
687                         result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
688                 }
689 
690                 if (resume_thread_indexes.empty())
691                 {
692                     result.AppendError ("no valid thread indexes were specified");
693                     result.SetStatus (eReturnStatusFailed);
694                     return false;
695                 }
696                 else
697                 {
698                     result.AppendMessage ("Resuming thread ");
699                     for (idx=0; idx<num_threads; ++idx)
700                     {
701                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
702                         if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
703                         {
704                             result.AppendMessageWithFormat ("%u ", idx);
705                             thread->SetResumeState (eStateRunning);
706                         }
707                         else
708                         {
709                             thread->SetResumeState (eStateSuspended);
710                         }
711                     }
712                     result.AppendMessageWithFormat ("in process %i\n", process->GetID());
713                 }
714             }
715             else
716             {
717                 Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
718                 if (current_thread == NULL)
719                 {
720                     result.AppendError ("the process doesn't have a current thread");
721                     result.SetStatus (eReturnStatusFailed);
722                     return false;
723                 }
724                 // Set the actions that the threads should each take when resuming
725                 for (idx=0; idx<num_threads; ++idx)
726                 {
727                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
728                     if (thread == current_thread)
729                     {
730                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
731                         thread->SetResumeState (eStateRunning);
732                     }
733                     else
734                     {
735                         thread->SetResumeState (eStateSuspended);
736                     }
737                 }
738             }
739 
740             Error error (process->Resume());
741             if (error.Success())
742             {
743                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
744                 if (synchronous_execution)
745                 {
746                     StateType state = process->WaitForProcessToStop (NULL);
747 
748                     result.SetDidChangeProcessState (true);
749                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
750                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
751                 }
752                 else
753                 {
754                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
755                 }
756             }
757             else
758             {
759                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
760                 result.SetStatus (eReturnStatusFailed);
761             }
762         }
763         else
764         {
765             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
766                                           StateAsCString(state));
767             result.SetStatus (eReturnStatusFailed);
768         }
769 
770         return result.Succeeded();
771     }
772 
773 };
774 
775 //-------------------------------------------------------------------------
776 // CommandObjectThreadUntil
777 //-------------------------------------------------------------------------
778 
779 class CommandObjectThreadUntil : public CommandObject
780 {
781 public:
782 
783     class CommandOptions : public Options
784     {
785     public:
786         uint32_t m_thread_idx;
787         uint32_t m_frame_idx;
788 
789         CommandOptions () :
790             Options(),
791             m_thread_idx(LLDB_INVALID_THREAD_ID),
792             m_frame_idx(LLDB_INVALID_FRAME_ID)
793         {
794             // Keep default values of all options in one place: ResetOptionValues ()
795             ResetOptionValues ();
796         }
797 
798         virtual
799         ~CommandOptions ()
800         {
801         }
802 
803         virtual Error
804         SetOptionValue (int option_idx, const char *option_arg)
805         {
806             Error error;
807             char short_option = (char) m_getopt_table[option_idx].val;
808 
809             switch (short_option)
810             {
811                 case 't':
812                 {
813                     uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
814                     if (m_thread_idx == LLDB_INVALID_INDEX32)
815                     {
816                         error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
817                     }
818                 }
819                 break;
820                 case 'f':
821                 {
822                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
823                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
824                     {
825                         error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
826                     }
827                 }
828                 break;
829                 case 'm':
830                 {
831                     bool found_one = false;
832                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
833                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
834 
835                     if (!found_one)
836                         error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
837                     else if (run_mode == eAllThreads)
838                         m_stop_others = false;
839                     else
840                         m_stop_others = true;
841 
842                 }
843                 break;
844                 default:
845                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
846                     break;
847 
848             }
849             return error;
850         }
851 
852         void
853         ResetOptionValues ()
854         {
855             Options::ResetOptionValues();
856             m_thread_idx = LLDB_INVALID_THREAD_ID;
857             m_frame_idx = 0;
858             m_stop_others = false;
859         }
860 
861         const lldb::OptionDefinition*
862         GetDefinitions ()
863         {
864             return g_option_table;
865         }
866 
867         uint32_t m_step_thread_idx;
868         bool m_stop_others;
869 
870         // Options table: Required for subclasses of Options.
871 
872         static lldb::OptionDefinition g_option_table[];
873 
874         // Instance variables to hold the values for command options.
875     };
876 
877     CommandObjectThreadUntil () :
878         CommandObject ("thread until",
879                        "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
880                        "thread until [<cmd-options>] <line-number>",
881                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
882         m_options ()
883     {
884     }
885 
886 
887     virtual
888     ~CommandObjectThreadUntil ()
889     {
890     }
891 
892     virtual
893     Options *
894     GetOptions ()
895     {
896         return &m_options;
897     }
898 
899     virtual bool
900     Execute (Args& command,
901              CommandContext *context,
902              CommandInterpreter *interpreter,
903              CommandReturnObject &result)
904     {
905         bool synchronous_execution = interpreter->GetSynchronous ();
906 
907         if (!context->GetTarget())
908         {
909             result.AppendError ("invalid target, set executable file using 'file' command");
910             result.SetStatus (eReturnStatusFailed);
911             return false;
912         }
913 
914         Process *process = context->GetExecutionContext().process;
915         if (process == NULL)
916         {
917             result.AppendError ("need a valid process to step");
918             result.SetStatus (eReturnStatusFailed);
919 
920         }
921         else
922         {
923             Thread *thread = NULL;
924             uint32_t line_number;
925 
926             if (command.GetArgumentCount() != 1)
927             {
928                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
929                 result.SetStatus (eReturnStatusFailed);
930                 return false;
931             }
932 
933             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
934             if (line_number == UINT32_MAX)
935             {
936                 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
937                 result.SetStatus (eReturnStatusFailed);
938                 return false;
939             }
940 
941             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
942             {
943                 thread = process->GetThreadList().GetCurrentThread().get();
944             }
945             else
946             {
947                 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
948             }
949 
950             if (thread == NULL)
951             {
952                 const uint32_t num_threads = process->GetThreadList().GetSize();
953                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
954                 result.SetStatus (eReturnStatusFailed);
955                 return false;
956             }
957 
958             const bool abort_other_plans = true;
959 
960             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
961             if (frame == NULL)
962             {
963 
964                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
965                 result.SetStatus (eReturnStatusFailed);
966                 return false;
967             }
968 
969             ThreadPlan *new_plan;
970 
971             if (frame->HasDebugInformation ())
972             {
973                 // Finally we got here...  Translate the given line number to a bunch of addresses:
974                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
975                 LineTable *line_table = NULL;
976                 if (sc.comp_unit)
977                     line_table = sc.comp_unit->GetLineTable();
978 
979                 if (line_table == NULL)
980                 {
981                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
982                                                  m_options.m_frame_idx, m_options.m_thread_idx);
983                     result.SetStatus (eReturnStatusFailed);
984                     return false;
985                 }
986 
987                 LineEntry function_start;
988                 uint32_t index_ptr = 0, end_ptr;
989                 std::vector<addr_t> address_list;
990 
991                 // Find the beginning & end index of the
992                 AddressRange fun_addr_range = sc.function->GetAddressRange();
993                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
994                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
995 
996                 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
997                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
998 
999                 while (index_ptr <= end_ptr)
1000                 {
1001                     LineEntry line_entry;
1002                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1003                     if (index_ptr == UINT32_MAX)
1004                         break;
1005 
1006                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
1007                     if (address != LLDB_INVALID_ADDRESS)
1008                         address_list.push_back (address);
1009                     index_ptr++;
1010                 }
1011 
1012                 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others);
1013                 new_plan->SetOkayToDiscard(false);
1014             }
1015             else
1016             {
1017                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1018                 result.SetStatus (eReturnStatusFailed);
1019                 return false;
1020 
1021             }
1022 
1023             process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
1024             Error error (process->Resume ());
1025             if (error.Success())
1026             {
1027                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1028                 if (synchronous_execution)
1029                 {
1030                     StateType state = process->WaitForProcessToStop (NULL);
1031 
1032                     result.SetDidChangeProcessState (true);
1033                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1034                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1035                 }
1036                 else
1037                 {
1038                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1039                 }
1040             }
1041             else
1042             {
1043                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1044                 result.SetStatus (eReturnStatusFailed);
1045             }
1046 
1047         }
1048         return result.Succeeded();
1049     }
1050 protected:
1051     CommandOptions m_options;
1052 
1053 };
1054 
1055 lldb::OptionDefinition
1056 CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1057 {
1058 { LLDB_OPT_SET_1, true, "frame", 'f', required_argument,       NULL, 0, "<frame>",        "Frame index for until operation - defaults to 0"},
1059 { LLDB_OPT_SET_1, true, "thread", 't', required_argument,       NULL, 0, "<thread>",      "Thread index for the thread for until operation"},
1060 { LLDB_OPT_SET_1, true, "run_mode", 'm', required_argument,       g_duo_running_mode, 0, "<run_mode>",        "Determine how to run other threads while stepping this one"},
1061 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1062 };
1063 
1064 
1065 //-------------------------------------------------------------------------
1066 // CommandObjectThreadSelect
1067 //-------------------------------------------------------------------------
1068 
1069 class CommandObjectThreadSelect : public CommandObject
1070 {
1071 public:
1072 
1073     CommandObjectThreadSelect () :
1074         CommandObject ("thread select",
1075                          "Selects a threads as the currently active thread.",
1076                          "thread select <thread-index>",
1077                          eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1078     {
1079     }
1080 
1081 
1082     virtual
1083     ~CommandObjectThreadSelect ()
1084     {
1085     }
1086 
1087     virtual bool
1088     Execute (Args& command,
1089              CommandContext *context,
1090              CommandInterpreter *interpreter,
1091              CommandReturnObject &result)
1092     {
1093         Process *process = context->GetExecutionContext().process;
1094         if (process == NULL)
1095         {
1096             result.AppendError ("no process");
1097             result.SetStatus (eReturnStatusFailed);
1098             return false;
1099         }
1100         else if (command.GetArgumentCount() != 1)
1101         {
1102             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1103             result.SetStatus (eReturnStatusFailed);
1104             return false;
1105         }
1106 
1107         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1108 
1109         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1110         if (new_thread == NULL)
1111         {
1112             result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1113             result.SetStatus (eReturnStatusFailed);
1114             return false;
1115         }
1116 
1117         process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
1118 
1119         DisplayThreadInfo (interpreter,
1120                            result.GetOutputStream(),
1121                            new_thread,
1122                            false,
1123                            true);
1124 
1125         return result.Succeeded();
1126     }
1127 
1128 };
1129 
1130 
1131 //-------------------------------------------------------------------------
1132 // CommandObjectThreadList
1133 //-------------------------------------------------------------------------
1134 
1135 CommandObjectThreadList::CommandObjectThreadList ():
1136     CommandObject ("thread list",
1137                      "Shows a summary of all current threads in a process.",
1138                      "thread list",
1139                      eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1140 {
1141 }
1142 
1143 CommandObjectThreadList::~CommandObjectThreadList()
1144 {
1145 }
1146 
1147 bool
1148 CommandObjectThreadList::Execute
1149 (
1150     Args& command,
1151     CommandContext *context,
1152     CommandInterpreter *interpreter,
1153     CommandReturnObject &result
1154 )
1155 {
1156     StreamString &strm = result.GetOutputStream();
1157     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1158     ExecutionContext exe_ctx(context->GetExecutionContext());
1159     if (exe_ctx.process)
1160     {
1161         const StateType state = exe_ctx.process->GetState();
1162 
1163         if (StateIsStoppedState(state))
1164         {
1165             if (state == eStateExited)
1166             {
1167                 int exit_status = exe_ctx.process->GetExitStatus();
1168                 const char *exit_description = exe_ctx.process->GetExitDescription();
1169                 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1170                                       exe_ctx.process->GetID(),
1171                                       exit_status,
1172                                       exit_status,
1173                                       exit_description ? exit_description : "");
1174             }
1175             else
1176             {
1177                 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1178                 if (exe_ctx.thread == NULL)
1179                     exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1180                 if (exe_ctx.thread != NULL)
1181                 {
1182                     DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1183                 }
1184                 else
1185                 {
1186                     result.AppendError ("no valid thread found in current process");
1187                     result.SetStatus (eReturnStatusFailed);
1188                 }
1189             }
1190         }
1191         else
1192         {
1193             result.AppendError ("process is currently running");
1194             result.SetStatus (eReturnStatusFailed);
1195         }
1196     }
1197     else
1198     {
1199         result.AppendError ("no current location or status available");
1200         result.SetStatus (eReturnStatusFailed);
1201     }
1202     return result.Succeeded();
1203 }
1204 
1205 //-------------------------------------------------------------------------
1206 // CommandObjectMultiwordThread
1207 //-------------------------------------------------------------------------
1208 
1209 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter *interpreter) :
1210     CommandObjectMultiword ("thread",
1211                             "A set of commands for operating on one or more thread within a running process.",
1212                             "thread <subcommand> [<subcommand-options>]")
1213 {
1214     LoadSubCommand (CommandObjectSP (new CommandObjectThreadBacktrace ()), "backtrace", interpreter);
1215     LoadSubCommand (CommandObjectSP (new CommandObjectThreadContinue ()), "continue", interpreter);
1216     LoadSubCommand (CommandObjectSP (new CommandObjectThreadList ()), "list", interpreter);
1217     LoadSubCommand (CommandObjectSP (new CommandObjectThreadSelect ()), "select", interpreter);
1218     LoadSubCommand (CommandObjectSP (new CommandObjectThreadUntil ()), "until", interpreter);
1219     LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-in",
1220                                                                                   "Source level single step in in specified thread (current thread, if none specified).",
1221                                                                                   "thread step-in [<thread-id>]",
1222                                                                                   eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1223                                                                                   eStepTypeInto,
1224                                                                                   eStepScopeSource)),
1225                     "step-in", interpreter);
1226 
1227     LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
1228                                                                                       "Source level single step out in specified thread (current thread, if none specified).",
1229                                                                                       "thread step-out [<thread-id>]",
1230                                                                                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1231                                                                                       eStepTypeOut,
1232                                                                                       eStepScopeSource)),
1233                     "step-out", interpreter);
1234 
1235     LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
1236                                                                                       "Source level single step over in specified thread (current thread, if none specified).",
1237                                                                                       "thread step-over [<thread-id>]",
1238                                                                                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1239                                                                                       eStepTypeOver,
1240                                                                                       eStepScopeSource)),
1241                     "step-over", interpreter);
1242 
1243     LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
1244                                                                                       "Single step one instruction in specified thread (current thread, if none specified).",
1245                                                                                       "thread step-inst [<thread-id>]",
1246                                                                                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1247                                                                                       eStepTypeTrace,
1248                                                                                       eStepScopeInstruction)),
1249                     "step-inst", interpreter);
1250     LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
1251                                                                                       "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1252                                                                                       "thread step-inst-over [<thread-id>]",
1253                                                                                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1254                                                                                       eStepTypeTraceOver,
1255                                                                                       eStepScopeInstruction)),
1256                     "step-inst-over", interpreter);
1257 }
1258 
1259 CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1260 {
1261 }
1262 
1263 
1264