blob: 01708a4e42809f9d616b5649f0b76474a892a3a8 [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.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000325 NULL,
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 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000329 CommandArgumentEntry arg;
330 CommandArgumentData thread_idx_arg;
331
332 // Define the first (and only) variant of this arg.
333 thread_idx_arg.arg_type = eArgTypeThreadIndex;
334 thread_idx_arg.arg_repetition = eArgRepeatStar;
335
336 // There is only one variant this argument could be; put it into the argument entry.
337 arg.push_back (thread_idx_arg);
338
339 // Push the data for the first argument into the m_arguments vector.
340 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000341 }
342
343 ~CommandObjectThreadBacktrace()
344 {
345 }
346
Jim Ingham8ab1a802010-08-26 23:36:03 +0000347 virtual Options *
348 GetOptions ()
349 {
350 return &m_options;
351 }
Chris Lattner24943d22010-06-08 16:52:24 +0000352
Greg Clayton63094e02010-06-23 01:19:29 +0000353 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000354 Execute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000355 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000356
357 bool show_frame_info = true;
358 uint32_t num_frames_with_source = 0; // Don't show any frames with source when backtracing
359
360 result.SetStatus (eReturnStatusSuccessFinishResult);
361
Chris Lattner24943d22010-06-08 16:52:24 +0000362 if (command.GetArgumentCount() == 0)
363 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000364 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000365 if (exe_ctx.thread)
366 {
Chris Lattner24943d22010-06-08 16:52:24 +0000367 if (DisplayFramesForExecutionContext (exe_ctx.thread,
Greg Clayton238c0a12010-09-18 01:14:36 +0000368 m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000369 result.GetOutputStream(),
Jim Ingham8ab1a802010-08-26 23:36:03 +0000370 m_options.m_start,
371 m_options.m_count,
Chris Lattner24943d22010-06-08 16:52:24 +0000372 show_frame_info,
373 num_frames_with_source,
374 3,
375 3))
376 {
377 result.SetStatus (eReturnStatusSuccessFinishResult);
378 }
379 }
380 else
381 {
382 result.AppendError ("invalid thread");
383 result.SetStatus (eReturnStatusFailed);
384 }
385 }
Jim Inghameb10f7b2010-08-27 00:58:05 +0000386 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
387 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000388 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000389 uint32_t num_threads = process->GetThreadList().GetSize();
390 for (uint32_t i = 0; i < num_threads; i++)
391 {
392 ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
393 if (!DisplayFramesForExecutionContext (thread_sp.get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000394 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000395 result.GetOutputStream(),
396 m_options.m_start,
397 m_options.m_count,
398 show_frame_info,
399 num_frames_with_source,
400 3,
401 3))
402 {
Greg Claytonf04d6612010-09-03 22:45:01 +0000403 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
Jim Inghameb10f7b2010-08-27 00:58:05 +0000404 result.SetStatus (eReturnStatusFailed);
405 return false;
406 }
407 if (i < num_threads - 1)
408 result.AppendMessage("");
409 }
410 }
Chris Lattner24943d22010-06-08 16:52:24 +0000411 else
412 {
Jim Inghameb10f7b2010-08-27 00:58:05 +0000413 uint32_t num_args = command.GetArgumentCount();
Greg Clayton238c0a12010-09-18 01:14:36 +0000414 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Inghameb10f7b2010-08-27 00:58:05 +0000415 std::vector<ThreadSP> thread_sps;
416
417 for (uint32_t i = 0; i < num_args; i++)
418 {
419 bool success;
420
421 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success);
422 if (!success)
423 {
424 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i));
425 result.SetStatus (eReturnStatusFailed);
426 return false;
427 }
428
429 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx));
430
431 if (!thread_sps[i])
432 {
433 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i));
434 result.SetStatus (eReturnStatusFailed);
435 return false;
436 }
437
438 }
439
440 for (uint32_t i = 0; i < num_args; i++)
441 {
442 if (!DisplayFramesForExecutionContext (thread_sps[i].get(),
Greg Clayton238c0a12010-09-18 01:14:36 +0000443 m_interpreter,
Jim Inghameb10f7b2010-08-27 00:58:05 +0000444 result.GetOutputStream(),
445 m_options.m_start,
446 m_options.m_count,
447 show_frame_info,
448 num_frames_with_source,
449 3,
450 3))
451 {
452 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"%s\"\n", command.GetArgumentAtIndex(i));
453 result.SetStatus (eReturnStatusFailed);
454 return false;
455 }
456
457 if (i < num_args - 1)
458 result.AppendMessage("");
459 }
Chris Lattner24943d22010-06-08 16:52:24 +0000460 }
461 return result.Succeeded();
462 }
463protected:
Jim Ingham8ab1a802010-08-26 23:36:03 +0000464 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000465};
466
Jim Ingham8ab1a802010-08-26 23:36:03 +0000467lldb::OptionDefinition
468CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
469{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000470{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
Caroline Tice43b014a2010-10-04 22:28:36 +0000471{ 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 +0000472{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Jim Ingham8ab1a802010-08-26 23:36:03 +0000473};
Chris Lattner24943d22010-06-08 16:52:24 +0000474
Greg Claytonc0418152010-07-07 17:07:17 +0000475enum StepScope
Chris Lattner24943d22010-06-08 16:52:24 +0000476{
477 eStepScopeSource,
478 eStepScopeInstruction
479};
480
481class CommandObjectThreadStepWithTypeAndScope : public CommandObject
482{
483public:
484
485 class CommandOptions : public Options
486 {
487 public:
488
489 CommandOptions () :
490 Options()
491 {
492 // Keep default values of all options in one place: ResetOptionValues ()
493 ResetOptionValues ();
494 }
495
496 virtual
497 ~CommandOptions ()
498 {
499 }
500
501 virtual Error
502 SetOptionValue (int option_idx, const char *option_arg)
503 {
504 Error error;
505 char short_option = (char) m_getopt_table[option_idx].val;
506
507 switch (short_option)
508 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000509 case 'a':
Chris Lattner24943d22010-06-08 16:52:24 +0000510 {
511 bool success;
512 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
513 if (!success)
514 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
515 }
516 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000517
518 case 'm':
Chris Lattner24943d22010-06-08 16:52:24 +0000519 {
520 bool found_one = false;
521 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
522 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
523 if (!found_one)
524 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
525 }
526 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000527
528 case 'r':
Jim Ingham809ab9b2010-07-10 02:27:39 +0000529 {
530 m_avoid_regexp.clear();
531 m_avoid_regexp.assign(option_arg);
532 }
533 break;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000534
535 default:
536 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
537 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000538
539 }
540 return error;
541 }
542
543 void
544 ResetOptionValues ()
545 {
546 Options::ResetOptionValues();
547 m_avoid_no_debug = true;
548 m_run_mode = eOnlyDuringStepping;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000549 m_avoid_regexp.clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000550 }
551
552 const lldb::OptionDefinition*
553 GetDefinitions ()
554 {
555 return g_option_table;
556 }
557
558 // Options table: Required for subclasses of Options.
559
560 static lldb::OptionDefinition g_option_table[];
561
562 // Instance variables to hold the values for command options.
563 bool m_avoid_no_debug;
564 RunMode m_run_mode;
Jim Ingham809ab9b2010-07-10 02:27:39 +0000565 std::string m_avoid_regexp;
Chris Lattner24943d22010-06-08 16:52:24 +0000566 };
567
Greg Clayton238c0a12010-09-18 01:14:36 +0000568 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter,
569 const char *name,
570 const char *help,
571 const char *syntax,
572 uint32_t flags,
573 StepType step_type,
574 StepScope step_scope) :
575 CommandObject (interpreter, name, help, syntax, flags),
Chris Lattner24943d22010-06-08 16:52:24 +0000576 m_step_type (step_type),
577 m_step_scope (step_scope),
578 m_options ()
579 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000580 CommandArgumentEntry arg;
581 CommandArgumentData thread_id_arg;
582
583 // Define the first (and only) variant of this arg.
584 thread_id_arg.arg_type = eArgTypeThreadID;
585 thread_id_arg.arg_repetition = eArgRepeatOptional;
586
587 // There is only one variant this argument could be; put it into the argument entry.
588 arg.push_back (thread_id_arg);
589
590 // Push the data for the first argument into the m_arguments vector.
591 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000592 }
593
594 virtual
595 ~CommandObjectThreadStepWithTypeAndScope ()
596 {
597 }
598
599 virtual
600 Options *
601 GetOptions ()
602 {
603 return &m_options;
604 }
605
606 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000607 Execute
608 (
Greg Clayton63094e02010-06-23 01:19:29 +0000609 Args& command,
610 CommandReturnObject &result
611 )
Chris Lattner24943d22010-06-08 16:52:24 +0000612 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000613 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
614 bool synchronous_execution = m_interpreter.GetSynchronous();
Chris Lattner24943d22010-06-08 16:52:24 +0000615
616 if (process == NULL)
617 {
618 result.AppendError ("need a valid process to step");
619 result.SetStatus (eReturnStatusFailed);
620
621 }
622 else
623 {
624 const uint32_t num_threads = process->GetThreadList().GetSize();
625 Thread *thread = NULL;
626
627 if (command.GetArgumentCount() == 0)
628 {
Jim Inghamc8332952010-08-26 21:32:51 +0000629 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000630 if (thread == NULL)
631 {
Jim Ingham8ab1a802010-08-26 23:36:03 +0000632 result.AppendError ("no selected thread in process");
Chris Lattner24943d22010-06-08 16:52:24 +0000633 result.SetStatus (eReturnStatusFailed);
634 return false;
635 }
636 }
637 else
638 {
639 const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
640 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
641 if (step_thread_idx == LLDB_INVALID_INDEX32)
642 {
643 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
644 result.SetStatus (eReturnStatusFailed);
645 return false;
646 }
647 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
648 if (thread == NULL)
649 {
650 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
651 step_thread_idx, 0, num_threads);
652 result.SetStatus (eReturnStatusFailed);
653 return false;
654 }
655 }
656
657 const bool abort_other_plans = false;
658 const lldb::RunMode stop_other_threads = m_options.m_run_mode;
659
660 // This is a bit unfortunate, but not all the commands in this command object support
661 // only while stepping, so I use the bool for them.
662 bool bool_stop_other_threads;
663 if (m_options.m_run_mode == eAllThreads)
664 bool_stop_other_threads = false;
665 else
666 bool_stop_other_threads = true;
667
668 if (m_step_type == eStepTypeInto)
669 {
670 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
671 ThreadPlan *new_plan;
672
673 if (frame->HasDebugInformation ())
674 {
675 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
676 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
677 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000678 stop_other_threads,
679 m_options.m_avoid_no_debug);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000680 if (new_plan && !m_options.m_avoid_regexp.empty())
681 {
682 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
683 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
684 }
Chris Lattner24943d22010-06-08 16:52:24 +0000685 }
686 else
687 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
688
Jim Inghamc8332952010-08-26 21:32:51 +0000689 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000690 process->Resume ();
691 }
692 else if (m_step_type == eStepTypeOver)
693 {
694 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
695 ThreadPlan *new_plan;
696
697 if (frame->HasDebugInformation())
698 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
699 m_step_type,
700 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
701 frame->GetSymbolContext(eSymbolContextEverything),
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000702 stop_other_threads,
703 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000704 else
705 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
706 abort_other_plans,
707 bool_stop_other_threads);
708
709 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
710 // Maybe there should be a parameter to control this.
711 new_plan->SetOkayToDiscard(false);
712
Jim Inghamc8332952010-08-26 21:32:51 +0000713 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000714 process->Resume ();
715 }
716 else if (m_step_type == eStepTypeTrace)
717 {
718 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000719 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000720 process->Resume ();
721 }
722 else if (m_step_type == eStepTypeTraceOver)
723 {
724 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
Jim Inghamc8332952010-08-26 21:32:51 +0000725 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000726 process->Resume ();
727 }
728 else if (m_step_type == eStepTypeOut)
729 {
730 ThreadPlan *new_plan;
731
732 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
733 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
734 // Maybe there should be a parameter to control this.
735 new_plan->SetOkayToDiscard(false);
736
Jim Inghamc8332952010-08-26 21:32:51 +0000737 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000738 process->Resume ();
739 }
740 else
741 {
742 result.AppendError ("step type is not supported");
743 result.SetStatus (eReturnStatusFailed);
744 }
745 if (synchronous_execution)
746 {
747 StateType state = process->WaitForProcessToStop (NULL);
748
749 //EventSP event_sp;
750 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
751 //while (! StateIsStoppedState (state))
752 // {
753 // state = process->WaitForStateChangedEvents (NULL, event_sp);
754 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000755 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000756 result.SetDidChangeProcessState (true);
757 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
758 result.SetStatus (eReturnStatusSuccessFinishNoResult);
759 }
760 }
761 return result.Succeeded();
762 }
763
764protected:
765 StepType m_step_type;
766 StepScope m_step_scope;
767 CommandOptions m_options;
768};
769
770static lldb::OptionEnumValueElement
771g_tri_running_mode[] =
772{
Greg Claytonfe424a92010-09-18 03:37:20 +0000773{ eOnlyThisThread, "this-thread", "Run only this thread"},
774{ eAllThreads, "all-threads", "Run all threads"},
775{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000776{ 0, NULL, NULL }
777};
778
779static lldb::OptionEnumValueElement
780g_duo_running_mode[] =
781{
Greg Claytonfe424a92010-09-18 03:37:20 +0000782{ eOnlyThisThread, "this-thread", "Run only this thread"},
783{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000784{ 0, NULL, NULL }
785};
786
787lldb::OptionDefinition
788CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
789{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000790{ 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."},
791{ 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."},
792{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
793{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000794};
795
796
797//-------------------------------------------------------------------------
798// CommandObjectThreadContinue
799//-------------------------------------------------------------------------
800
801class CommandObjectThreadContinue : public CommandObject
802{
803public:
804
Greg Clayton238c0a12010-09-18 01:14:36 +0000805 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
806 CommandObject (interpreter,
807 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000808 "Continue execution of one or more threads in an active process.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000809 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000810 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
811 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000812 CommandArgumentEntry arg;
813 CommandArgumentData thread_idx_arg;
814
815 // Define the first (and only) variant of this arg.
816 thread_idx_arg.arg_type = eArgTypeThreadIndex;
817 thread_idx_arg.arg_repetition = eArgRepeatPlus;
818
819 // There is only one variant this argument could be; put it into the argument entry.
820 arg.push_back (thread_idx_arg);
821
822 // Push the data for the first argument into the m_arguments vector.
823 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000824 }
825
826
827 virtual
828 ~CommandObjectThreadContinue ()
829 {
830 }
831
832 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000833 Execute
834 (
Greg Clayton63094e02010-06-23 01:19:29 +0000835 Args& command,
836 CommandReturnObject &result
837 )
Chris Lattner24943d22010-06-08 16:52:24 +0000838 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000839 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000840
Greg Clayton238c0a12010-09-18 01:14:36 +0000841 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000842 {
843 result.AppendError ("invalid target, set executable file using 'file' command");
844 result.SetStatus (eReturnStatusFailed);
845 return false;
846 }
847
Greg Clayton238c0a12010-09-18 01:14:36 +0000848 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000849 if (process == NULL)
850 {
851 result.AppendError ("no process exists. Cannot continue");
852 result.SetStatus (eReturnStatusFailed);
853 return false;
854 }
855
856 StateType state = process->GetState();
857 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
858 {
859 const uint32_t num_threads = process->GetThreadList().GetSize();
860 uint32_t idx;
861 const size_t argc = command.GetArgumentCount();
862 if (argc > 0)
863 {
864 std::vector<uint32_t> resume_thread_indexes;
865 for (uint32_t i=0; i<argc; ++i)
866 {
867 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
868 if (idx < num_threads)
869 resume_thread_indexes.push_back(idx);
870 else
871 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
872 }
873
874 if (resume_thread_indexes.empty())
875 {
876 result.AppendError ("no valid thread indexes were specified");
877 result.SetStatus (eReturnStatusFailed);
878 return false;
879 }
880 else
881 {
882 result.AppendMessage ("Resuming thread ");
883 for (idx=0; idx<num_threads; ++idx)
884 {
885 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
886 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
887 {
888 result.AppendMessageWithFormat ("%u ", idx);
889 thread->SetResumeState (eStateRunning);
890 }
891 else
892 {
893 thread->SetResumeState (eStateSuspended);
894 }
895 }
896 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
897 }
898 }
899 else
900 {
Jim Inghamc8332952010-08-26 21:32:51 +0000901 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000902 if (current_thread == NULL)
903 {
904 result.AppendError ("the process doesn't have a current thread");
905 result.SetStatus (eReturnStatusFailed);
906 return false;
907 }
908 // Set the actions that the threads should each take when resuming
909 for (idx=0; idx<num_threads; ++idx)
910 {
911 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
912 if (thread == current_thread)
913 {
914 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
915 thread->SetResumeState (eStateRunning);
916 }
917 else
918 {
919 thread->SetResumeState (eStateSuspended);
920 }
921 }
922 }
923
924 Error error (process->Resume());
925 if (error.Success())
926 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000927 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000928 if (synchronous_execution)
929 {
Greg Claytonbef15832010-07-14 00:18:15 +0000930 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000931
932 result.SetDidChangeProcessState (true);
933 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
934 result.SetStatus (eReturnStatusSuccessFinishNoResult);
935 }
936 else
937 {
938 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
939 }
940 }
941 else
942 {
943 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
944 result.SetStatus (eReturnStatusFailed);
945 }
946 }
947 else
948 {
949 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
950 StateAsCString(state));
951 result.SetStatus (eReturnStatusFailed);
952 }
953
954 return result.Succeeded();
955 }
956
957};
958
959//-------------------------------------------------------------------------
960// CommandObjectThreadUntil
961//-------------------------------------------------------------------------
962
963class CommandObjectThreadUntil : public CommandObject
964{
965public:
966
967 class CommandOptions : public Options
968 {
969 public:
970 uint32_t m_thread_idx;
971 uint32_t m_frame_idx;
972
973 CommandOptions () :
974 Options(),
975 m_thread_idx(LLDB_INVALID_THREAD_ID),
976 m_frame_idx(LLDB_INVALID_FRAME_ID)
977 {
978 // Keep default values of all options in one place: ResetOptionValues ()
979 ResetOptionValues ();
980 }
981
982 virtual
983 ~CommandOptions ()
984 {
985 }
986
987 virtual Error
988 SetOptionValue (int option_idx, const char *option_arg)
989 {
990 Error error;
991 char short_option = (char) m_getopt_table[option_idx].val;
992
993 switch (short_option)
994 {
995 case 't':
996 {
Greg Claytonbef15832010-07-14 00:18:15 +0000997 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +0000998 if (m_thread_idx == LLDB_INVALID_INDEX32)
999 {
1000 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
1001 }
1002 }
1003 break;
1004 case 'f':
1005 {
1006 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1007 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1008 {
1009 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
1010 }
1011 }
1012 break;
1013 case 'm':
1014 {
1015 bool found_one = false;
1016 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1017 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
1018
1019 if (!found_one)
1020 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
1021 else if (run_mode == eAllThreads)
1022 m_stop_others = false;
1023 else
1024 m_stop_others = true;
1025
1026 }
1027 break;
1028 default:
1029 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1030 break;
1031
1032 }
1033 return error;
1034 }
1035
1036 void
1037 ResetOptionValues ()
1038 {
1039 Options::ResetOptionValues();
1040 m_thread_idx = LLDB_INVALID_THREAD_ID;
1041 m_frame_idx = 0;
1042 m_stop_others = false;
1043 }
1044
1045 const lldb::OptionDefinition*
1046 GetDefinitions ()
1047 {
1048 return g_option_table;
1049 }
1050
1051 uint32_t m_step_thread_idx;
1052 bool m_stop_others;
1053
1054 // Options table: Required for subclasses of Options.
1055
1056 static lldb::OptionDefinition g_option_table[];
1057
1058 // Instance variables to hold the values for command options.
1059 };
1060
Greg Clayton238c0a12010-09-18 01:14:36 +00001061 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1062 CommandObject (interpreter,
1063 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001064 "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 +00001065 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +00001066 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1067 m_options ()
1068 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001069 CommandArgumentEntry arg;
1070 CommandArgumentData line_num_arg;
1071
1072 // Define the first (and only) variant of this arg.
1073 line_num_arg.arg_type = eArgTypeLineNum;
1074 line_num_arg.arg_repetition = eArgRepeatPlain;
1075
1076 // There is only one variant this argument could be; put it into the argument entry.
1077 arg.push_back (line_num_arg);
1078
1079 // Push the data for the first argument into the m_arguments vector.
1080 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001081 }
1082
1083
1084 virtual
1085 ~CommandObjectThreadUntil ()
1086 {
1087 }
1088
1089 virtual
1090 Options *
1091 GetOptions ()
1092 {
1093 return &m_options;
1094 }
1095
1096 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001097 Execute
1098 (
Greg Clayton63094e02010-06-23 01:19:29 +00001099 Args& command,
1100 CommandReturnObject &result
1101 )
Chris Lattner24943d22010-06-08 16:52:24 +00001102 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001103 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001104
Greg Clayton238c0a12010-09-18 01:14:36 +00001105 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001106 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001107 {
1108 result.AppendError ("invalid target, set executable file using 'file' command");
1109 result.SetStatus (eReturnStatusFailed);
1110 return false;
1111 }
1112
Greg Clayton238c0a12010-09-18 01:14:36 +00001113 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001114 if (process == NULL)
1115 {
1116 result.AppendError ("need a valid process to step");
1117 result.SetStatus (eReturnStatusFailed);
1118
1119 }
1120 else
1121 {
1122 Thread *thread = NULL;
1123 uint32_t line_number;
1124
1125 if (command.GetArgumentCount() != 1)
1126 {
1127 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1128 result.SetStatus (eReturnStatusFailed);
1129 return false;
1130 }
1131
1132 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1133 if (line_number == UINT32_MAX)
1134 {
1135 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1136 result.SetStatus (eReturnStatusFailed);
1137 return false;
1138 }
1139
1140 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1141 {
Jim Inghamc8332952010-08-26 21:32:51 +00001142 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001143 }
1144 else
1145 {
1146 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1147 }
1148
1149 if (thread == NULL)
1150 {
1151 const uint32_t num_threads = process->GetThreadList().GetSize();
1152 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1153 result.SetStatus (eReturnStatusFailed);
1154 return false;
1155 }
1156
1157 const bool abort_other_plans = true;
1158
1159 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1160 if (frame == NULL)
1161 {
1162
1163 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1164 result.SetStatus (eReturnStatusFailed);
1165 return false;
1166 }
1167
1168 ThreadPlan *new_plan;
1169
1170 if (frame->HasDebugInformation ())
1171 {
1172 // Finally we got here... Translate the given line number to a bunch of addresses:
1173 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1174 LineTable *line_table = NULL;
1175 if (sc.comp_unit)
1176 line_table = sc.comp_unit->GetLineTable();
1177
1178 if (line_table == NULL)
1179 {
1180 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1181 m_options.m_frame_idx, m_options.m_thread_idx);
1182 result.SetStatus (eReturnStatusFailed);
1183 return false;
1184 }
1185
1186 LineEntry function_start;
1187 uint32_t index_ptr = 0, end_ptr;
1188 std::vector<addr_t> address_list;
1189
1190 // Find the beginning & end index of the
1191 AddressRange fun_addr_range = sc.function->GetAddressRange();
1192 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1193 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1194
1195 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1196 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1197
1198 while (index_ptr <= end_ptr)
1199 {
1200 LineEntry line_entry;
1201 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1202 if (index_ptr == UINT32_MAX)
1203 break;
1204
Greg Claytoneea26402010-09-14 23:36:40 +00001205 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001206 if (address != LLDB_INVALID_ADDRESS)
1207 address_list.push_back (address);
1208 index_ptr++;
1209 }
1210
Greg Clayton53d68e72010-07-20 22:52:08 +00001211 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 +00001212 new_plan->SetOkayToDiscard(false);
1213 }
1214 else
1215 {
1216 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1217 result.SetStatus (eReturnStatusFailed);
1218 return false;
1219
1220 }
1221
Jim Inghamc8332952010-08-26 21:32:51 +00001222 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001223 Error error (process->Resume ());
1224 if (error.Success())
1225 {
Greg Claytonc1d37752010-10-18 01:45:30 +00001226 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001227 if (synchronous_execution)
1228 {
1229 StateType state = process->WaitForProcessToStop (NULL);
1230
1231 result.SetDidChangeProcessState (true);
1232 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1233 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1234 }
1235 else
1236 {
1237 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1238 }
1239 }
1240 else
1241 {
1242 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1243 result.SetStatus (eReturnStatusFailed);
1244 }
1245
1246 }
1247 return result.Succeeded();
1248 }
1249protected:
1250 CommandOptions m_options;
1251
1252};
1253
1254lldb::OptionDefinition
1255CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1256{
Caroline Tice43b014a2010-10-04 22:28:36 +00001257{ 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 +00001258{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1259{ 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"},
1260{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001261};
1262
1263
1264//-------------------------------------------------------------------------
1265// CommandObjectThreadSelect
1266//-------------------------------------------------------------------------
1267
1268class CommandObjectThreadSelect : public CommandObject
1269{
1270public:
1271
Greg Clayton238c0a12010-09-18 01:14:36 +00001272 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1273 CommandObject (interpreter,
1274 "thread select",
1275 "Select a thread as the currently active thread.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001276 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001277 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001278 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001279 CommandArgumentEntry arg;
1280 CommandArgumentData thread_idx_arg;
1281
1282 // Define the first (and only) variant of this arg.
1283 thread_idx_arg.arg_type = eArgTypeThreadIndex;
1284 thread_idx_arg.arg_repetition = eArgRepeatPlain;
1285
1286 // There is only one variant this argument could be; put it into the argument entry.
1287 arg.push_back (thread_idx_arg);
1288
1289 // Push the data for the first argument into the m_arguments vector.
1290 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001291 }
1292
1293
1294 virtual
1295 ~CommandObjectThreadSelect ()
1296 {
1297 }
1298
1299 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001300 Execute
1301 (
Greg Clayton63094e02010-06-23 01:19:29 +00001302 Args& command,
1303 CommandReturnObject &result
1304 )
Chris Lattner24943d22010-06-08 16:52:24 +00001305 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001306 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001307 if (process == NULL)
1308 {
1309 result.AppendError ("no process");
1310 result.SetStatus (eReturnStatusFailed);
1311 return false;
1312 }
1313 else if (command.GetArgumentCount() != 1)
1314 {
1315 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1316 result.SetStatus (eReturnStatusFailed);
1317 return false;
1318 }
1319
1320 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1321
1322 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1323 if (new_thread == NULL)
1324 {
1325 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1326 result.SetStatus (eReturnStatusFailed);
1327 return false;
1328 }
1329
Jim Inghamc8332952010-08-26 21:32:51 +00001330 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001331 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001332
Greg Clayton238c0a12010-09-18 01:14:36 +00001333 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001334 result.GetOutputStream(),
1335 new_thread,
1336 false,
1337 true);
1338
1339 return result.Succeeded();
1340 }
1341
1342};
1343
1344
1345//-------------------------------------------------------------------------
1346// CommandObjectThreadList
1347//-------------------------------------------------------------------------
1348
Greg Clayton63094e02010-06-23 01:19:29 +00001349class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001350{
Greg Clayton63094e02010-06-23 01:19:29 +00001351public:
Chris Lattner24943d22010-06-08 16:52:24 +00001352
Chris Lattner24943d22010-06-08 16:52:24 +00001353
Greg Clayton238c0a12010-09-18 01:14:36 +00001354 CommandObjectThreadList (CommandInterpreter &interpreter):
1355 CommandObject (interpreter,
1356 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001357 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001358 "thread list",
1359 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001360 {
Greg Clayton63094e02010-06-23 01:19:29 +00001361 }
Chris Lattner24943d22010-06-08 16:52:24 +00001362
Greg Clayton63094e02010-06-23 01:19:29 +00001363 ~CommandObjectThreadList()
1364 {
1365 }
1366
1367 bool
1368 Execute
1369 (
Greg Clayton63094e02010-06-23 01:19:29 +00001370 Args& command,
1371 CommandReturnObject &result
1372 )
1373 {
1374 StreamString &strm = result.GetOutputStream();
1375 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001376 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001377 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001378 {
Greg Clayton63094e02010-06-23 01:19:29 +00001379 const StateType state = exe_ctx.process->GetState();
1380
1381 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001382 {
Greg Clayton63094e02010-06-23 01:19:29 +00001383 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001384 {
Greg Clayton63094e02010-06-23 01:19:29 +00001385 int exit_status = exe_ctx.process->GetExitStatus();
1386 const char *exit_description = exe_ctx.process->GetExitDescription();
1387 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1388 exe_ctx.process->GetID(),
1389 exit_status,
1390 exit_status,
1391 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001392 }
1393 else
1394 {
Greg Clayton63094e02010-06-23 01:19:29 +00001395 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1396 if (exe_ctx.thread == NULL)
1397 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1398 if (exe_ctx.thread != NULL)
1399 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001400 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001401 }
1402 else
1403 {
1404 result.AppendError ("no valid thread found in current process");
1405 result.SetStatus (eReturnStatusFailed);
1406 }
Chris Lattner24943d22010-06-08 16:52:24 +00001407 }
1408 }
Greg Clayton63094e02010-06-23 01:19:29 +00001409 else
1410 {
1411 result.AppendError ("process is currently running");
1412 result.SetStatus (eReturnStatusFailed);
1413 }
Chris Lattner24943d22010-06-08 16:52:24 +00001414 }
1415 else
1416 {
Greg Clayton63094e02010-06-23 01:19:29 +00001417 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001418 result.SetStatus (eReturnStatusFailed);
1419 }
Greg Clayton63094e02010-06-23 01:19:29 +00001420 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001421 }
Greg Clayton63094e02010-06-23 01:19:29 +00001422};
Chris Lattner24943d22010-06-08 16:52:24 +00001423
1424//-------------------------------------------------------------------------
1425// CommandObjectMultiwordThread
1426//-------------------------------------------------------------------------
1427
Greg Clayton63094e02010-06-23 01:19:29 +00001428CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001429 CommandObjectMultiword (interpreter,
1430 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001431 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001432 "thread <subcommand> [<subcommand-options>]")
1433{
Greg Clayton238c0a12010-09-18 01:14:36 +00001434 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1435 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1436 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1437 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1438 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1439 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1440 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001441 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001442 "Source level single step in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001443 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001444 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1445 eStepTypeInto,
1446 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001447
Greg Clayton238c0a12010-09-18 01:14:36 +00001448 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1449 interpreter,
1450 "thread step-out",
1451 "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 +00001452 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001453 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1454 eStepTypeOut,
1455 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001456
Greg Clayton238c0a12010-09-18 01:14:36 +00001457 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1458 interpreter,
1459 "thread step-over",
1460 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001461 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001462 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1463 eStepTypeOver,
1464 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001465
Greg Clayton238c0a12010-09-18 01:14:36 +00001466 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1467 interpreter,
1468 "thread step-inst",
1469 "Single step one instruction in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001470 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001471 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1472 eStepTypeTrace,
1473 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001474
Greg Clayton238c0a12010-09-18 01:14:36 +00001475 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1476 interpreter,
1477 "thread step-inst-over",
1478 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001479 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001480 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1481 eStepTypeTraceOver,
1482 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001483}
1484
1485CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1486{
1487}
1488
1489