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