blob: 1ed9794663fab7b8da81cbc5c550a913deb1c8a2 [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
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 Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +000042 CommandInterpreter &interpreter,
Chris Lattner24943d22010-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 Clayton643ee732010-08-04 01:40:35 +000053 if (thread->GetStopInfo() == NULL)
54 return false;
Chris Lattner24943d22010-06-08 16:52:24 +000055 }
56
57 strm.Indent();
Jim Inghamc8332952010-08-26 21:32:51 +000058 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' ');
Chris Lattner24943d22010-06-08 16:52:24 +000059
60 // Show one frame with only the first showing source
61 if (show_source)
62 {
63 DisplayFramesForExecutionContext (thread,
64 interpreter,
65 strm,
Chris Lattner24943d22010-06-08 16:52:24 +000066 0, // Start at first frame
67 1, // Number of frames to show
68 false,// Don't show the frame info since we already displayed most of it above...
69 1, // Show source for the first frame
70 3, // lines of source context before
71 3); // lines of source context after
72 }
73 else
74 {
75 thread->DumpInfo (strm,
76 true, // Dump the stop reason?
77 true, // Dump the thread name?
78 true, // Dump the queue name?
79 0); // Display context info for stack frame zero
80
81 strm.EOL();
82 }
83
84 return true;
85 }
86 return false;
87}
88
89size_t
90lldb_private::DisplayThreadsInfo
91(
Greg Clayton63094e02010-06-23 01:19:29 +000092 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000093 ExecutionContext *exe_ctx,
94 CommandReturnObject &result,
95 bool only_threads_with_stop_reason,
96 bool show_source
97)
98{
99 StreamString strm;
100
101 size_t num_thread_infos_dumped = 0;
102
103 if (!exe_ctx->process)
104 return 0;
105
106 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
107 if (num_threads > 0)
108 {
109
110 for (uint32_t i = 0; i < num_threads; i++)
111 {
112 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
113 if (thread)
114 {
115 if (DisplayThreadInfo (interpreter,
116 strm,
117 thread,
118 only_threads_with_stop_reason,
119 show_source))
120 ++num_thread_infos_dumped;
121 }
122 }
123 }
124
125 if (num_thread_infos_dumped > 0)
126 {
127 if (num_thread_infos_dumped < num_threads)
128 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
129
130 result.GetOutputStream().GetString().append(strm.GetString());
131 result.SetStatus (eReturnStatusSuccessFinishNoResult);
132 }
133 return num_thread_infos_dumped;
134}
135
136
137size_t
138lldb_private::DisplayFramesForExecutionContext
139(
140 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000141 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000142 Stream& strm,
Chris Lattner24943d22010-06-08 16:52:24 +0000143 uint32_t first_frame,
144 uint32_t num_frames,
145 bool show_frame_info,
146 uint32_t num_frames_with_source,
147 uint32_t source_lines_before,
148 uint32_t source_lines_after
149)
150{
151 if (thread == NULL)
152 return 0;
153
154 size_t num_frames_displayed = 0;
155
156 if (num_frames == 0)
157 return 0;
158
159 thread->DumpInfo (strm,
160 true, // Dump the stop reason?
161 true, // Dump the thread name?
162 true, // Dump the queue name?
Greg Clayton33ed1702010-08-24 00:45:41 +0000163 num_frames > 1 ? UINT32_MAX : first_frame); // Dump info for the first stack frame if we are showing only on frame
Chris Lattner24943d22010-06-08 16:52:24 +0000164 strm.EOL();
165 strm.IndentMore();
166
167 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000168 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-08-26 23:36:03 +0000169 uint32_t last_frame;
170
171 // Don't let the last frame wrap around...
172 if (num_frames == UINT32_MAX)
173 last_frame = UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +0000174 else
Jim Ingham8ab1a802010-08-26 23:36:03 +0000175 last_frame = first_frame + num_frames;
176
177 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000178 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000179 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
180 if (frame_sp.get() == NULL)
181 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000182
Jim Ingham8ab1a802010-08-26 23:36:03 +0000183 if (DisplayFrameForExecutionContext (thread,
184 frame_sp.get(),
185 interpreter,
186 strm,
187 show_frame_info,
188 num_frames_with_source > first_frame - frame_idx,
189 source_lines_before,
190 source_lines_after) == false)
191 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000192
Jim Ingham8ab1a802010-08-26 23:36:03 +0000193 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000194 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000195
Chris Lattner24943d22010-06-08 16:52:24 +0000196 strm.IndentLess();
197 return num_frames_displayed;
198}
199
200bool
201lldb_private::DisplayFrameForExecutionContext
202(
203 Thread *thread,
204 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000205 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000206 Stream& strm,
207 bool show_frame_info,
208 bool show_source,
209 uint32_t source_lines_before,
210 uint32_t source_lines_after
211)
212{
213 // thread and frame must be filled in prior to calling this function
214 if (thread && frame)
215 {
216 if (show_frame_info)
217 {
218 strm.Indent();
219 frame->Dump (&strm, true);
220 strm.EOL();
221 }
222
223 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
224
225 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
226 {
Greg Clayton63094e02010-06-23 01:19:29 +0000227 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000228 sc.line_entry.file,
229 sc.line_entry.line,
230 3,
231 3,
232 "->",
233 &strm);
234
235 }
236 return true;
237 }
238 return false;
239}
240
241
242//-------------------------------------------------------------------------
243// CommandObjectThreadBacktrace
244//-------------------------------------------------------------------------
245
246class CommandObjectThreadBacktrace : public CommandObject
247{
248public:
249
Jim Ingham8ab1a802010-08-26 23:36:03 +0000250 class CommandOptions : public Options
251 {
252 public:
253
254 CommandOptions () :
255 Options()
256 {
257 // Keep default values of all options in one place: ResetOptionValues ()
258 ResetOptionValues ();
259 }
260
261 virtual
262 ~CommandOptions ()
263 {
264 }
265
266 virtual Error
267 SetOptionValue (int option_idx, const char *option_arg)
268 {
269 Error error;
270 char short_option = (char) m_getopt_table[option_idx].val;
271
272 switch (short_option)
273 {
274 case 'c':
275 {
276 bool success;
277 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
278 if (!success)
279 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
280 if (input_count < -1)
281 m_count = UINT32_MAX;
282 else
283 m_count = input_count;
284 }
285 break;
286 case 's':
287 {
288 bool success;
289 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
290 if (!success)
291 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
292 }
293 break;
294 default:
295 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
296 break;
297
298 }
299 return error;
300 }
301
302 void
303 ResetOptionValues ()
304 {
305 Options::ResetOptionValues();
306 m_count = -1;
307 m_start = 0;
308 }
309
310 const lldb::OptionDefinition*
311 GetDefinitions ()
312 {
313 return g_option_table;
314 }
315
316 // Options table: Required for subclasses of Options.
317
318 static lldb::OptionDefinition g_option_table[];
319
320 // Instance variables to hold the values for command options.
321 uint32_t m_count;
322 uint32_t m_start;
323 };
324
Chris Lattner24943d22010-06-08 16:52:24 +0000325 CommandObjectThreadBacktrace () :
326 CommandObject ("thread backtrace",
Jim Inghameb10f7b2010-08-27 00:58:05 +0000327 "Shows the stack for one or more threads. If no threads are specified, shows the currently selected thread. \nUse the thread-index \"all\" to see all threads.",
328 "thread backtrace [<thread-index>] ...",
Chris Lattner24943d22010-06-08 16:52:24 +0000329 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000330 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000331 {
332 }
333
334 ~CommandObjectThreadBacktrace()
335 {
336 }
337
Jim Ingham8ab1a802010-08-26 23:36:03 +0000338 virtual Options *
339 GetOptions ()
340 {
341 return &m_options;
342 }
Chris Lattner24943d22010-06-08 16:52:24 +0000343
Greg Clayton63094e02010-06-23 01:19:29 +0000344 virtual bool
Chris Lattner24943d22010-06-08 16:52:24 +0000345 Execute
346 (
Greg Clayton63094e02010-06-23 01:19:29 +0000347 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000348 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000349 CommandReturnObject &result
350 )
351 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000352
353 bool show_frame_info = true;
354 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
355
356 result.SetStatus (eReturnStatusSuccessFinishResult);
357
Chris Lattner24943d22010-06-08 16:52:24 +0000358 if (command.GetArgumentCount() == 0)
359 {
Greg Clayton63094e02010-06-23 01:19:29 +0000360 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000361 if (exe_ctx.thread)
362 {
Chris Lattner24943d22010-06-08 16:52:24 +0000363 if (DisplayFramesForExecutionContext (exe_ctx.thread,
364 interpreter,
365 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000366 m_options.m_start,
367 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000368 show_frame_info,
369 num_frames_with_source,
370 3,
371 3))
372 {
373 result.SetStatus (eReturnStatusSuccessFinishResult);
374 }
375 }
376 else
377 {
378 result.AppendError ("invalid thread");
379 result.SetStatus (eReturnStatusFailed);
380 }
381 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000382 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
383 {
384 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
385 uint32_t num_threads = process->GetThreadList().GetSize();
386 for (uint32_t i = 0; i < num_threads; i++)
387 {
388 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
389 if (!DisplayFramesForExecutionContext (thread_sp.get(),
390 interpreter,
391 result.GetOutputStream(),
392 m_options.m_start,
393 m_options.m_count,
394 show_frame_info,
395 num_frames_with_source,
396 3,
397 3))
398 {
399 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%d\"\n", i);
400 result.SetStatus (eReturnStatusFailed);
401 return false;
402 }
403 if (i < num_threads - 1)
404 result.AppendMessage("");
405 }
406 }
Chris Lattner24943d22010-06-08 16:52:24 +0000407 else
408 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000409 uint32_t num_args = command.GetArgumentCount();
410 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
411 std::vector<ThreadSP> thread_sps;
412
413 for (uint32_t i = 0; i < num_args; i++)
414 {
415 bool success;
416
417 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
418 if (!success)
419 {
420 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
421 result.SetStatus (eReturnStatusFailed);
422 return false;
423 }
424
425 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
426
427 if (!thread_sps[i])
428 {
429 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
430 result.SetStatus (eReturnStatusFailed);
431 return false;
432 }
433
434 }
435
436 for (uint32_t i = 0; i < num_args; i++)
437 {
438 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
439 interpreter,
440 result.GetOutputStream(),
441 m_options.m_start,
442 m_options.m_count,
443 show_frame_info,
444 num_frames_with_source,
445 3,
446 3))
447 {
448 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
449 result.SetStatus (eReturnStatusFailed);
450 return false;
451 }
452
453 if (i < num_args - 1)
454 result.AppendMessage("");
455 }
Chris Lattner24943d22010-06-08 16:52:24 +0000456 }
457 return result.Succeeded();
458 }
459protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000460 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000461};
462
Jim Ingham8ab1a802010-08-26 23:36:03 +0000463lldb::OptionDefinition
464CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
465{
466{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, "<count>", "How many frames to display (-1 for all)"},
467{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, "<start>", "Where to start the backtrace"},
468{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
469};
Chris Lattner24943d22010-06-08 16:52:24 +0000470
Greg Claytonc0418152010-07-07 17:07:17 +0000471enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000472{
473 eStepScopeSource,
474 eStepScopeInstruction
475};
476
477class CommandObjectThreadStepWithTypeAndScope : public CommandObject
478{
479public:
480
481 class CommandOptions : public Options
482 {
483 public:
484
485 CommandOptions () :
486 Options()
487 {
488 // Keep default values of all options in one place: ResetOptionValues ()
489 ResetOptionValues ();
490 }
491
492 virtual
493 ~CommandOptions ()
494 {
495 }
496
497 virtual Error
498 SetOptionValue (int option_idx, const char *option_arg)
499 {
500 Error error;
501 char short_option = (char) m_getopt_table[option_idx].val;
502
503 switch (short_option)
504 {
505 case 'a':
506 {
507 bool success;
508 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
509 if (!success)
510 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
511 }
512 break;
513 case 'm':
514 {
515 bool found_one = false;
516 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
517 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
518 if (!found_one)
519 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
520 }
521 break;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000522 case 'r':
523 {
524 m_avoid_regexp.clear();
525 m_avoid_regexp.assign(option_arg);
526 }
527 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000528 default:
529 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
530 break;
531
532 }
533 return error;
534 }
535
536 void
537 ResetOptionValues ()
538 {
539 Options::ResetOptionValues();
540 m_avoid_no_debug = true;
541 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000542 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000543 }
544
545 const lldb::OptionDefinition*
546 GetDefinitions ()
547 {
548 return g_option_table;
549 }
550
551 // Options table: Required for subclasses of Options.
552
553 static lldb::OptionDefinition g_option_table[];
554
555 // Instance variables to hold the values for command options.
556 bool m_avoid_no_debug;
557 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000558 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000559 };
560
561 CommandObjectThreadStepWithTypeAndScope (const char *name,
562 const char *help,
563 const char *syntax,
564 uint32_t flags,
565 StepType step_type,
566 StepScope step_scope) :
567 CommandObject (name, help, syntax, flags),
568 m_step_type (step_type),
569 m_step_scope (step_scope),
570 m_options ()
571 {
572 }
573
574 virtual
575 ~CommandObjectThreadStepWithTypeAndScope ()
576 {
577 }
578
579 virtual
580 Options *
581 GetOptions ()
582 {
583 return &m_options;
584 }
585
586 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000587 Execute
588 (
589 CommandInterpreter &interpreter,
590 Args& command,
591 CommandReturnObject &result
592 )
Chris Lattner24943d22010-06-08 16:52:24 +0000593 {
Greg Clayton63094e02010-06-23 01:19:29 +0000594 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
595 bool synchronous_execution = interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000596
597 if (process == NULL)
598 {
599 result.AppendError ("need a valid process to step");
600 result.SetStatus (eReturnStatusFailed);
601
602 }
603 else
604 {
605 const uint32_t num_threads = process->GetThreadList().GetSize();
606 Thread *thread = NULL;
607
608 if (command.GetArgumentCount() == 0)
609 {
Jim Inghamc8332952010-08-26 21:32:51 +0000610 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000611 if (thread == NULL)
612 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000613 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000614 result.SetStatus (eReturnStatusFailed);
615 return false;
616 }
617 }
618 else
619 {
620 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
621 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
622 if (step_thread_idx == LLDB_INVALID_INDEX32)
623 {
624 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
625 result.SetStatus (eReturnStatusFailed);
626 return false;
627 }
628 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
629 if (thread == NULL)
630 {
631 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
632 step_thread_idx, 0, num_threads);
633 result.SetStatus (eReturnStatusFailed);
634 return false;
635 }
636 }
637
638 const bool abort_other_plans = false;
639 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
640
641 // This is a bit unfortunate, but not all the commands in this command object support
642 // only while stepping, so I use the bool for them.
643 bool bool_stop_other_threads;
644 if (m_options.m_run_mode == eAllThreads)
645 bool_stop_other_threads = false;
646 else
647 bool_stop_other_threads = true;
648
649 if (m_step_type == eStepTypeInto)
650 {
651 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
652 ThreadPlan *new_plan;
653
654 if (frame->HasDebugInformation ())
655 {
656 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
657 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
658 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000659 stop_other_threads,
660 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000661 if (new_plan && !m_options.m_avoid_regexp.empty())
662 {
663 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
664 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
665 }
Chris Lattner24943d22010-06-08 16:52:24 +0000666 }
667 else
668 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
669
Jim Inghamc8332952010-08-26 21:32:51 +0000670 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000671 process->Resume ();
672 }
673 else if (m_step_type == eStepTypeOver)
674 {
675 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
676 ThreadPlan *new_plan;
677
678 if (frame->HasDebugInformation())
679 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
680 m_step_type,
681 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
682 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000683 stop_other_threads,
684 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000685 else
686 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
687 abort_other_plans,
688 bool_stop_other_threads);
689
690 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
691 // Maybe there should be a parameter to control this.
692 new_plan->SetOkayToDiscard(false);
693
Jim Inghamc8332952010-08-26 21:32:51 +0000694 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000695 process->Resume ();
696 }
697 else if (m_step_type == eStepTypeTrace)
698 {
699 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000700 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000701 process->Resume ();
702 }
703 else if (m_step_type == eStepTypeTraceOver)
704 {
705 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000706 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000707 process->Resume ();
708 }
709 else if (m_step_type == eStepTypeOut)
710 {
711 ThreadPlan *new_plan;
712
713 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
714 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
715 // Maybe there should be a parameter to control this.
716 new_plan->SetOkayToDiscard(false);
717
Jim Inghamc8332952010-08-26 21:32:51 +0000718 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000719 process->Resume ();
720 }
721 else
722 {
723 result.AppendError ("step type is not supported");
724 result.SetStatus (eReturnStatusFailed);
725 }
726 if (synchronous_execution)
727 {
728 StateType state = process->WaitForProcessToStop (NULL);
729
730 //EventSP event_sp;
731 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
732 //while (! StateIsStoppedState (state))
733 // {
734 // state = process->WaitForStateChangedEvents (NULL, event_sp);
735 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000736 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000737 result.SetDidChangeProcessState (true);
738 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
739 result.SetStatus (eReturnStatusSuccessFinishNoResult);
740 }
741 }
742 return result.Succeeded();
743 }
744
745protected:
746 StepType m_step_type;
747 StepScope m_step_scope;
748 CommandOptions m_options;
749};
750
751static lldb::OptionEnumValueElement
752g_tri_running_mode[] =
753{
754{ eOnlyThisThread, "thisThread", "Run only this thread"},
755{ eAllThreads, "allThreads", "Run all threads"},
756{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
757{ 0, NULL, NULL }
758};
759
760static lldb::OptionEnumValueElement
761g_duo_running_mode[] =
762{
763{ eOnlyThisThread, "thisThread", "Run only this thread"},
764{ eAllThreads, "allThreads", "Run all threads"},
765{ 0, NULL, NULL }
766};
767
768lldb::OptionDefinition
769CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
770{
Greg Clayton12bec712010-06-28 21:30:43 +0000771{ 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"},
772{ 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 Ingham809ab9b2010-07-10 02:27:39 +0000773{ 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 Lattner24943d22010-06-08 16:52:24 +0000774{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
775};
776
777
778//-------------------------------------------------------------------------
779// CommandObjectThreadContinue
780//-------------------------------------------------------------------------
781
782class CommandObjectThreadContinue : public CommandObject
783{
784public:
785
786 CommandObjectThreadContinue () :
787 CommandObject ("thread continue",
788 "Continues execution of one or more threads in an active process.",
789 "thread continue <thread-index> [<thread-index> ...]",
790 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
791 {
792 }
793
794
795 virtual
796 ~CommandObjectThreadContinue ()
797 {
798 }
799
800 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000801 Execute
802 (
803 CommandInterpreter &interpreter,
804 Args& command,
805 CommandReturnObject &result
806 )
Chris Lattner24943d22010-06-08 16:52:24 +0000807 {
Greg Clayton63094e02010-06-23 01:19:29 +0000808 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000809
Jim Inghamc8332952010-08-26 21:32:51 +0000810 if (!interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000811 {
812 result.AppendError ("invalid target, set executable file using 'file' command");
813 result.SetStatus (eReturnStatusFailed);
814 return false;
815 }
816
Greg Clayton63094e02010-06-23 01:19:29 +0000817 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000818 if (process == NULL)
819 {
820 result.AppendError ("no process exists. Cannot continue");
821 result.SetStatus (eReturnStatusFailed);
822 return false;
823 }
824
825 StateType state = process->GetState();
826 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
827 {
828 const uint32_t num_threads = process->GetThreadList().GetSize();
829 uint32_t idx;
830 const size_t argc = command.GetArgumentCount();
831 if (argc > 0)
832 {
833 std::vector<uint32_t> resume_thread_indexes;
834 for (uint32_t i=0; i<argc; ++i)
835 {
836 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
837 if (idx < num_threads)
838 resume_thread_indexes.push_back(idx);
839 else
840 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
841 }
842
843 if (resume_thread_indexes.empty())
844 {
845 result.AppendError ("no valid thread indexes were specified");
846 result.SetStatus (eReturnStatusFailed);
847 return false;
848 }
849 else
850 {
851 result.AppendMessage ("Resuming thread ");
852 for (idx=0; idx<num_threads; ++idx)
853 {
854 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
855 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
856 {
857 result.AppendMessageWithFormat ("%u ", idx);
858 thread->SetResumeState (eStateRunning);
859 }
860 else
861 {
862 thread->SetResumeState (eStateSuspended);
863 }
864 }
865 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
866 }
867 }
868 else
869 {
Jim Inghamc8332952010-08-26 21:32:51 +0000870 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000871 if (current_thread == NULL)
872 {
873 result.AppendError ("the process doesn't have a current thread");
874 result.SetStatus (eReturnStatusFailed);
875 return false;
876 }
877 // Set the actions that the threads should each take when resuming
878 for (idx=0; idx<num_threads; ++idx)
879 {
880 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
881 if (thread == current_thread)
882 {
883 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
884 thread->SetResumeState (eStateRunning);
885 }
886 else
887 {
888 thread->SetResumeState (eStateSuspended);
889 }
890 }
891 }
892
893 Error error (process->Resume());
894 if (error.Success())
895 {
896 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
897 if (synchronous_execution)
898 {
Greg Claytonbef15832010-07-14 00:18:15 +0000899 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000900
901 result.SetDidChangeProcessState (true);
902 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
903 result.SetStatus (eReturnStatusSuccessFinishNoResult);
904 }
905 else
906 {
907 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
908 }
909 }
910 else
911 {
912 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
913 result.SetStatus (eReturnStatusFailed);
914 }
915 }
916 else
917 {
918 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
919 StateAsCString(state));
920 result.SetStatus (eReturnStatusFailed);
921 }
922
923 return result.Succeeded();
924 }
925
926};
927
928//-------------------------------------------------------------------------
929// CommandObjectThreadUntil
930//-------------------------------------------------------------------------
931
932class CommandObjectThreadUntil : public CommandObject
933{
934public:
935
936 class CommandOptions : public Options
937 {
938 public:
939 uint32_t m_thread_idx;
940 uint32_t m_frame_idx;
941
942 CommandOptions () :
943 Options(),
944 m_thread_idx(LLDB_INVALID_THREAD_ID),
945 m_frame_idx(LLDB_INVALID_FRAME_ID)
946 {
947 // Keep default values of all options in one place: ResetOptionValues ()
948 ResetOptionValues ();
949 }
950
951 virtual
952 ~CommandOptions ()
953 {
954 }
955
956 virtual Error
957 SetOptionValue (int option_idx, const char *option_arg)
958 {
959 Error error;
960 char short_option = (char) m_getopt_table[option_idx].val;
961
962 switch (short_option)
963 {
964 case 't':
965 {
Greg Claytonbef15832010-07-14 00:18:15 +0000966 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +0000967 if (m_thread_idx == LLDB_INVALID_INDEX32)
968 {
969 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
970 }
971 }
972 break;
973 case 'f':
974 {
975 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
976 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
977 {
978 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
979 }
980 }
981 break;
982 case 'm':
983 {
984 bool found_one = false;
985 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
986 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
987
988 if (!found_one)
989 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
990 else if (run_mode == eAllThreads)
991 m_stop_others = false;
992 else
993 m_stop_others = true;
994
995 }
996 break;
997 default:
998 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
999 break;
1000
1001 }
1002 return error;
1003 }
1004
1005 void
1006 ResetOptionValues ()
1007 {
1008 Options::ResetOptionValues();
1009 m_thread_idx = LLDB_INVALID_THREAD_ID;
1010 m_frame_idx = 0;
1011 m_stop_others = false;
1012 }
1013
1014 const lldb::OptionDefinition*
1015 GetDefinitions ()
1016 {
1017 return g_option_table;
1018 }
1019
1020 uint32_t m_step_thread_idx;
1021 bool m_stop_others;
1022
1023 // Options table: Required for subclasses of Options.
1024
1025 static lldb::OptionDefinition g_option_table[];
1026
1027 // Instance variables to hold the values for command options.
1028 };
1029
1030 CommandObjectThreadUntil () :
1031 CommandObject ("thread until",
1032 "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
1033 "thread until [<cmd-options>] <line-number>",
1034 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1035 m_options ()
1036 {
1037 }
1038
1039
1040 virtual
1041 ~CommandObjectThreadUntil ()
1042 {
1043 }
1044
1045 virtual
1046 Options *
1047 GetOptions ()
1048 {
1049 return &m_options;
1050 }
1051
1052 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001053 Execute
1054 (
1055 CommandInterpreter &interpreter,
1056 Args& command,
1057 CommandReturnObject &result
1058 )
Chris Lattner24943d22010-06-08 16:52:24 +00001059 {
Greg Clayton63094e02010-06-23 01:19:29 +00001060 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001061
Jim Inghamc8332952010-08-26 21:32:51 +00001062 if (!interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +00001063 {
1064 result.AppendError ("invalid target, set executable file using 'file' command");
1065 result.SetStatus (eReturnStatusFailed);
1066 return false;
1067 }
1068
Greg Clayton63094e02010-06-23 01:19:29 +00001069 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001070 if (process == NULL)
1071 {
1072 result.AppendError ("need a valid process to step");
1073 result.SetStatus (eReturnStatusFailed);
1074
1075 }
1076 else
1077 {
1078 Thread *thread = NULL;
1079 uint32_t line_number;
1080
1081 if (command.GetArgumentCount() != 1)
1082 {
1083 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1084 result.SetStatus (eReturnStatusFailed);
1085 return false;
1086 }
1087
1088 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1089 if (line_number == UINT32_MAX)
1090 {
1091 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1092 result.SetStatus (eReturnStatusFailed);
1093 return false;
1094 }
1095
1096 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1097 {
Jim Inghamc8332952010-08-26 21:32:51 +00001098 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001099 }
1100 else
1101 {
1102 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1103 }
1104
1105 if (thread == NULL)
1106 {
1107 const uint32_t num_threads = process->GetThreadList().GetSize();
1108 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1109 result.SetStatus (eReturnStatusFailed);
1110 return false;
1111 }
1112
1113 const bool abort_other_plans = true;
1114
1115 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1116 if (frame == NULL)
1117 {
1118
1119 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1120 result.SetStatus (eReturnStatusFailed);
1121 return false;
1122 }
1123
1124 ThreadPlan *new_plan;
1125
1126 if (frame->HasDebugInformation ())
1127 {
1128 // Finally we got here... Translate the given line number to a bunch of addresses:
1129 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1130 LineTable *line_table = NULL;
1131 if (sc.comp_unit)
1132 line_table = sc.comp_unit->GetLineTable();
1133
1134 if (line_table == NULL)
1135 {
1136 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1137 m_options.m_frame_idx, m_options.m_thread_idx);
1138 result.SetStatus (eReturnStatusFailed);
1139 return false;
1140 }
1141
1142 LineEntry function_start;
1143 uint32_t index_ptr = 0, end_ptr;
1144 std::vector<addr_t> address_list;
1145
1146 // Find the beginning & end index of the
1147 AddressRange fun_addr_range = sc.function->GetAddressRange();
1148 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1149 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1150
1151 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1152 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1153
1154 while (index_ptr <= end_ptr)
1155 {
1156 LineEntry line_entry;
1157 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1158 if (index_ptr == UINT32_MAX)
1159 break;
1160
1161 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
1162 if (address != LLDB_INVALID_ADDRESS)
1163 address_list.push_back (address);
1164 index_ptr++;
1165 }
1166
Greg Clayton53d68e72010-07-20 22:52:08 +00001167 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others);
Chris Lattner24943d22010-06-08 16:52:24 +00001168 new_plan->SetOkayToDiscard(false);
1169 }
1170 else
1171 {
1172 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1173 result.SetStatus (eReturnStatusFailed);
1174 return false;
1175
1176 }
1177
Jim Inghamc8332952010-08-26 21:32:51 +00001178 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001179 Error error (process->Resume ());
1180 if (error.Success())
1181 {
1182 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1183 if (synchronous_execution)
1184 {
1185 StateType state = process->WaitForProcessToStop (NULL);
1186
1187 result.SetDidChangeProcessState (true);
1188 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1189 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1190 }
1191 else
1192 {
1193 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1194 }
1195 }
1196 else
1197 {
1198 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1199 result.SetStatus (eReturnStatusFailed);
1200 }
1201
1202 }
1203 return result.Succeeded();
1204 }
1205protected:
1206 CommandOptions m_options;
1207
1208};
1209
1210lldb::OptionDefinition
1211CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1212{
Greg Clayton12bec712010-06-28 21:30:43 +00001213{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
1214{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
1215{ 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 Lattner24943d22010-06-08 16:52:24 +00001216{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1217};
1218
1219
1220//-------------------------------------------------------------------------
1221// CommandObjectThreadSelect
1222//-------------------------------------------------------------------------
1223
1224class CommandObjectThreadSelect : public CommandObject
1225{
1226public:
1227
1228 CommandObjectThreadSelect () :
1229 CommandObject ("thread select",
1230 "Selects a threads as the currently active thread.",
1231 "thread select <thread-index>",
1232 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1233 {
1234 }
1235
1236
1237 virtual
1238 ~CommandObjectThreadSelect ()
1239 {
1240 }
1241
1242 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001243 Execute
1244 (
1245 CommandInterpreter &interpreter,
1246 Args& command,
1247 CommandReturnObject &result
1248 )
Chris Lattner24943d22010-06-08 16:52:24 +00001249 {
Greg Clayton63094e02010-06-23 01:19:29 +00001250 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001251 if (process == NULL)
1252 {
1253 result.AppendError ("no process");
1254 result.SetStatus (eReturnStatusFailed);
1255 return false;
1256 }
1257 else if (command.GetArgumentCount() != 1)
1258 {
1259 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1260 result.SetStatus (eReturnStatusFailed);
1261 return false;
1262 }
1263
1264 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1265
1266 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1267 if (new_thread == NULL)
1268 {
1269 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1270 result.SetStatus (eReturnStatusFailed);
1271 return false;
1272 }
1273
Jim Inghamc8332952010-08-26 21:32:51 +00001274 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001275
1276 DisplayThreadInfo (interpreter,
1277 result.GetOutputStream(),
1278 new_thread,
1279 false,
1280 true);
1281
1282 return result.Succeeded();
1283 }
1284
1285};
1286
1287
1288//-------------------------------------------------------------------------
1289// CommandObjectThreadList
1290//-------------------------------------------------------------------------
1291
Greg Clayton63094e02010-06-23 01:19:29 +00001292class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001293{
Greg Clayton63094e02010-06-23 01:19:29 +00001294public:
Chris Lattner24943d22010-06-08 16:52:24 +00001295
Chris Lattner24943d22010-06-08 16:52:24 +00001296
Greg Clayton63094e02010-06-23 01:19:29 +00001297 CommandObjectThreadList ():
1298 CommandObject ("thread list",
1299 "Shows a summary of all current threads in a process.",
1300 "thread list",
1301 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001302 {
Greg Clayton63094e02010-06-23 01:19:29 +00001303 }
Chris Lattner24943d22010-06-08 16:52:24 +00001304
Greg Clayton63094e02010-06-23 01:19:29 +00001305 ~CommandObjectThreadList()
1306 {
1307 }
1308
1309 bool
1310 Execute
1311 (
1312 CommandInterpreter &interpreter,
1313 Args& command,
1314 CommandReturnObject &result
1315 )
1316 {
1317 StreamString &strm = result.GetOutputStream();
1318 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1319 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
1320 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001321 {
Greg Clayton63094e02010-06-23 01:19:29 +00001322 const StateType state = exe_ctx.process->GetState();
1323
1324 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001325 {
Greg Clayton63094e02010-06-23 01:19:29 +00001326 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001327 {
Greg Clayton63094e02010-06-23 01:19:29 +00001328 int exit_status = exe_ctx.process->GetExitStatus();
1329 const char *exit_description = exe_ctx.process->GetExitDescription();
1330 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1331 exe_ctx.process->GetID(),
1332 exit_status,
1333 exit_status,
1334 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001335 }
1336 else
1337 {
Greg Clayton63094e02010-06-23 01:19:29 +00001338 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1339 if (exe_ctx.thread == NULL)
1340 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1341 if (exe_ctx.thread != NULL)
1342 {
1343 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1344 }
1345 else
1346 {
1347 result.AppendError ("no valid thread found in current process");
1348 result.SetStatus (eReturnStatusFailed);
1349 }
Chris Lattner24943d22010-06-08 16:52:24 +00001350 }
1351 }
Greg Clayton63094e02010-06-23 01:19:29 +00001352 else
1353 {
1354 result.AppendError ("process is currently running");
1355 result.SetStatus (eReturnStatusFailed);
1356 }
Chris Lattner24943d22010-06-08 16:52:24 +00001357 }
1358 else
1359 {
Greg Clayton63094e02010-06-23 01:19:29 +00001360 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001361 result.SetStatus (eReturnStatusFailed);
1362 }
Greg Clayton63094e02010-06-23 01:19:29 +00001363 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001364 }
Greg Clayton63094e02010-06-23 01:19:29 +00001365};
Chris Lattner24943d22010-06-08 16:52:24 +00001366
1367//-------------------------------------------------------------------------
1368// CommandObjectMultiwordThread
1369//-------------------------------------------------------------------------
1370
Greg Clayton63094e02010-06-23 01:19:29 +00001371CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +00001372 CommandObjectMultiword ("thread",
1373 "A set of commands for operating on one or more thread within a running process.",
1374 "thread <subcommand> [<subcommand-options>]")
1375{
Greg Clayton63094e02010-06-23 01:19:29 +00001376 LoadSubCommand (interpreter, "backtrace", CommandObjectSP (new CommandObjectThreadBacktrace ()));
1377 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectThreadContinue ()));
1378 LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectThreadList ()));
1379 LoadSubCommand (interpreter, "select", CommandObjectSP (new CommandObjectThreadSelect ()));
1380 LoadSubCommand (interpreter, "until", CommandObjectSP (new CommandObjectThreadUntil ()));
1381 LoadSubCommand (interpreter, "step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1382 "thread step-in",
1383 "Source level single step in in specified thread (current thread, if none specified).",
1384 "thread step-in [<thread-id>]",
1385 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1386 eStepTypeInto,
1387 eStepScopeSource)));
1388
1389 LoadSubCommand (interpreter, "step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
Chris Lattner24943d22010-06-08 16:52:24 +00001390 "Source level single step out in specified thread (current thread, if none specified).",
1391 "thread step-out [<thread-id>]",
1392 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1393 eStepTypeOut,
Greg Clayton63094e02010-06-23 01:19:29 +00001394 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001395
Greg Clayton63094e02010-06-23 01:19:29 +00001396 LoadSubCommand (interpreter, "step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001397 "Source level single step over in specified thread (current thread, if none specified).",
1398 "thread step-over [<thread-id>]",
1399 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1400 eStepTypeOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001401 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001402
Greg Clayton63094e02010-06-23 01:19:29 +00001403 LoadSubCommand (interpreter, "step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
Chris Lattner24943d22010-06-08 16:52:24 +00001404 "Single step one instruction in specified thread (current thread, if none specified).",
1405 "thread step-inst [<thread-id>]",
1406 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1407 eStepTypeTrace,
Greg Clayton63094e02010-06-23 01:19:29 +00001408 eStepScopeInstruction)));
1409
1410 LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001411 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1412 "thread step-inst-over [<thread-id>]",
1413 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1414 eStepTypeTraceOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001415 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001416}
1417
1418CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1419{
1420}
1421
1422