1ac7ddfbfSEd Maste //===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/lldb-python.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "CommandObjectThread.h"
13ac7ddfbfSEd Maste 
14ac7ddfbfSEd Maste // C Includes
15ac7ddfbfSEd Maste // C++ Includes
16ac7ddfbfSEd Maste // Other libraries and framework includes
17ac7ddfbfSEd Maste // Project includes
18ac7ddfbfSEd Maste #include "lldb/lldb-private.h"
19ac7ddfbfSEd Maste #include "lldb/Core/State.h"
20ac7ddfbfSEd Maste #include "lldb/Core/SourceManager.h"
21ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
22ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
23ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h"
25ac7ddfbfSEd Maste #include "lldb/Symbol/CompileUnit.h"
26ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
27ac7ddfbfSEd Maste #include "lldb/Symbol/LineTable.h"
28ac7ddfbfSEd Maste #include "lldb/Symbol/LineEntry.h"
29ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
30ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
31b952cd58SEd Maste #include "lldb/Target/SystemRuntime.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
33ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
34ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlan.h"
35ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInstruction.h"
36ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepOut.h"
37ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
38ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanStepInRange.h"
39ac7ddfbfSEd Maste 
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste using namespace lldb;
42ac7ddfbfSEd Maste using namespace lldb_private;
43ac7ddfbfSEd Maste 
44ac7ddfbfSEd Maste 
45ac7ddfbfSEd Maste //-------------------------------------------------------------------------
46ac7ddfbfSEd Maste // CommandObjectThreadBacktrace
47ac7ddfbfSEd Maste //-------------------------------------------------------------------------
48ac7ddfbfSEd Maste 
49ac7ddfbfSEd Maste class CommandObjectThreadBacktrace : public CommandObjectParsed
50ac7ddfbfSEd Maste {
51ac7ddfbfSEd Maste public:
52ac7ddfbfSEd Maste 
53ac7ddfbfSEd Maste     class CommandOptions : public Options
54ac7ddfbfSEd Maste     {
55ac7ddfbfSEd Maste     public:
56ac7ddfbfSEd Maste 
57ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
58ac7ddfbfSEd Maste             Options(interpreter)
59ac7ddfbfSEd Maste         {
60ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
61ac7ddfbfSEd Maste             OptionParsingStarting ();
62ac7ddfbfSEd Maste         }
63ac7ddfbfSEd Maste 
64ac7ddfbfSEd Maste         virtual
65ac7ddfbfSEd Maste         ~CommandOptions ()
66ac7ddfbfSEd Maste         {
67ac7ddfbfSEd Maste         }
68ac7ddfbfSEd Maste 
69ac7ddfbfSEd Maste         virtual Error
70ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
71ac7ddfbfSEd Maste         {
72ac7ddfbfSEd Maste             Error error;
73ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
74ac7ddfbfSEd Maste 
75ac7ddfbfSEd Maste             switch (short_option)
76ac7ddfbfSEd Maste             {
77ac7ddfbfSEd Maste                 case 'c':
78ac7ddfbfSEd Maste                 {
79ac7ddfbfSEd Maste                     bool success;
80ac7ddfbfSEd Maste                     int32_t input_count =  Args::StringToSInt32 (option_arg, -1, 0, &success);
81ac7ddfbfSEd Maste                     if (!success)
82ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
83ac7ddfbfSEd Maste                     if (input_count < -1)
84ac7ddfbfSEd Maste                         m_count = UINT32_MAX;
85ac7ddfbfSEd Maste                     else
86ac7ddfbfSEd Maste                         m_count = input_count;
87ac7ddfbfSEd Maste                 }
88ac7ddfbfSEd Maste                 break;
89ac7ddfbfSEd Maste                 case 's':
90ac7ddfbfSEd Maste                 {
91ac7ddfbfSEd Maste                     bool success;
92ac7ddfbfSEd Maste                     m_start =  Args::StringToUInt32 (option_arg, 0, 0, &success);
93ac7ddfbfSEd Maste                     if (!success)
94ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
95ac7ddfbfSEd Maste                 }
96b952cd58SEd Maste                 case 'e':
97b952cd58SEd Maste                 {
98b952cd58SEd Maste                     bool success;
99b952cd58SEd Maste                     m_extended_backtrace =  Args::StringToBoolean (option_arg, false, &success);
100b952cd58SEd Maste                     if (!success)
101b952cd58SEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
102b952cd58SEd Maste                 }
103ac7ddfbfSEd Maste                 break;
104ac7ddfbfSEd Maste                 default:
105ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
106ac7ddfbfSEd Maste                     break;
107ac7ddfbfSEd Maste 
108ac7ddfbfSEd Maste             }
109ac7ddfbfSEd Maste             return error;
110ac7ddfbfSEd Maste         }
111ac7ddfbfSEd Maste 
112ac7ddfbfSEd Maste         void
113ac7ddfbfSEd Maste         OptionParsingStarting ()
114ac7ddfbfSEd Maste         {
115ac7ddfbfSEd Maste             m_count = UINT32_MAX;
116ac7ddfbfSEd Maste             m_start = 0;
117b952cd58SEd Maste             m_extended_backtrace = false;
118ac7ddfbfSEd Maste         }
119ac7ddfbfSEd Maste 
120ac7ddfbfSEd Maste         const OptionDefinition*
121ac7ddfbfSEd Maste         GetDefinitions ()
122ac7ddfbfSEd Maste         {
123ac7ddfbfSEd Maste             return g_option_table;
124ac7ddfbfSEd Maste         }
125ac7ddfbfSEd Maste 
126ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
127ac7ddfbfSEd Maste 
128ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
129ac7ddfbfSEd Maste 
130ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
131ac7ddfbfSEd Maste         uint32_t m_count;
132ac7ddfbfSEd Maste         uint32_t m_start;
133b952cd58SEd Maste         bool     m_extended_backtrace;
134ac7ddfbfSEd Maste     };
135ac7ddfbfSEd Maste 
136ac7ddfbfSEd Maste     CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
137ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
138ac7ddfbfSEd Maste                              "thread backtrace",
139ac7ddfbfSEd Maste                              "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.",
140ac7ddfbfSEd Maste                              NULL,
141ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
142ac7ddfbfSEd Maste                              eFlagRequiresThread        |
143ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
144ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
145ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
146ac7ddfbfSEd Maste         m_options(interpreter)
147ac7ddfbfSEd Maste     {
148ac7ddfbfSEd Maste         CommandArgumentEntry arg;
149ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
150ac7ddfbfSEd Maste 
151ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
152ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
153ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatStar;
154ac7ddfbfSEd Maste 
155ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
156ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
157ac7ddfbfSEd Maste 
158ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
159ac7ddfbfSEd Maste         m_arguments.push_back (arg);
160ac7ddfbfSEd Maste     }
161ac7ddfbfSEd Maste 
162ac7ddfbfSEd Maste     ~CommandObjectThreadBacktrace()
163ac7ddfbfSEd Maste     {
164ac7ddfbfSEd Maste     }
165ac7ddfbfSEd Maste 
166ac7ddfbfSEd Maste     virtual Options *
167ac7ddfbfSEd Maste     GetOptions ()
168ac7ddfbfSEd Maste     {
169ac7ddfbfSEd Maste         return &m_options;
170ac7ddfbfSEd Maste     }
171ac7ddfbfSEd Maste 
172ac7ddfbfSEd Maste protected:
173b952cd58SEd Maste     void
174b952cd58SEd Maste     DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
175b952cd58SEd Maste     {
176b952cd58SEd Maste         SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
177b952cd58SEd Maste         if (runtime)
178b952cd58SEd Maste         {
179b952cd58SEd Maste             Stream &strm = result.GetOutputStream();
180b952cd58SEd Maste             const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
181b952cd58SEd Maste             for (auto type : types)
182b952cd58SEd Maste             {
183b952cd58SEd Maste                 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
184b952cd58SEd Maste                 if (ext_thread_sp && ext_thread_sp->IsValid ())
185b952cd58SEd Maste                 {
186b952cd58SEd Maste                     const uint32_t num_frames_with_source = 0;
187b952cd58SEd Maste                     if (ext_thread_sp->GetStatus (strm,
188b952cd58SEd Maste                         m_options.m_start,
189b952cd58SEd Maste                         m_options.m_count,
190b952cd58SEd Maste                         num_frames_with_source))
191b952cd58SEd Maste                     {
192b952cd58SEd Maste                         DoExtendedBacktrace (ext_thread_sp.get(), result);
193b952cd58SEd Maste                     }
194b952cd58SEd Maste                 }
195b952cd58SEd Maste             }
196b952cd58SEd Maste         }
197b952cd58SEd Maste     }
198b952cd58SEd Maste 
199ac7ddfbfSEd Maste     virtual bool
200ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
201ac7ddfbfSEd Maste     {
202ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
203ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
204ac7ddfbfSEd Maste 
205ac7ddfbfSEd Maste         // Don't show source context when doing backtraces.
206ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
207ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
208ac7ddfbfSEd Maste         {
209ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
210ac7ddfbfSEd Maste             // Thread::GetStatus() returns the number of frames shown.
211ac7ddfbfSEd Maste             if (thread->GetStatus (strm,
212ac7ddfbfSEd Maste                                    m_options.m_start,
213ac7ddfbfSEd Maste                                    m_options.m_count,
214ac7ddfbfSEd Maste                                    num_frames_with_source))
215ac7ddfbfSEd Maste             {
216ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
217b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
218b952cd58SEd Maste                 {
219b952cd58SEd Maste                     DoExtendedBacktrace (thread, result);
220b952cd58SEd Maste                 }
221ac7ddfbfSEd Maste             }
222ac7ddfbfSEd Maste         }
223ac7ddfbfSEd Maste         else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
224ac7ddfbfSEd Maste         {
225ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
226b952cd58SEd Maste             uint32_t idx = 0;
227b952cd58SEd Maste             for (ThreadSP thread_sp : process->Threads())
228ac7ddfbfSEd Maste             {
229b952cd58SEd Maste                 if (idx != 0)
230b952cd58SEd Maste                     result.AppendMessage("");
231b952cd58SEd Maste 
232ac7ddfbfSEd Maste                 if (!thread_sp->GetStatus (strm,
233ac7ddfbfSEd Maste                                            m_options.m_start,
234ac7ddfbfSEd Maste                                            m_options.m_count,
235ac7ddfbfSEd Maste                                            num_frames_with_source))
236ac7ddfbfSEd Maste                 {
237b952cd58SEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
238ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
239ac7ddfbfSEd Maste                     return false;
240ac7ddfbfSEd Maste                 }
241b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
242b952cd58SEd Maste                 {
243b952cd58SEd Maste                     DoExtendedBacktrace (thread_sp.get(), result);
244b952cd58SEd Maste                 }
245ac7ddfbfSEd Maste 
246b952cd58SEd Maste                 ++idx;
247ac7ddfbfSEd Maste             }
248ac7ddfbfSEd Maste         }
249ac7ddfbfSEd Maste         else
250ac7ddfbfSEd Maste         {
251ac7ddfbfSEd Maste             const size_t num_args = command.GetArgumentCount();
252ac7ddfbfSEd Maste             Process *process = m_exe_ctx.GetProcessPtr();
253ac7ddfbfSEd Maste             Mutex::Locker locker (process->GetThreadList().GetMutex());
254ac7ddfbfSEd Maste             std::vector<ThreadSP> thread_sps;
255ac7ddfbfSEd Maste 
256ac7ddfbfSEd Maste             for (size_t i = 0; i < num_args; i++)
257ac7ddfbfSEd Maste             {
258ac7ddfbfSEd Maste                 bool success;
259ac7ddfbfSEd Maste 
260ac7ddfbfSEd Maste                 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
261ac7ddfbfSEd Maste                 if (!success)
262ac7ddfbfSEd Maste                 {
263ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
264ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
265ac7ddfbfSEd Maste                     return false;
266ac7ddfbfSEd Maste                 }
267ac7ddfbfSEd Maste 
268ac7ddfbfSEd Maste                 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
269ac7ddfbfSEd Maste 
270ac7ddfbfSEd Maste                 if (!thread_sps[i])
271ac7ddfbfSEd Maste                 {
272ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
273ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
274ac7ddfbfSEd Maste                     return false;
275ac7ddfbfSEd Maste                 }
276ac7ddfbfSEd Maste 
277ac7ddfbfSEd Maste             }
278ac7ddfbfSEd Maste 
279ac7ddfbfSEd Maste             for (uint32_t i = 0; i < num_args; i++)
280ac7ddfbfSEd Maste             {
281ac7ddfbfSEd Maste                 if (!thread_sps[i]->GetStatus (strm,
282ac7ddfbfSEd Maste                                                m_options.m_start,
283ac7ddfbfSEd Maste                                                m_options.m_count,
284ac7ddfbfSEd Maste                                                num_frames_with_source))
285ac7ddfbfSEd Maste                 {
286ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
287ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
288ac7ddfbfSEd Maste                     return false;
289ac7ddfbfSEd Maste                 }
290b952cd58SEd Maste                 if (m_options.m_extended_backtrace)
291b952cd58SEd Maste                 {
292b952cd58SEd Maste                     DoExtendedBacktrace (thread_sps[i].get(), result);
293b952cd58SEd Maste                 }
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste                 if (i < num_args - 1)
296ac7ddfbfSEd Maste                     result.AppendMessage("");
297ac7ddfbfSEd Maste             }
298ac7ddfbfSEd Maste         }
299ac7ddfbfSEd Maste         return result.Succeeded();
300ac7ddfbfSEd Maste     }
301ac7ddfbfSEd Maste 
302ac7ddfbfSEd Maste     CommandOptions m_options;
303ac7ddfbfSEd Maste };
304ac7ddfbfSEd Maste 
305ac7ddfbfSEd Maste OptionDefinition
306ac7ddfbfSEd Maste CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
307ac7ddfbfSEd Maste {
30835617911SEd Maste { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
30935617911SEd Maste { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
310b952cd58SEd Maste { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
311ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
312ac7ddfbfSEd Maste };
313ac7ddfbfSEd Maste 
314ac7ddfbfSEd Maste enum StepScope
315ac7ddfbfSEd Maste {
316ac7ddfbfSEd Maste     eStepScopeSource,
317ac7ddfbfSEd Maste     eStepScopeInstruction
318ac7ddfbfSEd Maste };
319ac7ddfbfSEd Maste 
320ac7ddfbfSEd Maste class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed
321ac7ddfbfSEd Maste {
322ac7ddfbfSEd Maste public:
323ac7ddfbfSEd Maste 
324ac7ddfbfSEd Maste     class CommandOptions : public Options
325ac7ddfbfSEd Maste     {
326ac7ddfbfSEd Maste     public:
327ac7ddfbfSEd Maste 
328ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
329ac7ddfbfSEd Maste             Options (interpreter)
330ac7ddfbfSEd Maste         {
331ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
332ac7ddfbfSEd Maste             OptionParsingStarting ();
333ac7ddfbfSEd Maste         }
334ac7ddfbfSEd Maste 
335ac7ddfbfSEd Maste         virtual
336ac7ddfbfSEd Maste         ~CommandOptions ()
337ac7ddfbfSEd Maste         {
338ac7ddfbfSEd Maste         }
339ac7ddfbfSEd Maste 
340ac7ddfbfSEd Maste         virtual Error
341ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
342ac7ddfbfSEd Maste         {
343ac7ddfbfSEd Maste             Error error;
344ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
345ac7ddfbfSEd Maste 
346ac7ddfbfSEd Maste             switch (short_option)
347ac7ddfbfSEd Maste             {
348ac7ddfbfSEd Maste             case 'a':
349ac7ddfbfSEd Maste                 {
350ac7ddfbfSEd Maste                     bool success;
351ac7ddfbfSEd Maste                     m_avoid_no_debug =  Args::StringToBoolean (option_arg, true, &success);
352ac7ddfbfSEd Maste                     if (!success)
353ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
354ac7ddfbfSEd Maste                 }
355ac7ddfbfSEd Maste                 break;
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste             case 'm':
358ac7ddfbfSEd Maste                 {
359ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
360ac7ddfbfSEd Maste                     m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
361ac7ddfbfSEd Maste                 }
362ac7ddfbfSEd Maste                 break;
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste             case 'r':
365ac7ddfbfSEd Maste                 {
366ac7ddfbfSEd Maste                     m_avoid_regexp.clear();
367ac7ddfbfSEd Maste                     m_avoid_regexp.assign(option_arg);
368ac7ddfbfSEd Maste                 }
369ac7ddfbfSEd Maste                 break;
370ac7ddfbfSEd Maste 
371ac7ddfbfSEd Maste             case 't':
372ac7ddfbfSEd Maste                 {
373ac7ddfbfSEd Maste                     m_step_in_target.clear();
374ac7ddfbfSEd Maste                     m_step_in_target.assign(option_arg);
375ac7ddfbfSEd Maste 
376ac7ddfbfSEd Maste                 }
377ac7ddfbfSEd Maste                 break;
378ac7ddfbfSEd Maste             default:
379ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
380ac7ddfbfSEd Maste                 break;
381ac7ddfbfSEd Maste 
382ac7ddfbfSEd Maste             }
383ac7ddfbfSEd Maste             return error;
384ac7ddfbfSEd Maste         }
385ac7ddfbfSEd Maste 
386ac7ddfbfSEd Maste         void
387ac7ddfbfSEd Maste         OptionParsingStarting ()
388ac7ddfbfSEd Maste         {
389ac7ddfbfSEd Maste             m_avoid_no_debug = true;
390ac7ddfbfSEd Maste             m_run_mode = eOnlyDuringStepping;
391ac7ddfbfSEd Maste             m_avoid_regexp.clear();
392ac7ddfbfSEd Maste             m_step_in_target.clear();
393ac7ddfbfSEd Maste         }
394ac7ddfbfSEd Maste 
395ac7ddfbfSEd Maste         const OptionDefinition*
396ac7ddfbfSEd Maste         GetDefinitions ()
397ac7ddfbfSEd Maste         {
398ac7ddfbfSEd Maste             return g_option_table;
399ac7ddfbfSEd Maste         }
400ac7ddfbfSEd Maste 
401ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
402ac7ddfbfSEd Maste 
403ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
404ac7ddfbfSEd Maste 
405ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
406ac7ddfbfSEd Maste         bool m_avoid_no_debug;
407ac7ddfbfSEd Maste         RunMode m_run_mode;
408ac7ddfbfSEd Maste         std::string m_avoid_regexp;
409ac7ddfbfSEd Maste         std::string m_step_in_target;
410ac7ddfbfSEd Maste     };
411ac7ddfbfSEd Maste 
412ac7ddfbfSEd Maste     CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
413ac7ddfbfSEd Maste                                              const char *name,
414ac7ddfbfSEd Maste                                              const char *help,
415ac7ddfbfSEd Maste                                              const char *syntax,
416ac7ddfbfSEd Maste                                              StepType step_type,
417ac7ddfbfSEd Maste                                              StepScope step_scope) :
418ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax,
419ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
420ac7ddfbfSEd Maste                              eFlagRequiresThread        |
421ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
422ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
423ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
424ac7ddfbfSEd Maste         m_step_type (step_type),
425ac7ddfbfSEd Maste         m_step_scope (step_scope),
426ac7ddfbfSEd Maste         m_options (interpreter)
427ac7ddfbfSEd Maste     {
428ac7ddfbfSEd Maste         CommandArgumentEntry arg;
429ac7ddfbfSEd Maste         CommandArgumentData thread_id_arg;
430ac7ddfbfSEd Maste 
431ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
432ac7ddfbfSEd Maste         thread_id_arg.arg_type = eArgTypeThreadID;
433ac7ddfbfSEd Maste         thread_id_arg.arg_repetition = eArgRepeatOptional;
434ac7ddfbfSEd Maste 
435ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
436ac7ddfbfSEd Maste         arg.push_back (thread_id_arg);
437ac7ddfbfSEd Maste 
438ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
439ac7ddfbfSEd Maste         m_arguments.push_back (arg);
440ac7ddfbfSEd Maste     }
441ac7ddfbfSEd Maste 
442ac7ddfbfSEd Maste     virtual
443ac7ddfbfSEd Maste     ~CommandObjectThreadStepWithTypeAndScope ()
444ac7ddfbfSEd Maste     {
445ac7ddfbfSEd Maste     }
446ac7ddfbfSEd Maste 
447ac7ddfbfSEd Maste     virtual
448ac7ddfbfSEd Maste     Options *
449ac7ddfbfSEd Maste     GetOptions ()
450ac7ddfbfSEd Maste     {
451ac7ddfbfSEd Maste         return &m_options;
452ac7ddfbfSEd Maste     }
453ac7ddfbfSEd Maste 
454ac7ddfbfSEd Maste protected:
455ac7ddfbfSEd Maste     virtual bool
456ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
457ac7ddfbfSEd Maste     {
458ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
459ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous();
460ac7ddfbfSEd Maste 
461ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
462ac7ddfbfSEd Maste         Thread *thread = NULL;
463ac7ddfbfSEd Maste 
464ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
465ac7ddfbfSEd Maste         {
466ac7ddfbfSEd Maste             thread = process->GetThreadList().GetSelectedThread().get();
467ac7ddfbfSEd Maste             if (thread == NULL)
468ac7ddfbfSEd Maste             {
469ac7ddfbfSEd Maste                 result.AppendError ("no selected thread in process");
470ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
471ac7ddfbfSEd Maste                 return false;
472ac7ddfbfSEd Maste             }
473ac7ddfbfSEd Maste         }
474ac7ddfbfSEd Maste         else
475ac7ddfbfSEd Maste         {
476ac7ddfbfSEd Maste             const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
477ac7ddfbfSEd Maste             uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
478ac7ddfbfSEd Maste             if (step_thread_idx == LLDB_INVALID_INDEX32)
479ac7ddfbfSEd Maste             {
480ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
481ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
482ac7ddfbfSEd Maste                 return false;
483ac7ddfbfSEd Maste             }
484ac7ddfbfSEd Maste             thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
485ac7ddfbfSEd Maste             if (thread == NULL)
486ac7ddfbfSEd Maste             {
487ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
488ac7ddfbfSEd Maste                                               step_thread_idx, num_threads);
489ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
490ac7ddfbfSEd Maste                 return false;
491ac7ddfbfSEd Maste             }
492ac7ddfbfSEd Maste         }
493ac7ddfbfSEd Maste 
494ac7ddfbfSEd Maste         const bool abort_other_plans = false;
495ac7ddfbfSEd Maste         const lldb::RunMode stop_other_threads = m_options.m_run_mode;
496ac7ddfbfSEd Maste 
497ac7ddfbfSEd Maste         // This is a bit unfortunate, but not all the commands in this command object support
498ac7ddfbfSEd Maste         // only while stepping, so I use the bool for them.
499ac7ddfbfSEd Maste         bool bool_stop_other_threads;
500ac7ddfbfSEd Maste         if (m_options.m_run_mode == eAllThreads)
501ac7ddfbfSEd Maste             bool_stop_other_threads = false;
502ac7ddfbfSEd Maste         else if (m_options.m_run_mode == eOnlyDuringStepping)
503ac7ddfbfSEd Maste         {
504ac7ddfbfSEd Maste             if (m_step_type == eStepTypeOut)
505ac7ddfbfSEd Maste                 bool_stop_other_threads = false;
506ac7ddfbfSEd Maste             else
507ac7ddfbfSEd Maste                 bool_stop_other_threads = true;
508ac7ddfbfSEd Maste         }
509ac7ddfbfSEd Maste         else
510ac7ddfbfSEd Maste             bool_stop_other_threads = true;
511ac7ddfbfSEd Maste 
512ac7ddfbfSEd Maste         ThreadPlanSP new_plan_sp;
513ac7ddfbfSEd Maste 
514ac7ddfbfSEd Maste         if (m_step_type == eStepTypeInto)
515ac7ddfbfSEd Maste         {
516ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
517ac7ddfbfSEd Maste 
518ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
519ac7ddfbfSEd Maste             {
520ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
521ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
522ac7ddfbfSEd Maste                                                                 frame->GetSymbolContext(eSymbolContextEverything),
523ac7ddfbfSEd Maste                                                                 m_options.m_step_in_target.c_str(),
524ac7ddfbfSEd Maste                                                                 stop_other_threads,
525ac7ddfbfSEd Maste                                                                 m_options.m_avoid_no_debug);
526ac7ddfbfSEd Maste                 if (new_plan_sp && !m_options.m_avoid_regexp.empty())
527ac7ddfbfSEd Maste                 {
528ac7ddfbfSEd Maste                     ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get());
529ac7ddfbfSEd Maste                     step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
530ac7ddfbfSEd Maste                 }
531ac7ddfbfSEd Maste             }
532ac7ddfbfSEd Maste             else
533ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
534ac7ddfbfSEd Maste 
535ac7ddfbfSEd Maste         }
536ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOver)
537ac7ddfbfSEd Maste         {
538ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
539ac7ddfbfSEd Maste 
540ac7ddfbfSEd Maste             if (frame->HasDebugInformation())
541ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
542ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
543ac7ddfbfSEd Maste                                                                     frame->GetSymbolContext(eSymbolContextEverything),
544ac7ddfbfSEd Maste                                                                     stop_other_threads);
545ac7ddfbfSEd Maste             else
546ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true,
547ac7ddfbfSEd Maste                                                                             abort_other_plans,
548ac7ddfbfSEd Maste                                                                             bool_stop_other_threads);
549ac7ddfbfSEd Maste 
550ac7ddfbfSEd Maste         }
551ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTrace)
552ac7ddfbfSEd Maste         {
553ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
554ac7ddfbfSEd Maste         }
555ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeTraceOver)
556ac7ddfbfSEd Maste         {
557ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
558ac7ddfbfSEd Maste         }
559ac7ddfbfSEd Maste         else if (m_step_type == eStepTypeOut)
560ac7ddfbfSEd Maste         {
561ac7ddfbfSEd Maste             new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans,
562ac7ddfbfSEd Maste                                                           NULL,
563ac7ddfbfSEd Maste                                                           false,
564ac7ddfbfSEd Maste                                                           bool_stop_other_threads,
565ac7ddfbfSEd Maste                                                           eVoteYes,
566ac7ddfbfSEd Maste                                                           eVoteNoOpinion,
567ac7ddfbfSEd Maste                                                           thread->GetSelectedFrameIndex());
568ac7ddfbfSEd Maste         }
569ac7ddfbfSEd Maste         else
570ac7ddfbfSEd Maste         {
571ac7ddfbfSEd Maste             result.AppendError ("step type is not supported");
572ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
573ac7ddfbfSEd Maste             return false;
574ac7ddfbfSEd Maste         }
575ac7ddfbfSEd Maste 
576ac7ddfbfSEd Maste         // If we got a new plan, then set it to be a master plan (User level Plans should be master plans
577ac7ddfbfSEd Maste         // so that they can be interruptible).  Then resume the process.
578ac7ddfbfSEd Maste 
579ac7ddfbfSEd Maste         if (new_plan_sp)
580ac7ddfbfSEd Maste         {
581ac7ddfbfSEd Maste             new_plan_sp->SetIsMasterPlan (true);
582ac7ddfbfSEd Maste             new_plan_sp->SetOkayToDiscard (false);
583ac7ddfbfSEd Maste 
584ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (thread->GetID());
585ac7ddfbfSEd Maste             process->Resume ();
586ac7ddfbfSEd Maste 
587ac7ddfbfSEd Maste 
588ac7ddfbfSEd Maste             if (synchronous_execution)
589ac7ddfbfSEd Maste             {
590ac7ddfbfSEd Maste                 StateType state = process->WaitForProcessToStop (NULL);
591ac7ddfbfSEd Maste 
592ac7ddfbfSEd Maste                 //EventSP event_sp;
593ac7ddfbfSEd Maste                 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
594ac7ddfbfSEd Maste                 //while (! StateIsStoppedState (state))
595ac7ddfbfSEd Maste                 //  {
596ac7ddfbfSEd Maste                 //    state = process->WaitForStateChangedEvents (NULL, event_sp);
597ac7ddfbfSEd Maste                 //  }
598ac7ddfbfSEd Maste                 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
599ac7ddfbfSEd Maste                 result.SetDidChangeProcessState (true);
600ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
601ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
602ac7ddfbfSEd Maste             }
603ac7ddfbfSEd Maste             else
604ac7ddfbfSEd Maste             {
605ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
606ac7ddfbfSEd Maste             }
607ac7ddfbfSEd Maste         }
608ac7ddfbfSEd Maste         else
609ac7ddfbfSEd Maste         {
610ac7ddfbfSEd Maste             result.AppendError ("Couldn't find thread plan to implement step type.");
611ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
612ac7ddfbfSEd Maste         }
613ac7ddfbfSEd Maste         return result.Succeeded();
614ac7ddfbfSEd Maste     }
615ac7ddfbfSEd Maste 
616ac7ddfbfSEd Maste protected:
617ac7ddfbfSEd Maste     StepType m_step_type;
618ac7ddfbfSEd Maste     StepScope m_step_scope;
619ac7ddfbfSEd Maste     CommandOptions m_options;
620ac7ddfbfSEd Maste };
621ac7ddfbfSEd Maste 
622ac7ddfbfSEd Maste static OptionEnumValueElement
623ac7ddfbfSEd Maste g_tri_running_mode[] =
624ac7ddfbfSEd Maste {
625ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
626ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
627ac7ddfbfSEd Maste { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
628ac7ddfbfSEd Maste { 0, NULL, NULL }
629ac7ddfbfSEd Maste };
630ac7ddfbfSEd Maste 
631ac7ddfbfSEd Maste static OptionEnumValueElement
632ac7ddfbfSEd Maste g_duo_running_mode[] =
633ac7ddfbfSEd Maste {
634ac7ddfbfSEd Maste { eOnlyThisThread,     "this-thread",    "Run only this thread"},
635ac7ddfbfSEd Maste { eAllThreads,         "all-threads",    "Run all threads"},
636ac7ddfbfSEd Maste { 0, NULL, NULL }
637ac7ddfbfSEd Maste };
638ac7ddfbfSEd Maste 
639ac7ddfbfSEd Maste OptionDefinition
640ac7ddfbfSEd Maste CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
641ac7ddfbfSEd Maste {
64235617911SEd Maste { LLDB_OPT_SET_1, false, "avoid-no-debug",  'a', OptionParser::eRequiredArgument, NULL,               0, eArgTypeBoolean,     "A boolean value that sets whether step-in will step over functions with no debug information."},
64335617911SEd Maste { LLDB_OPT_SET_1, false, "run-mode",        'm', OptionParser::eRequiredArgument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
64435617911SEd Maste { LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL,               0, eArgTypeRegularExpression,   "A regular expression that defines function names to not to stop at when stepping in."},
64535617911SEd Maste { LLDB_OPT_SET_1, false, "step-in-target",  't', OptionParser::eRequiredArgument, NULL,               0, eArgTypeFunctionName,   "The name of the directly called function step in should stop at when stepping into."},
646ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
647ac7ddfbfSEd Maste };
648ac7ddfbfSEd Maste 
649ac7ddfbfSEd Maste 
650ac7ddfbfSEd Maste //-------------------------------------------------------------------------
651ac7ddfbfSEd Maste // CommandObjectThreadContinue
652ac7ddfbfSEd Maste //-------------------------------------------------------------------------
653ac7ddfbfSEd Maste 
654ac7ddfbfSEd Maste class CommandObjectThreadContinue : public CommandObjectParsed
655ac7ddfbfSEd Maste {
656ac7ddfbfSEd Maste public:
657ac7ddfbfSEd Maste 
658ac7ddfbfSEd Maste     CommandObjectThreadContinue (CommandInterpreter &interpreter) :
659ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
660ac7ddfbfSEd Maste                              "thread continue",
661ac7ddfbfSEd Maste                              "Continue execution of one or more threads in an active process.",
662ac7ddfbfSEd Maste                              NULL,
663ac7ddfbfSEd Maste                              eFlagRequiresThread        |
664ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
665ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
666ac7ddfbfSEd Maste                              eFlagProcessMustBePaused)
667ac7ddfbfSEd Maste     {
668ac7ddfbfSEd Maste         CommandArgumentEntry arg;
669ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
670ac7ddfbfSEd Maste 
671ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
672ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
673ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlus;
674ac7ddfbfSEd Maste 
675ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
676ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
677ac7ddfbfSEd Maste 
678ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
679ac7ddfbfSEd Maste         m_arguments.push_back (arg);
680ac7ddfbfSEd Maste     }
681ac7ddfbfSEd Maste 
682ac7ddfbfSEd Maste 
683ac7ddfbfSEd Maste     virtual
684ac7ddfbfSEd Maste     ~CommandObjectThreadContinue ()
685ac7ddfbfSEd Maste     {
686ac7ddfbfSEd Maste     }
687ac7ddfbfSEd Maste 
688ac7ddfbfSEd Maste     virtual bool
689ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
690ac7ddfbfSEd Maste     {
691ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
692ac7ddfbfSEd Maste 
693ac7ddfbfSEd Maste         if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
694ac7ddfbfSEd Maste         {
695ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
696ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
697ac7ddfbfSEd Maste             return false;
698ac7ddfbfSEd Maste         }
699ac7ddfbfSEd Maste 
700ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
701ac7ddfbfSEd Maste         if (process == NULL)
702ac7ddfbfSEd Maste         {
703ac7ddfbfSEd Maste             result.AppendError ("no process exists. Cannot continue");
704ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
705ac7ddfbfSEd Maste             return false;
706ac7ddfbfSEd Maste         }
707ac7ddfbfSEd Maste 
708ac7ddfbfSEd Maste         StateType state = process->GetState();
709ac7ddfbfSEd Maste         if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
710ac7ddfbfSEd Maste         {
711ac7ddfbfSEd Maste             const size_t argc = command.GetArgumentCount();
712ac7ddfbfSEd Maste             if (argc > 0)
713ac7ddfbfSEd Maste             {
71435617911SEd Maste                 // These two lines appear at the beginning of both blocks in
71535617911SEd Maste                 // this if..else, but that is because we need to release the
71635617911SEd Maste                 // lock before calling process->Resume below.
71735617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
71835617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
719ac7ddfbfSEd Maste                 std::vector<Thread *> resume_threads;
720ac7ddfbfSEd Maste                 for (uint32_t i=0; i<argc; ++i)
721ac7ddfbfSEd Maste                 {
722ac7ddfbfSEd Maste                     bool success;
723ac7ddfbfSEd Maste                     const int base = 0;
724ac7ddfbfSEd Maste                     uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success);
725ac7ddfbfSEd Maste                     if (success)
726ac7ddfbfSEd Maste                     {
727ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get();
728ac7ddfbfSEd Maste 
729ac7ddfbfSEd Maste                         if (thread)
730ac7ddfbfSEd Maste                         {
731ac7ddfbfSEd Maste                             resume_threads.push_back(thread);
732ac7ddfbfSEd Maste                         }
733ac7ddfbfSEd Maste                         else
734ac7ddfbfSEd Maste                         {
735ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx);
736ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
737ac7ddfbfSEd Maste                             return false;
738ac7ddfbfSEd Maste                         }
739ac7ddfbfSEd Maste                     }
740ac7ddfbfSEd Maste                     else
741ac7ddfbfSEd Maste                     {
742ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i));
743ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
744ac7ddfbfSEd Maste                         return false;
745ac7ddfbfSEd Maste                     }
746ac7ddfbfSEd Maste                 }
747ac7ddfbfSEd Maste 
748ac7ddfbfSEd Maste                 if (resume_threads.empty())
749ac7ddfbfSEd Maste                 {
750ac7ddfbfSEd Maste                     result.AppendError ("no valid thread indexes were specified");
751ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
752ac7ddfbfSEd Maste                     return false;
753ac7ddfbfSEd Maste                 }
754ac7ddfbfSEd Maste                 else
755ac7ddfbfSEd Maste                 {
756ac7ddfbfSEd Maste                     if (resume_threads.size() == 1)
757ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread: ");
758ac7ddfbfSEd Maste                     else
759ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming threads: ");
760ac7ddfbfSEd Maste 
761ac7ddfbfSEd Maste                     for (uint32_t idx=0; idx<num_threads; ++idx)
762ac7ddfbfSEd Maste                     {
763ac7ddfbfSEd Maste                         Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
764ac7ddfbfSEd Maste                         std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread);
765ac7ddfbfSEd Maste 
766ac7ddfbfSEd Maste                         if (this_thread_pos != resume_threads.end())
767ac7ddfbfSEd Maste                         {
768ac7ddfbfSEd Maste                             resume_threads.erase(this_thread_pos);
769ac7ddfbfSEd Maste                             if (resume_threads.size() > 0)
770ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID());
771ac7ddfbfSEd Maste                             else
772ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("%u ", thread->GetIndexID());
773ac7ddfbfSEd Maste 
774ac7ddfbfSEd Maste                             thread->SetResumeState (eStateRunning);
775ac7ddfbfSEd Maste                         }
776ac7ddfbfSEd Maste                         else
777ac7ddfbfSEd Maste                         {
778ac7ddfbfSEd Maste                             thread->SetResumeState (eStateSuspended);
779ac7ddfbfSEd Maste                         }
780ac7ddfbfSEd Maste                     }
781ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID());
782ac7ddfbfSEd Maste                 }
783ac7ddfbfSEd Maste             }
784ac7ddfbfSEd Maste             else
785ac7ddfbfSEd Maste             {
78635617911SEd Maste                 // These two lines appear at the beginning of both blocks in
78735617911SEd Maste                 // this if..else, but that is because we need to release the
78835617911SEd Maste                 // lock before calling process->Resume below.
78935617911SEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
79035617911SEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
791ac7ddfbfSEd Maste                 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
792ac7ddfbfSEd Maste                 if (current_thread == NULL)
793ac7ddfbfSEd Maste                 {
794ac7ddfbfSEd Maste                     result.AppendError ("the process doesn't have a current thread");
795ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
796ac7ddfbfSEd Maste                     return false;
797ac7ddfbfSEd Maste                 }
798ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
799ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
800ac7ddfbfSEd Maste                 {
801ac7ddfbfSEd Maste                     Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
802ac7ddfbfSEd Maste                     if (thread == current_thread)
803ac7ddfbfSEd Maste                     {
804ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID());
805ac7ddfbfSEd Maste                         thread->SetResumeState (eStateRunning);
806ac7ddfbfSEd Maste                     }
807ac7ddfbfSEd Maste                     else
808ac7ddfbfSEd Maste                     {
809ac7ddfbfSEd Maste                         thread->SetResumeState (eStateSuspended);
810ac7ddfbfSEd Maste                     }
811ac7ddfbfSEd Maste                 }
812ac7ddfbfSEd Maste             }
813ac7ddfbfSEd Maste 
81435617911SEd Maste             // We should not be holding the thread list lock when we do this.
815ac7ddfbfSEd Maste             Error error (process->Resume());
816ac7ddfbfSEd Maste             if (error.Success())
817ac7ddfbfSEd Maste             {
818ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
819ac7ddfbfSEd Maste                 if (synchronous_execution)
820ac7ddfbfSEd Maste                 {
821ac7ddfbfSEd Maste                     state = process->WaitForProcessToStop (NULL);
822ac7ddfbfSEd Maste 
823ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
824ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
825ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
826ac7ddfbfSEd Maste                 }
827ac7ddfbfSEd Maste                 else
828ac7ddfbfSEd Maste                 {
829ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
830ac7ddfbfSEd Maste                 }
831ac7ddfbfSEd Maste             }
832ac7ddfbfSEd Maste             else
833ac7ddfbfSEd Maste             {
834ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
835ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
836ac7ddfbfSEd Maste             }
837ac7ddfbfSEd Maste         }
838ac7ddfbfSEd Maste         else
839ac7ddfbfSEd Maste         {
840ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
841ac7ddfbfSEd Maste                                           StateAsCString(state));
842ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
843ac7ddfbfSEd Maste         }
844ac7ddfbfSEd Maste 
845ac7ddfbfSEd Maste         return result.Succeeded();
846ac7ddfbfSEd Maste     }
847ac7ddfbfSEd Maste 
848ac7ddfbfSEd Maste };
849ac7ddfbfSEd Maste 
850ac7ddfbfSEd Maste //-------------------------------------------------------------------------
851ac7ddfbfSEd Maste // CommandObjectThreadUntil
852ac7ddfbfSEd Maste //-------------------------------------------------------------------------
853ac7ddfbfSEd Maste 
854ac7ddfbfSEd Maste class CommandObjectThreadUntil : public CommandObjectParsed
855ac7ddfbfSEd Maste {
856ac7ddfbfSEd Maste public:
857ac7ddfbfSEd Maste 
858ac7ddfbfSEd Maste     class CommandOptions : public Options
859ac7ddfbfSEd Maste     {
860ac7ddfbfSEd Maste     public:
861ac7ddfbfSEd Maste         uint32_t m_thread_idx;
862ac7ddfbfSEd Maste         uint32_t m_frame_idx;
863ac7ddfbfSEd Maste 
864ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
865ac7ddfbfSEd Maste             Options (interpreter),
866ac7ddfbfSEd Maste             m_thread_idx(LLDB_INVALID_THREAD_ID),
867ac7ddfbfSEd Maste             m_frame_idx(LLDB_INVALID_FRAME_ID)
868ac7ddfbfSEd Maste         {
869ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
870ac7ddfbfSEd Maste             OptionParsingStarting ();
871ac7ddfbfSEd Maste         }
872ac7ddfbfSEd Maste 
873ac7ddfbfSEd Maste         virtual
874ac7ddfbfSEd Maste         ~CommandOptions ()
875ac7ddfbfSEd Maste         {
876ac7ddfbfSEd Maste         }
877ac7ddfbfSEd Maste 
878ac7ddfbfSEd Maste         virtual Error
879ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
880ac7ddfbfSEd Maste         {
881ac7ddfbfSEd Maste             Error error;
882ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
883ac7ddfbfSEd Maste 
884ac7ddfbfSEd Maste             switch (short_option)
885ac7ddfbfSEd Maste             {
886ac7ddfbfSEd Maste                 case 't':
887ac7ddfbfSEd Maste                 {
888ac7ddfbfSEd Maste                     m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
889ac7ddfbfSEd Maste                     if (m_thread_idx == LLDB_INVALID_INDEX32)
890ac7ddfbfSEd Maste                     {
891ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg);
892ac7ddfbfSEd Maste                     }
893ac7ddfbfSEd Maste                 }
894ac7ddfbfSEd Maste                 break;
895ac7ddfbfSEd Maste                 case 'f':
896ac7ddfbfSEd Maste                 {
897ac7ddfbfSEd Maste                     m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
898ac7ddfbfSEd Maste                     if (m_frame_idx == LLDB_INVALID_FRAME_ID)
899ac7ddfbfSEd Maste                     {
900ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg);
901ac7ddfbfSEd Maste                     }
902ac7ddfbfSEd Maste                 }
903ac7ddfbfSEd Maste                 break;
904ac7ddfbfSEd Maste                 case 'm':
905ac7ddfbfSEd Maste                 {
906ac7ddfbfSEd Maste                     OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
907ac7ddfbfSEd Maste                     lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error);
908ac7ddfbfSEd Maste 
909ac7ddfbfSEd Maste                     if (error.Success())
910ac7ddfbfSEd Maste                     {
911ac7ddfbfSEd Maste                         if (run_mode == eAllThreads)
912ac7ddfbfSEd Maste                             m_stop_others = false;
913ac7ddfbfSEd Maste                         else
914ac7ddfbfSEd Maste                             m_stop_others = true;
915ac7ddfbfSEd Maste                     }
916ac7ddfbfSEd Maste                 }
917ac7ddfbfSEd Maste                 break;
918ac7ddfbfSEd Maste                 default:
919ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
920ac7ddfbfSEd Maste                     break;
921ac7ddfbfSEd Maste 
922ac7ddfbfSEd Maste             }
923ac7ddfbfSEd Maste             return error;
924ac7ddfbfSEd Maste         }
925ac7ddfbfSEd Maste 
926ac7ddfbfSEd Maste         void
927ac7ddfbfSEd Maste         OptionParsingStarting ()
928ac7ddfbfSEd Maste         {
929ac7ddfbfSEd Maste             m_thread_idx = LLDB_INVALID_THREAD_ID;
930ac7ddfbfSEd Maste             m_frame_idx = 0;
931ac7ddfbfSEd Maste             m_stop_others = false;
932ac7ddfbfSEd Maste         }
933ac7ddfbfSEd Maste 
934ac7ddfbfSEd Maste         const OptionDefinition*
935ac7ddfbfSEd Maste         GetDefinitions ()
936ac7ddfbfSEd Maste         {
937ac7ddfbfSEd Maste             return g_option_table;
938ac7ddfbfSEd Maste         }
939ac7ddfbfSEd Maste 
940ac7ddfbfSEd Maste         uint32_t m_step_thread_idx;
941ac7ddfbfSEd Maste         bool m_stop_others;
942ac7ddfbfSEd Maste 
943ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
944ac7ddfbfSEd Maste 
945ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
946ac7ddfbfSEd Maste 
947ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
948ac7ddfbfSEd Maste     };
949ac7ddfbfSEd Maste 
950ac7ddfbfSEd Maste     CommandObjectThreadUntil (CommandInterpreter &interpreter) :
951ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
952ac7ddfbfSEd Maste                              "thread until",
953ac7ddfbfSEd Maste                              "Run the current or specified thread until it reaches a given line number or leaves the current function.",
954ac7ddfbfSEd Maste                              NULL,
955ac7ddfbfSEd Maste                              eFlagRequiresThread        |
956ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
957ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
958ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
959ac7ddfbfSEd Maste         m_options (interpreter)
960ac7ddfbfSEd Maste     {
961ac7ddfbfSEd Maste         CommandArgumentEntry arg;
962ac7ddfbfSEd Maste         CommandArgumentData line_num_arg;
963ac7ddfbfSEd Maste 
964ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
965ac7ddfbfSEd Maste         line_num_arg.arg_type = eArgTypeLineNum;
966ac7ddfbfSEd Maste         line_num_arg.arg_repetition = eArgRepeatPlain;
967ac7ddfbfSEd Maste 
968ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
969ac7ddfbfSEd Maste         arg.push_back (line_num_arg);
970ac7ddfbfSEd Maste 
971ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
972ac7ddfbfSEd Maste         m_arguments.push_back (arg);
973ac7ddfbfSEd Maste     }
974ac7ddfbfSEd Maste 
975ac7ddfbfSEd Maste 
976ac7ddfbfSEd Maste     virtual
977ac7ddfbfSEd Maste     ~CommandObjectThreadUntil ()
978ac7ddfbfSEd Maste     {
979ac7ddfbfSEd Maste     }
980ac7ddfbfSEd Maste 
981ac7ddfbfSEd Maste     virtual
982ac7ddfbfSEd Maste     Options *
983ac7ddfbfSEd Maste     GetOptions ()
984ac7ddfbfSEd Maste     {
985ac7ddfbfSEd Maste         return &m_options;
986ac7ddfbfSEd Maste     }
987ac7ddfbfSEd Maste 
988ac7ddfbfSEd Maste protected:
989ac7ddfbfSEd Maste     virtual bool
990ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
991ac7ddfbfSEd Maste     {
992ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
993ac7ddfbfSEd Maste 
994ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
995ac7ddfbfSEd Maste         if (target == NULL)
996ac7ddfbfSEd Maste         {
997ac7ddfbfSEd Maste             result.AppendError ("invalid target, create a debug target using the 'target create' command");
998ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
999ac7ddfbfSEd Maste             return false;
1000ac7ddfbfSEd Maste         }
1001ac7ddfbfSEd Maste 
1002ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1003ac7ddfbfSEd Maste         if (process == NULL)
1004ac7ddfbfSEd Maste         {
1005ac7ddfbfSEd Maste             result.AppendError ("need a valid process to step");
1006ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1007ac7ddfbfSEd Maste 
1008ac7ddfbfSEd Maste         }
1009ac7ddfbfSEd Maste         else
1010ac7ddfbfSEd Maste         {
1011ac7ddfbfSEd Maste             Thread *thread = NULL;
1012ac7ddfbfSEd Maste             uint32_t line_number;
1013ac7ddfbfSEd Maste 
1014ac7ddfbfSEd Maste             if (command.GetArgumentCount() != 1)
1015ac7ddfbfSEd Maste             {
1016ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1017ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1018ac7ddfbfSEd Maste                 return false;
1019ac7ddfbfSEd Maste             }
1020ac7ddfbfSEd Maste 
1021ac7ddfbfSEd Maste             line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1022ac7ddfbfSEd Maste             if (line_number == UINT32_MAX)
1023ac7ddfbfSEd Maste             {
1024ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1025ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1026ac7ddfbfSEd Maste                 return false;
1027ac7ddfbfSEd Maste             }
1028ac7ddfbfSEd Maste 
1029ac7ddfbfSEd Maste             if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1030ac7ddfbfSEd Maste             {
1031ac7ddfbfSEd Maste                 thread = process->GetThreadList().GetSelectedThread().get();
1032ac7ddfbfSEd Maste             }
1033ac7ddfbfSEd Maste             else
1034ac7ddfbfSEd Maste             {
1035ac7ddfbfSEd Maste                 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get();
1036ac7ddfbfSEd Maste             }
1037ac7ddfbfSEd Maste 
1038ac7ddfbfSEd Maste             if (thread == NULL)
1039ac7ddfbfSEd Maste             {
1040ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
1041ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
1042ac7ddfbfSEd Maste                                               m_options.m_thread_idx,
1043ac7ddfbfSEd Maste                                               num_threads);
1044ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1045ac7ddfbfSEd Maste                 return false;
1046ac7ddfbfSEd Maste             }
1047ac7ddfbfSEd Maste 
1048ac7ddfbfSEd Maste             const bool abort_other_plans = false;
1049ac7ddfbfSEd Maste 
1050ac7ddfbfSEd Maste             StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1051ac7ddfbfSEd Maste             if (frame == NULL)
1052ac7ddfbfSEd Maste             {
1053ac7ddfbfSEd Maste 
1054ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n",
1055ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1056ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1057ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1058ac7ddfbfSEd Maste                 return false;
1059ac7ddfbfSEd Maste             }
1060ac7ddfbfSEd Maste 
1061ac7ddfbfSEd Maste             ThreadPlanSP new_plan_sp;
1062ac7ddfbfSEd Maste 
1063ac7ddfbfSEd Maste             if (frame->HasDebugInformation ())
1064ac7ddfbfSEd Maste             {
1065ac7ddfbfSEd Maste                 // Finally we got here...  Translate the given line number to a bunch of addresses:
1066ac7ddfbfSEd Maste                 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1067ac7ddfbfSEd Maste                 LineTable *line_table = NULL;
1068ac7ddfbfSEd Maste                 if (sc.comp_unit)
1069ac7ddfbfSEd Maste                     line_table = sc.comp_unit->GetLineTable();
1070ac7ddfbfSEd Maste 
1071ac7ddfbfSEd Maste                 if (line_table == NULL)
1072ac7ddfbfSEd Maste                 {
1073ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1074ac7ddfbfSEd Maste                                                  m_options.m_frame_idx, m_options.m_thread_idx);
1075ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1076ac7ddfbfSEd Maste                     return false;
1077ac7ddfbfSEd Maste                 }
1078ac7ddfbfSEd Maste 
1079ac7ddfbfSEd Maste                 LineEntry function_start;
1080ac7ddfbfSEd Maste                 uint32_t index_ptr = 0, end_ptr;
1081ac7ddfbfSEd Maste                 std::vector<addr_t> address_list;
1082ac7ddfbfSEd Maste 
1083ac7ddfbfSEd Maste                 // Find the beginning & end index of the
1084ac7ddfbfSEd Maste                 AddressRange fun_addr_range = sc.function->GetAddressRange();
1085ac7ddfbfSEd Maste                 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1086ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1087ac7ddfbfSEd Maste 
1088ac7ddfbfSEd Maste                 Address fun_end_addr(fun_start_addr.GetSection(),
1089ac7ddfbfSEd Maste                                      fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1090ac7ddfbfSEd Maste                 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1091ac7ddfbfSEd Maste 
1092ac7ddfbfSEd Maste                 bool all_in_function = true;
1093ac7ddfbfSEd Maste 
1094ac7ddfbfSEd Maste                 while (index_ptr <= end_ptr)
1095ac7ddfbfSEd Maste                 {
1096ac7ddfbfSEd Maste                     LineEntry line_entry;
1097ac7ddfbfSEd Maste                     const bool exact = false;
1098ac7ddfbfSEd Maste                     index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry);
1099ac7ddfbfSEd Maste                     if (index_ptr == UINT32_MAX)
1100ac7ddfbfSEd Maste                         break;
1101ac7ddfbfSEd Maste 
1102ac7ddfbfSEd Maste                     addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
1103ac7ddfbfSEd Maste                     if (address != LLDB_INVALID_ADDRESS)
1104ac7ddfbfSEd Maste                     {
1105ac7ddfbfSEd Maste                         if (fun_addr_range.ContainsLoadAddress (address, target))
1106ac7ddfbfSEd Maste                             address_list.push_back (address);
1107ac7ddfbfSEd Maste                         else
1108ac7ddfbfSEd Maste                             all_in_function = false;
1109ac7ddfbfSEd Maste                     }
1110ac7ddfbfSEd Maste                     index_ptr++;
1111ac7ddfbfSEd Maste                 }
1112ac7ddfbfSEd Maste 
1113ac7ddfbfSEd Maste                 if (address_list.size() == 0)
1114ac7ddfbfSEd Maste                 {
1115ac7ddfbfSEd Maste                     if (all_in_function)
1116ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("No line entries matching until target.\n");
1117ac7ddfbfSEd Maste                     else
1118ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("Until target outside of the current function.\n");
1119ac7ddfbfSEd Maste 
1120ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1121ac7ddfbfSEd Maste                     return false;
1122ac7ddfbfSEd Maste                 }
1123ac7ddfbfSEd Maste 
1124ac7ddfbfSEd Maste                 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans,
1125ac7ddfbfSEd Maste                                                                 &address_list.front(),
1126ac7ddfbfSEd Maste                                                                 address_list.size(),
1127ac7ddfbfSEd Maste                                                                 m_options.m_stop_others,
1128ac7ddfbfSEd Maste                                                                 m_options.m_frame_idx);
1129ac7ddfbfSEd Maste                 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint)
1130ac7ddfbfSEd Maste                 // and other plans executed by the user (stepping around the breakpoint) and then a "continue"
1131ac7ddfbfSEd Maste                 // will resume the original plan.
1132ac7ddfbfSEd Maste                 new_plan_sp->SetIsMasterPlan (true);
1133ac7ddfbfSEd Maste                 new_plan_sp->SetOkayToDiscard(false);
1134ac7ddfbfSEd Maste             }
1135ac7ddfbfSEd Maste             else
1136ac7ddfbfSEd Maste             {
1137ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n",
1138ac7ddfbfSEd Maste                                               m_options.m_frame_idx,
1139ac7ddfbfSEd Maste                                               m_options.m_thread_idx);
1140ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1141ac7ddfbfSEd Maste                 return false;
1142ac7ddfbfSEd Maste 
1143ac7ddfbfSEd Maste             }
1144ac7ddfbfSEd Maste 
1145ac7ddfbfSEd Maste             process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
1146ac7ddfbfSEd Maste             Error error (process->Resume ());
1147ac7ddfbfSEd Maste             if (error.Success())
1148ac7ddfbfSEd Maste             {
1149ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
1150ac7ddfbfSEd Maste                 if (synchronous_execution)
1151ac7ddfbfSEd Maste                 {
1152ac7ddfbfSEd Maste                     StateType state = process->WaitForProcessToStop (NULL);
1153ac7ddfbfSEd Maste 
1154ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
1155ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
1156ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1157ac7ddfbfSEd Maste                 }
1158ac7ddfbfSEd Maste                 else
1159ac7ddfbfSEd Maste                 {
1160ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1161ac7ddfbfSEd Maste                 }
1162ac7ddfbfSEd Maste             }
1163ac7ddfbfSEd Maste             else
1164ac7ddfbfSEd Maste             {
1165ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1166ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1167ac7ddfbfSEd Maste             }
1168ac7ddfbfSEd Maste 
1169ac7ddfbfSEd Maste         }
1170ac7ddfbfSEd Maste         return result.Succeeded();
1171ac7ddfbfSEd Maste     }
1172ac7ddfbfSEd Maste 
1173ac7ddfbfSEd Maste     CommandOptions m_options;
1174ac7ddfbfSEd Maste 
1175ac7ddfbfSEd Maste };
1176ac7ddfbfSEd Maste 
1177ac7ddfbfSEd Maste OptionDefinition
1178ac7ddfbfSEd Maste CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1179ac7ddfbfSEd Maste {
118035617911SEd Maste { LLDB_OPT_SET_1, false, "frame",   'f', OptionParser::eRequiredArgument, NULL,               0, eArgTypeFrameIndex,   "Frame index for until operation - defaults to 0"},
118135617911SEd Maste { LLDB_OPT_SET_1, false, "thread",  't', OptionParser::eRequiredArgument, NULL,               0, eArgTypeThreadIndex,  "Thread index for the thread for until operation"},
118235617911SEd Maste { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
1183ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1184ac7ddfbfSEd Maste };
1185ac7ddfbfSEd Maste 
1186ac7ddfbfSEd Maste 
1187ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1188ac7ddfbfSEd Maste // CommandObjectThreadSelect
1189ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1190ac7ddfbfSEd Maste 
1191ac7ddfbfSEd Maste class CommandObjectThreadSelect : public CommandObjectParsed
1192ac7ddfbfSEd Maste {
1193ac7ddfbfSEd Maste public:
1194ac7ddfbfSEd Maste 
1195ac7ddfbfSEd Maste     CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1196ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1197ac7ddfbfSEd Maste                              "thread select",
1198ac7ddfbfSEd Maste                              "Select a thread as the currently active thread.",
1199ac7ddfbfSEd Maste                              NULL,
1200ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1201ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1202ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1203ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1204ac7ddfbfSEd Maste     {
1205ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1206ac7ddfbfSEd Maste         CommandArgumentData thread_idx_arg;
1207ac7ddfbfSEd Maste 
1208ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1209ac7ddfbfSEd Maste         thread_idx_arg.arg_type = eArgTypeThreadIndex;
1210ac7ddfbfSEd Maste         thread_idx_arg.arg_repetition = eArgRepeatPlain;
1211ac7ddfbfSEd Maste 
1212ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1213ac7ddfbfSEd Maste         arg.push_back (thread_idx_arg);
1214ac7ddfbfSEd Maste 
1215ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1216ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1217ac7ddfbfSEd Maste     }
1218ac7ddfbfSEd Maste 
1219ac7ddfbfSEd Maste 
1220ac7ddfbfSEd Maste     virtual
1221ac7ddfbfSEd Maste     ~CommandObjectThreadSelect ()
1222ac7ddfbfSEd Maste     {
1223ac7ddfbfSEd Maste     }
1224ac7ddfbfSEd Maste 
1225ac7ddfbfSEd Maste protected:
1226ac7ddfbfSEd Maste     virtual bool
1227ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1228ac7ddfbfSEd Maste     {
1229ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1230ac7ddfbfSEd Maste         if (process == NULL)
1231ac7ddfbfSEd Maste         {
1232ac7ddfbfSEd Maste             result.AppendError ("no process");
1233ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1234ac7ddfbfSEd Maste             return false;
1235ac7ddfbfSEd Maste         }
1236ac7ddfbfSEd Maste         else if (command.GetArgumentCount() != 1)
1237ac7ddfbfSEd Maste         {
1238ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1239ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1240ac7ddfbfSEd Maste             return false;
1241ac7ddfbfSEd Maste         }
1242ac7ddfbfSEd Maste 
1243ac7ddfbfSEd Maste         uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1244ac7ddfbfSEd Maste 
1245ac7ddfbfSEd Maste         Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1246ac7ddfbfSEd Maste         if (new_thread == NULL)
1247ac7ddfbfSEd Maste         {
1248ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1249ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1250ac7ddfbfSEd Maste             return false;
1251ac7ddfbfSEd Maste         }
1252ac7ddfbfSEd Maste 
1253ac7ddfbfSEd Maste         process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true);
1254ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1255ac7ddfbfSEd Maste 
1256ac7ddfbfSEd Maste         return result.Succeeded();
1257ac7ddfbfSEd Maste     }
1258ac7ddfbfSEd Maste 
1259ac7ddfbfSEd Maste };
1260ac7ddfbfSEd Maste 
1261ac7ddfbfSEd Maste 
1262ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1263ac7ddfbfSEd Maste // CommandObjectThreadList
1264ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1265ac7ddfbfSEd Maste 
1266ac7ddfbfSEd Maste class CommandObjectThreadList : public CommandObjectParsed
1267ac7ddfbfSEd Maste {
1268ac7ddfbfSEd Maste public:
1269ac7ddfbfSEd Maste 
1270ac7ddfbfSEd Maste 
1271ac7ddfbfSEd Maste     CommandObjectThreadList (CommandInterpreter &interpreter):
1272ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1273ac7ddfbfSEd Maste                              "thread list",
1274ac7ddfbfSEd Maste                              "Show a summary of all current threads in a process.",
1275ac7ddfbfSEd Maste                              "thread list",
1276ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1277ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1278ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1279ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1280ac7ddfbfSEd Maste     {
1281ac7ddfbfSEd Maste     }
1282ac7ddfbfSEd Maste 
1283ac7ddfbfSEd Maste     ~CommandObjectThreadList()
1284ac7ddfbfSEd Maste     {
1285ac7ddfbfSEd Maste     }
1286ac7ddfbfSEd Maste 
1287ac7ddfbfSEd Maste protected:
1288ac7ddfbfSEd Maste     bool
1289ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1290ac7ddfbfSEd Maste     {
1291ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1292ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1293ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1294ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = false;
1295ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1296ac7ddfbfSEd Maste         const uint32_t num_frames = 0;
1297ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 0;
1298ac7ddfbfSEd Maste         process->GetStatus(strm);
1299ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1300ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1301ac7ddfbfSEd Maste                                   start_frame,
1302ac7ddfbfSEd Maste                                   num_frames,
1303ac7ddfbfSEd Maste                                   num_frames_with_source);
1304ac7ddfbfSEd Maste         return result.Succeeded();
1305ac7ddfbfSEd Maste     }
1306ac7ddfbfSEd Maste };
1307ac7ddfbfSEd Maste 
1308ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1309ac7ddfbfSEd Maste // CommandObjectThreadReturn
1310ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1311ac7ddfbfSEd Maste 
1312ac7ddfbfSEd Maste class CommandObjectThreadReturn : public CommandObjectRaw
1313ac7ddfbfSEd Maste {
1314ac7ddfbfSEd Maste public:
1315ac7ddfbfSEd Maste     class CommandOptions : public Options
1316ac7ddfbfSEd Maste     {
1317ac7ddfbfSEd Maste     public:
1318ac7ddfbfSEd Maste 
1319ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1320ac7ddfbfSEd Maste             Options (interpreter),
1321ac7ddfbfSEd Maste             m_from_expression (false)
1322ac7ddfbfSEd Maste         {
1323ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1324ac7ddfbfSEd Maste             OptionParsingStarting ();
1325ac7ddfbfSEd Maste         }
1326ac7ddfbfSEd Maste 
1327ac7ddfbfSEd Maste         virtual
1328ac7ddfbfSEd Maste         ~CommandOptions ()
1329ac7ddfbfSEd Maste         {
1330ac7ddfbfSEd Maste         }
1331ac7ddfbfSEd Maste 
1332ac7ddfbfSEd Maste         virtual Error
1333ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1334ac7ddfbfSEd Maste         {
1335ac7ddfbfSEd Maste             Error error;
1336ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1337ac7ddfbfSEd Maste 
1338ac7ddfbfSEd Maste             switch (short_option)
1339ac7ddfbfSEd Maste             {
1340ac7ddfbfSEd Maste                 case 'x':
1341ac7ddfbfSEd Maste                 {
1342ac7ddfbfSEd Maste                     bool success;
1343ac7ddfbfSEd Maste                     bool tmp_value = Args::StringToBoolean (option_arg, false, &success);
1344ac7ddfbfSEd Maste                     if (success)
1345ac7ddfbfSEd Maste                         m_from_expression = tmp_value;
1346ac7ddfbfSEd Maste                     else
1347ac7ddfbfSEd Maste                     {
1348ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg);
1349ac7ddfbfSEd Maste                     }
1350ac7ddfbfSEd Maste                 }
1351ac7ddfbfSEd Maste                 break;
1352ac7ddfbfSEd Maste                 default:
1353ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1354ac7ddfbfSEd Maste                     break;
1355ac7ddfbfSEd Maste 
1356ac7ddfbfSEd Maste             }
1357ac7ddfbfSEd Maste             return error;
1358ac7ddfbfSEd Maste         }
1359ac7ddfbfSEd Maste 
1360ac7ddfbfSEd Maste         void
1361ac7ddfbfSEd Maste         OptionParsingStarting ()
1362ac7ddfbfSEd Maste         {
1363ac7ddfbfSEd Maste             m_from_expression = false;
1364ac7ddfbfSEd Maste         }
1365ac7ddfbfSEd Maste 
1366ac7ddfbfSEd Maste         const OptionDefinition*
1367ac7ddfbfSEd Maste         GetDefinitions ()
1368ac7ddfbfSEd Maste         {
1369ac7ddfbfSEd Maste             return g_option_table;
1370ac7ddfbfSEd Maste         }
1371ac7ddfbfSEd Maste 
1372ac7ddfbfSEd Maste         bool m_from_expression;
1373ac7ddfbfSEd Maste 
1374ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1375ac7ddfbfSEd Maste 
1376ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1377ac7ddfbfSEd Maste 
1378ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1379ac7ddfbfSEd Maste     };
1380ac7ddfbfSEd Maste 
1381ac7ddfbfSEd Maste     virtual
1382ac7ddfbfSEd Maste     Options *
1383ac7ddfbfSEd Maste     GetOptions ()
1384ac7ddfbfSEd Maste     {
1385ac7ddfbfSEd Maste         return &m_options;
1386ac7ddfbfSEd Maste     }
1387ac7ddfbfSEd Maste 
1388ac7ddfbfSEd Maste     CommandObjectThreadReturn (CommandInterpreter &interpreter) :
1389ac7ddfbfSEd Maste         CommandObjectRaw (interpreter,
1390ac7ddfbfSEd Maste                           "thread return",
1391ac7ddfbfSEd Maste                           "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value,"
1392ac7ddfbfSEd Maste                           " or with the -x option from the innermost function evaluation.",
1393ac7ddfbfSEd Maste                           "thread return",
1394ac7ddfbfSEd Maste                           eFlagRequiresFrame         |
1395ac7ddfbfSEd Maste                           eFlagTryTargetAPILock      |
1396ac7ddfbfSEd Maste                           eFlagProcessMustBeLaunched |
1397ac7ddfbfSEd Maste                           eFlagProcessMustBePaused   ),
1398ac7ddfbfSEd Maste         m_options (interpreter)
1399ac7ddfbfSEd Maste     {
1400ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1401ac7ddfbfSEd Maste         CommandArgumentData expression_arg;
1402ac7ddfbfSEd Maste 
1403ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1404ac7ddfbfSEd Maste         expression_arg.arg_type = eArgTypeExpression;
1405ac7ddfbfSEd Maste         expression_arg.arg_repetition = eArgRepeatOptional;
1406ac7ddfbfSEd Maste 
1407ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1408ac7ddfbfSEd Maste         arg.push_back (expression_arg);
1409ac7ddfbfSEd Maste 
1410ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1411ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1412ac7ddfbfSEd Maste 
1413ac7ddfbfSEd Maste 
1414ac7ddfbfSEd Maste     }
1415ac7ddfbfSEd Maste 
1416ac7ddfbfSEd Maste     ~CommandObjectThreadReturn()
1417ac7ddfbfSEd Maste     {
1418ac7ddfbfSEd Maste     }
1419ac7ddfbfSEd Maste 
1420ac7ddfbfSEd Maste protected:
1421ac7ddfbfSEd Maste 
1422ac7ddfbfSEd Maste     bool DoExecute
1423ac7ddfbfSEd Maste     (
1424ac7ddfbfSEd Maste         const char *command,
1425ac7ddfbfSEd Maste         CommandReturnObject &result
1426ac7ddfbfSEd Maste     )
1427ac7ddfbfSEd Maste     {
1428ac7ddfbfSEd Maste         // I am going to handle this by hand, because I don't want you to have to say:
1429ac7ddfbfSEd Maste         // "thread return -- -5".
1430ac7ddfbfSEd Maste         if (command[0] == '-' && command[1] == 'x')
1431ac7ddfbfSEd Maste         {
1432ac7ddfbfSEd Maste             if (command && command[2] != '\0')
1433ac7ddfbfSEd Maste                 result.AppendWarning("Return values ignored when returning from user called expressions");
1434ac7ddfbfSEd Maste 
1435ac7ddfbfSEd Maste             Thread *thread = m_exe_ctx.GetThreadPtr();
1436ac7ddfbfSEd Maste             Error error;
1437ac7ddfbfSEd Maste             error = thread->UnwindInnermostExpression();
1438ac7ddfbfSEd Maste             if (!error.Success())
1439ac7ddfbfSEd Maste             {
1440ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString());
1441ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1442ac7ddfbfSEd Maste             }
1443ac7ddfbfSEd Maste             else
1444ac7ddfbfSEd Maste             {
1445ac7ddfbfSEd Maste                 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream());
1446ac7ddfbfSEd Maste                 if (success)
1447ac7ddfbfSEd Maste                 {
1448ac7ddfbfSEd Maste                     m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
1449ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1450ac7ddfbfSEd Maste                 }
1451ac7ddfbfSEd Maste                 else
1452ac7ddfbfSEd Maste                 {
1453ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression.");
1454ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1455ac7ddfbfSEd Maste                 }
1456ac7ddfbfSEd Maste             }
1457ac7ddfbfSEd Maste             return result.Succeeded();
1458ac7ddfbfSEd Maste         }
1459ac7ddfbfSEd Maste 
1460ac7ddfbfSEd Maste         ValueObjectSP return_valobj_sp;
1461ac7ddfbfSEd Maste 
1462ac7ddfbfSEd Maste         StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
1463ac7ddfbfSEd Maste         uint32_t frame_idx = frame_sp->GetFrameIndex();
1464ac7ddfbfSEd Maste 
1465ac7ddfbfSEd Maste         if (frame_sp->IsInlined())
1466ac7ddfbfSEd Maste         {
1467ac7ddfbfSEd Maste             result.AppendError("Don't know how to return from inlined frames.");
1468ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1469ac7ddfbfSEd Maste             return false;
1470ac7ddfbfSEd Maste         }
1471ac7ddfbfSEd Maste 
1472ac7ddfbfSEd Maste         if (command && command[0] != '\0')
1473ac7ddfbfSEd Maste         {
1474ac7ddfbfSEd Maste             Target *target = m_exe_ctx.GetTargetPtr();
1475ac7ddfbfSEd Maste             EvaluateExpressionOptions options;
1476ac7ddfbfSEd Maste 
1477ac7ddfbfSEd Maste             options.SetUnwindOnError(true);
1478ac7ddfbfSEd Maste             options.SetUseDynamic(eNoDynamicValues);
1479ac7ddfbfSEd Maste 
1480ac7ddfbfSEd Maste             ExecutionResults exe_results = eExecutionSetupError;
1481ac7ddfbfSEd Maste             exe_results = target->EvaluateExpression (command,
1482ac7ddfbfSEd Maste                                                       frame_sp.get(),
1483ac7ddfbfSEd Maste                                                       return_valobj_sp,
1484ac7ddfbfSEd Maste                                                       options);
1485ac7ddfbfSEd Maste             if (exe_results != eExecutionCompleted)
1486ac7ddfbfSEd Maste             {
1487ac7ddfbfSEd Maste                 if (return_valobj_sp)
1488ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
1489ac7ddfbfSEd Maste                 else
1490ac7ddfbfSEd Maste                     result.AppendErrorWithFormat("Unknown error evaluating result expression.");
1491ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1492ac7ddfbfSEd Maste                 return false;
1493ac7ddfbfSEd Maste 
1494ac7ddfbfSEd Maste             }
1495ac7ddfbfSEd Maste         }
1496ac7ddfbfSEd Maste 
1497ac7ddfbfSEd Maste         Error error;
1498ac7ddfbfSEd Maste         ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
1499ac7ddfbfSEd Maste         const bool broadcast = true;
1500ac7ddfbfSEd Maste         error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
1501ac7ddfbfSEd Maste         if (!error.Success())
1502ac7ddfbfSEd Maste         {
1503ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
1504ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1505ac7ddfbfSEd Maste             return false;
1506ac7ddfbfSEd Maste         }
1507ac7ddfbfSEd Maste 
1508ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
1509ac7ddfbfSEd Maste         return true;
1510ac7ddfbfSEd Maste     }
1511ac7ddfbfSEd Maste 
1512ac7ddfbfSEd Maste     CommandOptions m_options;
1513ac7ddfbfSEd Maste 
1514ac7ddfbfSEd Maste };
1515ac7ddfbfSEd Maste OptionDefinition
1516ac7ddfbfSEd Maste CommandObjectThreadReturn::CommandOptions::g_option_table[] =
1517ac7ddfbfSEd Maste {
151835617911SEd Maste { LLDB_OPT_SET_ALL, false, "from-expression",  'x', OptionParser::eNoArgument, NULL,               0, eArgTypeNone,     "Return from the innermost expression evaluation."},
151935617911SEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
152035617911SEd Maste };
152135617911SEd Maste 
152235617911SEd Maste //-------------------------------------------------------------------------
152335617911SEd Maste // CommandObjectThreadJump
152435617911SEd Maste //-------------------------------------------------------------------------
152535617911SEd Maste 
152635617911SEd Maste class CommandObjectThreadJump : public CommandObjectParsed
152735617911SEd Maste {
152835617911SEd Maste public:
152935617911SEd Maste     class CommandOptions : public Options
153035617911SEd Maste     {
153135617911SEd Maste     public:
153235617911SEd Maste 
153335617911SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
153435617911SEd Maste             Options (interpreter)
153535617911SEd Maste         {
153635617911SEd Maste             OptionParsingStarting ();
153735617911SEd Maste         }
153835617911SEd Maste 
153935617911SEd Maste         void
154035617911SEd Maste         OptionParsingStarting ()
154135617911SEd Maste         {
154235617911SEd Maste             m_filenames.Clear();
154335617911SEd Maste             m_line_num = 0;
154435617911SEd Maste             m_line_offset = 0;
154535617911SEd Maste             m_load_addr = LLDB_INVALID_ADDRESS;
154635617911SEd Maste             m_force = false;
154735617911SEd Maste         }
154835617911SEd Maste 
154935617911SEd Maste         virtual
155035617911SEd Maste         ~CommandOptions ()
155135617911SEd Maste         {
155235617911SEd Maste         }
155335617911SEd Maste 
155435617911SEd Maste         virtual Error
155535617911SEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
155635617911SEd Maste         {
155735617911SEd Maste             bool success;
155835617911SEd Maste             const int short_option = m_getopt_table[option_idx].val;
155935617911SEd Maste             Error error;
156035617911SEd Maste 
156135617911SEd Maste             switch (short_option)
156235617911SEd Maste             {
156335617911SEd Maste                 case 'f':
156435617911SEd Maste                     m_filenames.AppendIfUnique (FileSpec(option_arg, false));
156535617911SEd Maste                     if (m_filenames.GetSize() > 1)
156635617911SEd Maste                         return Error("only one source file expected.");
156735617911SEd Maste                     break;
156835617911SEd Maste                 case 'l':
156935617911SEd Maste                     m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success);
157035617911SEd Maste                     if (!success || m_line_num == 0)
157135617911SEd Maste                         return Error("invalid line number: '%s'.", option_arg);
157235617911SEd Maste                     break;
157335617911SEd Maste                 case 'b':
157435617911SEd Maste                     m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success);
157535617911SEd Maste                     if (!success)
157635617911SEd Maste                         return Error("invalid line offset: '%s'.", option_arg);
157735617911SEd Maste                     break;
157835617911SEd Maste                 case 'a':
157935617911SEd Maste                     {
158035617911SEd Maste                         ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
158135617911SEd Maste                         m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
158235617911SEd Maste                     }
158335617911SEd Maste                     break;
158435617911SEd Maste                 case 'r':
158535617911SEd Maste                     m_force = true;
158635617911SEd Maste                     break;
158735617911SEd Maste 
158835617911SEd Maste                  default:
158935617911SEd Maste                     return Error("invalid short option character '%c'", short_option);
159035617911SEd Maste 
159135617911SEd Maste             }
159235617911SEd Maste             return error;
159335617911SEd Maste         }
159435617911SEd Maste 
159535617911SEd Maste         const OptionDefinition*
159635617911SEd Maste         GetDefinitions ()
159735617911SEd Maste         {
159835617911SEd Maste             return g_option_table;
159935617911SEd Maste         }
160035617911SEd Maste 
160135617911SEd Maste         FileSpecList m_filenames;
160235617911SEd Maste         uint32_t m_line_num;
160335617911SEd Maste         int32_t m_line_offset;
160435617911SEd Maste         lldb::addr_t m_load_addr;
160535617911SEd Maste         bool m_force;
160635617911SEd Maste 
160735617911SEd Maste         static OptionDefinition g_option_table[];
160835617911SEd Maste     };
160935617911SEd Maste 
161035617911SEd Maste     virtual
161135617911SEd Maste     Options *
161235617911SEd Maste     GetOptions ()
161335617911SEd Maste     {
161435617911SEd Maste         return &m_options;
161535617911SEd Maste     }
161635617911SEd Maste 
161735617911SEd Maste     CommandObjectThreadJump (CommandInterpreter &interpreter) :
161835617911SEd Maste         CommandObjectParsed (interpreter,
161935617911SEd Maste                           "thread jump",
162035617911SEd Maste                           "Sets the program counter to a new address.",
162135617911SEd Maste                           "thread jump",
162235617911SEd Maste                           eFlagRequiresFrame         |
162335617911SEd Maste                           eFlagTryTargetAPILock      |
162435617911SEd Maste                           eFlagProcessMustBeLaunched |
162535617911SEd Maste                           eFlagProcessMustBePaused   ),
162635617911SEd Maste         m_options (interpreter)
162735617911SEd Maste     {
162835617911SEd Maste     }
162935617911SEd Maste 
163035617911SEd Maste     ~CommandObjectThreadJump()
163135617911SEd Maste     {
163235617911SEd Maste     }
163335617911SEd Maste 
163435617911SEd Maste protected:
163535617911SEd Maste 
163635617911SEd Maste     bool DoExecute (Args& args, CommandReturnObject &result)
163735617911SEd Maste     {
163835617911SEd Maste         RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
163935617911SEd Maste         StackFrame *frame = m_exe_ctx.GetFramePtr();
164035617911SEd Maste         Thread *thread = m_exe_ctx.GetThreadPtr();
164135617911SEd Maste         Target *target = m_exe_ctx.GetTargetPtr();
164235617911SEd Maste         const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry);
164335617911SEd Maste 
164435617911SEd Maste         if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
164535617911SEd Maste         {
164635617911SEd Maste             // Use this address directly.
164735617911SEd Maste             Address dest = Address(m_options.m_load_addr);
164835617911SEd Maste 
164935617911SEd Maste             lldb::addr_t callAddr = dest.GetCallableLoadAddress (target);
165035617911SEd Maste             if (callAddr == LLDB_INVALID_ADDRESS)
165135617911SEd Maste             {
165235617911SEd Maste                 result.AppendErrorWithFormat ("Invalid destination address.");
165335617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
165435617911SEd Maste                 return false;
165535617911SEd Maste             }
165635617911SEd Maste 
165735617911SEd Maste             if (!reg_ctx->SetPC (callAddr))
165835617911SEd Maste             {
165935617911SEd Maste                 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID());
166035617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
166135617911SEd Maste                 return false;
166235617911SEd Maste             }
166335617911SEd Maste         }
166435617911SEd Maste         else
166535617911SEd Maste         {
166635617911SEd Maste             // Pick either the absolute line, or work out a relative one.
166735617911SEd Maste             int32_t line = (int32_t)m_options.m_line_num;
166835617911SEd Maste             if (line == 0)
166935617911SEd Maste                 line = sym_ctx.line_entry.line + m_options.m_line_offset;
167035617911SEd Maste 
167135617911SEd Maste             // Try the current file, but override if asked.
167235617911SEd Maste             FileSpec file = sym_ctx.line_entry.file;
167335617911SEd Maste             if (m_options.m_filenames.GetSize() == 1)
167435617911SEd Maste                 file = m_options.m_filenames.GetFileSpecAtIndex(0);
167535617911SEd Maste 
167635617911SEd Maste             if (!file)
167735617911SEd Maste             {
167835617911SEd Maste                 result.AppendErrorWithFormat ("No source file available for the current location.");
167935617911SEd Maste                 result.SetStatus (eReturnStatusFailed);
168035617911SEd Maste                 return false;
168135617911SEd Maste             }
168235617911SEd Maste 
168335617911SEd Maste             std::string warnings;
168435617911SEd Maste             Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings);
168535617911SEd Maste 
168635617911SEd Maste             if (err.Fail())
168735617911SEd Maste             {
168835617911SEd Maste                 result.SetError (err);
168935617911SEd Maste                 return false;
169035617911SEd Maste             }
169135617911SEd Maste 
169235617911SEd Maste             if (!warnings.empty())
169335617911SEd Maste                 result.AppendWarning (warnings.c_str());
169435617911SEd Maste         }
169535617911SEd Maste 
169635617911SEd Maste         result.SetStatus (eReturnStatusSuccessFinishResult);
169735617911SEd Maste         return true;
169835617911SEd Maste     }
169935617911SEd Maste 
170035617911SEd Maste     CommandOptions m_options;
170135617911SEd Maste };
170235617911SEd Maste OptionDefinition
170335617911SEd Maste CommandObjectThreadJump::CommandOptions::g_option_table[] =
170435617911SEd Maste {
170535617911SEd Maste     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
170635617911SEd Maste         "Specifies the source file to jump to."},
170735617911SEd Maste 
170835617911SEd Maste     { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum,
170935617911SEd Maste         "Specifies the line number to jump to."},
171035617911SEd Maste 
171135617911SEd Maste     { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset,
171235617911SEd Maste         "Jumps by a relative line offset from the current line."},
171335617911SEd Maste 
171435617911SEd Maste     { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression,
171535617911SEd Maste         "Jumps to a specific address."},
171635617911SEd Maste 
171735617911SEd Maste     { LLDB_OPT_SET_1|
171835617911SEd Maste       LLDB_OPT_SET_2|
171935617911SEd Maste       LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."},
172035617911SEd Maste 
1721ac7ddfbfSEd Maste     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1722ac7ddfbfSEd Maste };
1723ac7ddfbfSEd Maste 
1724ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1725ac7ddfbfSEd Maste // CommandObjectMultiwordThread
1726ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1727ac7ddfbfSEd Maste 
1728ac7ddfbfSEd Maste CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
1729ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
1730ac7ddfbfSEd Maste                             "thread",
1731ac7ddfbfSEd Maste                             "A set of commands for operating on one or more threads within a running process.",
1732ac7ddfbfSEd Maste                             "thread <subcommand> [<subcommand-options>]")
1733ac7ddfbfSEd Maste {
1734ac7ddfbfSEd Maste     LoadSubCommand ("backtrace",  CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1735ac7ddfbfSEd Maste     LoadSubCommand ("continue",   CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1736ac7ddfbfSEd Maste     LoadSubCommand ("list",       CommandObjectSP (new CommandObjectThreadList (interpreter)));
1737ac7ddfbfSEd Maste     LoadSubCommand ("return",     CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
173835617911SEd Maste     LoadSubCommand ("jump",       CommandObjectSP (new CommandObjectThreadJump (interpreter)));
1739ac7ddfbfSEd Maste     LoadSubCommand ("select",     CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1740ac7ddfbfSEd Maste     LoadSubCommand ("until",      CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1741ac7ddfbfSEd Maste     LoadSubCommand ("step-in",    CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1742ac7ddfbfSEd Maste                                                     interpreter,
1743ac7ddfbfSEd Maste                                                     "thread step-in",
1744ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified).",
1745ac7ddfbfSEd Maste                                                     NULL,
1746ac7ddfbfSEd Maste                                                     eStepTypeInto,
1747ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1748ac7ddfbfSEd Maste 
1749ac7ddfbfSEd Maste     LoadSubCommand ("step-out",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1750ac7ddfbfSEd Maste                                                     interpreter,
1751ac7ddfbfSEd Maste                                                     "thread step-out",
1752ac7ddfbfSEd Maste                                                     "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
1753ac7ddfbfSEd Maste                                                     NULL,
1754ac7ddfbfSEd Maste                                                     eStepTypeOut,
1755ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1756ac7ddfbfSEd Maste 
1757ac7ddfbfSEd Maste     LoadSubCommand ("step-over",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1758ac7ddfbfSEd Maste                                                     interpreter,
1759ac7ddfbfSEd Maste                                                     "thread step-over",
1760ac7ddfbfSEd Maste                                                     "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
1761ac7ddfbfSEd Maste                                                     NULL,
1762ac7ddfbfSEd Maste                                                     eStepTypeOver,
1763ac7ddfbfSEd Maste                                                     eStepScopeSource)));
1764ac7ddfbfSEd Maste 
1765ac7ddfbfSEd Maste     LoadSubCommand ("step-inst",   CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1766ac7ddfbfSEd Maste                                                     interpreter,
1767ac7ddfbfSEd Maste                                                     "thread step-inst",
1768ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified).",
1769ac7ddfbfSEd Maste                                                     NULL,
1770ac7ddfbfSEd Maste                                                     eStepTypeTrace,
1771ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
1772ac7ddfbfSEd Maste 
1773ac7ddfbfSEd Maste     LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1774ac7ddfbfSEd Maste                                                     interpreter,
1775ac7ddfbfSEd Maste                                                     "thread step-inst-over",
1776ac7ddfbfSEd Maste                                                     "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1777ac7ddfbfSEd Maste                                                     NULL,
1778ac7ddfbfSEd Maste                                                     eStepTypeTraceOver,
1779ac7ddfbfSEd Maste                                                     eStepScopeInstruction)));
1780ac7ddfbfSEd Maste }
1781ac7ddfbfSEd Maste 
1782ac7ddfbfSEd Maste CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1783ac7ddfbfSEd Maste {
1784ac7ddfbfSEd Maste }
1785ac7ddfbfSEd Maste 
1786ac7ddfbfSEd Maste 
1787