blob: 8f49237767f2f7655b8996de764f94b83b579b8f [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 {
53 StopReason thread_stop_reason = eStopReasonNone;
54 Thread::StopInfo thread_stop_info;
55 if (thread->GetStopInfo(&thread_stop_info))
56 {
57 thread_stop_reason = thread_stop_info.GetStopReason();
58 if (thread_stop_reason == eStopReasonNone)
59 return false;
60 }
61 }
62
63 strm.Indent();
64 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetCurrentThread().get() == thread ? '*' : ' ');
65
66 // Show one frame with only the first showing source
67 if (show_source)
68 {
69 DisplayFramesForExecutionContext (thread,
70 interpreter,
71 strm,
72 true,
73 0, // Start at first frame
74 1, // Number of frames to show
75 false,// Don't show the frame info since we already displayed most of it above...
76 1, // Show source for the first frame
77 3, // lines of source context before
78 3); // lines of source context after
79 }
80 else
81 {
82 thread->DumpInfo (strm,
83 true, // Dump the stop reason?
84 true, // Dump the thread name?
85 true, // Dump the queue name?
86 0); // Display context info for stack frame zero
87
88 strm.EOL();
89 }
90
91 return true;
92 }
93 return false;
94}
95
96size_t
97lldb_private::DisplayThreadsInfo
98(
Greg Clayton63094e02010-06-23 01:19:29 +000099 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000100 ExecutionContext *exe_ctx,
101 CommandReturnObject &result,
102 bool only_threads_with_stop_reason,
103 bool show_source
104)
105{
106 StreamString strm;
107
108 size_t num_thread_infos_dumped = 0;
109
110 if (!exe_ctx->process)
111 return 0;
112
113 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
114 if (num_threads > 0)
115 {
116
117 for (uint32_t i = 0; i < num_threads; i++)
118 {
119 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
120 if (thread)
121 {
122 if (DisplayThreadInfo (interpreter,
123 strm,
124 thread,
125 only_threads_with_stop_reason,
126 show_source))
127 ++num_thread_infos_dumped;
128 }
129 }
130 }
131
132 if (num_thread_infos_dumped > 0)
133 {
134 if (num_thread_infos_dumped < num_threads)
135 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
136
137 result.GetOutputStream().GetString().append(strm.GetString());
138 result.SetStatus (eReturnStatusSuccessFinishNoResult);
139 }
140 return num_thread_infos_dumped;
141}
142
143
144size_t
145lldb_private::DisplayFramesForExecutionContext
146(
147 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000148 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000149 Stream& strm,
150 bool ascending,
151 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?
171 0); // Dump info for stack frame zero
172 strm.EOL();
173 strm.IndentMore();
174
175 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000176 uint32_t frame_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000177
178 if (ascending)
179 {
180 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
181 {
182 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
183 if (frame_sp.get() == NULL)
184 break;
185
186 if (DisplayFrameForExecutionContext (thread,
187 frame_sp.get(),
188 interpreter,
189 strm,
190 show_frame_info,
191 num_frames_with_source > first_frame - frame_idx,
192 source_lines_before,
193 source_lines_after) == false)
194 break;
195
196 ++num_frames_displayed;
197 }
198 }
199 else
200 {
201 for (frame_idx = first_frame + num_frames - 1; frame_idx >= first_frame; --frame_idx)
202 {
203 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
204 if (frame_sp == NULL)
205 break;
206
207 if (DisplayFrameForExecutionContext (thread,
208 frame_sp.get(),
209 interpreter,
210 strm,
211 show_frame_info,
212 num_frames_with_source > first_frame - frame_idx,
213 source_lines_before,
214 source_lines_after) == false)
215 break;
216
217 ++num_frames_displayed;
218 }
219 }
220 strm.IndentLess();
221 return num_frames_displayed;
222}
223
224bool
225lldb_private::DisplayFrameForExecutionContext
226(
227 Thread *thread,
228 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000229 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000230 Stream& strm,
231 bool show_frame_info,
232 bool show_source,
233 uint32_t source_lines_before,
234 uint32_t source_lines_after
235)
236{
237 // thread and frame must be filled in prior to calling this function
238 if (thread && frame)
239 {
240 if (show_frame_info)
241 {
242 strm.Indent();
243 frame->Dump (&strm, true);
244 strm.EOL();
245 }
246
247 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
248
249 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
250 {
Greg Clayton63094e02010-06-23 01:19:29 +0000251 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000252 sc.line_entry.file,
253 sc.line_entry.line,
254 3,
255 3,
256 "->",
257 &strm);
258
259 }
260 return true;
261 }
262 return false;
263}
264
265
266//-------------------------------------------------------------------------
267// CommandObjectThreadBacktrace
268//-------------------------------------------------------------------------
269
270class CommandObjectThreadBacktrace : public CommandObject
271{
272public:
273
274 CommandObjectThreadBacktrace () :
275 CommandObject ("thread backtrace",
276 "Shows the stack for one or more threads.",
277 "thread backtrace [<thread-idx>] ...",
278 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
279 m_ascending (true)
280 {
281 }
282
283 ~CommandObjectThreadBacktrace()
284 {
285 }
286
287
Greg Clayton63094e02010-06-23 01:19:29 +0000288 virtual bool
Chris Lattner24943d22010-06-08 16:52:24 +0000289 Execute
290 (
Greg Clayton63094e02010-06-23 01:19:29 +0000291 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000292 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000293 CommandReturnObject &result
294 )
295 {
296 if (command.GetArgumentCount() == 0)
297 {
Greg Clayton63094e02010-06-23 01:19:29 +0000298 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000299 if (exe_ctx.thread)
300 {
301 bool show_frame_info = true;
302 uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing
303 if (DisplayFramesForExecutionContext (exe_ctx.thread,
304 interpreter,
305 result.GetOutputStream(),
306 m_ascending,
307 0,
308 UINT32_MAX,
309 show_frame_info,
310 num_frames_with_source,
311 3,
312 3))
313 {
314 result.SetStatus (eReturnStatusSuccessFinishResult);
315 }
316 }
317 else
318 {
319 result.AppendError ("invalid thread");
320 result.SetStatus (eReturnStatusFailed);
321 }
322 }
323 else
324 {
325 result.AppendError ("backtrace doesn't take arguments (for now)");
326 result.SetStatus (eReturnStatusFailed);
327 }
328 return result.Succeeded();
329 }
330protected:
331 bool m_ascending;
332};
333
334
Greg Claytonc0418152010-07-07 17:07:17 +0000335enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000336{
337 eStepScopeSource,
338 eStepScopeInstruction
339};
340
341class CommandObjectThreadStepWithTypeAndScope : public CommandObject
342{
343public:
344
345 class CommandOptions : public Options
346 {
347 public:
348
349 CommandOptions () :
350 Options()
351 {
352 // Keep default values of all options in one place: ResetOptionValues ()
353 ResetOptionValues ();
354 }
355
356 virtual
357 ~CommandOptions ()
358 {
359 }
360
361 virtual Error
362 SetOptionValue (int option_idx, const char *option_arg)
363 {
364 Error error;
365 char short_option = (char) m_getopt_table[option_idx].val;
366
367 switch (short_option)
368 {
369 case 'a':
370 {
371 bool success;
372 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
373 if (!success)
374 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
375 }
376 break;
377 case 'm':
378 {
379 bool found_one = false;
380 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
381 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
382 if (!found_one)
383 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
384 }
385 break;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000386 case 'r':
387 {
388 m_avoid_regexp.clear();
389 m_avoid_regexp.assign(option_arg);
390 }
391 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000392 default:
393 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
394 break;
395
396 }
397 return error;
398 }
399
400 void
401 ResetOptionValues ()
402 {
403 Options::ResetOptionValues();
404 m_avoid_no_debug = true;
405 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000406 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000407 }
408
409 const lldb::OptionDefinition*
410 GetDefinitions ()
411 {
412 return g_option_table;
413 }
414
415 // Options table: Required for subclasses of Options.
416
417 static lldb::OptionDefinition g_option_table[];
418
419 // Instance variables to hold the values for command options.
420 bool m_avoid_no_debug;
421 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000422 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000423 };
424
425 CommandObjectThreadStepWithTypeAndScope (const char *name,
426 const char *help,
427 const char *syntax,
428 uint32_t flags,
429 StepType step_type,
430 StepScope step_scope) :
431 CommandObject (name, help, syntax, flags),
432 m_step_type (step_type),
433 m_step_scope (step_scope),
434 m_options ()
435 {
436 }
437
438 virtual
439 ~CommandObjectThreadStepWithTypeAndScope ()
440 {
441 }
442
443 virtual
444 Options *
445 GetOptions ()
446 {
447 return &m_options;
448 }
449
450 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000451 Execute
452 (
453 CommandInterpreter &interpreter,
454 Args& command,
455 CommandReturnObject &result
456 )
Chris Lattner24943d22010-06-08 16:52:24 +0000457 {
Greg Clayton63094e02010-06-23 01:19:29 +0000458 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
459 bool synchronous_execution = interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000460
461 if (process == NULL)
462 {
463 result.AppendError ("need a valid process to step");
464 result.SetStatus (eReturnStatusFailed);
465
466 }
467 else
468 {
469 const uint32_t num_threads = process->GetThreadList().GetSize();
470 Thread *thread = NULL;
471
472 if (command.GetArgumentCount() == 0)
473 {
474 thread = process->GetThreadList().GetCurrentThread().get();
475 if (thread == NULL)
476 {
477 result.AppendError ("no current thread in process");
478 result.SetStatus (eReturnStatusFailed);
479 return false;
480 }
481 }
482 else
483 {
484 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
485 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
486 if (step_thread_idx == LLDB_INVALID_INDEX32)
487 {
488 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
489 result.SetStatus (eReturnStatusFailed);
490 return false;
491 }
492 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
493 if (thread == NULL)
494 {
495 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
496 step_thread_idx, 0, num_threads);
497 result.SetStatus (eReturnStatusFailed);
498 return false;
499 }
500 }
501
502 const bool abort_other_plans = false;
503 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
504
505 // This is a bit unfortunate, but not all the commands in this command object support
506 // only while stepping, so I use the bool for them.
507 bool bool_stop_other_threads;
508 if (m_options.m_run_mode == eAllThreads)
509 bool_stop_other_threads = false;
510 else
511 bool_stop_other_threads = true;
512
513 if (m_step_type == eStepTypeInto)
514 {
515 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
516 ThreadPlan *new_plan;
517
518 if (frame->HasDebugInformation ())
519 {
520 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
521 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
522 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000523 stop_other_threads,
524 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000525 if (new_plan && !m_options.m_avoid_regexp.empty())
526 {
527 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
528 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
529 }
Chris Lattner24943d22010-06-08 16:52:24 +0000530 }
531 else
532 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
533
534 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
535 process->Resume ();
536 }
537 else if (m_step_type == eStepTypeOver)
538 {
539 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
540 ThreadPlan *new_plan;
541
542 if (frame->HasDebugInformation())
543 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
544 m_step_type,
545 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
546 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000547 stop_other_threads,
548 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000549 else
550 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
551 abort_other_plans,
552 bool_stop_other_threads);
553
554 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
555 // Maybe there should be a parameter to control this.
556 new_plan->SetOkayToDiscard(false);
557
558 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
559 process->Resume ();
560 }
561 else if (m_step_type == eStepTypeTrace)
562 {
563 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
564 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
565 process->Resume ();
566 }
567 else if (m_step_type == eStepTypeTraceOver)
568 {
569 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
570 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
571 process->Resume ();
572 }
573 else if (m_step_type == eStepTypeOut)
574 {
575 ThreadPlan *new_plan;
576
577 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
578 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
579 // Maybe there should be a parameter to control this.
580 new_plan->SetOkayToDiscard(false);
581
582 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
583 process->Resume ();
584 }
585 else
586 {
587 result.AppendError ("step type is not supported");
588 result.SetStatus (eReturnStatusFailed);
589 }
590 if (synchronous_execution)
591 {
592 StateType state = process->WaitForProcessToStop (NULL);
593
594 //EventSP event_sp;
595 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
596 //while (! StateIsStoppedState (state))
597 // {
598 // state = process->WaitForStateChangedEvents (NULL, event_sp);
599 // }
600 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
601 result.SetDidChangeProcessState (true);
602 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
603 result.SetStatus (eReturnStatusSuccessFinishNoResult);
604 }
605 }
606 return result.Succeeded();
607 }
608
609protected:
610 StepType m_step_type;
611 StepScope m_step_scope;
612 CommandOptions m_options;
613};
614
615static lldb::OptionEnumValueElement
616g_tri_running_mode[] =
617{
618{ eOnlyThisThread, "thisThread", "Run only this thread"},
619{ eAllThreads, "allThreads", "Run all threads"},
620{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
621{ 0, NULL, NULL }
622};
623
624static lldb::OptionEnumValueElement
625g_duo_running_mode[] =
626{
627{ eOnlyThisThread, "thisThread", "Run only this thread"},
628{ eAllThreads, "allThreads", "Run all threads"},
629{ 0, NULL, NULL }
630};
631
632lldb::OptionDefinition
633CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
634{
Greg Clayton12bec712010-06-28 21:30:43 +0000635{ 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"},
636{ 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 +0000637{ 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 +0000638{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
639};
640
641
642//-------------------------------------------------------------------------
643// CommandObjectThreadContinue
644//-------------------------------------------------------------------------
645
646class CommandObjectThreadContinue : public CommandObject
647{
648public:
649
650 CommandObjectThreadContinue () :
651 CommandObject ("thread continue",
652 "Continues execution of one or more threads in an active process.",
653 "thread continue <thread-index> [<thread-index> ...]",
654 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
655 {
656 }
657
658
659 virtual
660 ~CommandObjectThreadContinue ()
661 {
662 }
663
664 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000665 Execute
666 (
667 CommandInterpreter &interpreter,
668 Args& command,
669 CommandReturnObject &result
670 )
Chris Lattner24943d22010-06-08 16:52:24 +0000671 {
Greg Clayton63094e02010-06-23 01:19:29 +0000672 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000673
Greg Clayton63094e02010-06-23 01:19:29 +0000674 if (!interpreter.GetDebugger().GetCurrentTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000675 {
676 result.AppendError ("invalid target, set executable file using 'file' command");
677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680
Greg Clayton63094e02010-06-23 01:19:29 +0000681 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000682 if (process == NULL)
683 {
684 result.AppendError ("no process exists. Cannot continue");
685 result.SetStatus (eReturnStatusFailed);
686 return false;
687 }
688
689 StateType state = process->GetState();
690 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
691 {
692 const uint32_t num_threads = process->GetThreadList().GetSize();
693 uint32_t idx;
694 const size_t argc = command.GetArgumentCount();
695 if (argc > 0)
696 {
697 std::vector<uint32_t> resume_thread_indexes;
698 for (uint32_t i=0; i<argc; ++i)
699 {
700 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
701 if (idx < num_threads)
702 resume_thread_indexes.push_back(idx);
703 else
704 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
705 }
706
707 if (resume_thread_indexes.empty())
708 {
709 result.AppendError ("no valid thread indexes were specified");
710 result.SetStatus (eReturnStatusFailed);
711 return false;
712 }
713 else
714 {
715 result.AppendMessage ("Resuming thread ");
716 for (idx=0; idx<num_threads; ++idx)
717 {
718 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
719 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
720 {
721 result.AppendMessageWithFormat ("%u ", idx);
722 thread->SetResumeState (eStateRunning);
723 }
724 else
725 {
726 thread->SetResumeState (eStateSuspended);
727 }
728 }
729 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
730 }
731 }
732 else
733 {
734 Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
735 if (current_thread == NULL)
736 {
737 result.AppendError ("the process doesn't have a current thread");
738 result.SetStatus (eReturnStatusFailed);
739 return false;
740 }
741 // Set the actions that the threads should each take when resuming
742 for (idx=0; idx<num_threads; ++idx)
743 {
744 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
745 if (thread == current_thread)
746 {
747 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
748 thread->SetResumeState (eStateRunning);
749 }
750 else
751 {
752 thread->SetResumeState (eStateSuspended);
753 }
754 }
755 }
756
757 Error error (process->Resume());
758 if (error.Success())
759 {
760 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
761 if (synchronous_execution)
762 {
Greg Claytonbef15832010-07-14 00:18:15 +0000763 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000764
765 result.SetDidChangeProcessState (true);
766 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
767 result.SetStatus (eReturnStatusSuccessFinishNoResult);
768 }
769 else
770 {
771 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
772 }
773 }
774 else
775 {
776 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
777 result.SetStatus (eReturnStatusFailed);
778 }
779 }
780 else
781 {
782 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
783 StateAsCString(state));
784 result.SetStatus (eReturnStatusFailed);
785 }
786
787 return result.Succeeded();
788 }
789
790};
791
792//-------------------------------------------------------------------------
793// CommandObjectThreadUntil
794//-------------------------------------------------------------------------
795
796class CommandObjectThreadUntil : public CommandObject
797{
798public:
799
800 class CommandOptions : public Options
801 {
802 public:
803 uint32_t m_thread_idx;
804 uint32_t m_frame_idx;
805
806 CommandOptions () :
807 Options(),
808 m_thread_idx(LLDB_INVALID_THREAD_ID),
809 m_frame_idx(LLDB_INVALID_FRAME_ID)
810 {
811 // Keep default values of all options in one place: ResetOptionValues ()
812 ResetOptionValues ();
813 }
814
815 virtual
816 ~CommandOptions ()
817 {
818 }
819
820 virtual Error
821 SetOptionValue (int option_idx, const char *option_arg)
822 {
823 Error error;
824 char short_option = (char) m_getopt_table[option_idx].val;
825
826 switch (short_option)
827 {
828 case 't':
829 {
Greg Claytonbef15832010-07-14 00:18:15 +0000830 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +0000831 if (m_thread_idx == LLDB_INVALID_INDEX32)
832 {
833 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
834 }
835 }
836 break;
837 case 'f':
838 {
839 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
840 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
841 {
842 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
843 }
844 }
845 break;
846 case 'm':
847 {
848 bool found_one = false;
849 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
850 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
851
852 if (!found_one)
853 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
854 else if (run_mode == eAllThreads)
855 m_stop_others = false;
856 else
857 m_stop_others = true;
858
859 }
860 break;
861 default:
862 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
863 break;
864
865 }
866 return error;
867 }
868
869 void
870 ResetOptionValues ()
871 {
872 Options::ResetOptionValues();
873 m_thread_idx = LLDB_INVALID_THREAD_ID;
874 m_frame_idx = 0;
875 m_stop_others = false;
876 }
877
878 const lldb::OptionDefinition*
879 GetDefinitions ()
880 {
881 return g_option_table;
882 }
883
884 uint32_t m_step_thread_idx;
885 bool m_stop_others;
886
887 // Options table: Required for subclasses of Options.
888
889 static lldb::OptionDefinition g_option_table[];
890
891 // Instance variables to hold the values for command options.
892 };
893
894 CommandObjectThreadUntil () :
895 CommandObject ("thread until",
896 "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
897 "thread until [<cmd-options>] <line-number>",
898 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
899 m_options ()
900 {
901 }
902
903
904 virtual
905 ~CommandObjectThreadUntil ()
906 {
907 }
908
909 virtual
910 Options *
911 GetOptions ()
912 {
913 return &m_options;
914 }
915
916 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000917 Execute
918 (
919 CommandInterpreter &interpreter,
920 Args& command,
921 CommandReturnObject &result
922 )
Chris Lattner24943d22010-06-08 16:52:24 +0000923 {
Greg Clayton63094e02010-06-23 01:19:29 +0000924 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000925
Greg Clayton63094e02010-06-23 01:19:29 +0000926 if (!interpreter.GetDebugger().GetCurrentTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000927 {
928 result.AppendError ("invalid target, set executable file using 'file' command");
929 result.SetStatus (eReturnStatusFailed);
930 return false;
931 }
932
Greg Clayton63094e02010-06-23 01:19:29 +0000933 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000934 if (process == NULL)
935 {
936 result.AppendError ("need a valid process to step");
937 result.SetStatus (eReturnStatusFailed);
938
939 }
940 else
941 {
942 Thread *thread = NULL;
943 uint32_t line_number;
944
945 if (command.GetArgumentCount() != 1)
946 {
947 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
948 result.SetStatus (eReturnStatusFailed);
949 return false;
950 }
951
952 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
953 if (line_number == UINT32_MAX)
954 {
955 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
956 result.SetStatus (eReturnStatusFailed);
957 return false;
958 }
959
960 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
961 {
962 thread = process->GetThreadList().GetCurrentThread().get();
963 }
964 else
965 {
966 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
967 }
968
969 if (thread == NULL)
970 {
971 const uint32_t num_threads = process->GetThreadList().GetSize();
972 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
973 result.SetStatus (eReturnStatusFailed);
974 return false;
975 }
976
977 const bool abort_other_plans = true;
978
979 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
980 if (frame == NULL)
981 {
982
983 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
984 result.SetStatus (eReturnStatusFailed);
985 return false;
986 }
987
988 ThreadPlan *new_plan;
989
990 if (frame->HasDebugInformation ())
991 {
992 // Finally we got here... Translate the given line number to a bunch of addresses:
993 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
994 LineTable *line_table = NULL;
995 if (sc.comp_unit)
996 line_table = sc.comp_unit->GetLineTable();
997
998 if (line_table == NULL)
999 {
1000 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1001 m_options.m_frame_idx, m_options.m_thread_idx);
1002 result.SetStatus (eReturnStatusFailed);
1003 return false;
1004 }
1005
1006 LineEntry function_start;
1007 uint32_t index_ptr = 0, end_ptr;
1008 std::vector<addr_t> address_list;
1009
1010 // Find the beginning & end index of the
1011 AddressRange fun_addr_range = sc.function->GetAddressRange();
1012 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1013 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1014
1015 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1016 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1017
1018 while (index_ptr <= end_ptr)
1019 {
1020 LineEntry line_entry;
1021 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1022 if (index_ptr == UINT32_MAX)
1023 break;
1024
1025 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
1026 if (address != LLDB_INVALID_ADDRESS)
1027 address_list.push_back (address);
1028 index_ptr++;
1029 }
1030
Greg Clayton53d68e72010-07-20 22:52:08 +00001031 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 +00001032 new_plan->SetOkayToDiscard(false);
1033 }
1034 else
1035 {
1036 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1037 result.SetStatus (eReturnStatusFailed);
1038 return false;
1039
1040 }
1041
1042 process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
1043 Error error (process->Resume ());
1044 if (error.Success())
1045 {
1046 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1047 if (synchronous_execution)
1048 {
1049 StateType state = process->WaitForProcessToStop (NULL);
1050
1051 result.SetDidChangeProcessState (true);
1052 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1053 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1054 }
1055 else
1056 {
1057 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1058 }
1059 }
1060 else
1061 {
1062 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1063 result.SetStatus (eReturnStatusFailed);
1064 }
1065
1066 }
1067 return result.Succeeded();
1068 }
1069protected:
1070 CommandOptions m_options;
1071
1072};
1073
1074lldb::OptionDefinition
1075CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1076{
Greg Clayton12bec712010-06-28 21:30:43 +00001077{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
1078{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
1079{ 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 +00001080{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1081};
1082
1083
1084//-------------------------------------------------------------------------
1085// CommandObjectThreadSelect
1086//-------------------------------------------------------------------------
1087
1088class CommandObjectThreadSelect : public CommandObject
1089{
1090public:
1091
1092 CommandObjectThreadSelect () :
1093 CommandObject ("thread select",
1094 "Selects a threads as the currently active thread.",
1095 "thread select <thread-index>",
1096 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1097 {
1098 }
1099
1100
1101 virtual
1102 ~CommandObjectThreadSelect ()
1103 {
1104 }
1105
1106 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001107 Execute
1108 (
1109 CommandInterpreter &interpreter,
1110 Args& command,
1111 CommandReturnObject &result
1112 )
Chris Lattner24943d22010-06-08 16:52:24 +00001113 {
Greg Clayton63094e02010-06-23 01:19:29 +00001114 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001115 if (process == NULL)
1116 {
1117 result.AppendError ("no process");
1118 result.SetStatus (eReturnStatusFailed);
1119 return false;
1120 }
1121 else if (command.GetArgumentCount() != 1)
1122 {
1123 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1124 result.SetStatus (eReturnStatusFailed);
1125 return false;
1126 }
1127
1128 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1129
1130 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1131 if (new_thread == NULL)
1132 {
1133 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1134 result.SetStatus (eReturnStatusFailed);
1135 return false;
1136 }
1137
1138 process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
1139
1140 DisplayThreadInfo (interpreter,
1141 result.GetOutputStream(),
1142 new_thread,
1143 false,
1144 true);
1145
1146 return result.Succeeded();
1147 }
1148
1149};
1150
1151
1152//-------------------------------------------------------------------------
1153// CommandObjectThreadList
1154//-------------------------------------------------------------------------
1155
Greg Clayton63094e02010-06-23 01:19:29 +00001156class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001157{
Greg Clayton63094e02010-06-23 01:19:29 +00001158public:
Chris Lattner24943d22010-06-08 16:52:24 +00001159
Chris Lattner24943d22010-06-08 16:52:24 +00001160
Greg Clayton63094e02010-06-23 01:19:29 +00001161 CommandObjectThreadList ():
1162 CommandObject ("thread list",
1163 "Shows a summary of all current threads in a process.",
1164 "thread list",
1165 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001166 {
Greg Clayton63094e02010-06-23 01:19:29 +00001167 }
Chris Lattner24943d22010-06-08 16:52:24 +00001168
Greg Clayton63094e02010-06-23 01:19:29 +00001169 ~CommandObjectThreadList()
1170 {
1171 }
1172
1173 bool
1174 Execute
1175 (
1176 CommandInterpreter &interpreter,
1177 Args& command,
1178 CommandReturnObject &result
1179 )
1180 {
1181 StreamString &strm = result.GetOutputStream();
1182 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1183 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
1184 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001185 {
Greg Clayton63094e02010-06-23 01:19:29 +00001186 const StateType state = exe_ctx.process->GetState();
1187
1188 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001189 {
Greg Clayton63094e02010-06-23 01:19:29 +00001190 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001191 {
Greg Clayton63094e02010-06-23 01:19:29 +00001192 int exit_status = exe_ctx.process->GetExitStatus();
1193 const char *exit_description = exe_ctx.process->GetExitDescription();
1194 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1195 exe_ctx.process->GetID(),
1196 exit_status,
1197 exit_status,
1198 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001199 }
1200 else
1201 {
Greg Clayton63094e02010-06-23 01:19:29 +00001202 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1203 if (exe_ctx.thread == NULL)
1204 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1205 if (exe_ctx.thread != NULL)
1206 {
1207 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1208 }
1209 else
1210 {
1211 result.AppendError ("no valid thread found in current process");
1212 result.SetStatus (eReturnStatusFailed);
1213 }
Chris Lattner24943d22010-06-08 16:52:24 +00001214 }
1215 }
Greg Clayton63094e02010-06-23 01:19:29 +00001216 else
1217 {
1218 result.AppendError ("process is currently running");
1219 result.SetStatus (eReturnStatusFailed);
1220 }
Chris Lattner24943d22010-06-08 16:52:24 +00001221 }
1222 else
1223 {
Greg Clayton63094e02010-06-23 01:19:29 +00001224 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001225 result.SetStatus (eReturnStatusFailed);
1226 }
Greg Clayton63094e02010-06-23 01:19:29 +00001227 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001228 }
Greg Clayton63094e02010-06-23 01:19:29 +00001229};
Chris Lattner24943d22010-06-08 16:52:24 +00001230
1231//-------------------------------------------------------------------------
1232// CommandObjectMultiwordThread
1233//-------------------------------------------------------------------------
1234
Greg Clayton63094e02010-06-23 01:19:29 +00001235CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +00001236 CommandObjectMultiword ("thread",
1237 "A set of commands for operating on one or more thread within a running process.",
1238 "thread <subcommand> [<subcommand-options>]")
1239{
Greg Clayton63094e02010-06-23 01:19:29 +00001240 LoadSubCommand (interpreter, "backtrace", CommandObjectSP (new CommandObjectThreadBacktrace ()));
1241 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectThreadContinue ()));
1242 LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectThreadList ()));
1243 LoadSubCommand (interpreter, "select", CommandObjectSP (new CommandObjectThreadSelect ()));
1244 LoadSubCommand (interpreter, "until", CommandObjectSP (new CommandObjectThreadUntil ()));
1245 LoadSubCommand (interpreter, "step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1246 "thread step-in",
1247 "Source level single step in in specified thread (current thread, if none specified).",
1248 "thread step-in [<thread-id>]",
1249 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1250 eStepTypeInto,
1251 eStepScopeSource)));
1252
1253 LoadSubCommand (interpreter, "step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
Chris Lattner24943d22010-06-08 16:52:24 +00001254 "Source level single step out in specified thread (current thread, if none specified).",
1255 "thread step-out [<thread-id>]",
1256 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1257 eStepTypeOut,
Greg Clayton63094e02010-06-23 01:19:29 +00001258 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001259
Greg Clayton63094e02010-06-23 01:19:29 +00001260 LoadSubCommand (interpreter, "step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001261 "Source level single step over in specified thread (current thread, if none specified).",
1262 "thread step-over [<thread-id>]",
1263 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1264 eStepTypeOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001265 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001266
Greg Clayton63094e02010-06-23 01:19:29 +00001267 LoadSubCommand (interpreter, "step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
Chris Lattner24943d22010-06-08 16:52:24 +00001268 "Single step one instruction in specified thread (current thread, if none specified).",
1269 "thread step-inst [<thread-id>]",
1270 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1271 eStepTypeTrace,
Greg Clayton63094e02010-06-23 01:19:29 +00001272 eStepScopeInstruction)));
1273
1274 LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001275 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1276 "thread step-inst-over [<thread-id>]",
1277 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1278 eStepTypeTraceOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001279 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001280}
1281
1282CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1283{
1284}
1285
1286