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