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