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