blob: bf4843da67fd34ef46494e29810363fee437f30a [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;
176 int frame_idx = 0;
177
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
335typedef enum StepScope
336{
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;
386 default:
387 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
388 break;
389
390 }
391 return error;
392 }
393
394 void
395 ResetOptionValues ()
396 {
397 Options::ResetOptionValues();
398 m_avoid_no_debug = true;
399 m_run_mode = eOnlyDuringStepping;
400 }
401
402 const lldb::OptionDefinition*
403 GetDefinitions ()
404 {
405 return g_option_table;
406 }
407
408 // Options table: Required for subclasses of Options.
409
410 static lldb::OptionDefinition g_option_table[];
411
412 // Instance variables to hold the values for command options.
413 bool m_avoid_no_debug;
414 RunMode m_run_mode;
415 };
416
417 CommandObjectThreadStepWithTypeAndScope (const char *name,
418 const char *help,
419 const char *syntax,
420 uint32_t flags,
421 StepType step_type,
422 StepScope step_scope) :
423 CommandObject (name, help, syntax, flags),
424 m_step_type (step_type),
425 m_step_scope (step_scope),
426 m_options ()
427 {
428 }
429
430 virtual
431 ~CommandObjectThreadStepWithTypeAndScope ()
432 {
433 }
434
435 virtual
436 Options *
437 GetOptions ()
438 {
439 return &m_options;
440 }
441
442 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000443 Execute
444 (
445 CommandInterpreter &interpreter,
446 Args& command,
447 CommandReturnObject &result
448 )
Chris Lattner24943d22010-06-08 16:52:24 +0000449 {
Greg Clayton63094e02010-06-23 01:19:29 +0000450 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
451 bool synchronous_execution = interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000452
453 if (process == NULL)
454 {
455 result.AppendError ("need a valid process to step");
456 result.SetStatus (eReturnStatusFailed);
457
458 }
459 else
460 {
461 const uint32_t num_threads = process->GetThreadList().GetSize();
462 Thread *thread = NULL;
463
464 if (command.GetArgumentCount() == 0)
465 {
466 thread = process->GetThreadList().GetCurrentThread().get();
467 if (thread == NULL)
468 {
469 result.AppendError ("no current thread in process");
470 result.SetStatus (eReturnStatusFailed);
471 return false;
472 }
473 }
474 else
475 {
476 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
477 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
478 if (step_thread_idx == LLDB_INVALID_INDEX32)
479 {
480 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
481 result.SetStatus (eReturnStatusFailed);
482 return false;
483 }
484 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
485 if (thread == NULL)
486 {
487 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
488 step_thread_idx, 0, num_threads);
489 result.SetStatus (eReturnStatusFailed);
490 return false;
491 }
492 }
493
494 const bool abort_other_plans = false;
495 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
496
497 // This is a bit unfortunate, but not all the commands in this command object support
498 // only while stepping, so I use the bool for them.
499 bool bool_stop_other_threads;
500 if (m_options.m_run_mode == eAllThreads)
501 bool_stop_other_threads = false;
502 else
503 bool_stop_other_threads = true;
504
505 if (m_step_type == eStepTypeInto)
506 {
507 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
508 ThreadPlan *new_plan;
509
510 if (frame->HasDebugInformation ())
511 {
512 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
513 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
514 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000515 stop_other_threads,
516 m_options.m_avoid_no_debug);
Chris Lattner24943d22010-06-08 16:52:24 +0000517 }
518 else
519 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
520
521 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
522 process->Resume ();
523 }
524 else if (m_step_type == eStepTypeOver)
525 {
526 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
527 ThreadPlan *new_plan;
528
529 if (frame->HasDebugInformation())
530 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
531 m_step_type,
532 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
533 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000534 stop_other_threads,
535 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000536 else
537 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
538 abort_other_plans,
539 bool_stop_other_threads);
540
541 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
542 // Maybe there should be a parameter to control this.
543 new_plan->SetOkayToDiscard(false);
544
545 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
546 process->Resume ();
547 }
548 else if (m_step_type == eStepTypeTrace)
549 {
550 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
551 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
552 process->Resume ();
553 }
554 else if (m_step_type == eStepTypeTraceOver)
555 {
556 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
557 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
558 process->Resume ();
559 }
560 else if (m_step_type == eStepTypeOut)
561 {
562 ThreadPlan *new_plan;
563
564 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
565 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
566 // Maybe there should be a parameter to control this.
567 new_plan->SetOkayToDiscard(false);
568
569 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
570 process->Resume ();
571 }
572 else
573 {
574 result.AppendError ("step type is not supported");
575 result.SetStatus (eReturnStatusFailed);
576 }
577 if (synchronous_execution)
578 {
579 StateType state = process->WaitForProcessToStop (NULL);
580
581 //EventSP event_sp;
582 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
583 //while (! StateIsStoppedState (state))
584 // {
585 // state = process->WaitForStateChangedEvents (NULL, event_sp);
586 // }
587 process->GetThreadList().SetCurrentThreadByID (thread->GetID());
588 result.SetDidChangeProcessState (true);
589 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
590 result.SetStatus (eReturnStatusSuccessFinishNoResult);
591 }
592 }
593 return result.Succeeded();
594 }
595
596protected:
597 StepType m_step_type;
598 StepScope m_step_scope;
599 CommandOptions m_options;
600};
601
602static lldb::OptionEnumValueElement
603g_tri_running_mode[] =
604{
605{ eOnlyThisThread, "thisThread", "Run only this thread"},
606{ eAllThreads, "allThreads", "Run all threads"},
607{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
608{ 0, NULL, NULL }
609};
610
611static lldb::OptionEnumValueElement
612g_duo_running_mode[] =
613{
614{ eOnlyThisThread, "thisThread", "Run only this thread"},
615{ eAllThreads, "allThreads", "Run all threads"},
616{ 0, NULL, NULL }
617};
618
619lldb::OptionDefinition
620CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
621{
Jim Ingham34e9a982010-06-15 18:47:14 +0000622{ LLDB_OPT_SET_1, true, "avoid_no_debug", 'a', required_argument, NULL, 0, "<avoid_no_debug>", "Should step-in step over functions with no debug information"},
623{ LLDB_OPT_SET_1, true, "run_mode", 'm', required_argument, g_tri_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"},
Chris Lattner24943d22010-06-08 16:52:24 +0000624{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
625};
626
627
628//-------------------------------------------------------------------------
629// CommandObjectThreadContinue
630//-------------------------------------------------------------------------
631
632class CommandObjectThreadContinue : public CommandObject
633{
634public:
635
636 CommandObjectThreadContinue () :
637 CommandObject ("thread continue",
638 "Continues execution of one or more threads in an active process.",
639 "thread continue <thread-index> [<thread-index> ...]",
640 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
641 {
642 }
643
644
645 virtual
646 ~CommandObjectThreadContinue ()
647 {
648 }
649
650 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000651 Execute
652 (
653 CommandInterpreter &interpreter,
654 Args& command,
655 CommandReturnObject &result
656 )
Chris Lattner24943d22010-06-08 16:52:24 +0000657 {
Greg Clayton63094e02010-06-23 01:19:29 +0000658 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000659
Greg Clayton63094e02010-06-23 01:19:29 +0000660 if (!interpreter.GetDebugger().GetCurrentTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000661 {
662 result.AppendError ("invalid target, set executable file using 'file' command");
663 result.SetStatus (eReturnStatusFailed);
664 return false;
665 }
666
Greg Clayton63094e02010-06-23 01:19:29 +0000667 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000668 if (process == NULL)
669 {
670 result.AppendError ("no process exists. Cannot continue");
671 result.SetStatus (eReturnStatusFailed);
672 return false;
673 }
674
675 StateType state = process->GetState();
676 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
677 {
678 const uint32_t num_threads = process->GetThreadList().GetSize();
679 uint32_t idx;
680 const size_t argc = command.GetArgumentCount();
681 if (argc > 0)
682 {
683 std::vector<uint32_t> resume_thread_indexes;
684 for (uint32_t i=0; i<argc; ++i)
685 {
686 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
687 if (idx < num_threads)
688 resume_thread_indexes.push_back(idx);
689 else
690 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
691 }
692
693 if (resume_thread_indexes.empty())
694 {
695 result.AppendError ("no valid thread indexes were specified");
696 result.SetStatus (eReturnStatusFailed);
697 return false;
698 }
699 else
700 {
701 result.AppendMessage ("Resuming thread ");
702 for (idx=0; idx<num_threads; ++idx)
703 {
704 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
705 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
706 {
707 result.AppendMessageWithFormat ("%u ", idx);
708 thread->SetResumeState (eStateRunning);
709 }
710 else
711 {
712 thread->SetResumeState (eStateSuspended);
713 }
714 }
715 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
716 }
717 }
718 else
719 {
720 Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
721 if (current_thread == NULL)
722 {
723 result.AppendError ("the process doesn't have a current thread");
724 result.SetStatus (eReturnStatusFailed);
725 return false;
726 }
727 // Set the actions that the threads should each take when resuming
728 for (idx=0; idx<num_threads; ++idx)
729 {
730 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
731 if (thread == current_thread)
732 {
733 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
734 thread->SetResumeState (eStateRunning);
735 }
736 else
737 {
738 thread->SetResumeState (eStateSuspended);
739 }
740 }
741 }
742
743 Error error (process->Resume());
744 if (error.Success())
745 {
746 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
747 if (synchronous_execution)
748 {
749 StateType state = process->WaitForProcessToStop (NULL);
750
751 result.SetDidChangeProcessState (true);
752 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
753 result.SetStatus (eReturnStatusSuccessFinishNoResult);
754 }
755 else
756 {
757 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
758 }
759 }
760 else
761 {
762 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
763 result.SetStatus (eReturnStatusFailed);
764 }
765 }
766 else
767 {
768 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
769 StateAsCString(state));
770 result.SetStatus (eReturnStatusFailed);
771 }
772
773 return result.Succeeded();
774 }
775
776};
777
778//-------------------------------------------------------------------------
779// CommandObjectThreadUntil
780//-------------------------------------------------------------------------
781
782class CommandObjectThreadUntil : public CommandObject
783{
784public:
785
786 class CommandOptions : public Options
787 {
788 public:
789 uint32_t m_thread_idx;
790 uint32_t m_frame_idx;
791
792 CommandOptions () :
793 Options(),
794 m_thread_idx(LLDB_INVALID_THREAD_ID),
795 m_frame_idx(LLDB_INVALID_FRAME_ID)
796 {
797 // Keep default values of all options in one place: ResetOptionValues ()
798 ResetOptionValues ();
799 }
800
801 virtual
802 ~CommandOptions ()
803 {
804 }
805
806 virtual Error
807 SetOptionValue (int option_idx, const char *option_arg)
808 {
809 Error error;
810 char short_option = (char) m_getopt_table[option_idx].val;
811
812 switch (short_option)
813 {
814 case 't':
815 {
816 uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
817 if (m_thread_idx == LLDB_INVALID_INDEX32)
818 {
819 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
820 }
821 }
822 break;
823 case 'f':
824 {
825 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
826 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
827 {
828 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
829 }
830 }
831 break;
832 case 'm':
833 {
834 bool found_one = false;
835 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
836 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
837
838 if (!found_one)
839 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
840 else if (run_mode == eAllThreads)
841 m_stop_others = false;
842 else
843 m_stop_others = true;
844
845 }
846 break;
847 default:
848 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
849 break;
850
851 }
852 return error;
853 }
854
855 void
856 ResetOptionValues ()
857 {
858 Options::ResetOptionValues();
859 m_thread_idx = LLDB_INVALID_THREAD_ID;
860 m_frame_idx = 0;
861 m_stop_others = false;
862 }
863
864 const lldb::OptionDefinition*
865 GetDefinitions ()
866 {
867 return g_option_table;
868 }
869
870 uint32_t m_step_thread_idx;
871 bool m_stop_others;
872
873 // Options table: Required for subclasses of Options.
874
875 static lldb::OptionDefinition g_option_table[];
876
877 // Instance variables to hold the values for command options.
878 };
879
880 CommandObjectThreadUntil () :
881 CommandObject ("thread until",
882 "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
883 "thread until [<cmd-options>] <line-number>",
884 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
885 m_options ()
886 {
887 }
888
889
890 virtual
891 ~CommandObjectThreadUntil ()
892 {
893 }
894
895 virtual
896 Options *
897 GetOptions ()
898 {
899 return &m_options;
900 }
901
902 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000903 Execute
904 (
905 CommandInterpreter &interpreter,
906 Args& command,
907 CommandReturnObject &result
908 )
Chris Lattner24943d22010-06-08 16:52:24 +0000909 {
Greg Clayton63094e02010-06-23 01:19:29 +0000910 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000911
Greg Clayton63094e02010-06-23 01:19:29 +0000912 if (!interpreter.GetDebugger().GetCurrentTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000913 {
914 result.AppendError ("invalid target, set executable file using 'file' command");
915 result.SetStatus (eReturnStatusFailed);
916 return false;
917 }
918
Greg Clayton63094e02010-06-23 01:19:29 +0000919 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000920 if (process == NULL)
921 {
922 result.AppendError ("need a valid process to step");
923 result.SetStatus (eReturnStatusFailed);
924
925 }
926 else
927 {
928 Thread *thread = NULL;
929 uint32_t line_number;
930
931 if (command.GetArgumentCount() != 1)
932 {
933 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
934 result.SetStatus (eReturnStatusFailed);
935 return false;
936 }
937
938 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
939 if (line_number == UINT32_MAX)
940 {
941 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
942 result.SetStatus (eReturnStatusFailed);
943 return false;
944 }
945
946 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
947 {
948 thread = process->GetThreadList().GetCurrentThread().get();
949 }
950 else
951 {
952 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
953 }
954
955 if (thread == NULL)
956 {
957 const uint32_t num_threads = process->GetThreadList().GetSize();
958 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
959 result.SetStatus (eReturnStatusFailed);
960 return false;
961 }
962
963 const bool abort_other_plans = true;
964
965 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
966 if (frame == NULL)
967 {
968
969 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
970 result.SetStatus (eReturnStatusFailed);
971 return false;
972 }
973
974 ThreadPlan *new_plan;
975
976 if (frame->HasDebugInformation ())
977 {
978 // Finally we got here... Translate the given line number to a bunch of addresses:
979 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
980 LineTable *line_table = NULL;
981 if (sc.comp_unit)
982 line_table = sc.comp_unit->GetLineTable();
983
984 if (line_table == NULL)
985 {
986 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
987 m_options.m_frame_idx, m_options.m_thread_idx);
988 result.SetStatus (eReturnStatusFailed);
989 return false;
990 }
991
992 LineEntry function_start;
993 uint32_t index_ptr = 0, end_ptr;
994 std::vector<addr_t> address_list;
995
996 // Find the beginning & end index of the
997 AddressRange fun_addr_range = sc.function->GetAddressRange();
998 Address fun_start_addr = fun_addr_range.GetBaseAddress();
999 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1000
1001 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1002 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1003
1004 while (index_ptr <= end_ptr)
1005 {
1006 LineEntry line_entry;
1007 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1008 if (index_ptr == UINT32_MAX)
1009 break;
1010
1011 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
1012 if (address != LLDB_INVALID_ADDRESS)
1013 address_list.push_back (address);
1014 index_ptr++;
1015 }
1016
1017 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others);
1018 new_plan->SetOkayToDiscard(false);
1019 }
1020 else
1021 {
1022 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1023 result.SetStatus (eReturnStatusFailed);
1024 return false;
1025
1026 }
1027
1028 process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
1029 Error error (process->Resume ());
1030 if (error.Success())
1031 {
1032 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1033 if (synchronous_execution)
1034 {
1035 StateType state = process->WaitForProcessToStop (NULL);
1036
1037 result.SetDidChangeProcessState (true);
1038 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1039 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1040 }
1041 else
1042 {
1043 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1044 }
1045 }
1046 else
1047 {
1048 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1049 result.SetStatus (eReturnStatusFailed);
1050 }
1051
1052 }
1053 return result.Succeeded();
1054 }
1055protected:
1056 CommandOptions m_options;
1057
1058};
1059
1060lldb::OptionDefinition
1061CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1062{
Jim Ingham34e9a982010-06-15 18:47:14 +00001063{ LLDB_OPT_SET_1, true, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
1064{ LLDB_OPT_SET_1, true, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
1065{ LLDB_OPT_SET_1, true, "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 +00001066{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
1067};
1068
1069
1070//-------------------------------------------------------------------------
1071// CommandObjectThreadSelect
1072//-------------------------------------------------------------------------
1073
1074class CommandObjectThreadSelect : public CommandObject
1075{
1076public:
1077
1078 CommandObjectThreadSelect () :
1079 CommandObject ("thread select",
1080 "Selects a threads as the currently active thread.",
1081 "thread select <thread-index>",
1082 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1083 {
1084 }
1085
1086
1087 virtual
1088 ~CommandObjectThreadSelect ()
1089 {
1090 }
1091
1092 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001093 Execute
1094 (
1095 CommandInterpreter &interpreter,
1096 Args& command,
1097 CommandReturnObject &result
1098 )
Chris Lattner24943d22010-06-08 16:52:24 +00001099 {
Greg Clayton63094e02010-06-23 01:19:29 +00001100 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001101 if (process == NULL)
1102 {
1103 result.AppendError ("no process");
1104 result.SetStatus (eReturnStatusFailed);
1105 return false;
1106 }
1107 else if (command.GetArgumentCount() != 1)
1108 {
1109 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1110 result.SetStatus (eReturnStatusFailed);
1111 return false;
1112 }
1113
1114 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1115
1116 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1117 if (new_thread == NULL)
1118 {
1119 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1120 result.SetStatus (eReturnStatusFailed);
1121 return false;
1122 }
1123
1124 process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
1125
1126 DisplayThreadInfo (interpreter,
1127 result.GetOutputStream(),
1128 new_thread,
1129 false,
1130 true);
1131
1132 return result.Succeeded();
1133 }
1134
1135};
1136
1137
1138//-------------------------------------------------------------------------
1139// CommandObjectThreadList
1140//-------------------------------------------------------------------------
1141
Greg Clayton63094e02010-06-23 01:19:29 +00001142class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001143{
Greg Clayton63094e02010-06-23 01:19:29 +00001144public:
Chris Lattner24943d22010-06-08 16:52:24 +00001145
Chris Lattner24943d22010-06-08 16:52:24 +00001146
Greg Clayton63094e02010-06-23 01:19:29 +00001147 CommandObjectThreadList ():
1148 CommandObject ("thread list",
1149 "Shows a summary of all current threads in a process.",
1150 "thread list",
1151 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001152 {
Greg Clayton63094e02010-06-23 01:19:29 +00001153 }
Chris Lattner24943d22010-06-08 16:52:24 +00001154
Greg Clayton63094e02010-06-23 01:19:29 +00001155 ~CommandObjectThreadList()
1156 {
1157 }
1158
1159 bool
1160 Execute
1161 (
1162 CommandInterpreter &interpreter,
1163 Args& command,
1164 CommandReturnObject &result
1165 )
1166 {
1167 StreamString &strm = result.GetOutputStream();
1168 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1169 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
1170 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001171 {
Greg Clayton63094e02010-06-23 01:19:29 +00001172 const StateType state = exe_ctx.process->GetState();
1173
1174 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001175 {
Greg Clayton63094e02010-06-23 01:19:29 +00001176 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001177 {
Greg Clayton63094e02010-06-23 01:19:29 +00001178 int exit_status = exe_ctx.process->GetExitStatus();
1179 const char *exit_description = exe_ctx.process->GetExitDescription();
1180 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1181 exe_ctx.process->GetID(),
1182 exit_status,
1183 exit_status,
1184 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001185 }
1186 else
1187 {
Greg Clayton63094e02010-06-23 01:19:29 +00001188 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1189 if (exe_ctx.thread == NULL)
1190 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1191 if (exe_ctx.thread != NULL)
1192 {
1193 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
1194 }
1195 else
1196 {
1197 result.AppendError ("no valid thread found in current process");
1198 result.SetStatus (eReturnStatusFailed);
1199 }
Chris Lattner24943d22010-06-08 16:52:24 +00001200 }
1201 }
Greg Clayton63094e02010-06-23 01:19:29 +00001202 else
1203 {
1204 result.AppendError ("process is currently running");
1205 result.SetStatus (eReturnStatusFailed);
1206 }
Chris Lattner24943d22010-06-08 16:52:24 +00001207 }
1208 else
1209 {
Greg Clayton63094e02010-06-23 01:19:29 +00001210 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001211 result.SetStatus (eReturnStatusFailed);
1212 }
Greg Clayton63094e02010-06-23 01:19:29 +00001213 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001214 }
Greg Clayton63094e02010-06-23 01:19:29 +00001215};
Chris Lattner24943d22010-06-08 16:52:24 +00001216
1217//-------------------------------------------------------------------------
1218// CommandObjectMultiwordThread
1219//-------------------------------------------------------------------------
1220
Greg Clayton63094e02010-06-23 01:19:29 +00001221CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +00001222 CommandObjectMultiword ("thread",
1223 "A set of commands for operating on one or more thread within a running process.",
1224 "thread <subcommand> [<subcommand-options>]")
1225{
Greg Clayton63094e02010-06-23 01:19:29 +00001226 LoadSubCommand (interpreter, "backtrace", CommandObjectSP (new CommandObjectThreadBacktrace ()));
1227 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectThreadContinue ()));
1228 LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectThreadList ()));
1229 LoadSubCommand (interpreter, "select", CommandObjectSP (new CommandObjectThreadSelect ()));
1230 LoadSubCommand (interpreter, "until", CommandObjectSP (new CommandObjectThreadUntil ()));
1231 LoadSubCommand (interpreter, "step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1232 "thread step-in",
1233 "Source level single step in in specified thread (current thread, if none specified).",
1234 "thread step-in [<thread-id>]",
1235 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1236 eStepTypeInto,
1237 eStepScopeSource)));
1238
1239 LoadSubCommand (interpreter, "step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
Chris Lattner24943d22010-06-08 16:52:24 +00001240 "Source level single step out in specified thread (current thread, if none specified).",
1241 "thread step-out [<thread-id>]",
1242 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1243 eStepTypeOut,
Greg Clayton63094e02010-06-23 01:19:29 +00001244 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001245
Greg Clayton63094e02010-06-23 01:19:29 +00001246 LoadSubCommand (interpreter, "step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001247 "Source level single step over in specified thread (current thread, if none specified).",
1248 "thread step-over [<thread-id>]",
1249 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1250 eStepTypeOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001251 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001252
Greg Clayton63094e02010-06-23 01:19:29 +00001253 LoadSubCommand (interpreter, "step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
Chris Lattner24943d22010-06-08 16:52:24 +00001254 "Single step one instruction in specified thread (current thread, if none specified).",
1255 "thread step-inst [<thread-id>]",
1256 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1257 eStepTypeTrace,
Greg Clayton63094e02010-06-23 01:19:29 +00001258 eStepScopeInstruction)));
1259
1260 LoadSubCommand (interpreter, "step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
Chris Lattner24943d22010-06-08 16:52:24 +00001261 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1262 "thread step-inst-over [<thread-id>]",
1263 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1264 eStepTypeTraceOver,
Greg Clayton63094e02010-06-23 01:19:29 +00001265 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001266}
1267
1268CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1269{
1270}
1271
1272