blob: f1b528d5856166cec17c1089926b15409056ed01 [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 {
Greg Claytona830adb2010-10-04 01:05:56 +000083 thread->DumpUsingSettingsFormat (strm, 0);
Chris Lattner24943d22010-06-08 16:52:24 +000084 }
85
86 return true;
87 }
88 return false;
89}
90
91size_t
92lldb_private::DisplayThreadsInfo
93(
Greg Clayton63094e02010-06-23 01:19:29 +000094 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000095 ExecutionContext *exe_ctx,
96 CommandReturnObject &result,
97 bool only_threads_with_stop_reason,
98 bool show_source
99)
100{
101 StreamString strm;
102
103 size_t num_thread_infos_dumped = 0;
104
105 if (!exe_ctx->process)
106 return 0;
107
108 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
109 if (num_threads > 0)
110 {
111
112 for (uint32_t i = 0; i < num_threads; i++)
113 {
114 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
115 if (thread)
116 {
117 if (DisplayThreadInfo (interpreter,
118 strm,
119 thread,
120 only_threads_with_stop_reason,
121 show_source))
122 ++num_thread_infos_dumped;
123 }
124 }
125 }
126
127 if (num_thread_infos_dumped > 0)
128 {
129 if (num_thread_infos_dumped < num_threads)
130 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
131
132 result.GetOutputStream().GetString().append(strm.GetString());
133 result.SetStatus (eReturnStatusSuccessFinishNoResult);
134 }
135 return num_thread_infos_dumped;
136}
137
138
139size_t
140lldb_private::DisplayFramesForExecutionContext
141(
142 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000143 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000144 Stream& strm,
Chris Lattner24943d22010-06-08 16:52:24 +0000145 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
Greg Claytona830adb2010-10-04 01:05:56 +0000161 thread->DumpUsingSettingsFormat (strm, num_frames > 1 ? UINT32_MAX : first_frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000162 strm.IndentMore();
163
164 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000165 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-08-26 23:36:03 +0000166 uint32_t last_frame;
167
168 // Don't let the last frame wrap around...
169 if (num_frames == UINT32_MAX)
170 last_frame = UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +0000171 else
Jim Ingham8ab1a802010-08-26 23:36:03 +0000172 last_frame = first_frame + num_frames;
173
174 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000175 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000176 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
177 if (frame_sp.get() == NULL)
178 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000179
Jim Ingham8ab1a802010-08-26 23:36:03 +0000180 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;
Chris Lattner24943d22010-06-08 16:52:24 +0000189
Jim Ingham8ab1a802010-08-26 23:36:03 +0000190 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000191 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000192
Chris Lattner24943d22010-06-08 16:52:24 +0000193 strm.IndentLess();
194 return num_frames_displayed;
195}
196
197bool
198lldb_private::DisplayFrameForExecutionContext
199(
200 Thread *thread,
201 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000202 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000203 Stream& strm,
204 bool show_frame_info,
205 bool show_source,
206 uint32_t source_lines_before,
207 uint32_t source_lines_after
208)
209{
210 // thread and frame must be filled in prior to calling this function
211 if (thread && frame)
212 {
213 if (show_frame_info)
214 {
215 strm.Indent();
Greg Claytona830adb2010-10-04 01:05:56 +0000216 frame->DumpUsingSettingsFormat (&strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000217 }
218
219 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
220
221 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
222 {
Greg Clayton63094e02010-06-23 01:19:29 +0000223 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000224 sc.line_entry.file,
225 sc.line_entry.line,
226 3,
227 3,
228 "->",
229 &strm);
230
231 }
232 return true;
233 }
234 return false;
235}
236
237
238//-------------------------------------------------------------------------
239// CommandObjectThreadBacktrace
240//-------------------------------------------------------------------------
241
242class CommandObjectThreadBacktrace : public CommandObject
243{
244public:
245
Jim Ingham8ab1a802010-08-26 23:36:03 +0000246 class CommandOptions : public Options
247 {
248 public:
249
250 CommandOptions () :
251 Options()
252 {
253 // Keep default values of all options in one place: ResetOptionValues ()
254 ResetOptionValues ();
255 }
256
257 virtual
258 ~CommandOptions ()
259 {
260 }
261
262 virtual Error
263 SetOptionValue (int option_idx, const char *option_arg)
264 {
265 Error error;
266 char short_option = (char) m_getopt_table[option_idx].val;
267
268 switch (short_option)
269 {
270 case 'c':
271 {
272 bool success;
273 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
274 if (!success)
275 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
276 if (input_count < -1)
277 m_count = UINT32_MAX;
278 else
279 m_count = input_count;
280 }
281 break;
282 case 's':
283 {
284 bool success;
285 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
286 if (!success)
287 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
288 }
289 break;
290 default:
291 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
292 break;
293
294 }
295 return error;
296 }
297
298 void
299 ResetOptionValues ()
300 {
301 Options::ResetOptionValues();
302 m_count = -1;
303 m_start = 0;
304 }
305
306 const lldb::OptionDefinition*
307 GetDefinitions ()
308 {
309 return g_option_table;
310 }
311
312 // Options table: Required for subclasses of Options.
313
314 static lldb::OptionDefinition g_option_table[];
315
316 // Instance variables to hold the values for command options.
317 uint32_t m_count;
318 uint32_t m_start;
319 };
320
Greg Clayton238c0a12010-09-18 01:14:36 +0000321 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
322 CommandObject (interpreter,
323 "thread backtrace",
Caroline Tice31fbb642010-09-08 22:08:58 +0000324 "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 +0000325 "thread backtrace [<thread-index>] ...",
Chris Lattner24943d22010-06-08 16:52:24 +0000326 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000327 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000328 {
329 }
330
331 ~CommandObjectThreadBacktrace()
332 {
333 }
334
Jim Ingham8ab1a802010-08-26 23:36:03 +0000335 virtual Options *
336 GetOptions ()
337 {
338 return &m_options;
339 }
Chris Lattner24943d22010-06-08 16:52:24 +0000340
Greg Clayton63094e02010-06-23 01:19:29 +0000341 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000342 Execute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000343 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000344
345 bool show_frame_info = true;
346 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
347
348 result.SetStatus (eReturnStatusSuccessFinishResult);
349
Chris Lattner24943d22010-06-08 16:52:24 +0000350 if (command.GetArgumentCount() == 0)
351 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000352 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000353 if (exe_ctx.thread)
354 {
Chris Lattner24943d22010-06-08 16:52:24 +0000355 if (DisplayFramesForExecutionContext (exe_ctx.thread,
Greg Clayton238c0a12010-09-18 01:14:36 +0000356 m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000357 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000358 m_options.m_start,
359 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000360 show_frame_info,
361 num_frames_with_source,
362 3,
363 3))
364 {
365 result.SetStatus (eReturnStatusSuccessFinishResult);
366 }
367 }
368 else
369 {
370 result.AppendError ("invalid thread");
371 result.SetStatus (eReturnStatusFailed);
372 }
373 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000374 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
375 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000376 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000377 uint32_t num_threads = process->GetThreadList().GetSize();
378 for (uint32_t i = 0; i < num_threads; i++)
379 {
380 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
381 if (!DisplayFramesForExecutionContext (thread_sp.get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000382 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000383 result.GetOutputStream(),
384 m_options.m_start,
385 m_options.m_count,
386 show_frame_info,
387 num_frames_with_source,
388 3,
389 3))
390 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000391 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-08-27 00:58:05 +0000392 result.SetStatus (eReturnStatusFailed);
393 return false;
394 }
395 if (i < num_threads - 1)
396 result.AppendMessage("");
397 }
398 }
Chris Lattner24943d22010-06-08 16:52:24 +0000399 else
400 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000401 uint32_t num_args = command.GetArgumentCount();
Greg Clayton238c0a12010-09-18 01:14:36 +0000402 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000403 std::vector<ThreadSP> thread_sps;
404
405 for (uint32_t i = 0; i < num_args; i++)
406 {
407 bool success;
408
409 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
410 if (!success)
411 {
412 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
413 result.SetStatus (eReturnStatusFailed);
414 return false;
415 }
416
417 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
418
419 if (!thread_sps[i])
420 {
421 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
422 result.SetStatus (eReturnStatusFailed);
423 return false;
424 }
425
426 }
427
428 for (uint32_t i = 0; i < num_args; i++)
429 {
430 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000431 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000432 result.GetOutputStream(),
433 m_options.m_start,
434 m_options.m_count,
435 show_frame_info,
436 num_frames_with_source,
437 3,
438 3))
439 {
440 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
441 result.SetStatus (eReturnStatusFailed);
442 return false;
443 }
444
445 if (i < num_args - 1)
446 result.AppendMessage("");
447 }
Chris Lattner24943d22010-06-08 16:52:24 +0000448 }
449 return result.Succeeded();
450 }
451protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000452 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000453};
454
Jim Ingham8ab1a802010-08-26 23:36:03 +0000455lldb::OptionDefinition
456CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
457{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000458{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
459{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameNum, "Frame in which to start the backtrace"},
460{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000461};
Chris Lattner24943d22010-06-08 16:52:24 +0000462
Greg Claytonc0418152010-07-07 17:07:17 +0000463enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000464{
465 eStepScopeSource,
466 eStepScopeInstruction
467};
468
469class CommandObjectThreadStepWithTypeAndScope : public CommandObject
470{
471public:
472
473 class CommandOptions : public Options
474 {
475 public:
476
477 CommandOptions () :
478 Options()
479 {
480 // Keep default values of all options in one place: ResetOptionValues ()
481 ResetOptionValues ();
482 }
483
484 virtual
485 ~CommandOptions ()
486 {
487 }
488
489 virtual Error
490 SetOptionValue (int option_idx, const char *option_arg)
491 {
492 Error error;
493 char short_option = (char) m_getopt_table[option_idx].val;
494
495 switch (short_option)
496 {
497 case 'a':
498 {
499 bool success;
500 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
501 if (!success)
502 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
503 }
504 break;
505 case 'm':
506 {
507 bool found_one = false;
508 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
509 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
510 if (!found_one)
511 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
512 }
513 break;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000514 case 'r':
515 {
516 m_avoid_regexp.clear();
517 m_avoid_regexp.assign(option_arg);
518 }
519 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000520 default:
521 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
522 break;
523
524 }
525 return error;
526 }
527
528 void
529 ResetOptionValues ()
530 {
531 Options::ResetOptionValues();
532 m_avoid_no_debug = true;
533 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000534 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000535 }
536
537 const lldb::OptionDefinition*
538 GetDefinitions ()
539 {
540 return g_option_table;
541 }
542
543 // Options table: Required for subclasses of Options.
544
545 static lldb::OptionDefinition g_option_table[];
546
547 // Instance variables to hold the values for command options.
548 bool m_avoid_no_debug;
549 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000550 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000551 };
552
Greg Clayton238c0a12010-09-18 01:14:36 +0000553 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
554 const char *name,
555 const char *help,
556 const char *syntax,
557 uint32_t flags,
558 StepType step_type,
559 StepScope step_scope) :
560 CommandObject (interpreter, name, help, syntax, flags),
Chris Lattner24943d22010-06-08 16:52:24 +0000561 m_step_type (step_type),
562 m_step_scope (step_scope),
563 m_options ()
564 {
565 }
566
567 virtual
568 ~CommandObjectThreadStepWithTypeAndScope ()
569 {
570 }
571
572 virtual
573 Options *
574 GetOptions ()
575 {
576 return &m_options;
577 }
578
579 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000580 Execute
581 (
Greg Clayton63094e02010-06-23 01:19:29 +0000582 Args& command,
583 CommandReturnObject &result
584 )
Chris Lattner24943d22010-06-08 16:52:24 +0000585 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000586 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
587 bool synchronous_execution = m_interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000588
589 if (process == NULL)
590 {
591 result.AppendError ("need a valid process to step");
592 result.SetStatus (eReturnStatusFailed);
593
594 }
595 else
596 {
597 const uint32_t num_threads = process->GetThreadList().GetSize();
598 Thread *thread = NULL;
599
600 if (command.GetArgumentCount() == 0)
601 {
Jim Inghamc8332952010-08-26 21:32:51 +0000602 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000603 if (thread == NULL)
604 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000605 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000606 result.SetStatus (eReturnStatusFailed);
607 return false;
608 }
609 }
610 else
611 {
612 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
613 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
614 if (step_thread_idx == LLDB_INVALID_INDEX32)
615 {
616 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
617 result.SetStatus (eReturnStatusFailed);
618 return false;
619 }
620 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
621 if (thread == NULL)
622 {
623 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
624 step_thread_idx, 0, num_threads);
625 result.SetStatus (eReturnStatusFailed);
626 return false;
627 }
628 }
629
630 const bool abort_other_plans = false;
631 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
632
633 // This is a bit unfortunate, but not all the commands in this command object support
634 // only while stepping, so I use the bool for them.
635 bool bool_stop_other_threads;
636 if (m_options.m_run_mode == eAllThreads)
637 bool_stop_other_threads = false;
638 else
639 bool_stop_other_threads = true;
640
641 if (m_step_type == eStepTypeInto)
642 {
643 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
644 ThreadPlan *new_plan;
645
646 if (frame->HasDebugInformation ())
647 {
648 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
649 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
650 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000651 stop_other_threads,
652 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000653 if (new_plan && !m_options.m_avoid_regexp.empty())
654 {
655 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
656 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
657 }
Chris Lattner24943d22010-06-08 16:52:24 +0000658 }
659 else
660 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
661
Jim Inghamc8332952010-08-26 21:32:51 +0000662 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000663 process->Resume ();
664 }
665 else if (m_step_type == eStepTypeOver)
666 {
667 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
668 ThreadPlan *new_plan;
669
670 if (frame->HasDebugInformation())
671 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
672 m_step_type,
673 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
674 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000675 stop_other_threads,
676 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000677 else
678 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
679 abort_other_plans,
680 bool_stop_other_threads);
681
682 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
683 // Maybe there should be a parameter to control this.
684 new_plan->SetOkayToDiscard(false);
685
Jim Inghamc8332952010-08-26 21:32:51 +0000686 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000687 process->Resume ();
688 }
689 else if (m_step_type == eStepTypeTrace)
690 {
691 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000692 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000693 process->Resume ();
694 }
695 else if (m_step_type == eStepTypeTraceOver)
696 {
697 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
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 == eStepTypeOut)
702 {
703 ThreadPlan *new_plan;
704
705 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
706 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
707 // Maybe there should be a parameter to control this.
708 new_plan->SetOkayToDiscard(false);
709
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
714 {
715 result.AppendError ("step type is not supported");
716 result.SetStatus (eReturnStatusFailed);
717 }
718 if (synchronous_execution)
719 {
720 StateType state = process->WaitForProcessToStop (NULL);
721
722 //EventSP event_sp;
723 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
724 //while (! StateIsStoppedState (state))
725 // {
726 // state = process->WaitForStateChangedEvents (NULL, event_sp);
727 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000728 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000729 result.SetDidChangeProcessState (true);
730 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
731 result.SetStatus (eReturnStatusSuccessFinishNoResult);
732 }
733 }
734 return result.Succeeded();
735 }
736
737protected:
738 StepType m_step_type;
739 StepScope m_step_scope;
740 CommandOptions m_options;
741};
742
743static lldb::OptionEnumValueElement
744g_tri_running_mode[] =
745{
Greg Claytonfe424a92010-09-18 03:37:20 +0000746{ eOnlyThisThread, "this-thread", "Run only this thread"},
747{ eAllThreads, "all-threads", "Run all threads"},
748{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000749{ 0, NULL, NULL }
750};
751
752static lldb::OptionEnumValueElement
753g_duo_running_mode[] =
754{
Greg Claytonfe424a92010-09-18 03:37:20 +0000755{ eOnlyThisThread, "this-thread", "Run only this thread"},
756{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000757{ 0, NULL, NULL }
758};
759
760lldb::OptionDefinition
761CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
762{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000763{ 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."},
764{ 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."},
765{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
766{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000767};
768
769
770//-------------------------------------------------------------------------
771// CommandObjectThreadContinue
772//-------------------------------------------------------------------------
773
774class CommandObjectThreadContinue : public CommandObject
775{
776public:
777
Greg Clayton238c0a12010-09-18 01:14:36 +0000778 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
779 CommandObject (interpreter,
780 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000781 "Continue execution of one or more threads in an active process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000782 "thread continue <thread-index> [<thread-index> ...]",
783 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
784 {
785 }
786
787
788 virtual
789 ~CommandObjectThreadContinue ()
790 {
791 }
792
793 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000794 Execute
795 (
Greg Clayton63094e02010-06-23 01:19:29 +0000796 Args& command,
797 CommandReturnObject &result
798 )
Chris Lattner24943d22010-06-08 16:52:24 +0000799 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000800 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000801
Greg Clayton238c0a12010-09-18 01:14:36 +0000802 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000803 {
804 result.AppendError ("invalid target, set executable file using 'file' command");
805 result.SetStatus (eReturnStatusFailed);
806 return false;
807 }
808
Greg Clayton238c0a12010-09-18 01:14:36 +0000809 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000810 if (process == NULL)
811 {
812 result.AppendError ("no process exists. Cannot continue");
813 result.SetStatus (eReturnStatusFailed);
814 return false;
815 }
816
817 StateType state = process->GetState();
818 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
819 {
820 const uint32_t num_threads = process->GetThreadList().GetSize();
821 uint32_t idx;
822 const size_t argc = command.GetArgumentCount();
823 if (argc > 0)
824 {
825 std::vector<uint32_t> resume_thread_indexes;
826 for (uint32_t i=0; i<argc; ++i)
827 {
828 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
829 if (idx < num_threads)
830 resume_thread_indexes.push_back(idx);
831 else
832 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
833 }
834
835 if (resume_thread_indexes.empty())
836 {
837 result.AppendError ("no valid thread indexes were specified");
838 result.SetStatus (eReturnStatusFailed);
839 return false;
840 }
841 else
842 {
843 result.AppendMessage ("Resuming thread ");
844 for (idx=0; idx<num_threads; ++idx)
845 {
846 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
847 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
848 {
849 result.AppendMessageWithFormat ("%u ", idx);
850 thread->SetResumeState (eStateRunning);
851 }
852 else
853 {
854 thread->SetResumeState (eStateSuspended);
855 }
856 }
857 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
858 }
859 }
860 else
861 {
Jim Inghamc8332952010-08-26 21:32:51 +0000862 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000863 if (current_thread == NULL)
864 {
865 result.AppendError ("the process doesn't have a current thread");
866 result.SetStatus (eReturnStatusFailed);
867 return false;
868 }
869 // Set the actions that the threads should each take when resuming
870 for (idx=0; idx<num_threads; ++idx)
871 {
872 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
873 if (thread == current_thread)
874 {
875 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
876 thread->SetResumeState (eStateRunning);
877 }
878 else
879 {
880 thread->SetResumeState (eStateSuspended);
881 }
882 }
883 }
884
885 Error error (process->Resume());
886 if (error.Success())
887 {
888 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
889 if (synchronous_execution)
890 {
Greg Claytonbef15832010-07-14 00:18:15 +0000891 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000892
893 result.SetDidChangeProcessState (true);
894 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
895 result.SetStatus (eReturnStatusSuccessFinishNoResult);
896 }
897 else
898 {
899 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
900 }
901 }
902 else
903 {
904 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
905 result.SetStatus (eReturnStatusFailed);
906 }
907 }
908 else
909 {
910 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
911 StateAsCString(state));
912 result.SetStatus (eReturnStatusFailed);
913 }
914
915 return result.Succeeded();
916 }
917
918};
919
920//-------------------------------------------------------------------------
921// CommandObjectThreadUntil
922//-------------------------------------------------------------------------
923
924class CommandObjectThreadUntil : public CommandObject
925{
926public:
927
928 class CommandOptions : public Options
929 {
930 public:
931 uint32_t m_thread_idx;
932 uint32_t m_frame_idx;
933
934 CommandOptions () :
935 Options(),
936 m_thread_idx(LLDB_INVALID_THREAD_ID),
937 m_frame_idx(LLDB_INVALID_FRAME_ID)
938 {
939 // Keep default values of all options in one place: ResetOptionValues ()
940 ResetOptionValues ();
941 }
942
943 virtual
944 ~CommandOptions ()
945 {
946 }
947
948 virtual Error
949 SetOptionValue (int option_idx, const char *option_arg)
950 {
951 Error error;
952 char short_option = (char) m_getopt_table[option_idx].val;
953
954 switch (short_option)
955 {
956 case 't':
957 {
Greg Claytonbef15832010-07-14 00:18:15 +0000958 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +0000959 if (m_thread_idx == LLDB_INVALID_INDEX32)
960 {
961 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
962 }
963 }
964 break;
965 case 'f':
966 {
967 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
968 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
969 {
970 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
971 }
972 }
973 break;
974 case 'm':
975 {
976 bool found_one = false;
977 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
978 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
979
980 if (!found_one)
981 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
982 else if (run_mode == eAllThreads)
983 m_stop_others = false;
984 else
985 m_stop_others = true;
986
987 }
988 break;
989 default:
990 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
991 break;
992
993 }
994 return error;
995 }
996
997 void
998 ResetOptionValues ()
999 {
1000 Options::ResetOptionValues();
1001 m_thread_idx = LLDB_INVALID_THREAD_ID;
1002 m_frame_idx = 0;
1003 m_stop_others = false;
1004 }
1005
1006 const lldb::OptionDefinition*
1007 GetDefinitions ()
1008 {
1009 return g_option_table;
1010 }
1011
1012 uint32_t m_step_thread_idx;
1013 bool m_stop_others;
1014
1015 // Options table: Required for subclasses of Options.
1016
1017 static lldb::OptionDefinition g_option_table[];
1018
1019 // Instance variables to hold the values for command options.
1020 };
1021
Greg Clayton238c0a12010-09-18 01:14:36 +00001022 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1023 CommandObject (interpreter,
1024 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001025 "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 +00001026 "thread until [<cmd-options>] <line-number>",
1027 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1028 m_options ()
1029 {
1030 }
1031
1032
1033 virtual
1034 ~CommandObjectThreadUntil ()
1035 {
1036 }
1037
1038 virtual
1039 Options *
1040 GetOptions ()
1041 {
1042 return &m_options;
1043 }
1044
1045 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001046 Execute
1047 (
Greg Clayton63094e02010-06-23 01:19:29 +00001048 Args& command,
1049 CommandReturnObject &result
1050 )
Chris Lattner24943d22010-06-08 16:52:24 +00001051 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001052 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001053
Greg Clayton238c0a12010-09-18 01:14:36 +00001054 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001055 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001056 {
1057 result.AppendError ("invalid target, set executable file using 'file' command");
1058 result.SetStatus (eReturnStatusFailed);
1059 return false;
1060 }
1061
Greg Clayton238c0a12010-09-18 01:14:36 +00001062 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001063 if (process == NULL)
1064 {
1065 result.AppendError ("need a valid process to step");
1066 result.SetStatus (eReturnStatusFailed);
1067
1068 }
1069 else
1070 {
1071 Thread *thread = NULL;
1072 uint32_t line_number;
1073
1074 if (command.GetArgumentCount() != 1)
1075 {
1076 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1077 result.SetStatus (eReturnStatusFailed);
1078 return false;
1079 }
1080
1081 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1082 if (line_number == UINT32_MAX)
1083 {
1084 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1085 result.SetStatus (eReturnStatusFailed);
1086 return false;
1087 }
1088
1089 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1090 {
Jim Inghamc8332952010-08-26 21:32:51 +00001091 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001092 }
1093 else
1094 {
1095 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1096 }
1097
1098 if (thread == NULL)
1099 {
1100 const uint32_t num_threads = process->GetThreadList().GetSize();
1101 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1102 result.SetStatus (eReturnStatusFailed);
1103 return false;
1104 }
1105
1106 const bool abort_other_plans = true;
1107
1108 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1109 if (frame == NULL)
1110 {
1111
1112 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1113 result.SetStatus (eReturnStatusFailed);
1114 return false;
1115 }
1116
1117 ThreadPlan *new_plan;
1118
1119 if (frame->HasDebugInformation ())
1120 {
1121 // Finally we got here... Translate the given line number to a bunch of addresses:
1122 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1123 LineTable *line_table = NULL;
1124 if (sc.comp_unit)
1125 line_table = sc.comp_unit->GetLineTable();
1126
1127 if (line_table == NULL)
1128 {
1129 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1130 m_options.m_frame_idx, m_options.m_thread_idx);
1131 result.SetStatus (eReturnStatusFailed);
1132 return false;
1133 }
1134
1135 LineEntry function_start;
1136 uint32_t index_ptr = 0, end_ptr;
1137 std::vector<addr_t> address_list;
1138
1139 // Find the beginning & end index of the
1140 AddressRange fun_addr_range = sc.function->GetAddressRange();
1141 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1142 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1143
1144 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1145 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1146
1147 while (index_ptr <= end_ptr)
1148 {
1149 LineEntry line_entry;
1150 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1151 if (index_ptr == UINT32_MAX)
1152 break;
1153
Greg Claytoneea26402010-09-14 23:36:40 +00001154 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001155 if (address != LLDB_INVALID_ADDRESS)
1156 address_list.push_back (address);
1157 index_ptr++;
1158 }
1159
Greg Clayton53d68e72010-07-20 22:52:08 +00001160 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 +00001161 new_plan->SetOkayToDiscard(false);
1162 }
1163 else
1164 {
1165 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1166 result.SetStatus (eReturnStatusFailed);
1167 return false;
1168
1169 }
1170
Jim Inghamc8332952010-08-26 21:32:51 +00001171 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001172 Error error (process->Resume ());
1173 if (error.Success())
1174 {
1175 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
1176 if (synchronous_execution)
1177 {
1178 StateType state = process->WaitForProcessToStop (NULL);
1179
1180 result.SetDidChangeProcessState (true);
1181 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1182 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1183 }
1184 else
1185 {
1186 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1187 }
1188 }
1189 else
1190 {
1191 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1192 result.SetStatus (eReturnStatusFailed);
1193 }
1194
1195 }
1196 return result.Succeeded();
1197 }
1198protected:
1199 CommandOptions m_options;
1200
1201};
1202
1203lldb::OptionDefinition
1204CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1205{
Caroline Tice4d6675c2010-10-01 19:59:14 +00001206{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameNum, "Frame index for until operation - defaults to 0"},
1207{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1208{ 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"},
1209{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001210};
1211
1212
1213//-------------------------------------------------------------------------
1214// CommandObjectThreadSelect
1215//-------------------------------------------------------------------------
1216
1217class CommandObjectThreadSelect : public CommandObject
1218{
1219public:
1220
Greg Clayton238c0a12010-09-18 01:14:36 +00001221 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1222 CommandObject (interpreter,
1223 "thread select",
1224 "Select a thread as the currently active thread.",
1225 "thread select <thread-index>",
1226 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001227 {
1228 }
1229
1230
1231 virtual
1232 ~CommandObjectThreadSelect ()
1233 {
1234 }
1235
1236 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001237 Execute
1238 (
Greg Clayton63094e02010-06-23 01:19:29 +00001239 Args& command,
1240 CommandReturnObject &result
1241 )
Chris Lattner24943d22010-06-08 16:52:24 +00001242 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001243 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001244 if (process == NULL)
1245 {
1246 result.AppendError ("no process");
1247 result.SetStatus (eReturnStatusFailed);
1248 return false;
1249 }
1250 else if (command.GetArgumentCount() != 1)
1251 {
1252 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1253 result.SetStatus (eReturnStatusFailed);
1254 return false;
1255 }
1256
1257 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1258
1259 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1260 if (new_thread == NULL)
1261 {
1262 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1263 result.SetStatus (eReturnStatusFailed);
1264 return false;
1265 }
1266
Jim Inghamc8332952010-08-26 21:32:51 +00001267 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001268 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001269
Greg Clayton238c0a12010-09-18 01:14:36 +00001270 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001271 result.GetOutputStream(),
1272 new_thread,
1273 false,
1274 true);
1275
1276 return result.Succeeded();
1277 }
1278
1279};
1280
1281
1282//-------------------------------------------------------------------------
1283// CommandObjectThreadList
1284//-------------------------------------------------------------------------
1285
Greg Clayton63094e02010-06-23 01:19:29 +00001286class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001287{
Greg Clayton63094e02010-06-23 01:19:29 +00001288public:
Chris Lattner24943d22010-06-08 16:52:24 +00001289
Chris Lattner24943d22010-06-08 16:52:24 +00001290
Greg Clayton238c0a12010-09-18 01:14:36 +00001291 CommandObjectThreadList (CommandInterpreter &interpreter):
1292 CommandObject (interpreter,
1293 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001294 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001295 "thread list",
1296 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001297 {
Greg Clayton63094e02010-06-23 01:19:29 +00001298 }
Chris Lattner24943d22010-06-08 16:52:24 +00001299
Greg Clayton63094e02010-06-23 01:19:29 +00001300 ~CommandObjectThreadList()
1301 {
1302 }
1303
1304 bool
1305 Execute
1306 (
Greg Clayton63094e02010-06-23 01:19:29 +00001307 Args& command,
1308 CommandReturnObject &result
1309 )
1310 {
1311 StreamString &strm = result.GetOutputStream();
1312 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001313 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001314 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001315 {
Greg Clayton63094e02010-06-23 01:19:29 +00001316 const StateType state = exe_ctx.process->GetState();
1317
1318 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001319 {
Greg Clayton63094e02010-06-23 01:19:29 +00001320 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001321 {
Greg Clayton63094e02010-06-23 01:19:29 +00001322 int exit_status = exe_ctx.process->GetExitStatus();
1323 const char *exit_description = exe_ctx.process->GetExitDescription();
1324 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1325 exe_ctx.process->GetID(),
1326 exit_status,
1327 exit_status,
1328 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001329 }
1330 else
1331 {
Greg Clayton63094e02010-06-23 01:19:29 +00001332 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1333 if (exe_ctx.thread == NULL)
1334 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1335 if (exe_ctx.thread != NULL)
1336 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001337 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001338 }
1339 else
1340 {
1341 result.AppendError ("no valid thread found in current process");
1342 result.SetStatus (eReturnStatusFailed);
1343 }
Chris Lattner24943d22010-06-08 16:52:24 +00001344 }
1345 }
Greg Clayton63094e02010-06-23 01:19:29 +00001346 else
1347 {
1348 result.AppendError ("process is currently running");
1349 result.SetStatus (eReturnStatusFailed);
1350 }
Chris Lattner24943d22010-06-08 16:52:24 +00001351 }
1352 else
1353 {
Greg Clayton63094e02010-06-23 01:19:29 +00001354 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001355 result.SetStatus (eReturnStatusFailed);
1356 }
Greg Clayton63094e02010-06-23 01:19:29 +00001357 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001358 }
Greg Clayton63094e02010-06-23 01:19:29 +00001359};
Chris Lattner24943d22010-06-08 16:52:24 +00001360
1361//-------------------------------------------------------------------------
1362// CommandObjectMultiwordThread
1363//-------------------------------------------------------------------------
1364
Greg Clayton63094e02010-06-23 01:19:29 +00001365CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001366 CommandObjectMultiword (interpreter,
1367 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001368 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001369 "thread <subcommand> [<subcommand-options>]")
1370{
Greg Clayton238c0a12010-09-18 01:14:36 +00001371 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1372 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1373 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1374 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1375 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1376 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1377 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001378 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001379 "Source level single step in specified thread (current thread, if none specified).",
1380 "thread step-in [<thread-id>]",
1381 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1382 eStepTypeInto,
1383 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001384
Greg Clayton238c0a12010-09-18 01:14:36 +00001385 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1386 interpreter,
1387 "thread step-out",
1388 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).",
1389 "thread step-out [<thread-id>]",
1390 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1391 eStepTypeOut,
1392 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001393
Greg Clayton238c0a12010-09-18 01:14:36 +00001394 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1395 interpreter,
1396 "thread step-over",
1397 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
1398 "thread step-over [<thread-id>]",
1399 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1400 eStepTypeOver,
1401 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001402
Greg Clayton238c0a12010-09-18 01:14:36 +00001403 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1404 interpreter,
1405 "thread step-inst",
1406 "Single step one instruction in specified thread (current thread, if none specified).",
1407 "thread step-inst [<thread-id>]",
1408 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1409 eStepTypeTrace,
1410 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001411
Greg Clayton238c0a12010-09-18 01:14:36 +00001412 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1413 interpreter,
1414 "thread step-inst-over",
1415 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
1416 "thread step-inst-over [<thread-id>]",
1417 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1418 eStepTypeTraceOver,
1419 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001420}
1421
1422CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1423{
1424}
1425
1426