blob: 8c5e968a67aff69e9340d5929a320951f3527726 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Ingham40af72e2010-06-15 19:49:27 +000016#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Core/State.h"
18#include "lldb/Core/SourceManager.h"
19
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22
23#include "lldb/Target/Process.h"
24#include "lldb/Target/RegisterContext.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadPlan.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028#include "lldb/Target/ThreadPlanStepInstruction.h"
29#include "lldb/Target/ThreadPlanStepOut.h"
30#include "lldb/Target/ThreadPlanStepRange.h"
31#include "lldb/Target/ThreadPlanStepInRange.h"
32#include "lldb/Symbol/LineTable.h"
33#include "lldb/Symbol/LineEntry.h"
34
35using namespace lldb;
36using namespace lldb_private;
37
38
39bool
40lldb_private::DisplayThreadInfo
41(
Greg Clayton66111032010-06-23 01:19:29 +000042 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043 Stream &strm,
44 Thread *thread,
45 bool only_threads_with_stop_reason,
46 bool show_source
47)
48{
49 if (thread)
50 {
51 if (only_threads_with_stop_reason)
52 {
Greg Claytonf4b47e12010-08-04 01:40:35 +000053 if (thread->GetStopInfo() == NULL)
54 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055 }
56
57 strm.Indent();
Jim Ingham2976d002010-08-26 21:32:51 +000058 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' ');
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059
60 // Show one frame with only the first showing source
61 if (show_source)
62 {
Jim Inghame40e4212010-08-30 19:44:40 +000063 bool already_shown = false;
64 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0);
65 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
66 if (interpreter.GetDebugger().UseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
67 {
68 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
69 }
70
Chris Lattner30fdc8d2010-06-08 16:52:24 +000071 DisplayFramesForExecutionContext (thread,
72 interpreter,
73 strm,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 0, // Start at first frame
75 1, // Number of frames to show
76 false,// Don't show the frame info since we already displayed most of it above...
Jim Inghame40e4212010-08-30 19:44:40 +000077 !already_shown, // Show source for the first frame
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 3, // lines of source context before
79 3); // lines of source context after
80 }
81 else
82 {
83 thread->DumpInfo (strm,
84 true, // Dump the stop reason?
85 true, // Dump the thread name?
86 true, // Dump the queue name?
87 0); // Display context info for stack frame zero
88
89 strm.EOL();
90 }
91
92 return true;
93 }
94 return false;
95}
96
97size_t
98lldb_private::DisplayThreadsInfo
99(
Greg Clayton66111032010-06-23 01:19:29 +0000100 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 ExecutionContext *exe_ctx,
102 CommandReturnObject &result,
103 bool only_threads_with_stop_reason,
104 bool show_source
105)
106{
107 StreamString strm;
108
109 size_t num_thread_infos_dumped = 0;
110
111 if (!exe_ctx->process)
112 return 0;
113
114 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
115 if (num_threads > 0)
116 {
117
118 for (uint32_t i = 0; i < num_threads; i++)
119 {
120 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
121 if (thread)
122 {
123 if (DisplayThreadInfo (interpreter,
124 strm,
125 thread,
126 only_threads_with_stop_reason,
127 show_source))
128 ++num_thread_infos_dumped;
129 }
130 }
131 }
132
133 if (num_thread_infos_dumped > 0)
134 {
135 if (num_thread_infos_dumped < num_threads)
136 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
137
138 result.GetOutputStream().GetString().append(strm.GetString());
139 result.SetStatus (eReturnStatusSuccessFinishNoResult);
140 }
141 return num_thread_infos_dumped;
142}
143
144
145size_t
146lldb_private::DisplayFramesForExecutionContext
147(
148 Thread *thread,
Greg Clayton66111032010-06-23 01:19:29 +0000149 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 Stream& strm,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 uint32_t first_frame,
152 uint32_t num_frames,
153 bool show_frame_info,
154 uint32_t num_frames_with_source,
155 uint32_t source_lines_before,
156 uint32_t source_lines_after
157)
158{
159 if (thread == NULL)
160 return 0;
161
162 size_t num_frames_displayed = 0;
163
164 if (num_frames == 0)
165 return 0;
166
167 thread->DumpInfo (strm,
168 true, // Dump the stop reason?
169 true, // Dump the thread name?
170 true, // Dump the queue name?
Greg Clayton1b72fcb2010-08-24 00:45:41 +0000171 num_frames > 1 ? UINT32_MAX : first_frame); // Dump info for the first stack frame if we are showing only on frame
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172 strm.EOL();
173 strm.IndentMore();
174
175 StackFrameSP frame_sp;
Greg Claytonc982c762010-07-09 20:39:50 +0000176 uint32_t frame_idx = 0;
Jim Inghame2e0b452010-08-26 23:36:03 +0000177 uint32_t last_frame;
178
179 // Don't let the last frame wrap around...
180 if (num_frames == UINT32_MAX)
181 last_frame = UINT32_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000182 else
Jim Inghame2e0b452010-08-26 23:36:03 +0000183 last_frame = first_frame + num_frames;
184
185 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186 {
Jim Inghame2e0b452010-08-26 23:36:03 +0000187 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
188 if (frame_sp.get() == NULL)
189 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190
Jim Inghame2e0b452010-08-26 23:36:03 +0000191 if (DisplayFrameForExecutionContext (thread,
192 frame_sp.get(),
193 interpreter,
194 strm,
195 show_frame_info,
196 num_frames_with_source > first_frame - frame_idx,
197 source_lines_before,
198 source_lines_after) == false)
199 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200
Jim Inghame2e0b452010-08-26 23:36:03 +0000201 ++num_frames_displayed;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 }
Jim Inghame2e0b452010-08-26 23:36:03 +0000203
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000204 strm.IndentLess();
205 return num_frames_displayed;
206}
207
208bool
209lldb_private::DisplayFrameForExecutionContext
210(
211 Thread *thread,
212 StackFrame *frame,
Greg Clayton66111032010-06-23 01:19:29 +0000213 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000214 Stream& strm,
215 bool show_frame_info,
216 bool show_source,
217 uint32_t source_lines_before,
218 uint32_t source_lines_after
219)
220{
221 // thread and frame must be filled in prior to calling this function
222 if (thread && frame)
223 {
224 if (show_frame_info)
225 {
226 strm.Indent();
Greg Clayton6dadd502010-09-02 21:44:10 +0000227 frame->Dump (&strm, true, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 strm.EOL();
229 }
230
231 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
232
233 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
234 {
Greg Clayton66111032010-06-23 01:19:29 +0000235 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 sc.line_entry.file,
237 sc.line_entry.line,
238 3,
239 3,
240 "->",
241 &strm);
242
243 }
244 return true;
245 }
246 return false;
247}
248
249
250//-------------------------------------------------------------------------
251// CommandObjectThreadBacktrace
252//-------------------------------------------------------------------------
253
254class CommandObjectThreadBacktrace : public CommandObject
255{
256public:
257
Jim Inghame2e0b452010-08-26 23:36:03 +0000258 class CommandOptions : public Options
259 {
260 public:
261
262 CommandOptions () :
263 Options()
264 {
265 // Keep default values of all options in one place: ResetOptionValues ()
266 ResetOptionValues ();
267 }
268
269 virtual
270 ~CommandOptions ()
271 {
272 }
273
274 virtual Error
275 SetOptionValue (int option_idx, const char *option_arg)
276 {
277 Error error;
278 char short_option = (char) m_getopt_table[option_idx].val;
279
280 switch (short_option)
281 {
282 case 'c':
283 {
284 bool success;
285 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
286 if (!success)
287 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
288 if (input_count < -1)
289 m_count = UINT32_MAX;
290 else
291 m_count = input_count;
292 }
293 break;
294 case 's':
295 {
296 bool success;
297 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
298 if (!success)
299 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
300 }
301 break;
302 default:
303 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
304 break;
305
306 }
307 return error;
308 }
309
310 void
311 ResetOptionValues ()
312 {
313 Options::ResetOptionValues();
314 m_count = -1;
315 m_start = 0;
316 }
317
318 const lldb::OptionDefinition*
319 GetDefinitions ()
320 {
321 return g_option_table;
322 }
323
324 // Options table: Required for subclasses of Options.
325
326 static lldb::OptionDefinition g_option_table[];
327
328 // Instance variables to hold the values for command options.
329 uint32_t m_count;
330 uint32_t m_start;
331 };
332
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333 CommandObjectThreadBacktrace () :
334 CommandObject ("thread backtrace",
Caroline Tice09799af2010-09-08 22:08:58 +0000335 "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.",
Jim Ingham09b263e2010-08-27 00:58:05 +0000336 "thread backtrace [<thread-index>] ...",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Inghame2e0b452010-08-26 23:36:03 +0000338 m_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000339 {
340 }
341
342 ~CommandObjectThreadBacktrace()
343 {
344 }
345
Jim Inghame2e0b452010-08-26 23:36:03 +0000346 virtual Options *
347 GetOptions ()
348 {
349 return &m_options;
350 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351
Greg Clayton66111032010-06-23 01:19:29 +0000352 virtual bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353 Execute
354 (
Greg Clayton66111032010-06-23 01:19:29 +0000355 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 CommandReturnObject &result
358 )
359 {
Jim Ingham09b263e2010-08-27 00:58:05 +0000360
361 bool show_frame_info = true;
362 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
363
364 result.SetStatus (eReturnStatusSuccessFinishResult);
365
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366 if (command.GetArgumentCount() == 0)
367 {
Greg Clayton66111032010-06-23 01:19:29 +0000368 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369 if (exe_ctx.thread)
370 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371 if (DisplayFramesForExecutionContext (exe_ctx.thread,
372 interpreter,
373 result.GetOutputStream(),
Jim Inghame2e0b452010-08-26 23:36:03 +0000374 m_options.m_start,
375 m_options.m_count,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 show_frame_info,
377 num_frames_with_source,
378 3,
379 3))
380 {
381 result.SetStatus (eReturnStatusSuccessFinishResult);
382 }
383 }
384 else
385 {
386 result.AppendError ("invalid thread");
387 result.SetStatus (eReturnStatusFailed);
388 }
389 }
Jim Ingham09b263e2010-08-27 00:58:05 +0000390 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
391 {
392 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
393 uint32_t num_threads = process->GetThreadList().GetSize();
394 for (uint32_t i = 0; i < num_threads; i++)
395 {
396 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
397 if (!DisplayFramesForExecutionContext (thread_sp.get(),
398 interpreter,
399 result.GetOutputStream(),
400 m_options.m_start,
401 m_options.m_count,
402 show_frame_info,
403 num_frames_with_source,
404 3,
405 3))
406 {
Greg Clayton1346f7e2010-09-03 22:45:01 +0000407 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Ingham09b263e2010-08-27 00:58:05 +0000408 result.SetStatus (eReturnStatusFailed);
409 return false;
410 }
411 if (i < num_threads - 1)
412 result.AppendMessage("");
413 }
414 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415 else
416 {
Jim Ingham09b263e2010-08-27 00:58:05 +0000417 uint32_t num_args = command.GetArgumentCount();
418 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
419 std::vector<ThreadSP> thread_sps;
420
421 for (uint32_t i = 0; i < num_args; i++)
422 {
423 bool success;
424
425 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
426 if (!success)
427 {
428 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
429 result.SetStatus (eReturnStatusFailed);
430 return false;
431 }
432
433 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
434
435 if (!thread_sps[i])
436 {
437 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
438 result.SetStatus (eReturnStatusFailed);
439 return false;
440 }
441
442 }
443
444 for (uint32_t i = 0; i < num_args; i++)
445 {
446 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
447 interpreter,
448 result.GetOutputStream(),
449 m_options.m_start,
450 m_options.m_count,
451 show_frame_info,
452 num_frames_with_source,
453 3,
454 3))
455 {
456 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
457 result.SetStatus (eReturnStatusFailed);
458 return false;
459 }
460
461 if (i < num_args - 1)
462 result.AppendMessage("");
463 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000464 }
465 return result.Succeeded();
466 }
467protected:
Jim Inghame2e0b452010-08-26 23:36:03 +0000468 CommandOptions m_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000469};
470
Jim Inghame2e0b452010-08-26 23:36:03 +0000471lldb::OptionDefinition
472CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
473{
474{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, "<count>", "How many frames to display (-1 for all)"},
Caroline Tice09799af2010-09-08 22:08:58 +0000475{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, "<start>", "Frame in which to start the backtrace"},
Jim Inghame2e0b452010-08-26 23:36:03 +0000476{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
477};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000478
Greg Clayton69b518f2010-07-07 17:07:17 +0000479enum StepScope
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480{
481 eStepScopeSource,
482 eStepScopeInstruction
483};
484
485class CommandObjectThreadStepWithTypeAndScope : public CommandObject
486{
487public:
488
489 class CommandOptions : public Options
490 {
491 public:
492
493 CommandOptions () :
494 Options()
495 {
496 // Keep default values of all options in one place: ResetOptionValues ()
497 ResetOptionValues ();
498 }
499
500 virtual
501 ~CommandOptions ()
502 {
503 }
504
505 virtual Error
506 SetOptionValue (int option_idx, const char *option_arg)
507 {
508 Error error;
509 char short_option = (char) m_getopt_table[option_idx].val;
510
511 switch (short_option)
512 {
513 case 'a':
514 {
515 bool success;
516 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
517 if (!success)
518 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
519 }
520 break;
521 case 'm':
522 {
523 bool found_one = false;
524 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
525 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
526 if (!found_one)
527 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
528 }
529 break;
Jim Inghama56c8002010-07-10 02:27:39 +0000530 case 'r':
531 {
532 m_avoid_regexp.clear();
533 m_avoid_regexp.assign(option_arg);
534 }
535 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000536 default:
537 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
538 break;
539
540 }
541 return error;
542 }
543
544 void
545 ResetOptionValues ()
546 {
547 Options::ResetOptionValues();
548 m_avoid_no_debug = true;
549 m_run_mode = eOnlyDuringStepping;
Jim Inghama56c8002010-07-10 02:27:39 +0000550 m_avoid_regexp.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 }
552
553 const lldb::OptionDefinition*
554 GetDefinitions ()
555 {
556 return g_option_table;
557 }
558
559 // Options table: Required for subclasses of Options.
560
561 static lldb::OptionDefinition g_option_table[];
562
563 // Instance variables to hold the values for command options.
564 bool m_avoid_no_debug;
565 RunMode m_run_mode;
Jim Inghama56c8002010-07-10 02:27:39 +0000566 std::string m_avoid_regexp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000567 };
568
569 CommandObjectThreadStepWithTypeAndScope (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 (name, help, syntax, flags),
576 m_step_type (step_type),
577 m_step_scope (step_scope),
578 m_options ()
579 {
580 }
581
582 virtual
583 ~CommandObjectThreadStepWithTypeAndScope ()
584 {
585 }
586
587 virtual
588 Options *
589 GetOptions ()
590 {
591 return &m_options;
592 }
593
594 virtual bool
Greg Clayton66111032010-06-23 01:19:29 +0000595 Execute
596 (
597 CommandInterpreter &interpreter,
598 Args& command,
599 CommandReturnObject &result
600 )
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601 {
Greg Clayton66111032010-06-23 01:19:29 +0000602 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
603 bool synchronous_execution = interpreter.GetSynchronous();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000604
605 if (process == NULL)
606 {
607 result.AppendError ("need a valid process to step");
608 result.SetStatus (eReturnStatusFailed);
609
610 }
611 else
612 {
613 const uint32_t num_threads = process->GetThreadList().GetSize();
614 Thread *thread = NULL;
615
616 if (command.GetArgumentCount() == 0)
617 {
Jim Ingham2976d002010-08-26 21:32:51 +0000618 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000619 if (thread == NULL)
620 {
Jim Inghame2e0b452010-08-26 23:36:03 +0000621 result.AppendError ("no selected thread in process");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000622 result.SetStatus (eReturnStatusFailed);
623 return false;
624 }
625 }
626 else
627 {
628 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
629 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
630 if (step_thread_idx == LLDB_INVALID_INDEX32)
631 {
632 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
633 result.SetStatus (eReturnStatusFailed);
634 return false;
635 }
636 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
637 if (thread == NULL)
638 {
639 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
640 step_thread_idx, 0, num_threads);
641 result.SetStatus (eReturnStatusFailed);
642 return false;
643 }
644 }
645
646 const bool abort_other_plans = false;
647 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
648
649 // This is a bit unfortunate, but not all the commands in this command object support
650 // only while stepping, so I use the bool for them.
651 bool bool_stop_other_threads;
652 if (m_options.m_run_mode == eAllThreads)
653 bool_stop_other_threads = false;
654 else
655 bool_stop_other_threads = true;
656
657 if (m_step_type == eStepTypeInto)
658 {
659 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
660 ThreadPlan *new_plan;
661
662 if (frame->HasDebugInformation ())
663 {
664 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
665 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
666 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton474966a2010-06-12 18:59:55 +0000667 stop_other_threads,
668 m_options.m_avoid_no_debug);
Jim Inghama56c8002010-07-10 02:27:39 +0000669 if (new_plan && !m_options.m_avoid_regexp.empty())
670 {
671 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
672 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
673 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000674 }
675 else
676 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
677
Jim Ingham2976d002010-08-26 21:32:51 +0000678 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000679 process->Resume ();
680 }
681 else if (m_step_type == eStepTypeOver)
682 {
683 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
684 ThreadPlan *new_plan;
685
686 if (frame->HasDebugInformation())
687 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
688 m_step_type,
689 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
690 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton474966a2010-06-12 18:59:55 +0000691 stop_other_threads,
692 false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 else
694 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
695 abort_other_plans,
696 bool_stop_other_threads);
697
698 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
699 // Maybe there should be a parameter to control this.
700 new_plan->SetOkayToDiscard(false);
701
Jim Ingham2976d002010-08-26 21:32:51 +0000702 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000703 process->Resume ();
704 }
705 else if (m_step_type == eStepTypeTrace)
706 {
707 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Ingham2976d002010-08-26 21:32:51 +0000708 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000709 process->Resume ();
710 }
711 else if (m_step_type == eStepTypeTraceOver)
712 {
713 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Ingham2976d002010-08-26 21:32:51 +0000714 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000715 process->Resume ();
716 }
717 else if (m_step_type == eStepTypeOut)
718 {
719 ThreadPlan *new_plan;
720
721 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
722 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
723 // Maybe there should be a parameter to control this.
724 new_plan->SetOkayToDiscard(false);
725
Jim Ingham2976d002010-08-26 21:32:51 +0000726 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000727 process->Resume ();
728 }
729 else
730 {
731 result.AppendError ("step type is not supported");
732 result.SetStatus (eReturnStatusFailed);
733 }
734 if (synchronous_execution)
735 {
736 StateType state = process->WaitForProcessToStop (NULL);
737
738 //EventSP event_sp;
739 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
740 //while (! StateIsStoppedState (state))
741 // {
742 // state = process->WaitForStateChangedEvents (NULL, event_sp);
743 // }
Jim Ingham2976d002010-08-26 21:32:51 +0000744 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000745 result.SetDidChangeProcessState (true);
746 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
747 result.SetStatus (eReturnStatusSuccessFinishNoResult);
748 }
749 }
750 return result.Succeeded();
751 }
752
753protected:
754 StepType m_step_type;
755 StepScope m_step_scope;
756 CommandOptions m_options;
757};
758
759static lldb::OptionEnumValueElement
760g_tri_running_mode[] =
761{
762{ eOnlyThisThread, "thisThread", "Run only this thread"},
763{ eAllThreads, "allThreads", "Run all threads"},
764{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
765{ 0, NULL, NULL }
766};
767
768static lldb::OptionEnumValueElement
769g_duo_running_mode[] =
770{
771{ eOnlyThisThread, "thisThread", "Run only this thread"},
772{ eAllThreads, "allThreads", "Run all threads"},
773{ 0, NULL, NULL }
774};
775
776lldb::OptionDefinition
777CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
778{
Greg Clayton0c5cd902010-06-28 21:30:43 +0000779{ LLDB_OPT_SET_1, false, "avoid_no_debug", 'a', required_argument, NULL, 0, "<avoid_no_debug>", "Should step-in step over functions with no debug information"},
780{ LLDB_OPT_SET_1, false, "run_mode", 'm', required_argument, g_tri_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"},
Jim Inghama56c8002010-07-10 02:27:39 +0000781{ LLDB_OPT_SET_1, false, "regexp_to_avoid",'r', required_argument, NULL, 0, "<avoid_regexp>", "Should step-in step over functions matching this regexp"},
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000782{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
783};
784
785
786//-------------------------------------------------------------------------
787// CommandObjectThreadContinue
788//-------------------------------------------------------------------------
789
790class CommandObjectThreadContinue : public CommandObject
791{
792public:
793
794 CommandObjectThreadContinue () :
795 CommandObject ("thread continue",
Caroline Ticee3d26312010-09-08 21:06:11 +0000796 "Continue execution of one or more threads in an active process.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797 "thread continue <thread-index> [<thread-index> ...]",
798 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
799 {
800 }
801
802
803 virtual
804 ~CommandObjectThreadContinue ()
805 {
806 }
807
808 virtual bool
Greg Clayton66111032010-06-23 01:19:29 +0000809 Execute
810 (
811 CommandInterpreter &interpreter,
812 Args& command,
813 CommandReturnObject &result
814 )
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000815 {
Greg Clayton66111032010-06-23 01:19:29 +0000816 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000817
Jim Ingham2976d002010-08-26 21:32:51 +0000818 if (!interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000819 {
820 result.AppendError ("invalid target, set executable file using 'file' command");
821 result.SetStatus (eReturnStatusFailed);
822 return false;
823 }
824
Greg Clayton66111032010-06-23 01:19:29 +0000825 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826 if (process == NULL)
827 {
828 result.AppendError ("no process exists. Cannot continue");
829 result.SetStatus (eReturnStatusFailed);
830 return false;
831 }
832
833 StateType state = process->GetState();
834 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
835 {
836 const uint32_t num_threads = process->GetThreadList().GetSize();
837 uint32_t idx;
838 const size_t argc = command.GetArgumentCount();
839 if (argc > 0)
840 {
841 std::vector<uint32_t> resume_thread_indexes;
842 for (uint32_t i=0; i<argc; ++i)
843 {
844 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
845 if (idx < num_threads)
846 resume_thread_indexes.push_back(idx);
847 else
848 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
849 }
850
851 if (resume_thread_indexes.empty())
852 {
853 result.AppendError ("no valid thread indexes were specified");
854 result.SetStatus (eReturnStatusFailed);
855 return false;
856 }
857 else
858 {
859 result.AppendMessage ("Resuming thread ");
860 for (idx=0; idx<num_threads; ++idx)
861 {
862 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
863 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
864 {
865 result.AppendMessageWithFormat ("%u ", idx);
866 thread->SetResumeState (eStateRunning);
867 }
868 else
869 {
870 thread->SetResumeState (eStateSuspended);
871 }
872 }
873 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
874 }
875 }
876 else
877 {
Jim Ingham2976d002010-08-26 21:32:51 +0000878 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000879 if (current_thread == NULL)
880 {
881 result.AppendError ("the process doesn't have a current thread");
882 result.SetStatus (eReturnStatusFailed);
883 return false;
884 }
885 // Set the actions that the threads should each take when resuming
886 for (idx=0; idx<num_threads; ++idx)
887 {
888 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
889 if (thread == current_thread)
890 {
891 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
892 thread->SetResumeState (eStateRunning);
893 }
894 else
895 {
896 thread->SetResumeState (eStateSuspended);
897 }
898 }
899 }
900
901 Error error (process->Resume());
902 if (error.Success())
903 {
904 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
905 if (synchronous_execution)
906 {
Greg Claytonb1320972010-07-14 00:18:15 +0000907 state = process->WaitForProcessToStop (NULL);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000908
909 result.SetDidChangeProcessState (true);
910 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
911 result.SetStatus (eReturnStatusSuccessFinishNoResult);
912 }
913 else
914 {
915 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
916 }
917 }
918 else
919 {
920 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
921 result.SetStatus (eReturnStatusFailed);
922 }
923 }
924 else
925 {
926 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
927 StateAsCString(state));
928 result.SetStatus (eReturnStatusFailed);
929 }
930
931 return result.Succeeded();
932 }
933
934};
935
936//-------------------------------------------------------------------------
937// CommandObjectThreadUntil
938//-------------------------------------------------------------------------
939
940class CommandObjectThreadUntil : public CommandObject
941{
942public:
943
944 class CommandOptions : public Options
945 {
946 public:
947 uint32_t m_thread_idx;
948 uint32_t m_frame_idx;
949
950 CommandOptions () :
951 Options(),
952 m_thread_idx(LLDB_INVALID_THREAD_ID),
953 m_frame_idx(LLDB_INVALID_FRAME_ID)
954 {
955 // Keep default values of all options in one place: ResetOptionValues ()
956 ResetOptionValues ();
957 }
958
959 virtual
960 ~CommandOptions ()
961 {
962 }
963
964 virtual Error
965 SetOptionValue (int option_idx, const char *option_arg)
966 {
967 Error error;
968 char short_option = (char) m_getopt_table[option_idx].val;
969
970 switch (short_option)
971 {
972 case 't':
973 {
Greg Claytonb1320972010-07-14 00:18:15 +0000974 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000975 if (m_thread_idx == LLDB_INVALID_INDEX32)
976 {
977 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
978 }
979 }
980 break;
981 case 'f':
982 {
983 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
984 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
985 {
986 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
987 }
988 }
989 break;
990 case 'm':
991 {
992 bool found_one = false;
993 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
994 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
995
996 if (!found_one)
997 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
998 else if (run_mode == eAllThreads)
999 m_stop_others = false;
1000 else
1001 m_stop_others = true;
1002
1003 }
1004 break;
1005 default:
1006 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1007 break;
1008
1009 }
1010 return error;
1011 }
1012
1013 void
1014 ResetOptionValues ()
1015 {
1016 Options::ResetOptionValues();
1017 m_thread_idx = LLDB_INVALID_THREAD_ID;
1018 m_frame_idx = 0;
1019 m_stop_others = false;
1020 }
1021
1022 const lldb::OptionDefinition*
1023 GetDefinitions ()
1024 {
1025 return g_option_table;
1026 }
1027
1028 uint32_t m_step_thread_idx;
1029 bool m_stop_others;
1030
1031 // Options table: Required for subclasses of Options.
1032
1033 static lldb::OptionDefinition g_option_table[];
1034
1035 // Instance variables to hold the values for command options.
1036 };
1037
1038 CommandObjectThreadUntil () :
1039 CommandObject ("thread until",
Caroline Ticee3d26312010-09-08 21:06:11 +00001040 "Run the current or specified thread until it reaches a given line number or leaves the current function.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001041 "thread until [<cmd-options>] <line-number>",
1042 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1043 m_options ()
1044 {
1045 }
1046
1047
1048 virtual
1049 ~CommandObjectThreadUntil ()
1050 {
1051 }
1052
1053 virtual
1054 Options *
1055 GetOptions ()
1056 {
1057 return &m_options;
1058 }
1059
1060 virtual bool
Greg Clayton66111032010-06-23 01:19:29 +00001061 Execute
1062 (
1063 CommandInterpreter &interpreter,
1064 Args& command,
1065 CommandReturnObject &result
1066 )
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001067 {
Greg Clayton66111032010-06-23 01:19:29 +00001068 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001069
Greg Claytonf5e56de2010-09-14 23:36:40 +00001070 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
1071 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001072 {
1073 result.AppendError ("invalid target, set executable file using 'file' command");
1074 result.SetStatus (eReturnStatusFailed);
1075 return false;
1076 }
1077
Greg Clayton66111032010-06-23 01:19:29 +00001078 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001079 if (process == NULL)
1080 {
1081 result.AppendError ("need a valid process to step");
1082 result.SetStatus (eReturnStatusFailed);
1083
1084 }
1085 else
1086 {
1087 Thread *thread = NULL;
1088 uint32_t line_number;
1089
1090 if (command.GetArgumentCount() != 1)
1091 {
1092 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1093 result.SetStatus (eReturnStatusFailed);
1094 return false;
1095 }
1096
1097 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1098 if (line_number == UINT32_MAX)
1099 {
1100 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1101 result.SetStatus (eReturnStatusFailed);
1102 return false;
1103 }
1104
1105 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1106 {
Jim Ingham2976d002010-08-26 21:32:51 +00001107 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001108 }
1109 else
1110 {
1111 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1112 }
1113
1114 if (thread == NULL)
1115 {
1116 const uint32_t num_threads = process->GetThreadList().GetSize();
1117 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1118 result.SetStatus (eReturnStatusFailed);
1119 return false;
1120 }
1121
1122 const bool abort_other_plans = true;
1123
1124 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1125 if (frame == NULL)
1126 {
1127
1128 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1129 result.SetStatus (eReturnStatusFailed);
1130 return false;
1131 }
1132
1133 ThreadPlan *new_plan;
1134
1135 if (frame->HasDebugInformation ())
1136 {
1137 // Finally we got here... Translate the given line number to a bunch of addresses:
1138 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1139 LineTable *line_table = NULL;
1140 if (sc.comp_unit)
1141 line_table = sc.comp_unit->GetLineTable();
1142
1143 if (line_table == NULL)
1144 {
1145 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1146 m_options.m_frame_idx, m_options.m_thread_idx);
1147 result.SetStatus (eReturnStatusFailed);
1148 return false;
1149 }
1150
1151 LineEntry function_start;
1152 uint32_t index_ptr = 0, end_ptr;
1153 std::vector<addr_t> address_list;
1154
1155 // Find the beginning & end index of the
1156 AddressRange fun_addr_range = sc.function->GetAddressRange();
1157 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1158 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1159
1160 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1161 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1162
1163 while (index_ptr <= end_ptr)
1164 {
1165 LineEntry line_entry;
1166 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1167 if (index_ptr == UINT32_MAX)
1168 break;
1169
Greg Claytonf5e56de2010-09-14 23:36:40 +00001170 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001171 if (address != LLDB_INVALID_ADDRESS)
1172 address_list.push_back (address);
1173 index_ptr++;
1174 }
1175
Greg Clayton471b31c2010-07-20 22:52:08 +00001176 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001177 new_plan->SetOkayToDiscard(false);
1178 }
1179 else
1180 {
1181 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1182 result.SetStatus (eReturnStatusFailed);
1183 return false;
1184
1185 }
1186
Jim Ingham2976d002010-08-26 21:32:51 +00001187 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001188 Error error (process->Resume ());
1189 if (error.Success())
1190 {
1191 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1192 if (synchronous_execution)
1193 {
1194 StateType state = process->WaitForProcessToStop (NULL);
1195
1196 result.SetDidChangeProcessState (true);
1197 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1198 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1199 }
1200 else
1201 {
1202 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1203 }
1204 }
1205 else
1206 {
1207 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1208 result.SetStatus (eReturnStatusFailed);
1209 }
1210
1211 }
1212 return result.Succeeded();
1213 }
1214protected:
1215 CommandOptions m_options;
1216
1217};
1218
1219lldb::OptionDefinition
1220CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1221{
Greg Clayton0c5cd902010-06-28 21:30:43 +00001222{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
1223{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
1224{ LLDB_OPT_SET_1, false, "run_mode",'m', required_argument, g_duo_running_mode, 0, "<run_mode>","Determine how to run other threads while stepping this one"},
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001225{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1226};
1227
1228
1229//-------------------------------------------------------------------------
1230// CommandObjectThreadSelect
1231//-------------------------------------------------------------------------
1232
1233class CommandObjectThreadSelect : public CommandObject
1234{
1235public:
1236
1237 CommandObjectThreadSelect () :
1238 CommandObject ("thread select",
Caroline Tice09799af2010-09-08 22:08:58 +00001239 "Select a thread as the currently active thread.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001240 "thread select <thread-index>",
1241 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1242 {
1243 }
1244
1245
1246 virtual
1247 ~CommandObjectThreadSelect ()
1248 {
1249 }
1250
1251 virtual bool
Greg Clayton66111032010-06-23 01:19:29 +00001252 Execute
1253 (
1254 CommandInterpreter &interpreter,
1255 Args& command,
1256 CommandReturnObject &result
1257 )
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001258 {
Greg Clayton66111032010-06-23 01:19:29 +00001259 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001260 if (process == NULL)
1261 {
1262 result.AppendError ("no process");
1263 result.SetStatus (eReturnStatusFailed);
1264 return false;
1265 }
1266 else if (command.GetArgumentCount() != 1)
1267 {
1268 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1269 result.SetStatus (eReturnStatusFailed);
1270 return false;
1271 }
1272
1273 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1274
1275 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1276 if (new_thread == NULL)
1277 {
1278 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1279 result.SetStatus (eReturnStatusFailed);
1280 return false;
1281 }
1282
Jim Ingham2976d002010-08-26 21:32:51 +00001283 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chenc13ee522010-09-14 00:53:53 +00001284 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001285
1286 DisplayThreadInfo (interpreter,
1287 result.GetOutputStream(),
1288 new_thread,
1289 false,
1290 true);
1291
1292 return result.Succeeded();
1293 }
1294
1295};
1296
1297
1298//-------------------------------------------------------------------------
1299// CommandObjectThreadList
1300//-------------------------------------------------------------------------
1301
Greg Clayton66111032010-06-23 01:19:29 +00001302class CommandObjectThreadList : public CommandObject
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001303{
Greg Clayton66111032010-06-23 01:19:29 +00001304public:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001305
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001306
Greg Clayton66111032010-06-23 01:19:29 +00001307 CommandObjectThreadList ():
1308 CommandObject ("thread list",
Caroline Ticee3d26312010-09-08 21:06:11 +00001309 "Show a summary of all current threads in a process.",
Greg Clayton66111032010-06-23 01:19:29 +00001310 "thread list",
1311 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001312 {
Greg Clayton66111032010-06-23 01:19:29 +00001313 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001314
Greg Clayton66111032010-06-23 01:19:29 +00001315 ~CommandObjectThreadList()
1316 {
1317 }
1318
1319 bool
1320 Execute
1321 (
1322 CommandInterpreter &interpreter,
1323 Args& command,
1324 CommandReturnObject &result
1325 )
1326 {
1327 StreamString &strm = result.GetOutputStream();
1328 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1329 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
1330 if (exe_ctx.process)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001331 {
Greg Clayton66111032010-06-23 01:19:29 +00001332 const StateType state = exe_ctx.process->GetState();
1333
1334 if (StateIsStoppedState(state))
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001335 {
Greg Clayton66111032010-06-23 01:19:29 +00001336 if (state == eStateExited)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001337 {
Greg Clayton66111032010-06-23 01:19:29 +00001338 int exit_status = exe_ctx.process->GetExitStatus();
1339 const char *exit_description = exe_ctx.process->GetExitDescription();
1340 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1341 exe_ctx.process->GetID(),
1342 exit_status,
1343 exit_status,
1344 exit_description ? exit_description : "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001345 }
1346 else
1347 {
Greg Clayton66111032010-06-23 01:19:29 +00001348 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1349 if (exe_ctx.thread == NULL)
1350 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1351 if (exe_ctx.thread != NULL)
1352 {
1353 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1354 }
1355 else
1356 {
1357 result.AppendError ("no valid thread found in current process");
1358 result.SetStatus (eReturnStatusFailed);
1359 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001360 }
1361 }
Greg Clayton66111032010-06-23 01:19:29 +00001362 else
1363 {
1364 result.AppendError ("process is currently running");
1365 result.SetStatus (eReturnStatusFailed);
1366 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001367 }
1368 else
1369 {
Greg Clayton66111032010-06-23 01:19:29 +00001370 result.AppendError ("no current location or status available");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001371 result.SetStatus (eReturnStatusFailed);
1372 }
Greg Clayton66111032010-06-23 01:19:29 +00001373 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001374 }
Greg Clayton66111032010-06-23 01:19:29 +00001375};
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001376
1377//-------------------------------------------------------------------------
1378// CommandObjectMultiwordThread
1379//-------------------------------------------------------------------------
1380
Greg Clayton66111032010-06-23 01:19:29 +00001381CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382 CommandObjectMultiword ("thread",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001383 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001384 "thread <subcommand> [<subcommand-options>]")
1385{
Greg Clayton66111032010-06-23 01:19:29 +00001386 LoadSubCommand (interpreter, "backtrace", CommandObjectSP (new CommandObjectThreadBacktrace ()));
1387 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectThreadContinue ()));
1388 LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectThreadList ()));
1389 LoadSubCommand (interpreter, "select", CommandObjectSP (new CommandObjectThreadSelect ()));
1390 LoadSubCommand (interpreter, "until", CommandObjectSP (new CommandObjectThreadUntil ()));
1391 LoadSubCommand (interpreter, "step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1392 "thread step-in",
Caroline Tice09799af2010-09-08 22:08:58 +00001393 "Source level single step in specified thread (current thread, if none specified).",
Greg Clayton66111032010-06-23 01:19:29 +00001394 "thread step-in [<thread-id>]",
1395 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1396 eStepTypeInto,
1397 eStepScopeSource)));
1398
1399 LoadSubCommand (interpreter, "step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
Caroline Tice09799af2010-09-08 22:08:58 +00001400 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001401 "thread step-out [<thread-id>]",
1402 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1403 eStepTypeOut,
Greg Clayton66111032010-06-23 01:19:29 +00001404 eStepScopeSource)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001405
Greg Clayton66111032010-06-23 01:19:29 +00001406 LoadSubCommand (interpreter, "step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
Caroline Tice09799af2010-09-08 22:08:58 +00001407 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001408 "thread step-over [<thread-id>]",
1409 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1410 eStepTypeOver,
Greg Clayton66111032010-06-23 01:19:29 +00001411 eStepScopeSource)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001412
Greg Clayton66111032010-06-23 01:19:29 +00001413 LoadSubCommand (interpreter, "step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001414 "Single step one instruction in specified thread (current thread, if none specified).",
1415 "thread step-inst [<thread-id>]",
1416 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1417 eStepTypeTrace,
Greg Clayton66111032010-06-23 01:19:29 +00001418 eStepScopeInstruction)));
1419
1420 LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001421 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1422 "thread step-inst-over [<thread-id>]",
1423 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1424 eStepTypeTraceOver,
Greg Clayton66111032010-06-23 01:19:29 +00001425 eStepScopeInstruction)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001426}
1427
1428CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1429{
1430}
1431
1432