blob: 9d42b47ca1362d4f9cc4aeadbc936ca7467f57ea [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectThread.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/State.h"
18#include "lldb/Core/SourceManager.h"
19
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22
23#include "lldb/Target/Process.h"
24#include "lldb/Target/RegisterContext.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028#include "lldb/Target/ThreadPlanStepInstruction.h"
29#include "lldb/Target/ThreadPlanStepOut.h"
30#include "lldb/Target/ThreadPlanStepRange.h"
31#include "lldb/Target/ThreadPlanStepInRange.h"
32#include "lldb/Symbol/LineTable.h"
33#include "lldb/Symbol/LineEntry.h"
34
35using namespace lldb;
36using namespace lldb_private;
37
38
39bool
40lldb_private::DisplayThreadInfo
41(
Greg Clayton63094e02010-06-23 01:19:29 +000042 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000043 Stream &strm,
44 Thread *thread,
45 bool only_threads_with_stop_reason,
46 bool show_source
47)
48{
49 if (thread)
50 {
51 if (only_threads_with_stop_reason)
52 {
Greg Clayton643ee732010-08-04 01:40:35 +000053 if (thread->GetStopInfo() == NULL)
54 return false;
Chris Lattner24943d22010-06-08 16:52:24 +000055 }
56
57 strm.Indent();
Jim Inghamc8332952010-08-26 21:32:51 +000058 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' ');
Chris Lattner24943d22010-06-08 16:52:24 +000059
60 // Show one frame with only the first showing source
61 if (show_source)
62 {
Jim Ingham74989e82010-08-30 19:44:40 +000063 bool already_shown = false;
64 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0);
65 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
Caroline Tice5bc8c972010-09-20 20:44:43 +000066 if (interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
Jim Ingham74989e82010-08-30 19:44:40 +000067 {
68 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
69 }
70
Chris Lattner24943d22010-06-08 16:52:24 +000071 DisplayFramesForExecutionContext (thread,
72 interpreter,
73 strm,
Chris Lattner24943d22010-06-08 16:52:24 +000074 0, // Start at first frame
75 1, // Number of frames to show
76 false,// Don't show the frame info since we already displayed most of it above...
Jim Ingham74989e82010-08-30 19:44:40 +000077 !already_shown, // Show source for the first frame
Chris Lattner24943d22010-06-08 16:52:24 +000078 3, // lines of source context before
79 3); // lines of source context after
80 }
81 else
82 {
83 thread->DumpInfo (strm,
84 true, // Dump the stop reason?
85 true, // Dump the thread name?
86 true, // Dump the queue name?
87 0); // Display context info for stack frame zero
88
89 strm.EOL();
90 }
91
92 return true;
93 }
94 return false;
95}
96
97size_t
98lldb_private::DisplayThreadsInfo
99(
Greg Clayton63094e02010-06-23 01:19:29 +0000100 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000101 ExecutionContext *exe_ctx,
102 CommandReturnObject &result,
103 bool only_threads_with_stop_reason,
104 bool show_source
105)
106{
107 StreamString strm;
108
109 size_t num_thread_infos_dumped = 0;
110
111 if (!exe_ctx->process)
112 return 0;
113
114 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
115 if (num_threads > 0)
116 {
117
118 for (uint32_t i = 0; i < num_threads; i++)
119 {
120 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
121 if (thread)
122 {
123 if (DisplayThreadInfo (interpreter,
124 strm,
125 thread,
126 only_threads_with_stop_reason,
127 show_source))
128 ++num_thread_infos_dumped;
129 }
130 }
131 }
132
133 if (num_thread_infos_dumped > 0)
134 {
135 if (num_thread_infos_dumped < num_threads)
136 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
137
138 result.GetOutputStream().GetString().append(strm.GetString());
139 result.SetStatus (eReturnStatusSuccessFinishNoResult);
140 }
141 return num_thread_infos_dumped;
142}
143
144
145size_t
146lldb_private::DisplayFramesForExecutionContext
147(
148 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000149 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000150 Stream& strm,
Chris Lattner24943d22010-06-08 16:52:24 +0000151 uint32_t first_frame,
152 uint32_t num_frames,
153 bool show_frame_info,
154 uint32_t num_frames_with_source,
155 uint32_t source_lines_before,
156 uint32_t source_lines_after
157)
158{
159 if (thread == NULL)
160 return 0;
161
162 size_t num_frames_displayed = 0;
163
164 if (num_frames == 0)
165 return 0;
166
167 thread->DumpInfo (strm,
168 true, // Dump the stop reason?
169 true, // Dump the thread name?
170 true, // Dump the queue name?
Greg Clayton33ed1702010-08-24 00:45:41 +0000171 num_frames > 1 ? UINT32_MAX : first_frame); // Dump info for the first stack frame if we are showing only on frame
Chris Lattner24943d22010-06-08 16:52:24 +0000172 strm.EOL();
173 strm.IndentMore();
174
175 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000176 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-08-26 23:36:03 +0000177 uint32_t last_frame;
178
179 // Don't let the last frame wrap around...
180 if (num_frames == UINT32_MAX)
181 last_frame = UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +0000182 else
Jim Ingham8ab1a802010-08-26 23:36:03 +0000183 last_frame = first_frame + num_frames;
184
185 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000186 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000187 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
188 if (frame_sp.get() == NULL)
189 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000190
Jim Ingham8ab1a802010-08-26 23:36:03 +0000191 if (DisplayFrameForExecutionContext (thread,
192 frame_sp.get(),
193 interpreter,
194 strm,
195 show_frame_info,
196 num_frames_with_source > first_frame - frame_idx,
197 source_lines_before,
198 source_lines_after) == false)
199 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000200
Jim Ingham8ab1a802010-08-26 23:36:03 +0000201 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000202 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000203
Chris Lattner24943d22010-06-08 16:52:24 +0000204 strm.IndentLess();
205 return num_frames_displayed;
206}
207
208bool
209lldb_private::DisplayFrameForExecutionContext
210(
211 Thread *thread,
212 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000213 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000214 Stream& strm,
215 bool show_frame_info,
216 bool show_source,
217 uint32_t source_lines_before,
218 uint32_t source_lines_after
219)
220{
221 // thread and frame must be filled in prior to calling this function
222 if (thread && frame)
223 {
224 if (show_frame_info)
225 {
226 strm.Indent();
Greg Clayton72b71582010-09-02 21:44:10 +0000227 frame->Dump (&strm, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000228 strm.EOL();
229 }
230
231 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
232
233 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
234 {
Greg Clayton63094e02010-06-23 01:19:29 +0000235 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000236 sc.line_entry.file,
237 sc.line_entry.line,
238 3,
239 3,
240 "->",
241 &strm);
242
243 }
244 return true;
245 }
246 return false;
247}
248
249
250//-------------------------------------------------------------------------
251// CommandObjectThreadBacktrace
252//-------------------------------------------------------------------------
253
254class CommandObjectThreadBacktrace : public CommandObject
255{
256public:
257
Jim Ingham8ab1a802010-08-26 23:36:03 +0000258 class CommandOptions : public Options
259 {
260 public:
261
262 CommandOptions () :
263 Options()
264 {
265 // Keep default values of all options in one place: ResetOptionValues ()
266 ResetOptionValues ();
267 }
268
269 virtual
270 ~CommandOptions ()
271 {
272 }
273
274 virtual Error
275 SetOptionValue (int option_idx, const char *option_arg)
276 {
277 Error error;
278 char short_option = (char) m_getopt_table[option_idx].val;
279
280 switch (short_option)
281 {
282 case 'c':
283 {
284 bool success;
285 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
286 if (!success)
287 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
288 if (input_count < -1)
289 m_count = UINT32_MAX;
290 else
291 m_count = input_count;
292 }
293 break;
294 case 's':
295 {
296 bool success;
297 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
298 if (!success)
299 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
300 }
301 break;
302 default:
303 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
304 break;
305
306 }
307 return error;
308 }
309
310 void
311 ResetOptionValues ()
312 {
313 Options::ResetOptionValues();
314 m_count = -1;
315 m_start = 0;
316 }
317
318 const lldb::OptionDefinition*
319 GetDefinitions ()
320 {
321 return g_option_table;
322 }
323
324 // Options table: Required for subclasses of Options.
325
326 static lldb::OptionDefinition g_option_table[];
327
328 // Instance variables to hold the values for command options.
329 uint32_t m_count;
330 uint32_t m_start;
331 };
332
Greg Clayton238c0a12010-09-18 01:14:36 +0000333 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
334 CommandObject (interpreter,
335 "thread backtrace",
Caroline Tice31fbb642010-09-08 22:08:58 +0000336 "Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
Jim Inghameb10f7b2010-08-27 00:58:05 +0000337 "thread backtrace [<thread-index>] ...",
Chris Lattner24943d22010-06-08 16:52:24 +0000338 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000339 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000340 {
341 }
342
343 ~CommandObjectThreadBacktrace()
344 {
345 }
346
Jim Ingham8ab1a802010-08-26 23:36:03 +0000347 virtual Options *
348 GetOptions ()
349 {
350 return &m_options;
351 }
Chris Lattner24943d22010-06-08 16:52:24 +0000352
Greg Clayton63094e02010-06-23 01:19:29 +0000353 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000354 Execute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000355 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000356
357 bool show_frame_info = true;
358 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
359
360 result.SetStatus (eReturnStatusSuccessFinishResult);
361
Chris Lattner24943d22010-06-08 16:52:24 +0000362 if (command.GetArgumentCount() == 0)
363 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000364 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000365 if (exe_ctx.thread)
366 {
Chris Lattner24943d22010-06-08 16:52:24 +0000367 if (DisplayFramesForExecutionContext (exe_ctx.thread,
Greg Clayton238c0a12010-09-18 01:14:36 +0000368 m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000369 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000370 m_options.m_start,
371 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000372 show_frame_info,
373 num_frames_with_source,
374 3,
375 3))
376 {
377 result.SetStatus (eReturnStatusSuccessFinishResult);
378 }
379 }
380 else
381 {
382 result.AppendError ("invalid thread");
383 result.SetStatus (eReturnStatusFailed);
384 }
385 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000386 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
387 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000388 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000389 uint32_t num_threads = process->GetThreadList().GetSize();
390 for (uint32_t i = 0; i < num_threads; i++)
391 {
392 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
393 if (!DisplayFramesForExecutionContext (thread_sp.get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000394 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000395 result.GetOutputStream(),
396 m_options.m_start,
397 m_options.m_count,
398 show_frame_info,
399 num_frames_with_source,
400 3,
401 3))
402 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000403 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-08-27 00:58:05 +0000404 result.SetStatus (eReturnStatusFailed);
405 return false;
406 }
407 if (i < num_threads - 1)
408 result.AppendMessage("");
409 }
410 }
Chris Lattner24943d22010-06-08 16:52:24 +0000411 else
412 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000413 uint32_t num_args = command.GetArgumentCount();
Greg Clayton238c0a12010-09-18 01:14:36 +0000414 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000415 std::vector<ThreadSP> thread_sps;
416
417 for (uint32_t i = 0; i < num_args; i++)
418 {
419 bool success;
420
421 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
422 if (!success)
423 {
424 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
425 result.SetStatus (eReturnStatusFailed);
426 return false;
427 }
428
429 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
430
431 if (!thread_sps[i])
432 {
433 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
434 result.SetStatus (eReturnStatusFailed);
435 return false;
436 }
437
438 }
439
440 for (uint32_t i = 0; i < num_args; i++)
441 {
442 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000443 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000444 result.GetOutputStream(),
445 m_options.m_start,
446 m_options.m_count,
447 show_frame_info,
448 num_frames_with_source,
449 3,
450 3))
451 {
452 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
453 result.SetStatus (eReturnStatusFailed);
454 return false;
455 }
456
457 if (i < num_args - 1)
458 result.AppendMessage("");
459 }
Chris Lattner24943d22010-06-08 16:52:24 +0000460 }
461 return result.Succeeded();
462 }
463protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000464 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000465};
466
Jim Ingham8ab1a802010-08-26 23:36:03 +0000467lldb::OptionDefinition
468CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
469{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000470{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
471{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameNum, "Frame in which to start the backtrace"},
472{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000473};
Chris Lattner24943d22010-06-08 16:52:24 +0000474
Greg Claytonc0418152010-07-07 17:07:17 +0000475enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000476{
477 eStepScopeSource,
478 eStepScopeInstruction
479};
480
481class CommandObjectThreadStepWithTypeAndScope : public CommandObject
482{
483public:
484
485 class CommandOptions : public Options
486 {
487 public:
488
489 CommandOptions () :
490 Options()
491 {
492 // Keep default values of all options in one place: ResetOptionValues ()
493 ResetOptionValues ();
494 }
495
496 virtual
497 ~CommandOptions ()
498 {
499 }
500
501 virtual Error
502 SetOptionValue (int option_idx, const char *option_arg)
503 {
504 Error error;
505 char short_option = (char) m_getopt_table[option_idx].val;
506
507 switch (short_option)
508 {
509 case 'a':
510 {
511 bool success;
512 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
513 if (!success)
514 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
515 }
516 break;
517 case 'm':
518 {
519 bool found_one = false;
520 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
521 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
522 if (!found_one)
523 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
524 }
525 break;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000526 case 'r':
527 {
528 m_avoid_regexp.clear();
529 m_avoid_regexp.assign(option_arg);
530 }
531 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000532 default:
533 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
534 break;
535
536 }
537 return error;
538 }
539
540 void
541 ResetOptionValues ()
542 {
543 Options::ResetOptionValues();
544 m_avoid_no_debug = true;
545 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000546 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000547 }
548
549 const lldb::OptionDefinition*
550 GetDefinitions ()
551 {
552 return g_option_table;
553 }
554
555 // Options table: Required for subclasses of Options.
556
557 static lldb::OptionDefinition g_option_table[];
558
559 // Instance variables to hold the values for command options.
560 bool m_avoid_no_debug;
561 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000562 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000563 };
564
Greg Clayton238c0a12010-09-18 01:14:36 +0000565 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
566 const char *name,
567 const char *help,
568 const char *syntax,
569 uint32_t flags,
570 StepType step_type,
571 StepScope step_scope) :
572 CommandObject (interpreter, name, help, syntax, flags),
Chris Lattner24943d22010-06-08 16:52:24 +0000573 m_step_type (step_type),
574 m_step_scope (step_scope),
575 m_options ()
576 {
577 }
578
579 virtual
580 ~CommandObjectThreadStepWithTypeAndScope ()
581 {
582 }
583
584 virtual
585 Options *
586 GetOptions ()
587 {
588 return &m_options;
589 }
590
591 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000592 Execute
593 (
Greg Clayton63094e02010-06-23 01:19:29 +0000594 Args& command,
595 CommandReturnObject &result
596 )
Chris Lattner24943d22010-06-08 16:52:24 +0000597 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000598 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
599 bool synchronous_execution = m_interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000600
601 if (process == NULL)
602 {
603 result.AppendError ("need a valid process to step");
604 result.SetStatus (eReturnStatusFailed);
605
606 }
607 else
608 {
609 const uint32_t num_threads = process->GetThreadList().GetSize();
610 Thread *thread = NULL;
611
612 if (command.GetArgumentCount() == 0)
613 {
Jim Inghamc8332952010-08-26 21:32:51 +0000614 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000615 if (thread == NULL)
616 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000617 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000618 result.SetStatus (eReturnStatusFailed);
619 return false;
620 }
621 }
622 else
623 {
624 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
625 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
626 if (step_thread_idx == LLDB_INVALID_INDEX32)
627 {
628 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
629 result.SetStatus (eReturnStatusFailed);
630 return false;
631 }
632 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
633 if (thread == NULL)
634 {
635 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
636 step_thread_idx, 0, num_threads);
637 result.SetStatus (eReturnStatusFailed);
638 return false;
639 }
640 }
641
642 const bool abort_other_plans = false;
643 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
644
645 // This is a bit unfortunate, but not all the commands in this command object support
646 // only while stepping, so I use the bool for them.
647 bool bool_stop_other_threads;
648 if (m_options.m_run_mode == eAllThreads)
649 bool_stop_other_threads = false;
650 else
651 bool_stop_other_threads = true;
652
653 if (m_step_type == eStepTypeInto)
654 {
655 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
656 ThreadPlan *new_plan;
657
658 if (frame->HasDebugInformation ())
659 {
660 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
661 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
662 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000663 stop_other_threads,
664 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000665 if (new_plan && !m_options.m_avoid_regexp.empty())
666 {
667 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
668 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
669 }
Chris Lattner24943d22010-06-08 16:52:24 +0000670 }
671 else
672 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
673
Jim Inghamc8332952010-08-26 21:32:51 +0000674 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000675 process->Resume ();
676 }
677 else if (m_step_type == eStepTypeOver)
678 {
679 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
680 ThreadPlan *new_plan;
681
682 if (frame->HasDebugInformation())
683 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
684 m_step_type,
685 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
686 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000687 stop_other_threads,
688 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000689 else
690 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
691 abort_other_plans,
692 bool_stop_other_threads);
693
694 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
695 // Maybe there should be a parameter to control this.
696 new_plan->SetOkayToDiscard(false);
697
Jim Inghamc8332952010-08-26 21:32:51 +0000698 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000699 process->Resume ();
700 }
701 else if (m_step_type == eStepTypeTrace)
702 {
703 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000704 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000705 process->Resume ();
706 }
707 else if (m_step_type == eStepTypeTraceOver)
708 {
709 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000710 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000711 process->Resume ();
712 }
713 else if (m_step_type == eStepTypeOut)
714 {
715 ThreadPlan *new_plan;
716
717 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
718 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
719 // Maybe there should be a parameter to control this.
720 new_plan->SetOkayToDiscard(false);
721
Jim Inghamc8332952010-08-26 21:32:51 +0000722 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000723 process->Resume ();
724 }
725 else
726 {
727 result.AppendError ("step type is not supported");
728 result.SetStatus (eReturnStatusFailed);
729 }
730 if (synchronous_execution)
731 {
732 StateType state = process->WaitForProcessToStop (NULL);
733
734 //EventSP event_sp;
735 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
736 //while (! StateIsStoppedState (state))
737 // {
738 // state = process->WaitForStateChangedEvents (NULL, event_sp);
739 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000740 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000741 result.SetDidChangeProcessState (true);
742 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
743 result.SetStatus (eReturnStatusSuccessFinishNoResult);
744 }
745 }
746 return result.Succeeded();
747 }
748
749protected:
750 StepType m_step_type;
751 StepScope m_step_scope;
752 CommandOptions m_options;
753};
754
755static lldb::OptionEnumValueElement
756g_tri_running_mode[] =
757{
Greg Claytonfe424a92010-09-18 03:37:20 +0000758{ eOnlyThisThread, "this-thread", "Run only this thread"},
759{ eAllThreads, "all-threads", "Run all threads"},
760{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000761{ 0, NULL, NULL }
762};
763
764static lldb::OptionEnumValueElement
765g_duo_running_mode[] =
766{
Greg Claytonfe424a92010-09-18 03:37:20 +0000767{ eOnlyThisThread, "this-thread", "Run only this thread"},
768{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000769{ 0, NULL, NULL }
770};
771
772lldb::OptionDefinition
773CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
774{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000775{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."},
776{ LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."},
777{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
778{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000779};
780
781
782//-------------------------------------------------------------------------
783// CommandObjectThreadContinue
784//-------------------------------------------------------------------------
785
786class CommandObjectThreadContinue : public CommandObject
787{
788public:
789
Greg Clayton238c0a12010-09-18 01:14:36 +0000790 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
791 CommandObject (interpreter,
792 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000793 "Continue execution of one or more threads in an active process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000794 "thread continue <thread-index> [<thread-index> ...]",
795 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
796 {
797 }
798
799
800 virtual
801 ~CommandObjectThreadContinue ()
802 {
803 }
804
805 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000806 Execute
807 (
Greg Clayton63094e02010-06-23 01:19:29 +0000808 Args& command,
809 CommandReturnObject &result
810 )
Chris Lattner24943d22010-06-08 16:52:24 +0000811 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000812 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000813
Greg Clayton238c0a12010-09-18 01:14:36 +0000814 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000815 {
816 result.AppendError ("invalid target, set executable file using 'file' command");
817 result.SetStatus (eReturnStatusFailed);
818 return false;
819 }
820
Greg Clayton238c0a12010-09-18 01:14:36 +0000821 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000822 if (process == NULL)
823 {
824 result.AppendError ("no process exists. Cannot continue");
825 result.SetStatus (eReturnStatusFailed);
826 return false;
827 }
828
829 StateType state = process->GetState();
830 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
831 {
832 const uint32_t num_threads = process->GetThreadList().GetSize();
833 uint32_t idx;
834 const size_t argc = command.GetArgumentCount();
835 if (argc > 0)
836 {
837 std::vector<uint32_t> resume_thread_indexes;
838 for (uint32_t i=0; i<argc; ++i)
839 {
840 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
841 if (idx < num_threads)
842 resume_thread_indexes.push_back(idx);
843 else
844 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
845 }
846
847 if (resume_thread_indexes.empty())
848 {
849 result.AppendError ("no valid thread indexes were specified");
850 result.SetStatus (eReturnStatusFailed);
851 return false;
852 }
853 else
854 {
855 result.AppendMessage ("Resuming thread ");
856 for (idx=0; idx<num_threads; ++idx)
857 {
858 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
859 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
860 {
861 result.AppendMessageWithFormat ("%u ", idx);
862 thread->SetResumeState (eStateRunning);
863 }
864 else
865 {
866 thread->SetResumeState (eStateSuspended);
867 }
868 }
869 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
870 }
871 }
872 else
873 {
Jim Inghamc8332952010-08-26 21:32:51 +0000874 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000875 if (current_thread == NULL)
876 {
877 result.AppendError ("the process doesn't have a current thread");
878 result.SetStatus (eReturnStatusFailed);
879 return false;
880 }
881 // Set the actions that the threads should each take when resuming
882 for (idx=0; idx<num_threads; ++idx)
883 {
884 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
885 if (thread == current_thread)
886 {
887 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
888 thread->SetResumeState (eStateRunning);
889 }
890 else
891 {
892 thread->SetResumeState (eStateSuspended);
893 }
894 }
895 }
896
897 Error error (process->Resume());
898 if (error.Success())
899 {
900 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
901 if (synchronous_execution)
902 {
Greg Claytonbef15832010-07-14 00:18:15 +0000903 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000904
905 result.SetDidChangeProcessState (true);
906 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
907 result.SetStatus (eReturnStatusSuccessFinishNoResult);
908 }
909 else
910 {
911 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
912 }
913 }
914 else
915 {
916 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
917 result.SetStatus (eReturnStatusFailed);
918 }
919 }
920 else
921 {
922 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
923 StateAsCString(state));
924 result.SetStatus (eReturnStatusFailed);
925 }
926
927 return result.Succeeded();
928 }
929
930};
931
932//-------------------------------------------------------------------------
933// CommandObjectThreadUntil
934//-------------------------------------------------------------------------
935
936class CommandObjectThreadUntil : public CommandObject
937{
938public:
939
940 class CommandOptions : public Options
941 {
942 public:
943 uint32_t m_thread_idx;
944 uint32_t m_frame_idx;
945
946 CommandOptions () :
947 Options(),
948 m_thread_idx(LLDB_INVALID_THREAD_ID),
949 m_frame_idx(LLDB_INVALID_FRAME_ID)
950 {
951 // Keep default values of all options in one place: ResetOptionValues ()
952 ResetOptionValues ();
953 }
954
955 virtual
956 ~CommandOptions ()
957 {
958 }
959
960 virtual Error
961 SetOptionValue (int option_idx, const char *option_arg)
962 {
963 Error error;
964 char short_option = (char) m_getopt_table[option_idx].val;
965
966 switch (short_option)
967 {
968 case 't':
969 {
Greg Claytonbef15832010-07-14 00:18:15 +0000970 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +0000971 if (m_thread_idx == LLDB_INVALID_INDEX32)
972 {
973 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
974 }
975 }
976 break;
977 case 'f':
978 {
979 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
980 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
981 {
982 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
983 }
984 }
985 break;
986 case 'm':
987 {
988 bool found_one = false;
989 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
990 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
991
992 if (!found_one)
993 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
994 else if (run_mode == eAllThreads)
995 m_stop_others = false;
996 else
997 m_stop_others = true;
998
999 }
1000 break;
1001 default:
1002 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1003 break;
1004
1005 }
1006 return error;
1007 }
1008
1009 void
1010 ResetOptionValues ()
1011 {
1012 Options::ResetOptionValues();
1013 m_thread_idx = LLDB_INVALID_THREAD_ID;
1014 m_frame_idx = 0;
1015 m_stop_others = false;
1016 }
1017
1018 const lldb::OptionDefinition*
1019 GetDefinitions ()
1020 {
1021 return g_option_table;
1022 }
1023
1024 uint32_t m_step_thread_idx;
1025 bool m_stop_others;
1026
1027 // Options table: Required for subclasses of Options.
1028
1029 static lldb::OptionDefinition g_option_table[];
1030
1031 // Instance variables to hold the values for command options.
1032 };
1033
Greg Clayton238c0a12010-09-18 01:14:36 +00001034 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1035 CommandObject (interpreter,
1036 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001037 "Run the current or specified thread until it reaches a given line number or leaves the current function.",
Chris Lattner24943d22010-06-08 16:52:24 +00001038 "thread until [<cmd-options>] <line-number>",
1039 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1040 m_options ()
1041 {
1042 }
1043
1044
1045 virtual
1046 ~CommandObjectThreadUntil ()
1047 {
1048 }
1049
1050 virtual
1051 Options *
1052 GetOptions ()
1053 {
1054 return &m_options;
1055 }
1056
1057 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001058 Execute
1059 (
Greg Clayton63094e02010-06-23 01:19:29 +00001060 Args& command,
1061 CommandReturnObject &result
1062 )
Chris Lattner24943d22010-06-08 16:52:24 +00001063 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001064 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001065
Greg Clayton238c0a12010-09-18 01:14:36 +00001066 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001067 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001068 {
1069 result.AppendError ("invalid target, set executable file using 'file' command");
1070 result.SetStatus (eReturnStatusFailed);
1071 return false;
1072 }
1073
Greg Clayton238c0a12010-09-18 01:14:36 +00001074 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001075 if (process == NULL)
1076 {
1077 result.AppendError ("need a valid process to step");
1078 result.SetStatus (eReturnStatusFailed);
1079
1080 }
1081 else
1082 {
1083 Thread *thread = NULL;
1084 uint32_t line_number;
1085
1086 if (command.GetArgumentCount() != 1)
1087 {
1088 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1089 result.SetStatus (eReturnStatusFailed);
1090 return false;
1091 }
1092
1093 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1094 if (line_number == UINT32_MAX)
1095 {
1096 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1097 result.SetStatus (eReturnStatusFailed);
1098 return false;
1099 }
1100
1101 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1102 {
Jim Inghamc8332952010-08-26 21:32:51 +00001103 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001104 }
1105 else
1106 {
1107 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1108 }
1109
1110 if (thread == NULL)
1111 {
1112 const uint32_t num_threads = process->GetThreadList().GetSize();
1113 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1114 result.SetStatus (eReturnStatusFailed);
1115 return false;
1116 }
1117
1118 const bool abort_other_plans = true;
1119
1120 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1121 if (frame == NULL)
1122 {
1123
1124 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1125 result.SetStatus (eReturnStatusFailed);
1126 return false;
1127 }
1128
1129 ThreadPlan *new_plan;
1130
1131 if (frame->HasDebugInformation ())
1132 {
1133 // Finally we got here... Translate the given line number to a bunch of addresses:
1134 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1135 LineTable *line_table = NULL;
1136 if (sc.comp_unit)
1137 line_table = sc.comp_unit->GetLineTable();
1138
1139 if (line_table == NULL)
1140 {
1141 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1142 m_options.m_frame_idx, m_options.m_thread_idx);
1143 result.SetStatus (eReturnStatusFailed);
1144 return false;
1145 }
1146
1147 LineEntry function_start;
1148 uint32_t index_ptr = 0, end_ptr;
1149 std::vector<addr_t> address_list;
1150
1151 // Find the beginning & end index of the
1152 AddressRange fun_addr_range = sc.function->GetAddressRange();
1153 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1154 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1155
1156 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1157 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1158
1159 while (index_ptr <= end_ptr)
1160 {
1161 LineEntry line_entry;
1162 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1163 if (index_ptr == UINT32_MAX)
1164 break;
1165
Greg Claytoneea26402010-09-14 23:36:40 +00001166 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001167 if (address != LLDB_INVALID_ADDRESS)
1168 address_list.push_back (address);
1169 index_ptr++;
1170 }
1171
Greg Clayton53d68e72010-07-20 22:52:08 +00001172 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 +00001173 new_plan->SetOkayToDiscard(false);
1174 }
1175 else
1176 {
1177 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1178 result.SetStatus (eReturnStatusFailed);
1179 return false;
1180
1181 }
1182
Jim Inghamc8332952010-08-26 21:32:51 +00001183 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001184 Error error (process->Resume ());
1185 if (error.Success())
1186 {
1187 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1188 if (synchronous_execution)
1189 {
1190 StateType state = process->WaitForProcessToStop (NULL);
1191
1192 result.SetDidChangeProcessState (true);
1193 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1194 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1195 }
1196 else
1197 {
1198 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1199 }
1200 }
1201 else
1202 {
1203 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1204 result.SetStatus (eReturnStatusFailed);
1205 }
1206
1207 }
1208 return result.Succeeded();
1209 }
1210protected:
1211 CommandOptions m_options;
1212
1213};
1214
1215lldb::OptionDefinition
1216CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1217{
Caroline Tice4d6675c2010-10-01 19:59:14 +00001218{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameNum, "Frame index for until operation - defaults to 0"},
1219{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1220{ LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"},
1221{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001222};
1223
1224
1225//-------------------------------------------------------------------------
1226// CommandObjectThreadSelect
1227//-------------------------------------------------------------------------
1228
1229class CommandObjectThreadSelect : public CommandObject
1230{
1231public:
1232
Greg Clayton238c0a12010-09-18 01:14:36 +00001233 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1234 CommandObject (interpreter,
1235 "thread select",
1236 "Select a thread as the currently active thread.",
1237 "thread select <thread-index>",
1238 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001239 {
1240 }
1241
1242
1243 virtual
1244 ~CommandObjectThreadSelect ()
1245 {
1246 }
1247
1248 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001249 Execute
1250 (
Greg Clayton63094e02010-06-23 01:19:29 +00001251 Args& command,
1252 CommandReturnObject &result
1253 )
Chris Lattner24943d22010-06-08 16:52:24 +00001254 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001255 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001256 if (process == NULL)
1257 {
1258 result.AppendError ("no process");
1259 result.SetStatus (eReturnStatusFailed);
1260 return false;
1261 }
1262 else if (command.GetArgumentCount() != 1)
1263 {
1264 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1265 result.SetStatus (eReturnStatusFailed);
1266 return false;
1267 }
1268
1269 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1270
1271 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1272 if (new_thread == NULL)
1273 {
1274 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1275 result.SetStatus (eReturnStatusFailed);
1276 return false;
1277 }
1278
Jim Inghamc8332952010-08-26 21:32:51 +00001279 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001280 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001281
Greg Clayton238c0a12010-09-18 01:14:36 +00001282 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001283 result.GetOutputStream(),
1284 new_thread,
1285 false,
1286 true);
1287
1288 return result.Succeeded();
1289 }
1290
1291};
1292
1293
1294//-------------------------------------------------------------------------
1295// CommandObjectThreadList
1296//-------------------------------------------------------------------------
1297
Greg Clayton63094e02010-06-23 01:19:29 +00001298class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001299{
Greg Clayton63094e02010-06-23 01:19:29 +00001300public:
Chris Lattner24943d22010-06-08 16:52:24 +00001301
Chris Lattner24943d22010-06-08 16:52:24 +00001302
Greg Clayton238c0a12010-09-18 01:14:36 +00001303 CommandObjectThreadList (CommandInterpreter &interpreter):
1304 CommandObject (interpreter,
1305 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001306 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001307 "thread list",
1308 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001309 {
Greg Clayton63094e02010-06-23 01:19:29 +00001310 }
Chris Lattner24943d22010-06-08 16:52:24 +00001311
Greg Clayton63094e02010-06-23 01:19:29 +00001312 ~CommandObjectThreadList()
1313 {
1314 }
1315
1316 bool
1317 Execute
1318 (
Greg Clayton63094e02010-06-23 01:19:29 +00001319 Args& command,
1320 CommandReturnObject &result
1321 )
1322 {
1323 StreamString &strm = result.GetOutputStream();
1324 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001325 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001326 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001327 {
Greg Clayton63094e02010-06-23 01:19:29 +00001328 const StateType state = exe_ctx.process->GetState();
1329
1330 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001331 {
Greg Clayton63094e02010-06-23 01:19:29 +00001332 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001333 {
Greg Clayton63094e02010-06-23 01:19:29 +00001334 int exit_status = exe_ctx.process->GetExitStatus();
1335 const char *exit_description = exe_ctx.process->GetExitDescription();
1336 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1337 exe_ctx.process->GetID(),
1338 exit_status,
1339 exit_status,
1340 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001341 }
1342 else
1343 {
Greg Clayton63094e02010-06-23 01:19:29 +00001344 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1345 if (exe_ctx.thread == NULL)
1346 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1347 if (exe_ctx.thread != NULL)
1348 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001349 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001350 }
1351 else
1352 {
1353 result.AppendError ("no valid thread found in current process");
1354 result.SetStatus (eReturnStatusFailed);
1355 }
Chris Lattner24943d22010-06-08 16:52:24 +00001356 }
1357 }
Greg Clayton63094e02010-06-23 01:19:29 +00001358 else
1359 {
1360 result.AppendError ("process is currently running");
1361 result.SetStatus (eReturnStatusFailed);
1362 }
Chris Lattner24943d22010-06-08 16:52:24 +00001363 }
1364 else
1365 {
Greg Clayton63094e02010-06-23 01:19:29 +00001366 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001367 result.SetStatus (eReturnStatusFailed);
1368 }
Greg Clayton63094e02010-06-23 01:19:29 +00001369 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001370 }
Greg Clayton63094e02010-06-23 01:19:29 +00001371};
Chris Lattner24943d22010-06-08 16:52:24 +00001372
1373//-------------------------------------------------------------------------
1374// CommandObjectMultiwordThread
1375//-------------------------------------------------------------------------
1376
Greg Clayton63094e02010-06-23 01:19:29 +00001377CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001378 CommandObjectMultiword (interpreter,
1379 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001380 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001381 "thread <subcommand> [<subcommand-options>]")
1382{
Greg Clayton238c0a12010-09-18 01:14:36 +00001383 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1384 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1385 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1386 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1387 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1388 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1389 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001390 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001391 "Source level single step in specified thread (current thread, if none specified).",
1392 "thread step-in [<thread-id>]",
1393 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1394 eStepTypeInto,
1395 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001396
Greg Clayton238c0a12010-09-18 01:14:36 +00001397 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1398 interpreter,
1399 "thread step-out",
1400 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).",
1401 "thread step-out [<thread-id>]",
1402 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1403 eStepTypeOut,
1404 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001405
Greg Clayton238c0a12010-09-18 01:14:36 +00001406 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1407 interpreter,
1408 "thread step-over",
1409 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
1410 "thread step-over [<thread-id>]",
1411 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1412 eStepTypeOver,
1413 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001414
Greg Clayton238c0a12010-09-18 01:14:36 +00001415 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1416 interpreter,
1417 "thread step-inst",
1418 "Single step one instruction in specified thread (current thread, if none specified).",
1419 "thread step-inst [<thread-id>]",
1420 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1421 eStepTypeTrace,
1422 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001423
Greg Clayton238c0a12010-09-18 01:14:36 +00001424 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1425 interpreter,
1426 "thread step-inst-over",
1427 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1428 "thread step-inst-over [<thread-id>]",
1429 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1430 eStepTypeTraceOver,
1431 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001432}
1433
1434CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1435{
1436}
1437
1438