blob: 977f63fee35bb430e8983c545f40751fdcfd2c77 [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
Greg Claytoncd548032011-02-01 01:31:41 +000020#include "lldb/Host/Host.h"
21
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandInterpreter.h"
23#include "lldb/Interpreter/CommandReturnObject.h"
24
25#include "lldb/Target/Process.h"
26#include "lldb/Target/RegisterContext.h"
27#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
29#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030#include "lldb/Target/ThreadPlanStepInstruction.h"
31#include "lldb/Target/ThreadPlanStepOut.h"
32#include "lldb/Target/ThreadPlanStepRange.h"
33#include "lldb/Target/ThreadPlanStepInRange.h"
34#include "lldb/Symbol/LineTable.h"
35#include "lldb/Symbol/LineEntry.h"
36
37using namespace lldb;
38using namespace lldb_private;
39
40
41bool
42lldb_private::DisplayThreadInfo
43(
Greg Clayton63094e02010-06-23 01:19:29 +000044 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000045 Stream &strm,
46 Thread *thread,
47 bool only_threads_with_stop_reason,
48 bool show_source
49)
50{
51 if (thread)
52 {
53 if (only_threads_with_stop_reason)
54 {
Greg Clayton643ee732010-08-04 01:40:35 +000055 if (thread->GetStopInfo() == NULL)
56 return false;
Chris Lattner24943d22010-06-08 16:52:24 +000057 }
58
59 strm.Indent();
Jim Inghamc8332952010-08-26 21:32:51 +000060 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' ');
Chris Lattner24943d22010-06-08 16:52:24 +000061
62 // Show one frame with only the first showing source
63 if (show_source)
64 {
Jim Ingham74989e82010-08-30 19:44:40 +000065 bool already_shown = false;
66 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0);
67 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry));
Caroline Tice5bc8c972010-09-20 20:44:43 +000068 if (interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
Jim Ingham74989e82010-08-30 19:44:40 +000069 {
70 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
71 }
72
Chris Lattner24943d22010-06-08 16:52:24 +000073 DisplayFramesForExecutionContext (thread,
74 interpreter,
75 strm,
Chris Lattner24943d22010-06-08 16:52:24 +000076 0, // Start at first frame
77 1, // Number of frames to show
78 false,// Don't show the frame info since we already displayed most of it above...
Jim Ingham74989e82010-08-30 19:44:40 +000079 !already_shown, // Show source for the first frame
Chris Lattner24943d22010-06-08 16:52:24 +000080 3, // lines of source context before
81 3); // lines of source context after
82 }
83 else
84 {
Greg Claytona830adb2010-10-04 01:05:56 +000085 thread->DumpUsingSettingsFormat (strm, 0);
Chris Lattner24943d22010-06-08 16:52:24 +000086 }
87
88 return true;
89 }
90 return false;
91}
92
93size_t
94lldb_private::DisplayThreadsInfo
95(
Greg Clayton63094e02010-06-23 01:19:29 +000096 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000097 ExecutionContext *exe_ctx,
98 CommandReturnObject &result,
99 bool only_threads_with_stop_reason,
100 bool show_source
101)
102{
103 StreamString strm;
104
105 size_t num_thread_infos_dumped = 0;
106
107 if (!exe_ctx->process)
108 return 0;
109
110 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
111 if (num_threads > 0)
112 {
113
114 for (uint32_t i = 0; i < num_threads; i++)
115 {
116 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
117 if (thread)
118 {
119 if (DisplayThreadInfo (interpreter,
120 strm,
121 thread,
122 only_threads_with_stop_reason,
123 show_source))
124 ++num_thread_infos_dumped;
125 }
126 }
127 }
128
129 if (num_thread_infos_dumped > 0)
130 {
131 if (num_thread_infos_dumped < num_threads)
132 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
133
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000134 result.AppendMessage (strm.GetString().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000135 result.SetStatus (eReturnStatusSuccessFinishNoResult);
136 }
137 return num_thread_infos_dumped;
138}
139
140
141size_t
142lldb_private::DisplayFramesForExecutionContext
143(
144 Thread *thread,
Greg Clayton63094e02010-06-23 01:19:29 +0000145 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000146 Stream& strm,
Chris Lattner24943d22010-06-08 16:52:24 +0000147 uint32_t first_frame,
148 uint32_t num_frames,
149 bool show_frame_info,
150 uint32_t num_frames_with_source,
151 uint32_t source_lines_before,
152 uint32_t source_lines_after
153)
154{
155 if (thread == NULL)
156 return 0;
157
158 size_t num_frames_displayed = 0;
159
160 if (num_frames == 0)
161 return 0;
162
Greg Claytona830adb2010-10-04 01:05:56 +0000163 thread->DumpUsingSettingsFormat (strm, num_frames > 1 ? UINT32_MAX : first_frame);
Chris Lattner24943d22010-06-08 16:52:24 +0000164 strm.IndentMore();
165
166 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000167 uint32_t frame_idx = 0;
Jim Ingham8ab1a802010-08-26 23:36:03 +0000168 uint32_t last_frame;
169
170 // Don't let the last frame wrap around...
171 if (num_frames == UINT32_MAX)
172 last_frame = UINT32_MAX;
Chris Lattner24943d22010-06-08 16:52:24 +0000173 else
Jim Ingham8ab1a802010-08-26 23:36:03 +0000174 last_frame = first_frame + num_frames;
175
176 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000178 frame_sp = thread->GetStackFrameAtIndex (frame_idx);
179 if (frame_sp.get() == NULL)
180 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000181
Jim Ingham8ab1a802010-08-26 23:36:03 +0000182 if (DisplayFrameForExecutionContext (thread,
183 frame_sp.get(),
184 interpreter,
185 strm,
186 show_frame_info,
187 num_frames_with_source > first_frame - frame_idx,
188 source_lines_before,
189 source_lines_after) == false)
190 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000191
Jim Ingham8ab1a802010-08-26 23:36:03 +0000192 ++num_frames_displayed;
Chris Lattner24943d22010-06-08 16:52:24 +0000193 }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000194
Chris Lattner24943d22010-06-08 16:52:24 +0000195 strm.IndentLess();
196 return num_frames_displayed;
197}
198
199bool
200lldb_private::DisplayFrameForExecutionContext
201(
202 Thread *thread,
203 StackFrame *frame,
Greg Clayton63094e02010-06-23 01:19:29 +0000204 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000205 Stream& strm,
206 bool show_frame_info,
207 bool show_source,
208 uint32_t source_lines_before,
209 uint32_t source_lines_after
210)
211{
212 // thread and frame must be filled in prior to calling this function
213 if (thread && frame)
214 {
215 if (show_frame_info)
216 {
217 strm.Indent();
Greg Claytona830adb2010-10-04 01:05:56 +0000218 frame->DumpUsingSettingsFormat (&strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000219 }
220
221 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
222
223 if (show_source && sc.comp_unit && sc.line_entry.IsValid())
224 {
Greg Clayton63094e02010-06-23 01:19:29 +0000225 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (
Chris Lattner24943d22010-06-08 16:52:24 +0000226 sc.line_entry.file,
227 sc.line_entry.line,
228 3,
229 3,
230 "->",
231 &strm);
232
233 }
234 return true;
235 }
236 return false;
237}
238
239
240//-------------------------------------------------------------------------
241// CommandObjectThreadBacktrace
242//-------------------------------------------------------------------------
243
244class CommandObjectThreadBacktrace : public CommandObject
245{
246public:
247
Jim Ingham8ab1a802010-08-26 23:36:03 +0000248 class CommandOptions : public Options
249 {
250 public:
251
252 CommandOptions () :
253 Options()
254 {
255 // Keep default values of all options in one place: ResetOptionValues ()
256 ResetOptionValues ();
257 }
258
259 virtual
260 ~CommandOptions ()
261 {
262 }
263
264 virtual Error
265 SetOptionValue (int option_idx, const char *option_arg)
266 {
267 Error error;
268 char short_option = (char) m_getopt_table[option_idx].val;
269
270 switch (short_option)
271 {
272 case 'c':
273 {
274 bool success;
275 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success);
276 if (!success)
277 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
278 if (input_count < -1)
279 m_count = UINT32_MAX;
280 else
281 m_count = input_count;
282 }
283 break;
284 case 's':
285 {
286 bool success;
287 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
288 if (!success)
289 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option);
290 }
291 break;
292 default:
293 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
294 break;
295
296 }
297 return error;
298 }
299
300 void
301 ResetOptionValues ()
302 {
303 Options::ResetOptionValues();
304 m_count = -1;
305 m_start = 0;
306 }
307
Greg Claytonb3448432011-03-24 21:19:54 +0000308 const OptionDefinition*
Jim Ingham8ab1a802010-08-26 23:36:03 +0000309 GetDefinitions ()
310 {
311 return g_option_table;
312 }
313
314 // Options table: Required for subclasses of Options.
315
Greg Claytonb3448432011-03-24 21:19:54 +0000316 static OptionDefinition g_option_table[];
Jim Ingham8ab1a802010-08-26 23:36:03 +0000317
318 // Instance variables to hold the values for command options.
319 uint32_t m_count;
320 uint32_t m_start;
321 };
322
Greg Clayton238c0a12010-09-18 01:14:36 +0000323 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
324 CommandObject (interpreter,
325 "thread backtrace",
Caroline Tice31fbb642010-09-08 22:08:58 +0000326 "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.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000327 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000328 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000329 m_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000330 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000331 CommandArgumentEntry arg;
332 CommandArgumentData thread_idx_arg;
333
334 // Define the first (and only) variant of this arg.
335 thread_idx_arg.arg_type = eArgTypeThreadIndex;
336 thread_idx_arg.arg_repetition = eArgRepeatStar;
337
338 // There is only one variant this argument could be; put it into the argument entry.
339 arg.push_back (thread_idx_arg);
340
341 // Push the data for the first argument into the m_arguments vector.
342 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000343 }
344
345 ~CommandObjectThreadBacktrace()
346 {
347 }
348
Jim Ingham8ab1a802010-08-26 23:36:03 +0000349 virtual Options *
350 GetOptions ()
351 {
352 return &m_options;
353 }
Chris Lattner24943d22010-06-08 16:52:24 +0000354
Greg Clayton63094e02010-06-23 01:19:29 +0000355 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000356 Execute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000357 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000358
359 bool show_frame_info = true;
360 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
361
362 result.SetStatus (eReturnStatusSuccessFinishResult);
363
Chris Lattner24943d22010-06-08 16:52:24 +0000364 if (command.GetArgumentCount() == 0)
365 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000366 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000367 if (exe_ctx.thread)
368 {
Chris Lattner24943d22010-06-08 16:52:24 +0000369 if (DisplayFramesForExecutionContext (exe_ctx.thread,
Greg Clayton238c0a12010-09-18 01:14:36 +0000370 m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000371 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000372 m_options.m_start,
373 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000374 show_frame_info,
375 num_frames_with_source,
376 3,
377 3))
378 {
379 result.SetStatus (eReturnStatusSuccessFinishResult);
380 }
381 }
382 else
383 {
384 result.AppendError ("invalid thread");
385 result.SetStatus (eReturnStatusFailed);
386 }
387 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000388 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
389 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000390 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000391 uint32_t num_threads = process->GetThreadList().GetSize();
392 for (uint32_t i = 0; i < num_threads; i++)
393 {
394 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
395 if (!DisplayFramesForExecutionContext (thread_sp.get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000396 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000397 result.GetOutputStream(),
398 m_options.m_start,
399 m_options.m_count,
400 show_frame_info,
401 num_frames_with_source,
402 3,
403 3))
404 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000405 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-08-27 00:58:05 +0000406 result.SetStatus (eReturnStatusFailed);
407 return false;
408 }
409 if (i < num_threads - 1)
410 result.AppendMessage("");
411 }
412 }
Chris Lattner24943d22010-06-08 16:52:24 +0000413 else
414 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000415 uint32_t num_args = command.GetArgumentCount();
Greg Clayton238c0a12010-09-18 01:14:36 +0000416 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000417 std::vector<ThreadSP> thread_sps;
418
419 for (uint32_t i = 0; i < num_args; i++)
420 {
421 bool success;
422
423 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
424 if (!success)
425 {
426 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
427 result.SetStatus (eReturnStatusFailed);
428 return false;
429 }
430
431 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
432
433 if (!thread_sps[i])
434 {
435 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
436 result.SetStatus (eReturnStatusFailed);
437 return false;
438 }
439
440 }
441
442 for (uint32_t i = 0; i < num_args; i++)
443 {
444 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000445 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000446 result.GetOutputStream(),
447 m_options.m_start,
448 m_options.m_count,
449 show_frame_info,
450 num_frames_with_source,
451 3,
452 3))
453 {
454 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
455 result.SetStatus (eReturnStatusFailed);
456 return false;
457 }
458
459 if (i < num_args - 1)
460 result.AppendMessage("");
461 }
Chris Lattner24943d22010-06-08 16:52:24 +0000462 }
463 return result.Succeeded();
464 }
465protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000466 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000467};
468
Greg Claytonb3448432011-03-24 21:19:54 +0000469OptionDefinition
Jim Ingham8ab1a802010-08-26 23:36:03 +0000470CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
471{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000472{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
Caroline Tice43b014a2010-10-04 22:28:36 +0000473{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
Caroline Tice4d6675c2010-10-01 19:59:14 +0000474{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000475};
Chris Lattner24943d22010-06-08 16:52:24 +0000476
Greg Claytonc0418152010-07-07 17:07:17 +0000477enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000478{
479 eStepScopeSource,
480 eStepScopeInstruction
481};
482
483class CommandObjectThreadStepWithTypeAndScope : public CommandObject
484{
485public:
486
487 class CommandOptions : public Options
488 {
489 public:
490
491 CommandOptions () :
492 Options()
493 {
494 // Keep default values of all options in one place: ResetOptionValues ()
495 ResetOptionValues ();
496 }
497
498 virtual
499 ~CommandOptions ()
500 {
501 }
502
503 virtual Error
504 SetOptionValue (int option_idx, const char *option_arg)
505 {
506 Error error;
507 char short_option = (char) m_getopt_table[option_idx].val;
508
509 switch (short_option)
510 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000511 case 'a':
Chris Lattner24943d22010-06-08 16:52:24 +0000512 {
513 bool success;
514 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
515 if (!success)
516 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
517 }
518 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000519
520 case 'm':
Chris Lattner24943d22010-06-08 16:52:24 +0000521 {
522 bool found_one = false;
523 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
524 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
525 if (!found_one)
526 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
527 }
528 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000529
530 case 'r':
Jim Ingham809ab9b2010-07-10 02:27:39 +0000531 {
532 m_avoid_regexp.clear();
533 m_avoid_regexp.assign(option_arg);
534 }
535 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000536
537 default:
538 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
539 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000540
541 }
542 return error;
543 }
544
545 void
546 ResetOptionValues ()
547 {
548 Options::ResetOptionValues();
549 m_avoid_no_debug = true;
550 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000551 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000552 }
553
Greg Claytonb3448432011-03-24 21:19:54 +0000554 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000555 GetDefinitions ()
556 {
557 return g_option_table;
558 }
559
560 // Options table: Required for subclasses of Options.
561
Greg Claytonb3448432011-03-24 21:19:54 +0000562 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000563
564 // Instance variables to hold the values for command options.
565 bool m_avoid_no_debug;
566 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000567 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000568 };
569
Greg Clayton238c0a12010-09-18 01:14:36 +0000570 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
571 const char *name,
572 const char *help,
573 const char *syntax,
574 uint32_t flags,
575 StepType step_type,
576 StepScope step_scope) :
577 CommandObject (interpreter, name, help, syntax, flags),
Chris Lattner24943d22010-06-08 16:52:24 +0000578 m_step_type (step_type),
579 m_step_scope (step_scope),
580 m_options ()
581 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000582 CommandArgumentEntry arg;
583 CommandArgumentData thread_id_arg;
584
585 // Define the first (and only) variant of this arg.
586 thread_id_arg.arg_type = eArgTypeThreadID;
587 thread_id_arg.arg_repetition = eArgRepeatOptional;
588
589 // There is only one variant this argument could be; put it into the argument entry.
590 arg.push_back (thread_id_arg);
591
592 // Push the data for the first argument into the m_arguments vector.
593 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000594 }
595
596 virtual
597 ~CommandObjectThreadStepWithTypeAndScope ()
598 {
599 }
600
601 virtual
602 Options *
603 GetOptions ()
604 {
605 return &m_options;
606 }
607
608 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000609 Execute
610 (
Greg Clayton63094e02010-06-23 01:19:29 +0000611 Args& command,
612 CommandReturnObject &result
613 )
Chris Lattner24943d22010-06-08 16:52:24 +0000614 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000615 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
616 bool synchronous_execution = m_interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000617
618 if (process == NULL)
619 {
620 result.AppendError ("need a valid process to step");
621 result.SetStatus (eReturnStatusFailed);
622
623 }
624 else
625 {
626 const uint32_t num_threads = process->GetThreadList().GetSize();
627 Thread *thread = NULL;
628
629 if (command.GetArgumentCount() == 0)
630 {
Jim Inghamc8332952010-08-26 21:32:51 +0000631 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000632 if (thread == NULL)
633 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000634 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000635 result.SetStatus (eReturnStatusFailed);
636 return false;
637 }
638 }
639 else
640 {
641 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
642 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
643 if (step_thread_idx == LLDB_INVALID_INDEX32)
644 {
645 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
646 result.SetStatus (eReturnStatusFailed);
647 return false;
648 }
649 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
650 if (thread == NULL)
651 {
652 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
653 step_thread_idx, 0, num_threads);
654 result.SetStatus (eReturnStatusFailed);
655 return false;
656 }
657 }
658
659 const bool abort_other_plans = false;
660 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
661
662 // This is a bit unfortunate, but not all the commands in this command object support
663 // only while stepping, so I use the bool for them.
664 bool bool_stop_other_threads;
665 if (m_options.m_run_mode == eAllThreads)
666 bool_stop_other_threads = false;
667 else
668 bool_stop_other_threads = true;
669
670 if (m_step_type == eStepTypeInto)
671 {
672 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
673 ThreadPlan *new_plan;
674
675 if (frame->HasDebugInformation ())
676 {
677 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
678 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
679 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000680 stop_other_threads,
681 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000682 if (new_plan && !m_options.m_avoid_regexp.empty())
683 {
684 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
685 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
686 }
Chris Lattner24943d22010-06-08 16:52:24 +0000687 }
688 else
689 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
690
Jim Inghamc8332952010-08-26 21:32:51 +0000691 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000692 process->Resume ();
693 }
694 else if (m_step_type == eStepTypeOver)
695 {
696 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
697 ThreadPlan *new_plan;
698
699 if (frame->HasDebugInformation())
700 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
701 m_step_type,
702 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
703 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000704 stop_other_threads,
705 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000706 else
707 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
708 abort_other_plans,
709 bool_stop_other_threads);
710
711 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
712 // Maybe there should be a parameter to control this.
713 new_plan->SetOkayToDiscard(false);
714
Jim Inghamc8332952010-08-26 21:32:51 +0000715 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000716 process->Resume ();
717 }
718 else if (m_step_type == eStepTypeTrace)
719 {
720 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000721 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000722 process->Resume ();
723 }
724 else if (m_step_type == eStepTypeTraceOver)
725 {
726 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000727 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000728 process->Resume ();
729 }
730 else if (m_step_type == eStepTypeOut)
731 {
732 ThreadPlan *new_plan;
733
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000734 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
735 NULL,
736 false,
737 bool_stop_other_threads,
738 eVoteYes,
739 eVoteNoOpinion,
740 thread->GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000741 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
742 // Maybe there should be a parameter to control this.
743 new_plan->SetOkayToDiscard(false);
744
Jim Inghamc8332952010-08-26 21:32:51 +0000745 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000746 process->Resume ();
747 }
748 else
749 {
750 result.AppendError ("step type is not supported");
751 result.SetStatus (eReturnStatusFailed);
752 }
753 if (synchronous_execution)
754 {
755 StateType state = process->WaitForProcessToStop (NULL);
756
757 //EventSP event_sp;
758 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
759 //while (! StateIsStoppedState (state))
760 // {
761 // state = process->WaitForStateChangedEvents (NULL, event_sp);
762 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000763 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000764 result.SetDidChangeProcessState (true);
765 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
766 result.SetStatus (eReturnStatusSuccessFinishNoResult);
767 }
768 }
769 return result.Succeeded();
770 }
771
772protected:
773 StepType m_step_type;
774 StepScope m_step_scope;
775 CommandOptions m_options;
776};
777
Greg Claytonb3448432011-03-24 21:19:54 +0000778static OptionEnumValueElement
Chris Lattner24943d22010-06-08 16:52:24 +0000779g_tri_running_mode[] =
780{
Greg Claytonfe424a92010-09-18 03:37:20 +0000781{ eOnlyThisThread, "this-thread", "Run only this thread"},
782{ eAllThreads, "all-threads", "Run all threads"},
783{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000784{ 0, NULL, NULL }
785};
786
Greg Claytonb3448432011-03-24 21:19:54 +0000787static OptionEnumValueElement
Chris Lattner24943d22010-06-08 16:52:24 +0000788g_duo_running_mode[] =
789{
Greg Claytonfe424a92010-09-18 03:37:20 +0000790{ eOnlyThisThread, "this-thread", "Run only this thread"},
791{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000792{ 0, NULL, NULL }
793};
794
Greg Claytonb3448432011-03-24 21:19:54 +0000795OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000796CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
797{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000798{ 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."},
799{ 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."},
800{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
801{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000802};
803
804
805//-------------------------------------------------------------------------
806// CommandObjectThreadContinue
807//-------------------------------------------------------------------------
808
809class CommandObjectThreadContinue : public CommandObject
810{
811public:
812
Greg Clayton238c0a12010-09-18 01:14:36 +0000813 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
814 CommandObject (interpreter,
815 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000816 "Continue execution of one or more threads in an active process.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000817 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000818 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
819 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000820 CommandArgumentEntry arg;
821 CommandArgumentData thread_idx_arg;
822
823 // Define the first (and only) variant of this arg.
824 thread_idx_arg.arg_type = eArgTypeThreadIndex;
825 thread_idx_arg.arg_repetition = eArgRepeatPlus;
826
827 // There is only one variant this argument could be; put it into the argument entry.
828 arg.push_back (thread_idx_arg);
829
830 // Push the data for the first argument into the m_arguments vector.
831 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000832 }
833
834
835 virtual
836 ~CommandObjectThreadContinue ()
837 {
838 }
839
840 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000841 Execute
842 (
Greg Clayton63094e02010-06-23 01:19:29 +0000843 Args& command,
844 CommandReturnObject &result
845 )
Chris Lattner24943d22010-06-08 16:52:24 +0000846 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000847 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000848
Greg Clayton238c0a12010-09-18 01:14:36 +0000849 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000850 {
851 result.AppendError ("invalid target, set executable file using 'file' command");
852 result.SetStatus (eReturnStatusFailed);
853 return false;
854 }
855
Greg Clayton238c0a12010-09-18 01:14:36 +0000856 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000857 if (process == NULL)
858 {
859 result.AppendError ("no process exists. Cannot continue");
860 result.SetStatus (eReturnStatusFailed);
861 return false;
862 }
863
864 StateType state = process->GetState();
865 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
866 {
867 const uint32_t num_threads = process->GetThreadList().GetSize();
868 uint32_t idx;
869 const size_t argc = command.GetArgumentCount();
870 if (argc > 0)
871 {
872 std::vector<uint32_t> resume_thread_indexes;
873 for (uint32_t i=0; i<argc; ++i)
874 {
875 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
876 if (idx < num_threads)
877 resume_thread_indexes.push_back(idx);
878 else
879 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
880 }
881
882 if (resume_thread_indexes.empty())
883 {
884 result.AppendError ("no valid thread indexes were specified");
885 result.SetStatus (eReturnStatusFailed);
886 return false;
887 }
888 else
889 {
890 result.AppendMessage ("Resuming thread ");
891 for (idx=0; idx<num_threads; ++idx)
892 {
893 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
894 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
895 {
896 result.AppendMessageWithFormat ("%u ", idx);
897 thread->SetResumeState (eStateRunning);
898 }
899 else
900 {
901 thread->SetResumeState (eStateSuspended);
902 }
903 }
904 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
905 }
906 }
907 else
908 {
Jim Inghamc8332952010-08-26 21:32:51 +0000909 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000910 if (current_thread == NULL)
911 {
912 result.AppendError ("the process doesn't have a current thread");
913 result.SetStatus (eReturnStatusFailed);
914 return false;
915 }
916 // Set the actions that the threads should each take when resuming
917 for (idx=0; idx<num_threads; ++idx)
918 {
919 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
920 if (thread == current_thread)
921 {
922 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
923 thread->SetResumeState (eStateRunning);
924 }
925 else
926 {
927 thread->SetResumeState (eStateSuspended);
928 }
929 }
930 }
931
932 Error error (process->Resume());
933 if (error.Success())
934 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000935 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000936 if (synchronous_execution)
937 {
Greg Claytonbef15832010-07-14 00:18:15 +0000938 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000939
940 result.SetDidChangeProcessState (true);
941 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
942 result.SetStatus (eReturnStatusSuccessFinishNoResult);
943 }
944 else
945 {
946 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
947 }
948 }
949 else
950 {
951 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
952 result.SetStatus (eReturnStatusFailed);
953 }
954 }
955 else
956 {
957 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
958 StateAsCString(state));
959 result.SetStatus (eReturnStatusFailed);
960 }
961
962 return result.Succeeded();
963 }
964
965};
966
967//-------------------------------------------------------------------------
968// CommandObjectThreadUntil
969//-------------------------------------------------------------------------
970
971class CommandObjectThreadUntil : public CommandObject
972{
973public:
974
975 class CommandOptions : public Options
976 {
977 public:
978 uint32_t m_thread_idx;
979 uint32_t m_frame_idx;
980
981 CommandOptions () :
982 Options(),
983 m_thread_idx(LLDB_INVALID_THREAD_ID),
984 m_frame_idx(LLDB_INVALID_FRAME_ID)
985 {
986 // Keep default values of all options in one place: ResetOptionValues ()
987 ResetOptionValues ();
988 }
989
990 virtual
991 ~CommandOptions ()
992 {
993 }
994
995 virtual Error
996 SetOptionValue (int option_idx, const char *option_arg)
997 {
998 Error error;
999 char short_option = (char) m_getopt_table[option_idx].val;
1000
1001 switch (short_option)
1002 {
1003 case 't':
1004 {
Greg Claytonbef15832010-07-14 00:18:15 +00001005 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +00001006 if (m_thread_idx == LLDB_INVALID_INDEX32)
1007 {
1008 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
1009 }
1010 }
1011 break;
1012 case 'f':
1013 {
1014 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1015 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1016 {
1017 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
1018 }
1019 }
1020 break;
1021 case 'm':
1022 {
1023 bool found_one = false;
1024 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1025 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
1026
1027 if (!found_one)
1028 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
1029 else if (run_mode == eAllThreads)
1030 m_stop_others = false;
1031 else
1032 m_stop_others = true;
1033
1034 }
1035 break;
1036 default:
1037 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1038 break;
1039
1040 }
1041 return error;
1042 }
1043
1044 void
1045 ResetOptionValues ()
1046 {
1047 Options::ResetOptionValues();
1048 m_thread_idx = LLDB_INVALID_THREAD_ID;
1049 m_frame_idx = 0;
1050 m_stop_others = false;
1051 }
1052
Greg Claytonb3448432011-03-24 21:19:54 +00001053 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +00001054 GetDefinitions ()
1055 {
1056 return g_option_table;
1057 }
1058
1059 uint32_t m_step_thread_idx;
1060 bool m_stop_others;
1061
1062 // Options table: Required for subclasses of Options.
1063
Greg Claytonb3448432011-03-24 21:19:54 +00001064 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +00001065
1066 // Instance variables to hold the values for command options.
1067 };
1068
Greg Clayton238c0a12010-09-18 01:14:36 +00001069 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1070 CommandObject (interpreter,
1071 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001072 "Run the current or specified thread until it reaches a given line number or leaves the current function.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001073 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +00001074 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1075 m_options ()
1076 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001077 CommandArgumentEntry arg;
1078 CommandArgumentData line_num_arg;
1079
1080 // Define the first (and only) variant of this arg.
1081 line_num_arg.arg_type = eArgTypeLineNum;
1082 line_num_arg.arg_repetition = eArgRepeatPlain;
1083
1084 // There is only one variant this argument could be; put it into the argument entry.
1085 arg.push_back (line_num_arg);
1086
1087 // Push the data for the first argument into the m_arguments vector.
1088 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001089 }
1090
1091
1092 virtual
1093 ~CommandObjectThreadUntil ()
1094 {
1095 }
1096
1097 virtual
1098 Options *
1099 GetOptions ()
1100 {
1101 return &m_options;
1102 }
1103
1104 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001105 Execute
1106 (
Greg Clayton63094e02010-06-23 01:19:29 +00001107 Args& command,
1108 CommandReturnObject &result
1109 )
Chris Lattner24943d22010-06-08 16:52:24 +00001110 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001111 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001112
Greg Clayton238c0a12010-09-18 01:14:36 +00001113 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001114 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001115 {
1116 result.AppendError ("invalid target, set executable file using 'file' command");
1117 result.SetStatus (eReturnStatusFailed);
1118 return false;
1119 }
1120
Greg Clayton238c0a12010-09-18 01:14:36 +00001121 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001122 if (process == NULL)
1123 {
1124 result.AppendError ("need a valid process to step");
1125 result.SetStatus (eReturnStatusFailed);
1126
1127 }
1128 else
1129 {
1130 Thread *thread = NULL;
1131 uint32_t line_number;
1132
1133 if (command.GetArgumentCount() != 1)
1134 {
1135 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1136 result.SetStatus (eReturnStatusFailed);
1137 return false;
1138 }
1139
1140 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1141 if (line_number == UINT32_MAX)
1142 {
1143 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1144 result.SetStatus (eReturnStatusFailed);
1145 return false;
1146 }
1147
1148 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1149 {
Jim Inghamc8332952010-08-26 21:32:51 +00001150 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001151 }
1152 else
1153 {
1154 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1155 }
1156
1157 if (thread == NULL)
1158 {
1159 const uint32_t num_threads = process->GetThreadList().GetSize();
1160 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1161 result.SetStatus (eReturnStatusFailed);
1162 return false;
1163 }
1164
1165 const bool abort_other_plans = true;
1166
1167 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1168 if (frame == NULL)
1169 {
1170
1171 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1172 result.SetStatus (eReturnStatusFailed);
1173 return false;
1174 }
1175
1176 ThreadPlan *new_plan;
1177
1178 if (frame->HasDebugInformation ())
1179 {
1180 // Finally we got here... Translate the given line number to a bunch of addresses:
1181 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1182 LineTable *line_table = NULL;
1183 if (sc.comp_unit)
1184 line_table = sc.comp_unit->GetLineTable();
1185
1186 if (line_table == NULL)
1187 {
1188 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1189 m_options.m_frame_idx, m_options.m_thread_idx);
1190 result.SetStatus (eReturnStatusFailed);
1191 return false;
1192 }
1193
1194 LineEntry function_start;
1195 uint32_t index_ptr = 0, end_ptr;
1196 std::vector<addr_t> address_list;
1197
1198 // Find the beginning & end index of the
1199 AddressRange fun_addr_range = sc.function->GetAddressRange();
1200 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1201 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1202
1203 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1204 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1205
1206 while (index_ptr <= end_ptr)
1207 {
1208 LineEntry line_entry;
1209 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1210 if (index_ptr == UINT32_MAX)
1211 break;
1212
Greg Claytoneea26402010-09-14 23:36:40 +00001213 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001214 if (address != LLDB_INVALID_ADDRESS)
1215 address_list.push_back (address);
1216 index_ptr++;
1217 }
1218
Greg Clayton1ebdcc72011-01-21 06:11:58 +00001219 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others, thread->GetSelectedFrameIndex ());
Chris Lattner24943d22010-06-08 16:52:24 +00001220 new_plan->SetOkayToDiscard(false);
1221 }
1222 else
1223 {
1224 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1225 result.SetStatus (eReturnStatusFailed);
1226 return false;
1227
1228 }
1229
Jim Inghamc8332952010-08-26 21:32:51 +00001230 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001231 Error error (process->Resume ());
1232 if (error.Success())
1233 {
Greg Claytonc1d37752010-10-18 01:45:30 +00001234 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001235 if (synchronous_execution)
1236 {
1237 StateType state = process->WaitForProcessToStop (NULL);
1238
1239 result.SetDidChangeProcessState (true);
1240 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1241 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1242 }
1243 else
1244 {
1245 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1246 }
1247 }
1248 else
1249 {
1250 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1251 result.SetStatus (eReturnStatusFailed);
1252 }
1253
1254 }
1255 return result.Succeeded();
1256 }
1257protected:
1258 CommandOptions m_options;
1259
1260};
1261
Greg Claytonb3448432011-03-24 21:19:54 +00001262OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001263CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1264{
Caroline Tice43b014a2010-10-04 22:28:36 +00001265{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"},
Caroline Tice4d6675c2010-10-01 19:59:14 +00001266{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1267{ 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"},
1268{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001269};
1270
1271
1272//-------------------------------------------------------------------------
1273// CommandObjectThreadSelect
1274//-------------------------------------------------------------------------
1275
1276class CommandObjectThreadSelect : public CommandObject
1277{
1278public:
1279
Greg Clayton238c0a12010-09-18 01:14:36 +00001280 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1281 CommandObject (interpreter,
1282 "thread select",
1283 "Select a thread as the currently active thread.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001284 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001285 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001286 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001287 CommandArgumentEntry arg;
1288 CommandArgumentData thread_idx_arg;
1289
1290 // Define the first (and only) variant of this arg.
1291 thread_idx_arg.arg_type = eArgTypeThreadIndex;
1292 thread_idx_arg.arg_repetition = eArgRepeatPlain;
1293
1294 // There is only one variant this argument could be; put it into the argument entry.
1295 arg.push_back (thread_idx_arg);
1296
1297 // Push the data for the first argument into the m_arguments vector.
1298 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001299 }
1300
1301
1302 virtual
1303 ~CommandObjectThreadSelect ()
1304 {
1305 }
1306
1307 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001308 Execute
1309 (
Greg Clayton63094e02010-06-23 01:19:29 +00001310 Args& command,
1311 CommandReturnObject &result
1312 )
Chris Lattner24943d22010-06-08 16:52:24 +00001313 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001314 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001315 if (process == NULL)
1316 {
1317 result.AppendError ("no process");
1318 result.SetStatus (eReturnStatusFailed);
1319 return false;
1320 }
1321 else if (command.GetArgumentCount() != 1)
1322 {
1323 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1324 result.SetStatus (eReturnStatusFailed);
1325 return false;
1326 }
1327
1328 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1329
1330 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1331 if (new_thread == NULL)
1332 {
1333 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1334 result.SetStatus (eReturnStatusFailed);
1335 return false;
1336 }
1337
Jim Inghamc8332952010-08-26 21:32:51 +00001338 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001339 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001340
Greg Clayton238c0a12010-09-18 01:14:36 +00001341 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001342 result.GetOutputStream(),
1343 new_thread,
1344 false,
1345 true);
1346
1347 return result.Succeeded();
1348 }
1349
1350};
1351
1352
1353//-------------------------------------------------------------------------
1354// CommandObjectThreadList
1355//-------------------------------------------------------------------------
1356
Greg Clayton63094e02010-06-23 01:19:29 +00001357class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001358{
Greg Clayton63094e02010-06-23 01:19:29 +00001359public:
Chris Lattner24943d22010-06-08 16:52:24 +00001360
Chris Lattner24943d22010-06-08 16:52:24 +00001361
Greg Clayton238c0a12010-09-18 01:14:36 +00001362 CommandObjectThreadList (CommandInterpreter &interpreter):
1363 CommandObject (interpreter,
1364 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001365 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001366 "thread list",
1367 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001368 {
Greg Clayton63094e02010-06-23 01:19:29 +00001369 }
Chris Lattner24943d22010-06-08 16:52:24 +00001370
Greg Clayton63094e02010-06-23 01:19:29 +00001371 ~CommandObjectThreadList()
1372 {
1373 }
1374
1375 bool
1376 Execute
1377 (
Greg Clayton63094e02010-06-23 01:19:29 +00001378 Args& command,
1379 CommandReturnObject &result
1380 )
1381 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00001382 Stream &strm = result.GetOutputStream();
Greg Clayton63094e02010-06-23 01:19:29 +00001383 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001384 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001385 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001386 {
Greg Clayton63094e02010-06-23 01:19:29 +00001387 const StateType state = exe_ctx.process->GetState();
1388
1389 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001390 {
Greg Clayton63094e02010-06-23 01:19:29 +00001391 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001392 {
Greg Clayton63094e02010-06-23 01:19:29 +00001393 int exit_status = exe_ctx.process->GetExitStatus();
1394 const char *exit_description = exe_ctx.process->GetExitDescription();
1395 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1396 exe_ctx.process->GetID(),
1397 exit_status,
1398 exit_status,
1399 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001400 }
1401 else
1402 {
Greg Clayton63094e02010-06-23 01:19:29 +00001403 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1404 if (exe_ctx.thread == NULL)
1405 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1406 if (exe_ctx.thread != NULL)
1407 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001408 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001409 }
1410 else
1411 {
1412 result.AppendError ("no valid thread found in current process");
1413 result.SetStatus (eReturnStatusFailed);
1414 }
Chris Lattner24943d22010-06-08 16:52:24 +00001415 }
1416 }
Greg Clayton63094e02010-06-23 01:19:29 +00001417 else
1418 {
1419 result.AppendError ("process is currently running");
1420 result.SetStatus (eReturnStatusFailed);
1421 }
Chris Lattner24943d22010-06-08 16:52:24 +00001422 }
1423 else
1424 {
Greg Clayton63094e02010-06-23 01:19:29 +00001425 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001426 result.SetStatus (eReturnStatusFailed);
1427 }
Greg Clayton63094e02010-06-23 01:19:29 +00001428 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001429 }
Greg Clayton63094e02010-06-23 01:19:29 +00001430};
Chris Lattner24943d22010-06-08 16:52:24 +00001431
1432//-------------------------------------------------------------------------
1433// CommandObjectMultiwordThread
1434//-------------------------------------------------------------------------
1435
Greg Clayton63094e02010-06-23 01:19:29 +00001436CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001437 CommandObjectMultiword (interpreter,
1438 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001439 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001440 "thread <subcommand> [<subcommand-options>]")
1441{
Greg Clayton238c0a12010-09-18 01:14:36 +00001442 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1443 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1444 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1445 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1446 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1447 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1448 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001449 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001450 "Source level single step in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001451 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001452 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1453 eStepTypeInto,
1454 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001455
Greg Clayton238c0a12010-09-18 01:14:36 +00001456 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1457 interpreter,
1458 "thread step-out",
1459 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001460 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001461 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1462 eStepTypeOut,
1463 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001464
Greg Clayton238c0a12010-09-18 01:14:36 +00001465 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1466 interpreter,
1467 "thread step-over",
1468 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001469 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001470 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1471 eStepTypeOver,
1472 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001473
Greg Clayton238c0a12010-09-18 01:14:36 +00001474 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1475 interpreter,
1476 "thread step-inst",
1477 "Single step one instruction in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001478 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001479 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1480 eStepTypeTrace,
1481 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001482
Greg Clayton238c0a12010-09-18 01:14:36 +00001483 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1484 interpreter,
1485 "thread step-inst-over",
1486 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001487 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001488 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1489 eStepTypeTraceOver,
1490 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001491}
1492
1493CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1494{
1495}
1496
1497