1 //===-- 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 16 #include "lldb/Interpreter/Options.h" 17 #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" 28 #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 35 using namespace lldb; 36 using namespace lldb_private; 37 38 39 bool 40 lldb_private::DisplayThreadInfo 41 ( 42 CommandInterpreter &interpreter, 43 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 { 53 if (thread->GetStopInfo() == NULL) 54 return false; 55 } 56 57 strm.Indent(); 58 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetSelectedThread().get() == thread ? '*' : ' '); 59 60 // Show one frame with only the first showing source 61 if (show_source) 62 { 63 bool already_shown = false; 64 StackFrameSP frame_sp = thread->GetStackFrameAtIndex(0); 65 SymbolContext frame_sc(frame_sp->GetSymbolContext (eSymbolContextLineEntry)); 66 if (interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0) 67 { 68 already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line); 69 } 70 71 DisplayFramesForExecutionContext (thread, 72 interpreter, 73 strm, 74 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... 77 !already_shown, // Show source for the first frame 78 3, // lines of source context before 79 3); // lines of source context after 80 } 81 else 82 { 83 thread->DumpInfo (strm, 84 true, // Dump the stop reason? 85 true, // Dump the thread name? 86 true, // Dump the queue name? 87 0); // Display context info for stack frame zero 88 89 strm.EOL(); 90 } 91 92 return true; 93 } 94 return false; 95 } 96 97 size_t 98 lldb_private::DisplayThreadsInfo 99 ( 100 CommandInterpreter &interpreter, 101 ExecutionContext *exe_ctx, 102 CommandReturnObject &result, 103 bool only_threads_with_stop_reason, 104 bool show_source 105 ) 106 { 107 StreamString strm; 108 109 size_t num_thread_infos_dumped = 0; 110 111 if (!exe_ctx->process) 112 return 0; 113 114 const size_t num_threads = exe_ctx->process->GetThreadList().GetSize(); 115 if (num_threads > 0) 116 { 117 118 for (uint32_t i = 0; i < num_threads; i++) 119 { 120 Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get(); 121 if (thread) 122 { 123 if (DisplayThreadInfo (interpreter, 124 strm, 125 thread, 126 only_threads_with_stop_reason, 127 show_source)) 128 ++num_thread_infos_dumped; 129 } 130 } 131 } 132 133 if (num_thread_infos_dumped > 0) 134 { 135 if (num_thread_infos_dumped < num_threads) 136 result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads); 137 138 result.GetOutputStream().GetString().append(strm.GetString()); 139 result.SetStatus (eReturnStatusSuccessFinishNoResult); 140 } 141 return num_thread_infos_dumped; 142 } 143 144 145 size_t 146 lldb_private::DisplayFramesForExecutionContext 147 ( 148 Thread *thread, 149 CommandInterpreter &interpreter, 150 Stream& strm, 151 uint32_t first_frame, 152 uint32_t num_frames, 153 bool show_frame_info, 154 uint32_t num_frames_with_source, 155 uint32_t source_lines_before, 156 uint32_t source_lines_after 157 ) 158 { 159 if (thread == NULL) 160 return 0; 161 162 size_t num_frames_displayed = 0; 163 164 if (num_frames == 0) 165 return 0; 166 167 thread->DumpInfo (strm, 168 true, // Dump the stop reason? 169 true, // Dump the thread name? 170 true, // Dump the queue name? 171 num_frames > 1 ? UINT32_MAX : first_frame); // Dump info for the first stack frame if we are showing only on frame 172 strm.EOL(); 173 strm.IndentMore(); 174 175 StackFrameSP frame_sp; 176 uint32_t frame_idx = 0; 177 uint32_t last_frame; 178 179 // Don't let the last frame wrap around... 180 if (num_frames == UINT32_MAX) 181 last_frame = UINT32_MAX; 182 else 183 last_frame = first_frame + num_frames; 184 185 for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) 186 { 187 frame_sp = thread->GetStackFrameAtIndex (frame_idx); 188 if (frame_sp.get() == NULL) 189 break; 190 191 if (DisplayFrameForExecutionContext (thread, 192 frame_sp.get(), 193 interpreter, 194 strm, 195 show_frame_info, 196 num_frames_with_source > first_frame - frame_idx, 197 source_lines_before, 198 source_lines_after) == false) 199 break; 200 201 ++num_frames_displayed; 202 } 203 204 strm.IndentLess(); 205 return num_frames_displayed; 206 } 207 208 bool 209 lldb_private::DisplayFrameForExecutionContext 210 ( 211 Thread *thread, 212 StackFrame *frame, 213 CommandInterpreter &interpreter, 214 Stream& strm, 215 bool show_frame_info, 216 bool show_source, 217 uint32_t source_lines_before, 218 uint32_t source_lines_after 219 ) 220 { 221 // thread and frame must be filled in prior to calling this function 222 if (thread && frame) 223 { 224 if (show_frame_info) 225 { 226 strm.Indent(); 227 frame->Dump (&strm, true, false); 228 strm.EOL(); 229 } 230 231 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry)); 232 233 if (show_source && sc.comp_unit && sc.line_entry.IsValid()) 234 { 235 interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers ( 236 sc.line_entry.file, 237 sc.line_entry.line, 238 3, 239 3, 240 "->", 241 &strm); 242 243 } 244 return true; 245 } 246 return false; 247 } 248 249 250 //------------------------------------------------------------------------- 251 // CommandObjectThreadBacktrace 252 //------------------------------------------------------------------------- 253 254 class CommandObjectThreadBacktrace : public CommandObject 255 { 256 public: 257 258 class CommandOptions : public Options 259 { 260 public: 261 262 CommandOptions () : 263 Options() 264 { 265 // Keep default values of all options in one place: ResetOptionValues () 266 ResetOptionValues (); 267 } 268 269 virtual 270 ~CommandOptions () 271 { 272 } 273 274 virtual Error 275 SetOptionValue (int option_idx, const char *option_arg) 276 { 277 Error error; 278 char short_option = (char) m_getopt_table[option_idx].val; 279 280 switch (short_option) 281 { 282 case 'c': 283 { 284 bool success; 285 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success); 286 if (!success) 287 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option); 288 if (input_count < -1) 289 m_count = UINT32_MAX; 290 else 291 m_count = input_count; 292 } 293 break; 294 case 's': 295 { 296 bool success; 297 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 298 if (!success) 299 error.SetErrorStringWithFormat("Invalid integer value for option '%c'.\n", short_option); 300 } 301 break; 302 default: 303 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 304 break; 305 306 } 307 return error; 308 } 309 310 void 311 ResetOptionValues () 312 { 313 Options::ResetOptionValues(); 314 m_count = -1; 315 m_start = 0; 316 } 317 318 const lldb::OptionDefinition* 319 GetDefinitions () 320 { 321 return g_option_table; 322 } 323 324 // Options table: Required for subclasses of Options. 325 326 static lldb::OptionDefinition g_option_table[]; 327 328 // Instance variables to hold the values for command options. 329 uint32_t m_count; 330 uint32_t m_start; 331 }; 332 333 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : 334 CommandObject (interpreter, 335 "thread backtrace", 336 "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.", 337 "thread backtrace [<thread-index>] ...", 338 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 339 m_options() 340 { 341 } 342 343 ~CommandObjectThreadBacktrace() 344 { 345 } 346 347 virtual Options * 348 GetOptions () 349 { 350 return &m_options; 351 } 352 353 virtual bool 354 Execute (Args& command, CommandReturnObject &result) 355 { 356 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 362 if (command.GetArgumentCount() == 0) 363 { 364 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 365 if (exe_ctx.thread) 366 { 367 if (DisplayFramesForExecutionContext (exe_ctx.thread, 368 m_interpreter, 369 result.GetOutputStream(), 370 m_options.m_start, 371 m_options.m_count, 372 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 } 386 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 387 { 388 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 389 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(), 394 m_interpreter, 395 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 { 403 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i); 404 result.SetStatus (eReturnStatusFailed); 405 return false; 406 } 407 if (i < num_threads - 1) 408 result.AppendMessage(""); 409 } 410 } 411 else 412 { 413 uint32_t num_args = command.GetArgumentCount(); 414 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 415 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(), 443 m_interpreter, 444 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 } 460 } 461 return result.Succeeded(); 462 } 463 protected: 464 CommandOptions m_options; 465 }; 466 467 lldb::OptionDefinition 468 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = 469 { 470 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 471 { LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameNum, "Frame in which to start the backtrace"}, 472 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 473 }; 474 475 enum StepScope 476 { 477 eStepScopeSource, 478 eStepScopeInstruction 479 }; 480 481 class CommandObjectThreadStepWithTypeAndScope : public CommandObject 482 { 483 public: 484 485 class CommandOptions : public Options 486 { 487 public: 488 489 CommandOptions () : 490 Options() 491 { 492 // Keep default values of all options in one place: ResetOptionValues () 493 ResetOptionValues (); 494 } 495 496 virtual 497 ~CommandOptions () 498 { 499 } 500 501 virtual Error 502 SetOptionValue (int option_idx, const char *option_arg) 503 { 504 Error error; 505 char short_option = (char) m_getopt_table[option_idx].val; 506 507 switch (short_option) 508 { 509 case 'a': 510 { 511 bool success; 512 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 513 if (!success) 514 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option); 515 } 516 break; 517 case 'm': 518 { 519 bool found_one = false; 520 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 521 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 522 if (!found_one) 523 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 524 } 525 break; 526 case 'r': 527 { 528 m_avoid_regexp.clear(); 529 m_avoid_regexp.assign(option_arg); 530 } 531 break; 532 default: 533 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 534 break; 535 536 } 537 return error; 538 } 539 540 void 541 ResetOptionValues () 542 { 543 Options::ResetOptionValues(); 544 m_avoid_no_debug = true; 545 m_run_mode = eOnlyDuringStepping; 546 m_avoid_regexp.clear(); 547 } 548 549 const lldb::OptionDefinition* 550 GetDefinitions () 551 { 552 return g_option_table; 553 } 554 555 // Options table: Required for subclasses of Options. 556 557 static lldb::OptionDefinition g_option_table[]; 558 559 // Instance variables to hold the values for command options. 560 bool m_avoid_no_debug; 561 RunMode m_run_mode; 562 std::string m_avoid_regexp; 563 }; 564 565 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 566 const char *name, 567 const char *help, 568 const char *syntax, 569 uint32_t flags, 570 StepType step_type, 571 StepScope step_scope) : 572 CommandObject (interpreter, name, help, syntax, flags), 573 m_step_type (step_type), 574 m_step_scope (step_scope), 575 m_options () 576 { 577 } 578 579 virtual 580 ~CommandObjectThreadStepWithTypeAndScope () 581 { 582 } 583 584 virtual 585 Options * 586 GetOptions () 587 { 588 return &m_options; 589 } 590 591 virtual bool 592 Execute 593 ( 594 Args& command, 595 CommandReturnObject &result 596 ) 597 { 598 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 599 bool synchronous_execution = m_interpreter.GetSynchronous(); 600 601 if (process == NULL) 602 { 603 result.AppendError ("need a valid process to step"); 604 result.SetStatus (eReturnStatusFailed); 605 606 } 607 else 608 { 609 const uint32_t num_threads = process->GetThreadList().GetSize(); 610 Thread *thread = NULL; 611 612 if (command.GetArgumentCount() == 0) 613 { 614 thread = process->GetThreadList().GetSelectedThread().get(); 615 if (thread == NULL) 616 { 617 result.AppendError ("no selected thread in process"); 618 result.SetStatus (eReturnStatusFailed); 619 return false; 620 } 621 } 622 else 623 { 624 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 625 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 626 if (step_thread_idx == LLDB_INVALID_INDEX32) 627 { 628 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr); 629 result.SetStatus (eReturnStatusFailed); 630 return false; 631 } 632 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 633 if (thread == NULL) 634 { 635 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 636 step_thread_idx, 0, num_threads); 637 result.SetStatus (eReturnStatusFailed); 638 return false; 639 } 640 } 641 642 const bool abort_other_plans = false; 643 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 644 645 // This is a bit unfortunate, but not all the commands in this command object support 646 // only while stepping, so I use the bool for them. 647 bool bool_stop_other_threads; 648 if (m_options.m_run_mode == eAllThreads) 649 bool_stop_other_threads = false; 650 else 651 bool_stop_other_threads = true; 652 653 if (m_step_type == eStepTypeInto) 654 { 655 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 656 ThreadPlan *new_plan; 657 658 if (frame->HasDebugInformation ()) 659 { 660 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 661 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 662 frame->GetSymbolContext(eSymbolContextEverything), 663 stop_other_threads, 664 m_options.m_avoid_no_debug); 665 if (new_plan && !m_options.m_avoid_regexp.empty()) 666 { 667 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan); 668 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 669 } 670 } 671 else 672 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 673 674 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 675 process->Resume (); 676 } 677 else if (m_step_type == eStepTypeOver) 678 { 679 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 680 ThreadPlan *new_plan; 681 682 if (frame->HasDebugInformation()) 683 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 684 m_step_type, 685 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 686 frame->GetSymbolContext(eSymbolContextEverything), 687 stop_other_threads, 688 false); 689 else 690 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 691 abort_other_plans, 692 bool_stop_other_threads); 693 694 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 695 // Maybe there should be a parameter to control this. 696 new_plan->SetOkayToDiscard(false); 697 698 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 699 process->Resume (); 700 } 701 else if (m_step_type == eStepTypeTrace) 702 { 703 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 704 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 705 process->Resume (); 706 } 707 else if (m_step_type == eStepTypeTraceOver) 708 { 709 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 710 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 711 process->Resume (); 712 } 713 else if (m_step_type == eStepTypeOut) 714 { 715 ThreadPlan *new_plan; 716 717 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion); 718 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 719 // Maybe there should be a parameter to control this. 720 new_plan->SetOkayToDiscard(false); 721 722 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 723 process->Resume (); 724 } 725 else 726 { 727 result.AppendError ("step type is not supported"); 728 result.SetStatus (eReturnStatusFailed); 729 } 730 if (synchronous_execution) 731 { 732 StateType state = process->WaitForProcessToStop (NULL); 733 734 //EventSP event_sp; 735 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); 736 //while (! StateIsStoppedState (state)) 737 // { 738 // state = process->WaitForStateChangedEvents (NULL, event_sp); 739 // } 740 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 741 result.SetDidChangeProcessState (true); 742 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 743 result.SetStatus (eReturnStatusSuccessFinishNoResult); 744 } 745 } 746 return result.Succeeded(); 747 } 748 749 protected: 750 StepType m_step_type; 751 StepScope m_step_scope; 752 CommandOptions m_options; 753 }; 754 755 static lldb::OptionEnumValueElement 756 g_tri_running_mode[] = 757 { 758 { eOnlyThisThread, "this-thread", "Run only this thread"}, 759 { eAllThreads, "all-threads", "Run all threads"}, 760 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 761 { 0, NULL, NULL } 762 }; 763 764 static lldb::OptionEnumValueElement 765 g_duo_running_mode[] = 766 { 767 { eOnlyThisThread, "this-thread", "Run only this thread"}, 768 { eAllThreads, "all-threads", "Run all threads"}, 769 { 0, NULL, NULL } 770 }; 771 772 lldb::OptionDefinition 773 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 774 { 775 { LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, 776 { LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, 777 { LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to step over."}, 778 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 779 }; 780 781 782 //------------------------------------------------------------------------- 783 // CommandObjectThreadContinue 784 //------------------------------------------------------------------------- 785 786 class CommandObjectThreadContinue : public CommandObject 787 { 788 public: 789 790 CommandObjectThreadContinue (CommandInterpreter &interpreter) : 791 CommandObject (interpreter, 792 "thread continue", 793 "Continue execution of one or more threads in an active process.", 794 "thread continue <thread-index> [<thread-index> ...]", 795 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 796 { 797 } 798 799 800 virtual 801 ~CommandObjectThreadContinue () 802 { 803 } 804 805 virtual bool 806 Execute 807 ( 808 Args& command, 809 CommandReturnObject &result 810 ) 811 { 812 bool synchronous_execution = m_interpreter.GetSynchronous (); 813 814 if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 815 { 816 result.AppendError ("invalid target, set executable file using 'file' command"); 817 result.SetStatus (eReturnStatusFailed); 818 return false; 819 } 820 821 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 822 if (process == NULL) 823 { 824 result.AppendError ("no process exists. Cannot continue"); 825 result.SetStatus (eReturnStatusFailed); 826 return false; 827 } 828 829 StateType state = process->GetState(); 830 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 831 { 832 const uint32_t num_threads = process->GetThreadList().GetSize(); 833 uint32_t idx; 834 const size_t argc = command.GetArgumentCount(); 835 if (argc > 0) 836 { 837 std::vector<uint32_t> resume_thread_indexes; 838 for (uint32_t i=0; i<argc; ++i) 839 { 840 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32); 841 if (idx < num_threads) 842 resume_thread_indexes.push_back(idx); 843 else 844 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx); 845 } 846 847 if (resume_thread_indexes.empty()) 848 { 849 result.AppendError ("no valid thread indexes were specified"); 850 result.SetStatus (eReturnStatusFailed); 851 return false; 852 } 853 else 854 { 855 result.AppendMessage ("Resuming thread "); 856 for (idx=0; idx<num_threads; ++idx) 857 { 858 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 859 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end()) 860 { 861 result.AppendMessageWithFormat ("%u ", idx); 862 thread->SetResumeState (eStateRunning); 863 } 864 else 865 { 866 thread->SetResumeState (eStateSuspended); 867 } 868 } 869 result.AppendMessageWithFormat ("in process %i\n", process->GetID()); 870 } 871 } 872 else 873 { 874 Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 875 if (current_thread == NULL) 876 { 877 result.AppendError ("the process doesn't have a current thread"); 878 result.SetStatus (eReturnStatusFailed); 879 return false; 880 } 881 // Set the actions that the threads should each take when resuming 882 for (idx=0; idx<num_threads; ++idx) 883 { 884 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 885 if (thread == current_thread) 886 { 887 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID()); 888 thread->SetResumeState (eStateRunning); 889 } 890 else 891 { 892 thread->SetResumeState (eStateSuspended); 893 } 894 } 895 } 896 897 Error error (process->Resume()); 898 if (error.Success()) 899 { 900 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 901 if (synchronous_execution) 902 { 903 state = process->WaitForProcessToStop (NULL); 904 905 result.SetDidChangeProcessState (true); 906 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 907 result.SetStatus (eReturnStatusSuccessFinishNoResult); 908 } 909 else 910 { 911 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 912 } 913 } 914 else 915 { 916 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 917 result.SetStatus (eReturnStatusFailed); 918 } 919 } 920 else 921 { 922 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 923 StateAsCString(state)); 924 result.SetStatus (eReturnStatusFailed); 925 } 926 927 return result.Succeeded(); 928 } 929 930 }; 931 932 //------------------------------------------------------------------------- 933 // CommandObjectThreadUntil 934 //------------------------------------------------------------------------- 935 936 class CommandObjectThreadUntil : public CommandObject 937 { 938 public: 939 940 class CommandOptions : public Options 941 { 942 public: 943 uint32_t m_thread_idx; 944 uint32_t m_frame_idx; 945 946 CommandOptions () : 947 Options(), 948 m_thread_idx(LLDB_INVALID_THREAD_ID), 949 m_frame_idx(LLDB_INVALID_FRAME_ID) 950 { 951 // Keep default values of all options in one place: ResetOptionValues () 952 ResetOptionValues (); 953 } 954 955 virtual 956 ~CommandOptions () 957 { 958 } 959 960 virtual Error 961 SetOptionValue (int option_idx, const char *option_arg) 962 { 963 Error error; 964 char short_option = (char) m_getopt_table[option_idx].val; 965 966 switch (short_option) 967 { 968 case 't': 969 { 970 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); 971 if (m_thread_idx == LLDB_INVALID_INDEX32) 972 { 973 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg); 974 } 975 } 976 break; 977 case 'f': 978 { 979 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 980 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 981 { 982 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg); 983 } 984 } 985 break; 986 case 'm': 987 { 988 bool found_one = false; 989 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 990 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 991 992 if (!found_one) 993 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 994 else if (run_mode == eAllThreads) 995 m_stop_others = false; 996 else 997 m_stop_others = true; 998 999 } 1000 break; 1001 default: 1002 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1003 break; 1004 1005 } 1006 return error; 1007 } 1008 1009 void 1010 ResetOptionValues () 1011 { 1012 Options::ResetOptionValues(); 1013 m_thread_idx = LLDB_INVALID_THREAD_ID; 1014 m_frame_idx = 0; 1015 m_stop_others = false; 1016 } 1017 1018 const lldb::OptionDefinition* 1019 GetDefinitions () 1020 { 1021 return g_option_table; 1022 } 1023 1024 uint32_t m_step_thread_idx; 1025 bool m_stop_others; 1026 1027 // Options table: Required for subclasses of Options. 1028 1029 static lldb::OptionDefinition g_option_table[]; 1030 1031 // Instance variables to hold the values for command options. 1032 }; 1033 1034 CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1035 CommandObject (interpreter, 1036 "thread until", 1037 "Run the current or specified thread until it reaches a given line number or leaves the current function.", 1038 "thread until [<cmd-options>] <line-number>", 1039 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1040 m_options () 1041 { 1042 } 1043 1044 1045 virtual 1046 ~CommandObjectThreadUntil () 1047 { 1048 } 1049 1050 virtual 1051 Options * 1052 GetOptions () 1053 { 1054 return &m_options; 1055 } 1056 1057 virtual bool 1058 Execute 1059 ( 1060 Args& command, 1061 CommandReturnObject &result 1062 ) 1063 { 1064 bool synchronous_execution = m_interpreter.GetSynchronous (); 1065 1066 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1067 if (target == NULL) 1068 { 1069 result.AppendError ("invalid target, set executable file using 'file' command"); 1070 result.SetStatus (eReturnStatusFailed); 1071 return false; 1072 } 1073 1074 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1075 if (process == NULL) 1076 { 1077 result.AppendError ("need a valid process to step"); 1078 result.SetStatus (eReturnStatusFailed); 1079 1080 } 1081 else 1082 { 1083 Thread *thread = NULL; 1084 uint32_t line_number; 1085 1086 if (command.GetArgumentCount() != 1) 1087 { 1088 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); 1089 result.SetStatus (eReturnStatusFailed); 1090 return false; 1091 } 1092 1093 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1094 if (line_number == UINT32_MAX) 1095 { 1096 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1097 result.SetStatus (eReturnStatusFailed); 1098 return false; 1099 } 1100 1101 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1102 { 1103 thread = process->GetThreadList().GetSelectedThread().get(); 1104 } 1105 else 1106 { 1107 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get(); 1108 } 1109 1110 if (thread == NULL) 1111 { 1112 const uint32_t num_threads = process->GetThreadList().GetSize(); 1113 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads); 1114 result.SetStatus (eReturnStatusFailed); 1115 return false; 1116 } 1117 1118 const bool abort_other_plans = true; 1119 1120 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1121 if (frame == NULL) 1122 { 1123 1124 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx); 1125 result.SetStatus (eReturnStatusFailed); 1126 return false; 1127 } 1128 1129 ThreadPlan *new_plan; 1130 1131 if (frame->HasDebugInformation ()) 1132 { 1133 // Finally we got here... Translate the given line number to a bunch of addresses: 1134 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1135 LineTable *line_table = NULL; 1136 if (sc.comp_unit) 1137 line_table = sc.comp_unit->GetLineTable(); 1138 1139 if (line_table == NULL) 1140 { 1141 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1142 m_options.m_frame_idx, m_options.m_thread_idx); 1143 result.SetStatus (eReturnStatusFailed); 1144 return false; 1145 } 1146 1147 LineEntry function_start; 1148 uint32_t index_ptr = 0, end_ptr; 1149 std::vector<addr_t> address_list; 1150 1151 // Find the beginning & end index of the 1152 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1153 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1154 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1155 1156 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1157 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 1158 1159 while (index_ptr <= end_ptr) 1160 { 1161 LineEntry line_entry; 1162 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry); 1163 if (index_ptr == UINT32_MAX) 1164 break; 1165 1166 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1167 if (address != LLDB_INVALID_ADDRESS) 1168 address_list.push_back (address); 1169 index_ptr++; 1170 } 1171 1172 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others); 1173 new_plan->SetOkayToDiscard(false); 1174 } 1175 else 1176 { 1177 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx); 1178 result.SetStatus (eReturnStatusFailed); 1179 return false; 1180 1181 } 1182 1183 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 1184 Error error (process->Resume ()); 1185 if (error.Success()) 1186 { 1187 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 1188 if (synchronous_execution) 1189 { 1190 StateType state = process->WaitForProcessToStop (NULL); 1191 1192 result.SetDidChangeProcessState (true); 1193 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 1194 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1195 } 1196 else 1197 { 1198 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1199 } 1200 } 1201 else 1202 { 1203 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1204 result.SetStatus (eReturnStatusFailed); 1205 } 1206 1207 } 1208 return result.Succeeded(); 1209 } 1210 protected: 1211 CommandOptions m_options; 1212 1213 }; 1214 1215 lldb::OptionDefinition 1216 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1217 { 1218 { LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameNum, "Frame index for until operation - defaults to 0"}, 1219 { LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 1220 { LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, 1221 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1222 }; 1223 1224 1225 //------------------------------------------------------------------------- 1226 // CommandObjectThreadSelect 1227 //------------------------------------------------------------------------- 1228 1229 class CommandObjectThreadSelect : public CommandObject 1230 { 1231 public: 1232 1233 CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1234 CommandObject (interpreter, 1235 "thread select", 1236 "Select a thread as the currently active thread.", 1237 "thread select <thread-index>", 1238 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1239 { 1240 } 1241 1242 1243 virtual 1244 ~CommandObjectThreadSelect () 1245 { 1246 } 1247 1248 virtual bool 1249 Execute 1250 ( 1251 Args& command, 1252 CommandReturnObject &result 1253 ) 1254 { 1255 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1256 if (process == NULL) 1257 { 1258 result.AppendError ("no process"); 1259 result.SetStatus (eReturnStatusFailed); 1260 return false; 1261 } 1262 else if (command.GetArgumentCount() != 1) 1263 { 1264 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1265 result.SetStatus (eReturnStatusFailed); 1266 return false; 1267 } 1268 1269 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1270 1271 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1272 if (new_thread == NULL) 1273 { 1274 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1275 result.SetStatus (eReturnStatusFailed); 1276 return false; 1277 } 1278 1279 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID()); 1280 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1281 1282 DisplayThreadInfo (m_interpreter, 1283 result.GetOutputStream(), 1284 new_thread, 1285 false, 1286 true); 1287 1288 return result.Succeeded(); 1289 } 1290 1291 }; 1292 1293 1294 //------------------------------------------------------------------------- 1295 // CommandObjectThreadList 1296 //------------------------------------------------------------------------- 1297 1298 class CommandObjectThreadList : public CommandObject 1299 { 1300 public: 1301 1302 1303 CommandObjectThreadList (CommandInterpreter &interpreter): 1304 CommandObject (interpreter, 1305 "thread list", 1306 "Show a summary of all current threads in a process.", 1307 "thread list", 1308 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1309 { 1310 } 1311 1312 ~CommandObjectThreadList() 1313 { 1314 } 1315 1316 bool 1317 Execute 1318 ( 1319 Args& command, 1320 CommandReturnObject &result 1321 ) 1322 { 1323 StreamString &strm = result.GetOutputStream(); 1324 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1325 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 1326 if (exe_ctx.process) 1327 { 1328 const StateType state = exe_ctx.process->GetState(); 1329 1330 if (StateIsStoppedState(state)) 1331 { 1332 if (state == eStateExited) 1333 { 1334 int exit_status = exe_ctx.process->GetExitStatus(); 1335 const char *exit_description = exe_ctx.process->GetExitDescription(); 1336 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1337 exe_ctx.process->GetID(), 1338 exit_status, 1339 exit_status, 1340 exit_description ? exit_description : ""); 1341 } 1342 else 1343 { 1344 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1345 if (exe_ctx.thread == NULL) 1346 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1347 if (exe_ctx.thread != NULL) 1348 { 1349 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, false, false); 1350 } 1351 else 1352 { 1353 result.AppendError ("no valid thread found in current process"); 1354 result.SetStatus (eReturnStatusFailed); 1355 } 1356 } 1357 } 1358 else 1359 { 1360 result.AppendError ("process is currently running"); 1361 result.SetStatus (eReturnStatusFailed); 1362 } 1363 } 1364 else 1365 { 1366 result.AppendError ("no current location or status available"); 1367 result.SetStatus (eReturnStatusFailed); 1368 } 1369 return result.Succeeded(); 1370 } 1371 }; 1372 1373 //------------------------------------------------------------------------- 1374 // CommandObjectMultiwordThread 1375 //------------------------------------------------------------------------- 1376 1377 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 1378 CommandObjectMultiword (interpreter, 1379 "thread", 1380 "A set of commands for operating on one or more threads within a running process.", 1381 "thread <subcommand> [<subcommand-options>]") 1382 { 1383 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 1384 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 1385 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 1386 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 1387 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 1388 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1389 interpreter, 1390 "thread step-in", 1391 "Source level single step in specified thread (current thread, if none specified).", 1392 "thread step-in [<thread-id>]", 1393 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1394 eStepTypeInto, 1395 eStepScopeSource))); 1396 1397 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1398 interpreter, 1399 "thread step-out", 1400 "Finish executing the current fucntion and return to its call site in specified thread (current thread, if none specified).", 1401 "thread step-out [<thread-id>]", 1402 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1403 eStepTypeOut, 1404 eStepScopeSource))); 1405 1406 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1407 interpreter, 1408 "thread step-over", 1409 "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 1410 "thread step-over [<thread-id>]", 1411 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1412 eStepTypeOver, 1413 eStepScopeSource))); 1414 1415 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1416 interpreter, 1417 "thread step-inst", 1418 "Single step one instruction in specified thread (current thread, if none specified).", 1419 "thread step-inst [<thread-id>]", 1420 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1421 eStepTypeTrace, 1422 eStepScopeInstruction))); 1423 1424 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 1425 interpreter, 1426 "thread step-inst-over", 1427 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 1428 "thread step-inst-over [<thread-id>]", 1429 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1430 eStepTypeTraceOver, 1431 eStepScopeInstruction))); 1432 } 1433 1434 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 1435 { 1436 } 1437 1438 1439