blob: 28520bb561a8b2a7daf0dabbeec69b9fa457bcf8 [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 {
Jim Ingham74989e82010-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 Lattner24943d22010-06-08 16:52:24 +000071 DisplayFramesForExecutionContext (thread,
72 interpreter,
73 strm,
Chris Lattner24943d22010-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 Ingham74989e82010-08-30 19:44:40 +000077 !already_shown, // Show source for the first frame
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000100 CommandInterpreter &interpreter,
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000149 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000150 Stream& strm,
Chris Lattner24943d22010-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 Clayton33ed1702010-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 Lattner24943d22010-06-08 16:52:24 +0000172 strm.EOL();
173 strm.IndentMore();
174
175 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000176 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-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 Lattner24943d22010-06-08 16:52:24 +0000182 else
Jim Ingham8ab1a802010-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 Lattner24943d22010-06-08 16:52:24 +0000186 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000187 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
188 if (frame_sp.get() == NULL)
189 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000190
Jim Ingham8ab1a802010-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 Lattner24943d22010-06-08 16:52:24 +0000200
Jim Ingham8ab1a802010-08-26 23:36:03 +0000201 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000202 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000203
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000213 CommandInterpreter &interpreter,
Chris Lattner24943d22010-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 Clayton72b71582010-09-02 21:44:10 +0000227 frame->Dump (&strm, true, false);
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000235 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-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 Ingham8ab1a802010-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 Lattner24943d22010-06-08 16:52:24 +0000333 CommandObjectThreadBacktrace () :
334 CommandObject ("thread backtrace",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000335 "Shows the stack for one or more threads. If no threads are specified, shows the currently selected thread. Use the thread-index \"all\" to see all threads.",
Jim Inghameb10f7b2010-08-27 00:58:05 +0000336 "thread backtrace [<thread-index>] ...",
Chris Lattner24943d22010-06-08 16:52:24 +0000337 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000338 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000339 {
340 }
341
342 ~CommandObjectThreadBacktrace()
343 {
344 }
345
Jim Ingham8ab1a802010-08-26 23:36:03 +0000346 virtual Options *
347 GetOptions ()
348 {
349 return &m_options;
350 }
Chris Lattner24943d22010-06-08 16:52:24 +0000351
Greg Clayton63094e02010-06-23 01:19:29 +0000352 virtual bool
Chris Lattner24943d22010-06-08 16:52:24 +0000353 Execute
354 (
Greg Clayton63094e02010-06-23 01:19:29 +0000355 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000356 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000357 CommandReturnObject &result
358 )
359 {
Jim Inghameb10f7b2010-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 Lattner24943d22010-06-08 16:52:24 +0000366 if (command.GetArgumentCount() == 0)
367 {
Greg Clayton63094e02010-06-23 01:19:29 +0000368 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000369 if (exe_ctx.thread)
370 {
Chris Lattner24943d22010-06-08 16:52:24 +0000371 if (DisplayFramesForExecutionContext (exe_ctx.thread,
372 interpreter,
373 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000374 m_options.m_start,
375 m_options.m_count,
Chris Lattner24943d22010-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 Inghameb10f7b2010-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 Claytonf04d6612010-09-03 22:45:01 +0000407 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-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 Lattner24943d22010-06-08 16:52:24 +0000415 else
416 {
Jim Inghameb10f7b2010-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 Lattner24943d22010-06-08 16:52:24 +0000464 }
465 return result.Succeeded();
466 }
467protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000468 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000469};
470
Jim Ingham8ab1a802010-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)"},
475{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, "<start>", "Where to start the backtrace"},
476{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
477};
Chris Lattner24943d22010-06-08 16:52:24 +0000478
Greg Claytonc0418152010-07-07 17:07:17 +0000479enum StepScope
Chris Lattner24943d22010-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 Ingham809ab9b2010-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 Lattner24943d22010-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 Ingham809ab9b2010-07-10 02:27:39 +0000550 m_avoid_regexp.clear();
Chris Lattner24943d22010-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 Ingham809ab9b2010-07-10 02:27:39 +0000566 std::string m_avoid_regexp;
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000595 Execute
596 (
597 CommandInterpreter &interpreter,
598 Args& command,
599 CommandReturnObject &result
600 )
Chris Lattner24943d22010-06-08 16:52:24 +0000601 {
Greg Clayton63094e02010-06-23 01:19:29 +0000602 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
603 bool synchronous_execution = interpreter.GetSynchronous();
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000618 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000619 if (thread == NULL)
620 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000621 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-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 Clayton8f5fd6b2010-06-12 18:59:55 +0000667 stop_other_threads,
668 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-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 Lattner24943d22010-06-08 16:52:24 +0000674 }
675 else
676 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
677
Jim Inghamc8332952010-08-26 21:32:51 +0000678 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Clayton8f5fd6b2010-06-12 18:59:55 +0000691 stop_other_threads,
692 false);
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000702 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000708 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000714 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000726 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000744 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-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 Clayton12bec712010-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 Ingham809ab9b2010-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 Lattner24943d22010-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",
796 "Continues execution of one or more threads in an active process.",
797 "thread continue <thread-index> [<thread-index> ...]",
798 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
799 {
800 }
801
802
803 virtual
804 ~CommandObjectThreadContinue ()
805 {
806 }
807
808 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000809 Execute
810 (
811 CommandInterpreter &interpreter,
812 Args& command,
813 CommandReturnObject &result
814 )
Chris Lattner24943d22010-06-08 16:52:24 +0000815 {
Greg Clayton63094e02010-06-23 01:19:29 +0000816 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000817
Jim Inghamc8332952010-08-26 21:32:51 +0000818 if (!interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +0000825 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-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 Inghamc8332952010-08-26 21:32:51 +0000878 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-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 Claytonbef15832010-07-14 00:18:15 +0000907 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-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 Claytonbef15832010-07-14 00:18:15 +0000974 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-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",
1040 "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
1041 "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 Clayton63094e02010-06-23 01:19:29 +00001061 Execute
1062 (
1063 CommandInterpreter &interpreter,
1064 Args& command,
1065 CommandReturnObject &result
1066 )
Chris Lattner24943d22010-06-08 16:52:24 +00001067 {
Greg Clayton63094e02010-06-23 01:19:29 +00001068 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001069
Jim Inghamc8332952010-08-26 21:32:51 +00001070 if (!interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +00001071 {
1072 result.AppendError ("invalid target, set executable file using 'file' command");
1073 result.SetStatus (eReturnStatusFailed);
1074 return false;
1075 }
1076
Greg Clayton63094e02010-06-23 01:19:29 +00001077 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001078 if (process == NULL)
1079 {
1080 result.AppendError ("need a valid process to step");
1081 result.SetStatus (eReturnStatusFailed);
1082
1083 }
1084 else
1085 {
1086 Thread *thread = NULL;
1087 uint32_t line_number;
1088
1089 if (command.GetArgumentCount() != 1)
1090 {
1091 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1092 result.SetStatus (eReturnStatusFailed);
1093 return false;
1094 }
1095
1096 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1097 if (line_number == UINT32_MAX)
1098 {
1099 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1100 result.SetStatus (eReturnStatusFailed);
1101 return false;
1102 }
1103
1104 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1105 {
Jim Inghamc8332952010-08-26 21:32:51 +00001106 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001107 }
1108 else
1109 {
1110 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1111 }
1112
1113 if (thread == NULL)
1114 {
1115 const uint32_t num_threads = process->GetThreadList().GetSize();
1116 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1117 result.SetStatus (eReturnStatusFailed);
1118 return false;
1119 }
1120
1121 const bool abort_other_plans = true;
1122
1123 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1124 if (frame == NULL)
1125 {
1126
1127 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1128 result.SetStatus (eReturnStatusFailed);
1129 return false;
1130 }
1131
1132 ThreadPlan *new_plan;
1133
1134 if (frame->HasDebugInformation ())
1135 {
1136 // Finally we got here... Translate the given line number to a bunch of addresses:
1137 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1138 LineTable *line_table = NULL;
1139 if (sc.comp_unit)
1140 line_table = sc.comp_unit->GetLineTable();
1141
1142 if (line_table == NULL)
1143 {
1144 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1145 m_options.m_frame_idx, m_options.m_thread_idx);
1146 result.SetStatus (eReturnStatusFailed);
1147 return false;
1148 }
1149
1150 LineEntry function_start;
1151 uint32_t index_ptr = 0, end_ptr;
1152 std::vector<addr_t> address_list;
1153
1154 // Find the beginning & end index of the
1155 AddressRange fun_addr_range = sc.function->GetAddressRange();
1156 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1157 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1158
1159 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1160 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1161
1162 while (index_ptr <= end_ptr)
1163 {
1164 LineEntry line_entry;
1165 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1166 if (index_ptr == UINT32_MAX)
1167 break;
1168
1169 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
1170 if (address != LLDB_INVALID_ADDRESS)
1171 address_list.push_back (address);
1172 index_ptr++;
1173 }
1174
Greg Clayton53d68e72010-07-20 22:52:08 +00001175 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 +00001176 new_plan->SetOkayToDiscard(false);
1177 }
1178 else
1179 {
1180 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1181 result.SetStatus (eReturnStatusFailed);
1182 return false;
1183
1184 }
1185
Jim Inghamc8332952010-08-26 21:32:51 +00001186 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001187 Error error (process->Resume ());
1188 if (error.Success())
1189 {
1190 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1191 if (synchronous_execution)
1192 {
1193 StateType state = process->WaitForProcessToStop (NULL);
1194
1195 result.SetDidChangeProcessState (true);
1196 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1197 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1198 }
1199 else
1200 {
1201 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1202 }
1203 }
1204 else
1205 {
1206 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1207 result.SetStatus (eReturnStatusFailed);
1208 }
1209
1210 }
1211 return result.Succeeded();
1212 }
1213protected:
1214 CommandOptions m_options;
1215
1216};
1217
1218lldb::OptionDefinition
1219CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1220{
Greg Clayton12bec712010-06-28 21:30:43 +00001221{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
1222{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
1223{ 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 +00001224{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1225};
1226
1227
1228//-------------------------------------------------------------------------
1229// CommandObjectThreadSelect
1230//-------------------------------------------------------------------------
1231
1232class CommandObjectThreadSelect : public CommandObject
1233{
1234public:
1235
1236 CommandObjectThreadSelect () :
1237 CommandObject ("thread select",
1238 "Selects a threads as the currently active thread.",
1239 "thread select <thread-index>",
1240 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1241 {
1242 }
1243
1244
1245 virtual
1246 ~CommandObjectThreadSelect ()
1247 {
1248 }
1249
1250 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001251 Execute
1252 (
1253 CommandInterpreter &interpreter,
1254 Args& command,
1255 CommandReturnObject &result
1256 )
Chris Lattner24943d22010-06-08 16:52:24 +00001257 {
Greg Clayton63094e02010-06-23 01:19:29 +00001258 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001259 if (process == NULL)
1260 {
1261 result.AppendError ("no process");
1262 result.SetStatus (eReturnStatusFailed);
1263 return false;
1264 }
1265 else if (command.GetArgumentCount() != 1)
1266 {
1267 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1268 result.SetStatus (eReturnStatusFailed);
1269 return false;
1270 }
1271
1272 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1273
1274 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1275 if (new_thread == NULL)
1276 {
1277 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1278 result.SetStatus (eReturnStatusFailed);
1279 return false;
1280 }
1281
Jim Inghamc8332952010-08-26 21:32:51 +00001282 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001283
1284 DisplayThreadInfo (interpreter,
1285 result.GetOutputStream(),
1286 new_thread,
1287 false,
1288 true);
1289
1290 return result.Succeeded();
1291 }
1292
1293};
1294
1295
1296//-------------------------------------------------------------------------
1297// CommandObjectThreadList
1298//-------------------------------------------------------------------------
1299
Greg Clayton63094e02010-06-23 01:19:29 +00001300class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001301{
Greg Clayton63094e02010-06-23 01:19:29 +00001302public:
Chris Lattner24943d22010-06-08 16:52:24 +00001303
Chris Lattner24943d22010-06-08 16:52:24 +00001304
Greg Clayton63094e02010-06-23 01:19:29 +00001305 CommandObjectThreadList ():
1306 CommandObject ("thread list",
1307 "Shows a summary of all current threads in a process.",
1308 "thread list",
1309 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001310 {
Greg Clayton63094e02010-06-23 01:19:29 +00001311 }
Chris Lattner24943d22010-06-08 16:52:24 +00001312
Greg Clayton63094e02010-06-23 01:19:29 +00001313 ~CommandObjectThreadList()
1314 {
1315 }
1316
1317 bool
1318 Execute
1319 (
1320 CommandInterpreter &interpreter,
1321 Args& command,
1322 CommandReturnObject &result
1323 )
1324 {
1325 StreamString &strm = result.GetOutputStream();
1326 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1327 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
1328 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001329 {
Greg Clayton63094e02010-06-23 01:19:29 +00001330 const StateType state = exe_ctx.process->GetState();
1331
1332 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001333 {
Greg Clayton63094e02010-06-23 01:19:29 +00001334 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001335 {
Greg Clayton63094e02010-06-23 01:19:29 +00001336 int exit_status = exe_ctx.process->GetExitStatus();
1337 const char *exit_description = exe_ctx.process->GetExitDescription();
1338 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1339 exe_ctx.process->GetID(),
1340 exit_status,
1341 exit_status,
1342 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001343 }
1344 else
1345 {
Greg Clayton63094e02010-06-23 01:19:29 +00001346 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1347 if (exe_ctx.thread == NULL)
1348 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1349 if (exe_ctx.thread != NULL)
1350 {
1351 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1352 }
1353 else
1354 {
1355 result.AppendError ("no valid thread found in current process");
1356 result.SetStatus (eReturnStatusFailed);
1357 }
Chris Lattner24943d22010-06-08 16:52:24 +00001358 }
1359 }
Greg Clayton63094e02010-06-23 01:19:29 +00001360 else
1361 {
1362 result.AppendError ("process is currently running");
1363 result.SetStatus (eReturnStatusFailed);
1364 }
Chris Lattner24943d22010-06-08 16:52:24 +00001365 }
1366 else
1367 {
Greg Clayton63094e02010-06-23 01:19:29 +00001368 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001369 result.SetStatus (eReturnStatusFailed);
1370 }
Greg Clayton63094e02010-06-23 01:19:29 +00001371 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001372 }
Greg Clayton63094e02010-06-23 01:19:29 +00001373};
Chris Lattner24943d22010-06-08 16:52:24 +00001374
1375//-------------------------------------------------------------------------
1376// CommandObjectMultiwordThread
1377//-------------------------------------------------------------------------
1378
Greg Clayton63094e02010-06-23 01:19:29 +00001379CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +00001380 CommandObjectMultiword ("thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001381 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001382 "thread <subcommand> [<subcommand-options>]")
1383{
Greg Clayton63094e02010-06-23 01:19:29 +00001384 LoadSubCommand (interpreter, "backtrace", CommandObjectSP (new CommandObjectThreadBacktrace ()));
1385 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectThreadContinue ()));
1386 LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectThreadList ()));
1387 LoadSubCommand (interpreter, "select", CommandObjectSP (new CommandObjectThreadSelect ()));
1388 LoadSubCommand (interpreter, "until", CommandObjectSP (new CommandObjectThreadUntil ()));
1389 LoadSubCommand (interpreter, "step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1390 "thread step-in",
1391 "Source level single step in in specified thread (current thread, if none specified).",
1392 "thread step-in [<thread-id>]",
1393 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1394 eStepTypeInto,
1395 eStepScopeSource)));
1396
1397 LoadSubCommand (interpreter, "step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
Chris Lattner24943d22010-06-08 16:52:24 +00001398 "Source level single step out in specified thread (current thread, if none specified).",
1399 "thread step-out [<thread-id>]",
1400 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1401 eStepTypeOut,
Greg Clayton63094e02010-06-23 01:19:29 +00001402 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001403
Greg Clayton63094e02010-06-23 01:19:29 +00001404 LoadSubCommand (interpreter, "step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001405 "Source level single step over in specified thread (current thread, if none specified).",
1406 "thread step-over [<thread-id>]",
1407 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1408 eStepTypeOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001409 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001410
Greg Clayton63094e02010-06-23 01:19:29 +00001411 LoadSubCommand (interpreter, "step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
Chris Lattner24943d22010-06-08 16:52:24 +00001412 "Single step one instruction in specified thread (current thread, if none specified).",
1413 "thread step-inst [<thread-id>]",
1414 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1415 eStepTypeTrace,
Greg Clayton63094e02010-06-23 01:19:29 +00001416 eStepScopeInstruction)));
1417
1418 LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001419 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1420 "thread step-inst-over [<thread-id>]",
1421 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1422 eStepTypeTraceOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001423 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001424}
1425
1426CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1427{
1428}
1429
1430