blob: 5cde70efa1bd0ee48ef08864ca81a7d7695a3b08 [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
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000732 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
733 NULL,
734 false,
735 bool_stop_other_threads,
736 eVoteYes,
737 eVoteNoOpinion,
738 thread->GetSelectedFrameIndex());
Chris Lattner24943d22010-06-08 16:52:24 +0000739 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
740 // Maybe there should be a parameter to control this.
741 new_plan->SetOkayToDiscard(false);
742
Jim Inghamc8332952010-08-26 21:32:51 +0000743 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000744 process->Resume ();
745 }
746 else
747 {
748 result.AppendError ("step type is not supported");
749 result.SetStatus (eReturnStatusFailed);
750 }
751 if (synchronous_execution)
752 {
753 StateType state = process->WaitForProcessToStop (NULL);
754
755 //EventSP event_sp;
756 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
757 //while (! StateIsStoppedState (state))
758 // {
759 // state = process->WaitForStateChangedEvents (NULL, event_sp);
760 // }
Jim Inghamc8332952010-08-26 21:32:51 +0000761 process->GetThreadList().SetSelectedThreadByID (thread->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000762 result.SetDidChangeProcessState (true);
763 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
764 result.SetStatus (eReturnStatusSuccessFinishNoResult);
765 }
766 }
767 return result.Succeeded();
768 }
769
770protected:
771 StepType m_step_type;
772 StepScope m_step_scope;
773 CommandOptions m_options;
774};
775
776static lldb::OptionEnumValueElement
777g_tri_running_mode[] =
778{
Greg Claytonfe424a92010-09-18 03:37:20 +0000779{ eOnlyThisThread, "this-thread", "Run only this thread"},
780{ eAllThreads, "all-threads", "Run all threads"},
781{ eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"},
Chris Lattner24943d22010-06-08 16:52:24 +0000782{ 0, NULL, NULL }
783};
784
785static lldb::OptionEnumValueElement
786g_duo_running_mode[] =
787{
Greg Claytonfe424a92010-09-18 03:37:20 +0000788{ eOnlyThisThread, "this-thread", "Run only this thread"},
789{ eAllThreads, "all-threads", "Run all threads"},
Chris Lattner24943d22010-06-08 16:52:24 +0000790{ 0, NULL, NULL }
791};
792
793lldb::OptionDefinition
794CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
795{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000796{ 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."},
797{ 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."},
798{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."},
799{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000800};
801
802
803//-------------------------------------------------------------------------
804// CommandObjectThreadContinue
805//-------------------------------------------------------------------------
806
807class CommandObjectThreadContinue : public CommandObject
808{
809public:
810
Greg Clayton238c0a12010-09-18 01:14:36 +0000811 CommandObjectThreadContinue (CommandInterpreter &interpreter) :
812 CommandObject (interpreter,
813 "thread continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000814 "Continue execution of one or more threads in an active process.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000815 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000816 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
817 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000818 CommandArgumentEntry arg;
819 CommandArgumentData thread_idx_arg;
820
821 // Define the first (and only) variant of this arg.
822 thread_idx_arg.arg_type = eArgTypeThreadIndex;
823 thread_idx_arg.arg_repetition = eArgRepeatPlus;
824
825 // There is only one variant this argument could be; put it into the argument entry.
826 arg.push_back (thread_idx_arg);
827
828 // Push the data for the first argument into the m_arguments vector.
829 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000830 }
831
832
833 virtual
834 ~CommandObjectThreadContinue ()
835 {
836 }
837
838 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000839 Execute
840 (
Greg Clayton63094e02010-06-23 01:19:29 +0000841 Args& command,
842 CommandReturnObject &result
843 )
Chris Lattner24943d22010-06-08 16:52:24 +0000844 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000845 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000846
Greg Clayton238c0a12010-09-18 01:14:36 +0000847 if (!m_interpreter.GetDebugger().GetSelectedTarget().get())
Chris Lattner24943d22010-06-08 16:52:24 +0000848 {
849 result.AppendError ("invalid target, set executable file using 'file' command");
850 result.SetStatus (eReturnStatusFailed);
851 return false;
852 }
853
Greg Clayton238c0a12010-09-18 01:14:36 +0000854 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000855 if (process == NULL)
856 {
857 result.AppendError ("no process exists. Cannot continue");
858 result.SetStatus (eReturnStatusFailed);
859 return false;
860 }
861
862 StateType state = process->GetState();
863 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
864 {
865 const uint32_t num_threads = process->GetThreadList().GetSize();
866 uint32_t idx;
867 const size_t argc = command.GetArgumentCount();
868 if (argc > 0)
869 {
870 std::vector<uint32_t> resume_thread_indexes;
871 for (uint32_t i=0; i<argc; ++i)
872 {
873 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
874 if (idx < num_threads)
875 resume_thread_indexes.push_back(idx);
876 else
877 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
878 }
879
880 if (resume_thread_indexes.empty())
881 {
882 result.AppendError ("no valid thread indexes were specified");
883 result.SetStatus (eReturnStatusFailed);
884 return false;
885 }
886 else
887 {
888 result.AppendMessage ("Resuming thread ");
889 for (idx=0; idx<num_threads; ++idx)
890 {
891 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
892 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
893 {
894 result.AppendMessageWithFormat ("%u ", idx);
895 thread->SetResumeState (eStateRunning);
896 }
897 else
898 {
899 thread->SetResumeState (eStateSuspended);
900 }
901 }
902 result.AppendMessageWithFormat ("in process %i\n", process->GetID());
903 }
904 }
905 else
906 {
Jim Inghamc8332952010-08-26 21:32:51 +0000907 Thread *current_thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000908 if (current_thread == NULL)
909 {
910 result.AppendError ("the process doesn't have a current thread");
911 result.SetStatus (eReturnStatusFailed);
912 return false;
913 }
914 // Set the actions that the threads should each take when resuming
915 for (idx=0; idx<num_threads; ++idx)
916 {
917 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
918 if (thread == current_thread)
919 {
920 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
921 thread->SetResumeState (eStateRunning);
922 }
923 else
924 {
925 thread->SetResumeState (eStateSuspended);
926 }
927 }
928 }
929
930 Error error (process->Resume());
931 if (error.Success())
932 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000933 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000934 if (synchronous_execution)
935 {
Greg Claytonbef15832010-07-14 00:18:15 +0000936 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000937
938 result.SetDidChangeProcessState (true);
939 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
940 result.SetStatus (eReturnStatusSuccessFinishNoResult);
941 }
942 else
943 {
944 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
945 }
946 }
947 else
948 {
949 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
950 result.SetStatus (eReturnStatusFailed);
951 }
952 }
953 else
954 {
955 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
956 StateAsCString(state));
957 result.SetStatus (eReturnStatusFailed);
958 }
959
960 return result.Succeeded();
961 }
962
963};
964
965//-------------------------------------------------------------------------
966// CommandObjectThreadUntil
967//-------------------------------------------------------------------------
968
969class CommandObjectThreadUntil : public CommandObject
970{
971public:
972
973 class CommandOptions : public Options
974 {
975 public:
976 uint32_t m_thread_idx;
977 uint32_t m_frame_idx;
978
979 CommandOptions () :
980 Options(),
981 m_thread_idx(LLDB_INVALID_THREAD_ID),
982 m_frame_idx(LLDB_INVALID_FRAME_ID)
983 {
984 // Keep default values of all options in one place: ResetOptionValues ()
985 ResetOptionValues ();
986 }
987
988 virtual
989 ~CommandOptions ()
990 {
991 }
992
993 virtual Error
994 SetOptionValue (int option_idx, const char *option_arg)
995 {
996 Error error;
997 char short_option = (char) m_getopt_table[option_idx].val;
998
999 switch (short_option)
1000 {
1001 case 't':
1002 {
Greg Claytonbef15832010-07-14 00:18:15 +00001003 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
Chris Lattner24943d22010-06-08 16:52:24 +00001004 if (m_thread_idx == LLDB_INVALID_INDEX32)
1005 {
1006 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
1007 }
1008 }
1009 break;
1010 case 'f':
1011 {
1012 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
1013 if (m_frame_idx == LLDB_INVALID_FRAME_ID)
1014 {
1015 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
1016 }
1017 }
1018 break;
1019 case 'm':
1020 {
1021 bool found_one = false;
1022 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
1023 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
1024
1025 if (!found_one)
1026 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
1027 else if (run_mode == eAllThreads)
1028 m_stop_others = false;
1029 else
1030 m_stop_others = true;
1031
1032 }
1033 break;
1034 default:
1035 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1036 break;
1037
1038 }
1039 return error;
1040 }
1041
1042 void
1043 ResetOptionValues ()
1044 {
1045 Options::ResetOptionValues();
1046 m_thread_idx = LLDB_INVALID_THREAD_ID;
1047 m_frame_idx = 0;
1048 m_stop_others = false;
1049 }
1050
1051 const lldb::OptionDefinition*
1052 GetDefinitions ()
1053 {
1054 return g_option_table;
1055 }
1056
1057 uint32_t m_step_thread_idx;
1058 bool m_stop_others;
1059
1060 // Options table: Required for subclasses of Options.
1061
1062 static lldb::OptionDefinition g_option_table[];
1063
1064 // Instance variables to hold the values for command options.
1065 };
1066
Greg Clayton238c0a12010-09-18 01:14:36 +00001067 CommandObjectThreadUntil (CommandInterpreter &interpreter) :
1068 CommandObject (interpreter,
1069 "thread until",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001070 "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 +00001071 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +00001072 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1073 m_options ()
1074 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001075 CommandArgumentEntry arg;
1076 CommandArgumentData line_num_arg;
1077
1078 // Define the first (and only) variant of this arg.
1079 line_num_arg.arg_type = eArgTypeLineNum;
1080 line_num_arg.arg_repetition = eArgRepeatPlain;
1081
1082 // There is only one variant this argument could be; put it into the argument entry.
1083 arg.push_back (line_num_arg);
1084
1085 // Push the data for the first argument into the m_arguments vector.
1086 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001087 }
1088
1089
1090 virtual
1091 ~CommandObjectThreadUntil ()
1092 {
1093 }
1094
1095 virtual
1096 Options *
1097 GetOptions ()
1098 {
1099 return &m_options;
1100 }
1101
1102 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001103 Execute
1104 (
Greg Clayton63094e02010-06-23 01:19:29 +00001105 Args& command,
1106 CommandReturnObject &result
1107 )
Chris Lattner24943d22010-06-08 16:52:24 +00001108 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001109 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +00001110
Greg Clayton238c0a12010-09-18 01:14:36 +00001111 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Greg Claytoneea26402010-09-14 23:36:40 +00001112 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001113 {
1114 result.AppendError ("invalid target, set executable file using 'file' command");
1115 result.SetStatus (eReturnStatusFailed);
1116 return false;
1117 }
1118
Greg Clayton238c0a12010-09-18 01:14:36 +00001119 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001120 if (process == NULL)
1121 {
1122 result.AppendError ("need a valid process to step");
1123 result.SetStatus (eReturnStatusFailed);
1124
1125 }
1126 else
1127 {
1128 Thread *thread = NULL;
1129 uint32_t line_number;
1130
1131 if (command.GetArgumentCount() != 1)
1132 {
1133 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
1134 result.SetStatus (eReturnStatusFailed);
1135 return false;
1136 }
1137
1138 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
1139 if (line_number == UINT32_MAX)
1140 {
1141 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
1142 result.SetStatus (eReturnStatusFailed);
1143 return false;
1144 }
1145
1146 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
1147 {
Jim Inghamc8332952010-08-26 21:32:51 +00001148 thread = process->GetThreadList().GetSelectedThread().get();
Chris Lattner24943d22010-06-08 16:52:24 +00001149 }
1150 else
1151 {
1152 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
1153 }
1154
1155 if (thread == NULL)
1156 {
1157 const uint32_t num_threads = process->GetThreadList().GetSize();
1158 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
1159 result.SetStatus (eReturnStatusFailed);
1160 return false;
1161 }
1162
1163 const bool abort_other_plans = true;
1164
1165 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
1166 if (frame == NULL)
1167 {
1168
1169 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1170 result.SetStatus (eReturnStatusFailed);
1171 return false;
1172 }
1173
1174 ThreadPlan *new_plan;
1175
1176 if (frame->HasDebugInformation ())
1177 {
1178 // Finally we got here... Translate the given line number to a bunch of addresses:
1179 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
1180 LineTable *line_table = NULL;
1181 if (sc.comp_unit)
1182 line_table = sc.comp_unit->GetLineTable();
1183
1184 if (line_table == NULL)
1185 {
1186 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
1187 m_options.m_frame_idx, m_options.m_thread_idx);
1188 result.SetStatus (eReturnStatusFailed);
1189 return false;
1190 }
1191
1192 LineEntry function_start;
1193 uint32_t index_ptr = 0, end_ptr;
1194 std::vector<addr_t> address_list;
1195
1196 // Find the beginning & end index of the
1197 AddressRange fun_addr_range = sc.function->GetAddressRange();
1198 Address fun_start_addr = fun_addr_range.GetBaseAddress();
1199 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
1200
1201 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
1202 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
1203
1204 while (index_ptr <= end_ptr)
1205 {
1206 LineEntry line_entry;
1207 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
1208 if (index_ptr == UINT32_MAX)
1209 break;
1210
Greg Claytoneea26402010-09-14 23:36:40 +00001211 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target);
Chris Lattner24943d22010-06-08 16:52:24 +00001212 if (address != LLDB_INVALID_ADDRESS)
1213 address_list.push_back (address);
1214 index_ptr++;
1215 }
1216
Greg Clayton1ebdcc72011-01-21 06:11:58 +00001217 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 +00001218 new_plan->SetOkayToDiscard(false);
1219 }
1220 else
1221 {
1222 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
1223 result.SetStatus (eReturnStatusFailed);
1224 return false;
1225
1226 }
1227
Jim Inghamc8332952010-08-26 21:32:51 +00001228 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx);
Chris Lattner24943d22010-06-08 16:52:24 +00001229 Error error (process->Resume ());
1230 if (error.Success())
1231 {
Greg Claytonc1d37752010-10-18 01:45:30 +00001232 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +00001233 if (synchronous_execution)
1234 {
1235 StateType state = process->WaitForProcessToStop (NULL);
1236
1237 result.SetDidChangeProcessState (true);
1238 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
1239 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1240 }
1241 else
1242 {
1243 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
1244 }
1245 }
1246 else
1247 {
1248 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
1249 result.SetStatus (eReturnStatusFailed);
1250 }
1251
1252 }
1253 return result.Succeeded();
1254 }
1255protected:
1256 CommandOptions m_options;
1257
1258};
1259
1260lldb::OptionDefinition
1261CommandObjectThreadUntil::CommandOptions::g_option_table[] =
1262{
Caroline Tice43b014a2010-10-04 22:28:36 +00001263{ 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 +00001264{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"},
1265{ 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"},
1266{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001267};
1268
1269
1270//-------------------------------------------------------------------------
1271// CommandObjectThreadSelect
1272//-------------------------------------------------------------------------
1273
1274class CommandObjectThreadSelect : public CommandObject
1275{
1276public:
1277
Greg Clayton238c0a12010-09-18 01:14:36 +00001278 CommandObjectThreadSelect (CommandInterpreter &interpreter) :
1279 CommandObject (interpreter,
1280 "thread select",
1281 "Select a thread as the currently active thread.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001282 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001283 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001284 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001285 CommandArgumentEntry arg;
1286 CommandArgumentData thread_idx_arg;
1287
1288 // Define the first (and only) variant of this arg.
1289 thread_idx_arg.arg_type = eArgTypeThreadIndex;
1290 thread_idx_arg.arg_repetition = eArgRepeatPlain;
1291
1292 // There is only one variant this argument could be; put it into the argument entry.
1293 arg.push_back (thread_idx_arg);
1294
1295 // Push the data for the first argument into the m_arguments vector.
1296 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001297 }
1298
1299
1300 virtual
1301 ~CommandObjectThreadSelect ()
1302 {
1303 }
1304
1305 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +00001306 Execute
1307 (
Greg Clayton63094e02010-06-23 01:19:29 +00001308 Args& command,
1309 CommandReturnObject &result
1310 )
Chris Lattner24943d22010-06-08 16:52:24 +00001311 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001312 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001313 if (process == NULL)
1314 {
1315 result.AppendError ("no process");
1316 result.SetStatus (eReturnStatusFailed);
1317 return false;
1318 }
1319 else if (command.GetArgumentCount() != 1)
1320 {
1321 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
1322 result.SetStatus (eReturnStatusFailed);
1323 return false;
1324 }
1325
1326 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
1327
1328 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
1329 if (new_thread == NULL)
1330 {
1331 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
1332 result.SetStatus (eReturnStatusFailed);
1333 return false;
1334 }
1335
Jim Inghamc8332952010-08-26 21:32:51 +00001336 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID());
Johnny Chen8dbb6e82010-09-14 00:53:53 +00001337 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001338
Greg Clayton238c0a12010-09-18 01:14:36 +00001339 DisplayThreadInfo (m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +00001340 result.GetOutputStream(),
1341 new_thread,
1342 false,
1343 true);
1344
1345 return result.Succeeded();
1346 }
1347
1348};
1349
1350
1351//-------------------------------------------------------------------------
1352// CommandObjectThreadList
1353//-------------------------------------------------------------------------
1354
Greg Clayton63094e02010-06-23 01:19:29 +00001355class CommandObjectThreadList : public CommandObject
Chris Lattner24943d22010-06-08 16:52:24 +00001356{
Greg Clayton63094e02010-06-23 01:19:29 +00001357public:
Chris Lattner24943d22010-06-08 16:52:24 +00001358
Chris Lattner24943d22010-06-08 16:52:24 +00001359
Greg Clayton238c0a12010-09-18 01:14:36 +00001360 CommandObjectThreadList (CommandInterpreter &interpreter):
1361 CommandObject (interpreter,
1362 "thread list",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001363 "Show a summary of all current threads in a process.",
Greg Clayton63094e02010-06-23 01:19:29 +00001364 "thread list",
1365 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
Chris Lattner24943d22010-06-08 16:52:24 +00001366 {
Greg Clayton63094e02010-06-23 01:19:29 +00001367 }
Chris Lattner24943d22010-06-08 16:52:24 +00001368
Greg Clayton63094e02010-06-23 01:19:29 +00001369 ~CommandObjectThreadList()
1370 {
1371 }
1372
1373 bool
1374 Execute
1375 (
Greg Clayton63094e02010-06-23 01:19:29 +00001376 Args& command,
1377 CommandReturnObject &result
1378 )
1379 {
1380 StreamString &strm = result.GetOutputStream();
1381 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001382 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Greg Clayton63094e02010-06-23 01:19:29 +00001383 if (exe_ctx.process)
Chris Lattner24943d22010-06-08 16:52:24 +00001384 {
Greg Clayton63094e02010-06-23 01:19:29 +00001385 const StateType state = exe_ctx.process->GetState();
1386
1387 if (StateIsStoppedState(state))
Chris Lattner24943d22010-06-08 16:52:24 +00001388 {
Greg Clayton63094e02010-06-23 01:19:29 +00001389 if (state == eStateExited)
Chris Lattner24943d22010-06-08 16:52:24 +00001390 {
Greg Clayton63094e02010-06-23 01:19:29 +00001391 int exit_status = exe_ctx.process->GetExitStatus();
1392 const char *exit_description = exe_ctx.process->GetExitDescription();
1393 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1394 exe_ctx.process->GetID(),
1395 exit_status,
1396 exit_status,
1397 exit_description ? exit_description : "");
Chris Lattner24943d22010-06-08 16:52:24 +00001398 }
1399 else
1400 {
Greg Clayton63094e02010-06-23 01:19:29 +00001401 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1402 if (exe_ctx.thread == NULL)
1403 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1404 if (exe_ctx.thread != NULL)
1405 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001406 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false);
Greg Clayton63094e02010-06-23 01:19:29 +00001407 }
1408 else
1409 {
1410 result.AppendError ("no valid thread found in current process");
1411 result.SetStatus (eReturnStatusFailed);
1412 }
Chris Lattner24943d22010-06-08 16:52:24 +00001413 }
1414 }
Greg Clayton63094e02010-06-23 01:19:29 +00001415 else
1416 {
1417 result.AppendError ("process is currently running");
1418 result.SetStatus (eReturnStatusFailed);
1419 }
Chris Lattner24943d22010-06-08 16:52:24 +00001420 }
1421 else
1422 {
Greg Clayton63094e02010-06-23 01:19:29 +00001423 result.AppendError ("no current location or status available");
Chris Lattner24943d22010-06-08 16:52:24 +00001424 result.SetStatus (eReturnStatusFailed);
1425 }
Greg Clayton63094e02010-06-23 01:19:29 +00001426 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +00001427 }
Greg Clayton63094e02010-06-23 01:19:29 +00001428};
Chris Lattner24943d22010-06-08 16:52:24 +00001429
1430//-------------------------------------------------------------------------
1431// CommandObjectMultiwordThread
1432//-------------------------------------------------------------------------
1433
Greg Clayton63094e02010-06-23 01:19:29 +00001434CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001435 CommandObjectMultiword (interpreter,
1436 "thread",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001437 "A set of commands for operating on one or more threads within a running process.",
Chris Lattner24943d22010-06-08 16:52:24 +00001438 "thread <subcommand> [<subcommand-options>]")
1439{
Greg Clayton238c0a12010-09-18 01:14:36 +00001440 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
1441 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
1442 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
1443 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
1444 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
1445 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1446 interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +00001447 "thread step-in",
Greg Clayton238c0a12010-09-18 01:14:36 +00001448 "Source level single step in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001449 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001450 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1451 eStepTypeInto,
1452 eStepScopeSource)));
Greg Clayton63094e02010-06-23 01:19:29 +00001453
Greg Clayton238c0a12010-09-18 01:14:36 +00001454 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1455 interpreter,
1456 "thread step-out",
1457 "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 +00001458 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001459 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1460 eStepTypeOut,
1461 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001462
Greg Clayton238c0a12010-09-18 01:14:36 +00001463 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1464 interpreter,
1465 "thread step-over",
1466 "Source level single step in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001467 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001468 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1469 eStepTypeOver,
1470 eStepScopeSource)));
Chris Lattner24943d22010-06-08 16:52:24 +00001471
Greg Clayton238c0a12010-09-18 01:14:36 +00001472 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1473 interpreter,
1474 "thread step-inst",
1475 "Single step one instruction in specified thread (current thread, if none specified).",
Caroline Tice43b014a2010-10-04 22:28:36 +00001476 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001477 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1478 eStepTypeTrace,
1479 eStepScopeInstruction)));
Greg Clayton63094e02010-06-23 01:19:29 +00001480
Greg Clayton238c0a12010-09-18 01:14:36 +00001481 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
1482 interpreter,
1483 "thread step-inst-over",
1484 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001485 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +00001486 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
1487 eStepTypeTraceOver,
1488 eStepScopeInstruction)));
Chris Lattner24943d22010-06-08 16:52:24 +00001489}
1490
1491CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
1492{
1493}
1494
1495