blob: d5da8807ae68f9b1a3a8cec9de129b71854a48c3 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectThread.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/State.h"
18#include "lldb/Core/SourceManager.h"
19
Greg Claytoncd548032011-02-01 01:31:41 +000020#include "lldb/Host/Host.h"
21
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandInterpreter.h"
23#include "lldb/Interpreter/CommandReturnObject.h"
24
25#include "lldb/Target/Process.h"
26#include "lldb/Target/RegisterContext.h"
27#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
29#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030#include "lldb/Target/ThreadPlanStepInstruction.h"
31#include "lldb/Target/ThreadPlanStepOut.h"
32#include "lldb/Target/ThreadPlanStepRange.h"
33#include "lldb/Target/ThreadPlanStepInRange.h"
34#include "lldb/Symbol/LineTable.h"
35#include "lldb/Symbol/LineEntry.h"
36
37using namespace lldb;
38using namespace lldb_private;
39
40
41bool
42lldb_private::DisplayThreadInfo
43(
Greg Clayton63094e02010-06-23 01:19:29 +000044 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000045 Stream &strm,
46 Thread *thread,
47 bool only_threads_with_stop_reason,
48 bool show_source
49)
50{
51 if (thread)
52 {
53 if (only_threads_with_stop_reason)
54 {
Greg Clayton643ee732010-08-04 01:40:35 +000055 if (thread->GetStopInfo() == NULL)
56 return false;
Chris Lattner24943d22010-06-08 16:52:24 +000057 }
58
59 strm.Indent();
Jim Inghamc8332952010-08-26 21:32:51 +000060 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' ');
Chris Lattner24943d22010-06-08 16:52:24 +000061
62 // Show one frame with only the first showing source
63 if (show_source)
64 {
Jim Ingham74989e82010-08-30 19:44:40 +000065 bool already_shown = false;
66 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0);
67 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
Caroline Tice5bc8c972010-09-20 20:44:43 +000068 if (interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
Jim Ingham74989e82010-08-30 19:44:40 +000069 {
70 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
71 }
72
Chris Lattner24943d22010-06-08 16:52:24 +000073 DisplayFramesForExecutionContext (thread,
74 interpreter,
75 strm,
Chris Lattner24943d22010-06-08 16:52:24 +000076 0, // Start at first frame
77 1, // Number of frames to show
78 false,// Don't show the frame info since we already displayed most of it above...
Jim Ingham74989e82010-08-30 19:44:40 +000079 !already_shown, // Show source for the first frame
Chris Lattner24943d22010-06-08 16:52:24 +000080 3, // lines of source context before
81 3); // lines of source context after
82 }
83 else
84 {
Greg Claytona830adb2010-10-04 01:05:56 +000085 thread->DumpUsingSettingsFormat (strm, 0);
Chris Lattner24943d22010-06-08 16:52:24 +000086 }
87
88 return true;
89 }
90 return false;
91}
92
93size_t
94lldb_private::DisplayThreadsInfo
95(
Greg Clayton63094e02010-06-23 01:19:29 +000096 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000097 ExecutionContext *exe_ctx,
98 CommandReturnObject &result,
99 bool only_threads_with_stop_reason,
100 bool show_source
101)
102{
103 StreamString strm;
104
105 size_t num_thread_infos_dumped = 0;
106
107 if (!exe_ctx->process)
108 return 0;
109
110 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
111 if (num_threads > 0)
112 {
113
114 for (uint32_t i = 0; i < num_threads; i++)
115 {
116 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
117 if (thread)
118 {
119 if (DisplayThreadInfo (interpreter,
120 strm,
121 thread,
122 only_threads_with_stop_reason,
123 show_source))
124 ++num_thread_infos_dumped;
125 }
126 }
127 }
128
129 if (num_thread_infos_dumped > 0)
130 {
131 if (num_thread_infos_dumped < num_threads)
132 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
133
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000134 result.AppendMessage (strm.GetString().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000135 result.SetStatus (eReturnStatusSuccessFinishNoResult);
136 }
137 return num_thread_infos_dumped;
138}
139
140
141size_t
142lldb_private::DisplayFramesForExecutionContext
143(
144 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000145 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000146 Stream& strm,
Chris Lattner24943d22010-06-08 16:52:24 +0000147 uint32_t first_frame,
148 uint32_t num_frames,
149 bool show_frame_info,
150 uint32_t num_frames_with_source,
151 uint32_t source_lines_before,
152 uint32_t source_lines_after
153)
154{
155 if (thread == NULL)
156 return 0;
157
158 size_t num_frames_displayed = 0;
159
160 if (num_frames == 0)
161 return 0;
162
Greg Claytona830adb2010-10-04 01:05:56 +0000163 thread->DumpUsingSettingsFormat (strm, num_frames > 1 ? UINT32_MAX : first_frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000164 strm.IndentMore();
165
166 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000167 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-08-26 23:36:03 +0000168 uint32_t last_frame;
169
170 // Don't let the last frame wrap around...
171 if (num_frames == UINT32_MAX)
172 last_frame = UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +0000173 else
Jim Ingham8ab1a802010-08-26 23:36:03 +0000174 last_frame = first_frame + num_frames;
175
176 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000178 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
179 if (frame_sp.get() == NULL)
180 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000181
Jim Ingham8ab1a802010-08-26 23:36:03 +0000182 if (DisplayFrameForExecutionContext (thread,
183 frame_sp.get(),
184 interpreter,
185 strm,
186 show_frame_info,
187 num_frames_with_source > first_frame - frame_idx,
188 source_lines_before,
189 source_lines_after) == false)
190 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000191
Jim Ingham8ab1a802010-08-26 23:36:03 +0000192 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000193 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000194
Chris Lattner24943d22010-06-08 16:52:24 +0000195 strm.IndentLess();
196 return num_frames_displayed;
197}
198
199bool
200lldb_private::DisplayFrameForExecutionContext
201(
202 Thread *thread,
203 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000204 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000205 Stream& strm,
206 bool show_frame_info,
207 bool show_source,
208 uint32_t source_lines_before,
209 uint32_t source_lines_after
210)
211{
212 // thread and frame must be filled in prior to calling this function
213 if (thread && frame)
214 {
215 if (show_frame_info)
216 {
217 strm.Indent();
Greg Claytona830adb2010-10-04 01:05:56 +0000218 frame->DumpUsingSettingsFormat (&strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000219 }
220
221 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
222
223 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
224 {
Greg Clayton63094e02010-06-23 01:19:29 +0000225 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000226 sc.line_entry.file,
227 sc.line_entry.line,
228 3,
229 3,
230 "->",
231 &strm);
232
233 }
234 return true;
235 }
236 return false;
237}
238
239
240//-------------------------------------------------------------------------
241// CommandObjectThreadBacktrace
242//-------------------------------------------------------------------------
243
244class CommandObjectThreadBacktrace : public CommandObject
245{
246public:
247
Jim Ingham8ab1a802010-08-26 23:36:03 +0000248 class CommandOptions : public Options
249 {
250 public:
251
252 CommandOptions () :
253 Options()
254 {
255 // Keep default values of all options in one place: ResetOptionValues ()
256 ResetOptionValues ();
257 }
258
259 virtual
260 ~CommandOptions ()
261 {
262 }
263
264 virtual Error
265 SetOptionValue (int option_idx, const char *option_arg)
266 {
267 Error error;
268 char short_option = (char) m_getopt_table[option_idx].val;
269
270 switch (short_option)
271 {
272 case 'c':
273 {
274 bool success;
275 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
276 if (!success)
277 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
278 if (input_count < -1)
279 m_count = UINT32_MAX;
280 else
281 m_count = input_count;
282 }
283 break;
284 case 's':
285 {
286 bool success;
287 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
288 if (!success)
289 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
290 }
291 break;
292 default:
293 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
294 break;
295
296 }
297 return error;
298 }
299
300 void
301 ResetOptionValues ()
302 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000303 m_count = -1;
304 m_start = 0;
305 }
306
Greg Claytonb3448432011-03-24 21:19:54 +0000307 const OptionDefinition*
Jim Ingham8ab1a802010-08-26 23:36:03 +0000308 GetDefinitions ()
309 {
310 return g_option_table;
311 }
312
313 // Options table: Required for subclasses of Options.
314
Greg Claytonb3448432011-03-24 21:19:54 +0000315 static OptionDefinition g_option_table[];
Jim Ingham8ab1a802010-08-26 23:36:03 +0000316
317 // Instance variables to hold the values for command options.
318 uint32_t m_count;
319 uint32_t m_start;
320 };
321
Greg Clayton238c0a12010-09-18 01:14:36 +0000322 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
323 CommandObject (interpreter,
324 "thread backtrace",
Caroline Tice31fbb642010-09-08 22:08:58 +0000325 "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.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000326 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000327 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000328 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000329 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000330 CommandArgumentEntry arg;
331 CommandArgumentData thread_idx_arg;
332
333 // Define the first (and only) variant of this arg.
334 thread_idx_arg.arg_type = eArgTypeThreadIndex;
335 thread_idx_arg.arg_repetition = eArgRepeatStar;
336
337 // There is only one variant this argument could be; put it into the argument entry.
338 arg.push_back (thread_idx_arg);
339
340 // Push the data for the first argument into the m_arguments vector.
341 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000342 }
343
344 ~CommandObjectThreadBacktrace()
345 {
346 }
347
Jim Ingham8ab1a802010-08-26 23:36:03 +0000348 virtual Options *
349 GetOptions ()
350 {
351 return &m_options;
352 }
Chris Lattner24943d22010-06-08 16:52:24 +0000353
Greg Clayton63094e02010-06-23 01:19:29 +0000354 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000355 Execute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000356 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000357
358 bool show_frame_info = true;
359 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
360
361 result.SetStatus (eReturnStatusSuccessFinishResult);
362
Chris Lattner24943d22010-06-08 16:52:24 +0000363 if (command.GetArgumentCount() == 0)
364 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000365 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000366 if (exe_ctx.thread)
367 {
Chris Lattner24943d22010-06-08 16:52:24 +0000368 if (DisplayFramesForExecutionContext (exe_ctx.thread,
Greg Clayton238c0a12010-09-18 01:14:36 +0000369 m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000370 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000371 m_options.m_start,
372 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000373 show_frame_info,
374 num_frames_with_source,
375 3,
376 3))
377 {
378 result.SetStatus (eReturnStatusSuccessFinishResult);
379 }
380 }
381 else
382 {
383 result.AppendError ("invalid thread");
384 result.SetStatus (eReturnStatusFailed);
385 }
386 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000387 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
388 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000389 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000390 uint32_t num_threads = process->GetThreadList().GetSize();
391 for (uint32_t i = 0; i < num_threads; i++)
392 {
393 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
394 if (!DisplayFramesForExecutionContext (thread_sp.get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000395 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000396 result.GetOutputStream(),
397 m_options.m_start,
398 m_options.m_count,
399 show_frame_info,
400 num_frames_with_source,
401 3,
402 3))
403 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000404 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-08-27 00:58:05 +0000405 result.SetStatus (eReturnStatusFailed);
406 return false;
407 }
408 if (i < num_threads - 1)
409 result.AppendMessage("");
410 }
411 }
Chris Lattner24943d22010-06-08 16:52:24 +0000412 else
413 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000414 uint32_t num_args = command.GetArgumentCount();
Greg Clayton238c0a12010-09-18 01:14:36 +0000415 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000416 std::vector<ThreadSP> thread_sps;
417
418 for (uint32_t i = 0; i < num_args; i++)
419 {
420 bool success;
421
422 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
423 if (!success)
424 {
425 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
426 result.SetStatus (eReturnStatusFailed);
427 return false;
428 }
429
430 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
431
432 if (!thread_sps[i])
433 {
434 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
435 result.SetStatus (eReturnStatusFailed);
436 return false;
437 }
438
439 }
440
441 for (uint32_t i = 0; i < num_args; i++)
442 {
443 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000444 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000445 result.GetOutputStream(),
446 m_options.m_start,
447 m_options.m_count,
448 show_frame_info,
449 num_frames_with_source,
450 3,
451 3))
452 {
453 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
454 result.SetStatus (eReturnStatusFailed);
455 return false;
456 }
457
458 if (i < num_args - 1)
459 result.AppendMessage("");
460 }
Chris Lattner24943d22010-06-08 16:52:24 +0000461 }
462 return result.Succeeded();
463 }
464protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000465 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000466};
467
Greg Claytonb3448432011-03-24 21:19:54 +0000468OptionDefinition
Jim Ingham8ab1a802010-08-26 23:36:03 +0000469CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
470{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000471{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
Caroline Tice43b014a2010-10-04 22:28:36 +0000472{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
Caroline Tice4d6675c2010-10-01 19:59:14 +0000473{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000474};
Chris Lattner24943d22010-06-08 16:52:24 +0000475
Greg Claytonc0418152010-07-07 17:07:17 +0000476enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000477{
478 eStepScopeSource,
479 eStepScopeInstruction
480};
481
482class CommandObjectThreadStepWithTypeAndScope : public CommandObject
483{
484public:
485
486 class CommandOptions : public Options
487 {
488 public:
489
490 CommandOptions () :
491 Options()
492 {
493 // Keep default values of all options in one place: ResetOptionValues ()
494 ResetOptionValues ();
495 }
496
497 virtual
498 ~CommandOptions ()
499 {
500 }
501
502 virtual Error
503 SetOptionValue (int option_idx, const char *option_arg)
504 {
505 Error error;
506 char short_option = (char) m_getopt_table[option_idx].val;
507
508 switch (short_option)
509 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000510 case 'a':
Chris Lattner24943d22010-06-08 16:52:24 +0000511 {
512 bool success;
513 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
514 if (!success)
515 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
516 }
517 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000518
519 case 'm':
Chris Lattner24943d22010-06-08 16:52:24 +0000520 {
521 bool found_one = false;
522 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
523 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
524 if (!found_one)
525 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
526 }
527 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000528
529 case 'r':
Jim Ingham809ab9b2010-07-10 02:27:39 +0000530 {
531 m_avoid_regexp.clear();
532 m_avoid_regexp.assign(option_arg);
533 }
534 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000535
536 default:
537 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
538 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000539
540 }
541 return error;
542 }
543
544 void
545 ResetOptionValues ()
546 {
Chris Lattner24943d22010-06-08 16:52:24 +0000547 m_avoid_no_debug = true;
548 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000549 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000550 }
551
Greg Claytonb3448432011-03-24 21:19:54 +0000552 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000553 GetDefinitions ()
554 {
555 return g_option_table;
556 }
557
558 // Options table: Required for subclasses of Options.
559
Greg Claytonb3448432011-03-24 21:19:54 +0000560 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000561
562 // Instance variables to hold the values for command options.
563 bool m_avoid_no_debug;
564 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000565 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000566 };
567
Greg Clayton238c0a12010-09-18 01:14:36 +0000568 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
569 const char *name,
570 const char *help,
571 const char *syntax,
572 uint32_t flags,
573 StepType step_type,
574 StepScope step_scope) :
575 CommandObject (interpreter, name, help, syntax, flags),
Chris Lattner24943d22010-06-08 16:52:24 +0000576 m_step_type (step_type),
577 m_step_scope (step_scope),
578 m_options ()
579 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000580 CommandArgumentEntry arg;
581 CommandArgumentData thread_id_arg;
582
583 // Define the first (and only) variant of this arg.
584 thread_id_arg.arg_type = eArgTypeThreadID;
585 thread_id_arg.arg_repetition = eArgRepeatOptional;
586
587 // There is only one variant this argument could be; put it into the argument entry.
588 arg.push_back (thread_id_arg);
589
590 // Push the data for the first argument into the m_arguments vector.
591 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000592 }
593
594 virtual
595 ~CommandObjectThreadStepWithTypeAndScope ()
596 {
597 }
598
599 virtual
600 Options *
601 GetOptions ()
602 {
603 return &m_options;
604 }
605
606 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000607 Execute
608 (
Greg Clayton63094e02010-06-23 01:19:29 +0000609 Args& command,
610 CommandReturnObject &result
611 )
Chris Lattner24943d22010-06-08 16:52:24 +0000612 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000613 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
614 bool synchronous_execution = m_interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000615
616 if (process == NULL)
617 {
618 result.AppendError ("need a valid process to step");
619 result.SetStatus (eReturnStatusFailed);
620
621 }
622 else
623 {
624 const uint32_t num_threads = process->GetThreadList().GetSize();
625 Thread *thread = NULL;
626
627 if (command.GetArgumentCount() == 0)
628 {
Jim Inghamc8332952010-08-26 21:32:51 +0000629 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000630 if (thread == NULL)
631 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000632 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000633 result.SetStatus (eReturnStatusFailed);
634 return false;
635 }
636 }
637 else
638 {
639 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
640 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
641 if (step_thread_idx == LLDB_INVALID_INDEX32)
642 {
643 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
644 result.SetStatus (eReturnStatusFailed);
645 return false;
646 }
647 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
648 if (thread == NULL)
649 {
650 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
651 step_thread_idx, 0, num_threads);
652 result.SetStatus (eReturnStatusFailed);
653 return false;
654 }
655 }
656
657 const bool abort_other_plans = false;
658 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
659
660 // This is a bit unfortunate, but not all the commands in this command object support
661 // only while stepping, so I use the bool for them.
662 bool bool_stop_other_threads;
663 if (m_options.m_run_mode == eAllThreads)
664 bool_stop_other_threads = false;
665 else
666 bool_stop_other_threads = true;
667
668 if (m_step_type == eStepTypeInto)
669 {
670 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
671 ThreadPlan *new_plan;
672
673 if (frame->HasDebugInformation ())
674 {
675 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
676 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
677 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000678 stop_other_threads,
679 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000680 if (new_plan && !m_options.m_avoid_regexp.empty())
681 {
682 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
683 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
684 }
Chris Lattner24943d22010-06-08 16:52:24 +0000685 }
686 else
687 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
688
Jim Inghamc8332952010-08-26 21:32:51 +0000689 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000690 process->Resume ();
691 }
692 else if (m_step_type == eStepTypeOver)
693 {
694 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
695 ThreadPlan *new_plan;
696
697 if (frame->HasDebugInformation())
698 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
699 m_step_type,
700 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
701 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000702 stop_other_threads,
703 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000704 else
705 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
706 abort_other_plans,
707 bool_stop_other_threads);
708
709 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
710 // Maybe there should be a parameter to control this.
711 new_plan->SetOkayToDiscard(false);
712
Jim Inghamc8332952010-08-26 21:32:51 +0000713 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000714 process->Resume ();
715 }
716 else if (m_step_type == eStepTypeTrace)
717 {
718 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000719 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000720 process->Resume ();
721 }
722 else if (m_step_type == eStepTypeTraceOver)
723 {
724 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000725 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000726 process->Resume ();
727 }
728 else if (m_step_type == eStepTypeOut)
729 {
730 ThreadPlan *new_plan;
731
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000732 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
733 NULL,
734 false,
735 bool_stop_other_threads,
736 eVoteYes,
737 eVoteNoOpinion,
738 thread->GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000739 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
740 // Maybe there should be a parameter to control this.
741 new_plan->SetOkayToDiscard(false);
742
Jim Inghamc8332952010-08-26 21:32:51 +0000743 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000744 process->Resume ();
745 }
746 else
747 {
748 result.AppendError ("step type is not supported");
749 result.SetStatus (eReturnStatusFailed);
750 }
751 if (synchronous_execution)
752 {
753 StateType state = process->WaitForProcessToStop (NULL);
754
755 //EventSP event_sp;
756 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
757 //while (! StateIsStoppedState (state))
758 // {
759 // state = process->WaitForStateChangedEvents (NULL, event_sp);
760 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000761 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000762 result.SetDidChangeProcessState (true);
763 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
764 result.SetStatus (eReturnStatusSuccessFinishNoResult);
765 }
766 }
767 return result.Succeeded();
768 }
769
770protected:
771 StepType m_step_type;
772 StepScope m_step_scope;
773 CommandOptions m_options;
774};
775
Greg Claytonb3448432011-03-24 21:19:54 +0000776static OptionEnumValueElement
Chris Lattner24943d22010-06-08 16:52:24 +0000777g_tri_running_mode[] =
778{
Greg Claytonfe424a92010-09-18 03:37:20 +0000779{ eOnlyThisThread, "this-thread", "Run only this thread"},
780{ eAllThreads, "all-threads", "Run all threads"},
781{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000782{ 0, NULL, NULL }
783};
784
Greg Claytonb3448432011-03-24 21:19:54 +0000785static OptionEnumValueElement
Chris Lattner24943d22010-06-08 16:52:24 +0000786g_duo_running_mode[] =
787{
Greg Claytonfe424a92010-09-18 03:37:20 +0000788{ eOnlyThisThread, "this-thread", "Run only this thread"},
789{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000790{ 0, NULL, NULL }
791};
792
Greg Claytonb3448432011-03-24 21:19:54 +0000793OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000794CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
795{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000796{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."},
797{ LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
798{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
799{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000800};
801
802
803//-------------------------------------------------------------------------
804// CommandObjectThreadContinue
805//-------------------------------------------------------------------------
806
807class CommandObjectThreadContinue : public CommandObject
808{
809public:
810
Greg Clayton238c0a12010-09-18 01:14:36 +0000811 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
812 CommandObject (interpreter,
813 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000814 "Continue execution of one or more threads in an active process.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000815 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000816 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
817 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000818 CommandArgumentEntry arg;
819 CommandArgumentData thread_idx_arg;
820
821 // Define the first (and only) variant of this arg.
822 thread_idx_arg.arg_type = eArgTypeThreadIndex;
823 thread_idx_arg.arg_repetition = eArgRepeatPlus;
824
825 // There is only one variant this argument could be; put it into the argument entry.
826 arg.push_back (thread_idx_arg);
827
828 // Push the data for the first argument into the m_arguments vector.
829 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000830 }
831
832
833 virtual
834 ~CommandObjectThreadContinue ()
835 {
836 }
837
838 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000839 Execute
840 (
Greg Clayton63094e02010-06-23 01:19:29 +0000841 Args& command,
842 CommandReturnObject &result
843 )
Chris Lattner24943d22010-06-08 16:52:24 +0000844 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000845 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000846
Greg Clayton238c0a12010-09-18 01:14:36 +0000847 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000848 {
849 result.AppendError ("invalid target, set executable file using 'file' command");
850 result.SetStatus (eReturnStatusFailed);
851 return false;
852 }
853
Greg Clayton238c0a12010-09-18 01:14:36 +0000854 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000855 if (process == NULL)
856 {
857 result.AppendError ("no process exists. Cannot continue");
858 result.SetStatus (eReturnStatusFailed);
859 return false;
860 }
861
862 StateType state = process->GetState();
863 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
864 {
865 const uint32_t num_threads = process->GetThreadList().GetSize();
866 uint32_t idx;
867 const size_t argc = command.GetArgumentCount();
868 if (argc > 0)
869 {
870 std::vector<uint32_t> resume_thread_indexes;
871 for (uint32_t i=0; i<argc; ++i)
872 {
873 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
874 if (idx < num_threads)
875 resume_thread_indexes.push_back(idx);
876 else
877 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
878 }
879
880 if (resume_thread_indexes.empty())
881 {
882 result.AppendError ("no valid thread indexes were specified");
883 result.SetStatus (eReturnStatusFailed);
884 return false;
885 }
886 else
887 {
888 result.AppendMessage ("Resuming thread ");
889 for (idx=0; idx<num_threads; ++idx)
890 {
891 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
892 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
893 {
894 result.AppendMessageWithFormat ("%u ", idx);
895 thread->SetResumeState (eStateRunning);
896 }
897 else
898 {
899 thread->SetResumeState (eStateSuspended);
900 }
901 }
902 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
903 }
904 }
905 else
906 {
Jim Inghamc8332952010-08-26 21:32:51 +0000907 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000908 if (current_thread == NULL)
909 {
910 result.AppendError ("the process doesn't have a current thread");
911 result.SetStatus (eReturnStatusFailed);
912 return false;
913 }
914 // Set the actions that the threads should each take when resuming
915 for (idx=0; idx<num_threads; ++idx)
916 {
917 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
918 if (thread == current_thread)
919 {
920 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
921 thread->SetResumeState (eStateRunning);
922 }
923 else
924 {
925 thread->SetResumeState (eStateSuspended);
926 }
927 }
928 }
929
930 Error error (process->Resume());
931 if (error.Success())
932 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000933 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000934 if (synchronous_execution)
935 {
Greg Claytonbef15832010-07-14 00:18:15 +0000936 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000937
938 result.SetDidChangeProcessState (true);
939 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
940 result.SetStatus (eReturnStatusSuccessFinishNoResult);
941 }
942 else
943 {
944 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
945 }
946 }
947 else
948 {
949 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
950 result.SetStatus (eReturnStatusFailed);
951 }
952 }
953 else
954 {
955 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
956 StateAsCString(state));
957 result.SetStatus (eReturnStatusFailed);
958 }
959
960 return result.Succeeded();
961 }
962
963};
964
965//-------------------------------------------------------------------------
966// CommandObjectThreadUntil
967//-------------------------------------------------------------------------
968
969class CommandObjectThreadUntil : public CommandObject
970{
971public:
972
973 class CommandOptions : public Options
974 {
975 public:
976 uint32_t m_thread_idx;
977 uint32_t m_frame_idx;
978
979 CommandOptions () :
980 Options(),
981 m_thread_idx(LLDB_INVALID_THREAD_ID),
982 m_frame_idx(LLDB_INVALID_FRAME_ID)
983 {
984 // Keep default values of all options in one place: ResetOptionValues ()
985 ResetOptionValues ();
986 }
987
988 virtual
989 ~CommandOptions ()
990 {
991 }
992
993 virtual Error
994 SetOptionValue (int option_idx, const char *option_arg)
995 {
996 Error error;
997 char short_option = (char) m_getopt_table[option_idx].val;
998
999 switch (short_option)
1000 {
1001 case 't':
1002 {
Greg Claytonbef15832010-07-14 00:18:15 +00001003 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +00001004 if (m_thread_idx == LLDB_INVALID_INDEX32)
1005 {
1006 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
1007 }
1008 }
1009 break;
1010 case 'f':
1011 {
1012 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1013 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1014 {
1015 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
1016 }
1017 }
1018 break;
1019 case 'm':
1020 {
1021 bool found_one = false;
1022 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1023 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
1024
1025 if (!found_one)
1026 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
1027 else if (run_mode == eAllThreads)
1028 m_stop_others = false;
1029 else
1030 m_stop_others = true;
1031
1032 }
1033 break;
1034 default:
1035 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1036 break;
1037
1038 }
1039 return error;
1040 }
1041
1042 void
1043 ResetOptionValues ()
1044 {
Chris Lattner24943d22010-06-08 16:52:24 +00001045 m_thread_idx = LLDB_INVALID_THREAD_ID;
1046 m_frame_idx = 0;
1047 m_stop_others = false;
1048 }
1049
Greg Claytonb3448432011-03-24 21:19:54 +00001050 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +00001051 GetDefinitions ()
1052 {
1053 return g_option_table;
1054 }
1055
1056 uint32_t m_step_thread_idx;
1057 bool m_stop_others;
1058
1059 // Options table: Required for subclasses of Options.
1060
Greg Claytonb3448432011-03-24 21:19:54 +00001061 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +00001062
1063 // Instance variables to hold the values for command options.
1064 };
1065
Greg Clayton238c0a12010-09-18 01:14:36 +00001066 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1067 CommandObject (interpreter,
1068 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001069 "Run the current or specified thread until it reaches a given line number or leaves the current function.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001070 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +00001071 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1072 m_options ()
1073 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001074 CommandArgumentEntry arg;
1075 CommandArgumentData line_num_arg;
1076
1077 // Define the first (and only) variant of this arg.
1078 line_num_arg.arg_type = eArgTypeLineNum;
1079 line_num_arg.arg_repetition = eArgRepeatPlain;
1080
1081 // There is only one variant this argument could be; put it into the argument entry.
1082 arg.push_back (line_num_arg);
1083
1084 // Push the data for the first argument into the m_arguments vector.
1085 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001086 }
1087
1088
1089 virtual
1090 ~CommandObjectThreadUntil ()
1091 {
1092 }
1093
1094 virtual
1095 Options *
1096 GetOptions ()
1097 {
1098 return &m_options;
1099 }
1100
1101 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001102 Execute
1103 (
Greg Clayton63094e02010-06-23 01:19:29 +00001104 Args& command,
1105 CommandReturnObject &result
1106 )
Chris Lattner24943d22010-06-08 16:52:24 +00001107 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001108 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001109
Greg Clayton238c0a12010-09-18 01:14:36 +00001110 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001111 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001112 {
1113 result.AppendError ("invalid target, set executable file using 'file' command");
1114 result.SetStatus (eReturnStatusFailed);
1115 return false;
1116 }
1117
Greg Clayton238c0a12010-09-18 01:14:36 +00001118 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001119 if (process == NULL)
1120 {
1121 result.AppendError ("need a valid process to step");
1122 result.SetStatus (eReturnStatusFailed);
1123
1124 }
1125 else
1126 {
1127 Thread *thread = NULL;
1128 uint32_t line_number;
1129
1130 if (command.GetArgumentCount() != 1)
1131 {
1132 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1133 result.SetStatus (eReturnStatusFailed);
1134 return false;
1135 }
1136
1137 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1138 if (line_number == UINT32_MAX)
1139 {
1140 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1141 result.SetStatus (eReturnStatusFailed);
1142 return false;
1143 }
1144
1145 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1146 {
Jim Inghamc8332952010-08-26 21:32:51 +00001147 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001148 }
1149 else
1150 {
1151 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1152 }
1153
1154 if (thread == NULL)
1155 {
1156 const uint32_t num_threads = process->GetThreadList().GetSize();
1157 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1158 result.SetStatus (eReturnStatusFailed);
1159 return false;
1160 }
1161
1162 const bool abort_other_plans = true;
1163
1164 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1165 if (frame == NULL)
1166 {
1167
1168 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1169 result.SetStatus (eReturnStatusFailed);
1170 return false;
1171 }
1172
1173 ThreadPlan *new_plan;
1174
1175 if (frame->HasDebugInformation ())
1176 {
1177 // Finally we got here... Translate the given line number to a bunch of addresses:
1178 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1179 LineTable *line_table = NULL;
1180 if (sc.comp_unit)
1181 line_table = sc.comp_unit->GetLineTable();
1182
1183 if (line_table == NULL)
1184 {
1185 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1186 m_options.m_frame_idx, m_options.m_thread_idx);
1187 result.SetStatus (eReturnStatusFailed);
1188 return false;
1189 }
1190
1191 LineEntry function_start;
1192 uint32_t index_ptr = 0, end_ptr;
1193 std::vector<addr_t> address_list;
1194
1195 // Find the beginning & end index of the
1196 AddressRange fun_addr_range = sc.function->GetAddressRange();
1197 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1198 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1199
1200 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1201 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1202
1203 while (index_ptr <= end_ptr)
1204 {
1205 LineEntry line_entry;
1206 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1207 if (index_ptr == UINT32_MAX)
1208 break;
1209
Greg Claytoneea26402010-09-14 23:36:40 +00001210 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001211 if (address != LLDB_INVALID_ADDRESS)
1212 address_list.push_back (address);
1213 index_ptr++;
1214 }
1215
Greg Clayton1ebdcc72011-01-21 06:11:58 +00001216 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others, thread->GetSelectedFrameIndex ());
Chris Lattner24943d22010-06-08 16:52:24 +00001217 new_plan->SetOkayToDiscard(false);
1218 }
1219 else
1220 {
1221 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1222 result.SetStatus (eReturnStatusFailed);
1223 return false;
1224
1225 }
1226
Jim Inghamc8332952010-08-26 21:32:51 +00001227 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001228 Error error (process->Resume ());
1229 if (error.Success())
1230 {
Greg Claytonc1d37752010-10-18 01:45:30 +00001231 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001232 if (synchronous_execution)
1233 {
1234 StateType state = process->WaitForProcessToStop (NULL);
1235
1236 result.SetDidChangeProcessState (true);
1237 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1238 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1239 }
1240 else
1241 {
1242 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1243 }
1244 }
1245 else
1246 {
1247 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1248 result.SetStatus (eReturnStatusFailed);
1249 }
1250
1251 }
1252 return result.Succeeded();
1253 }
1254protected:
1255 CommandOptions m_options;
1256
1257};
1258
Greg Claytonb3448432011-03-24 21:19:54 +00001259OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001260CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1261{
Caroline Tice43b014a2010-10-04 22:28:36 +00001262{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
Caroline Tice4d6675c2010-10-01 19:59:14 +00001263{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1264{ LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
1265{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001266};
1267
1268
1269//-------------------------------------------------------------------------
1270// CommandObjectThreadSelect
1271//-------------------------------------------------------------------------
1272
1273class CommandObjectThreadSelect : public CommandObject
1274{
1275public:
1276
Greg Clayton238c0a12010-09-18 01:14:36 +00001277 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1278 CommandObject (interpreter,
1279 "thread select",
1280 "Select a thread as the currently active thread.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001281 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001282 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001283 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001284 CommandArgumentEntry arg;
1285 CommandArgumentData thread_idx_arg;
1286
1287 // Define the first (and only) variant of this arg.
1288 thread_idx_arg.arg_type = eArgTypeThreadIndex;
1289 thread_idx_arg.arg_repetition = eArgRepeatPlain;
1290
1291 // There is only one variant this argument could be; put it into the argument entry.
1292 arg.push_back (thread_idx_arg);
1293
1294 // Push the data for the first argument into the m_arguments vector.
1295 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001296 }
1297
1298
1299 virtual
1300 ~CommandObjectThreadSelect ()
1301 {
1302 }
1303
1304 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001305 Execute
1306 (
Greg Clayton63094e02010-06-23 01:19:29 +00001307 Args& command,
1308 CommandReturnObject &result
1309 )
Chris Lattner24943d22010-06-08 16:52:24 +00001310 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001311 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001312 if (process == NULL)
1313 {
1314 result.AppendError ("no process");
1315 result.SetStatus (eReturnStatusFailed);
1316 return false;
1317 }
1318 else if (command.GetArgumentCount() != 1)
1319 {
1320 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1321 result.SetStatus (eReturnStatusFailed);
1322 return false;
1323 }
1324
1325 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1326
1327 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1328 if (new_thread == NULL)
1329 {
1330 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1331 result.SetStatus (eReturnStatusFailed);
1332 return false;
1333 }
1334
Jim Inghamc8332952010-08-26 21:32:51 +00001335 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001336 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001337
Greg Clayton238c0a12010-09-18 01:14:36 +00001338 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001339 result.GetOutputStream(),
1340 new_thread,
1341 false,
1342 true);
1343
1344 return result.Succeeded();
1345 }
1346
1347};
1348
1349
1350//-------------------------------------------------------------------------
1351// CommandObjectThreadList
1352//-------------------------------------------------------------------------
1353
Greg Clayton63094e02010-06-23 01:19:29 +00001354class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001355{
Greg Clayton63094e02010-06-23 01:19:29 +00001356public:
Chris Lattner24943d22010-06-08 16:52:24 +00001357
Chris Lattner24943d22010-06-08 16:52:24 +00001358
Greg Clayton238c0a12010-09-18 01:14:36 +00001359 CommandObjectThreadList (CommandInterpreter &interpreter):
1360 CommandObject (interpreter,
1361 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001362 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001363 "thread list",
1364 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001365 {
Greg Clayton63094e02010-06-23 01:19:29 +00001366 }
Chris Lattner24943d22010-06-08 16:52:24 +00001367
Greg Clayton63094e02010-06-23 01:19:29 +00001368 ~CommandObjectThreadList()
1369 {
1370 }
1371
1372 bool
1373 Execute
1374 (
Greg Clayton63094e02010-06-23 01:19:29 +00001375 Args& command,
1376 CommandReturnObject &result
1377 )
1378 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00001379 Stream &strm = result.GetOutputStream();
Greg Clayton63094e02010-06-23 01:19:29 +00001380 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001381 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001382 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001383 {
Greg Clayton63094e02010-06-23 01:19:29 +00001384 const StateType state = exe_ctx.process->GetState();
1385
1386 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001387 {
Greg Clayton63094e02010-06-23 01:19:29 +00001388 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001389 {
Greg Clayton63094e02010-06-23 01:19:29 +00001390 int exit_status = exe_ctx.process->GetExitStatus();
1391 const char *exit_description = exe_ctx.process->GetExitDescription();
1392 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1393 exe_ctx.process->GetID(),
1394 exit_status,
1395 exit_status,
1396 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001397 }
1398 else
1399 {
Greg Clayton63094e02010-06-23 01:19:29 +00001400 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1401 if (exe_ctx.thread == NULL)
1402 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1403 if (exe_ctx.thread != NULL)
1404 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001405 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001406 }
1407 else
1408 {
1409 result.AppendError ("no valid thread found in current process");
1410 result.SetStatus (eReturnStatusFailed);
1411 }
Chris Lattner24943d22010-06-08 16:52:24 +00001412 }
1413 }
Greg Clayton63094e02010-06-23 01:19:29 +00001414 else
1415 {
1416 result.AppendError ("process is currently running");
1417 result.SetStatus (eReturnStatusFailed);
1418 }
Chris Lattner24943d22010-06-08 16:52:24 +00001419 }
1420 else
1421 {
Greg Clayton63094e02010-06-23 01:19:29 +00001422 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001423 result.SetStatus (eReturnStatusFailed);
1424 }
Greg Clayton63094e02010-06-23 01:19:29 +00001425 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001426 }
Greg Clayton63094e02010-06-23 01:19:29 +00001427};
Chris Lattner24943d22010-06-08 16:52:24 +00001428
1429//-------------------------------------------------------------------------
1430// CommandObjectMultiwordThread
1431//-------------------------------------------------------------------------
1432
Greg Clayton63094e02010-06-23 01:19:29 +00001433CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001434 CommandObjectMultiword (interpreter,
1435 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001436 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001437 "thread <subcommand> [<subcommand-options>]")
1438{
Greg Clayton238c0a12010-09-18 01:14:36 +00001439 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1440 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1441 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1442 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1443 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1444 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1445 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001446 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001447 "Source level single step in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001448 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001449 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1450 eStepTypeInto,
1451 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001452
Greg Clayton238c0a12010-09-18 01:14:36 +00001453 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1454 interpreter,
1455 "thread step-out",
1456 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001457 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001458 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1459 eStepTypeOut,
1460 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001461
Greg Clayton238c0a12010-09-18 01:14:36 +00001462 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1463 interpreter,
1464 "thread step-over",
1465 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001466 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001467 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1468 eStepTypeOver,
1469 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001470
Greg Clayton238c0a12010-09-18 01:14:36 +00001471 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1472 interpreter,
1473 "thread step-inst",
1474 "Single step one instruction in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001475 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001476 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1477 eStepTypeTrace,
1478 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001479
Greg Clayton238c0a12010-09-18 01:14:36 +00001480 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1481 interpreter,
1482 "thread step-inst-over",
1483 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001484 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001485 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1486 eStepTypeTraceOver,
1487 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001488}
1489
1490CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1491{
1492}
1493
1494