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/Core/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/ThreadPlanContinue.h" 29 #include "lldb/Target/ThreadPlanStepInstruction.h" 30 #include "lldb/Target/ThreadPlanStepOut.h" 31 #include "lldb/Target/ThreadPlanStepRange.h" 32 #include "lldb/Target/ThreadPlanStepInRange.h" 33 #include "lldb/Symbol/LineTable.h" 34 #include "lldb/Symbol/LineEntry.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 39 40 bool 41 lldb_private::DisplayThreadInfo 42 ( 43 CommandInterpreter *interpreter, 44 Stream &strm, 45 Thread *thread, 46 bool only_threads_with_stop_reason, 47 bool show_source 48 ) 49 { 50 if (thread) 51 { 52 if (only_threads_with_stop_reason) 53 { 54 StopReason thread_stop_reason = eStopReasonNone; 55 Thread::StopInfo thread_stop_info; 56 if (thread->GetStopInfo(&thread_stop_info)) 57 { 58 thread_stop_reason = thread_stop_info.GetStopReason(); 59 if (thread_stop_reason == eStopReasonNone) 60 return false; 61 } 62 } 63 64 strm.Indent(); 65 strm.Printf("%c ", thread->GetProcess().GetThreadList().GetCurrentThread().get() == thread ? '*' : ' '); 66 67 // Show one frame with only the first showing source 68 if (show_source) 69 { 70 DisplayFramesForExecutionContext (thread, 71 interpreter, 72 strm, 73 true, 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 1, // 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 bool ascending, 152 uint32_t first_frame, 153 uint32_t num_frames, 154 bool show_frame_info, 155 uint32_t num_frames_with_source, 156 uint32_t source_lines_before, 157 uint32_t source_lines_after 158 ) 159 { 160 if (thread == NULL) 161 return 0; 162 163 size_t num_frames_displayed = 0; 164 165 if (num_frames == 0) 166 return 0; 167 168 thread->DumpInfo (strm, 169 true, // Dump the stop reason? 170 true, // Dump the thread name? 171 true, // Dump the queue name? 172 0); // Dump info for stack frame zero 173 strm.EOL(); 174 strm.IndentMore(); 175 176 StackFrameSP frame_sp; 177 int frame_idx = 0; 178 179 if (ascending) 180 { 181 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx) 182 { 183 frame_sp = thread->GetStackFrameAtIndex (frame_idx); 184 if (frame_sp.get() == NULL) 185 break; 186 187 if (DisplayFrameForExecutionContext (thread, 188 frame_sp.get(), 189 interpreter, 190 strm, 191 show_frame_info, 192 num_frames_with_source > first_frame - frame_idx, 193 source_lines_before, 194 source_lines_after) == false) 195 break; 196 197 ++num_frames_displayed; 198 } 199 } 200 else 201 { 202 for (frame_idx = first_frame + num_frames - 1; frame_idx >= first_frame; --frame_idx) 203 { 204 frame_sp = thread->GetStackFrameAtIndex (frame_idx); 205 if (frame_sp == NULL) 206 break; 207 208 if (DisplayFrameForExecutionContext (thread, 209 frame_sp.get(), 210 interpreter, 211 strm, 212 show_frame_info, 213 num_frames_with_source > first_frame - frame_idx, 214 source_lines_before, 215 source_lines_after) == false) 216 break; 217 218 ++num_frames_displayed; 219 } 220 } 221 strm.IndentLess(); 222 return num_frames_displayed; 223 } 224 225 bool 226 lldb_private::DisplayFrameForExecutionContext 227 ( 228 Thread *thread, 229 StackFrame *frame, 230 CommandInterpreter *interpreter, 231 Stream& strm, 232 bool show_frame_info, 233 bool show_source, 234 uint32_t source_lines_before, 235 uint32_t source_lines_after 236 ) 237 { 238 // thread and frame must be filled in prior to calling this function 239 if (thread && frame) 240 { 241 if (show_frame_info) 242 { 243 strm.Indent(); 244 frame->Dump (&strm, true); 245 strm.EOL(); 246 } 247 248 SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry)); 249 250 if (show_source && sc.comp_unit && sc.line_entry.IsValid()) 251 { 252 interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers ( 253 sc.line_entry.file, 254 sc.line_entry.line, 255 3, 256 3, 257 "->", 258 &strm); 259 260 } 261 return true; 262 } 263 return false; 264 } 265 266 267 //------------------------------------------------------------------------- 268 // CommandObjectThreadBacktrace 269 //------------------------------------------------------------------------- 270 271 class CommandObjectThreadBacktrace : public CommandObject 272 { 273 public: 274 275 CommandObjectThreadBacktrace () : 276 CommandObject ("thread backtrace", 277 "Shows the stack for one or more threads.", 278 "thread backtrace [<thread-idx>] ...", 279 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 280 m_ascending (true) 281 { 282 } 283 284 ~CommandObjectThreadBacktrace() 285 { 286 } 287 288 289 bool 290 Execute 291 ( 292 Args& command, 293 CommandContext *context, 294 CommandInterpreter *interpreter, 295 CommandReturnObject &result 296 ) 297 { 298 if (command.GetArgumentCount() == 0) 299 { 300 ExecutionContext exe_ctx(context->GetExecutionContext()); 301 if (exe_ctx.thread) 302 { 303 bool show_frame_info = true; 304 uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing 305 if (DisplayFramesForExecutionContext (exe_ctx.thread, 306 interpreter, 307 result.GetOutputStream(), 308 m_ascending, 309 0, 310 UINT32_MAX, 311 show_frame_info, 312 num_frames_with_source, 313 3, 314 3)) 315 { 316 result.SetStatus (eReturnStatusSuccessFinishResult); 317 } 318 } 319 else 320 { 321 result.AppendError ("invalid thread"); 322 result.SetStatus (eReturnStatusFailed); 323 } 324 } 325 else 326 { 327 result.AppendError ("backtrace doesn't take arguments (for now)"); 328 result.SetStatus (eReturnStatusFailed); 329 } 330 return result.Succeeded(); 331 } 332 protected: 333 bool m_ascending; 334 }; 335 336 337 typedef enum StepScope 338 { 339 eStepScopeSource, 340 eStepScopeInstruction 341 }; 342 343 class CommandObjectThreadStepWithTypeAndScope : public CommandObject 344 { 345 public: 346 347 class CommandOptions : public Options 348 { 349 public: 350 351 CommandOptions () : 352 Options() 353 { 354 // Keep default values of all options in one place: ResetOptionValues () 355 ResetOptionValues (); 356 } 357 358 virtual 359 ~CommandOptions () 360 { 361 } 362 363 virtual Error 364 SetOptionValue (int option_idx, const char *option_arg) 365 { 366 Error error; 367 char short_option = (char) m_getopt_table[option_idx].val; 368 369 switch (short_option) 370 { 371 case 'a': 372 { 373 bool success; 374 m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 375 if (!success) 376 error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option); 377 } 378 break; 379 case 'm': 380 { 381 bool found_one = false; 382 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 383 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 384 if (!found_one) 385 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 386 } 387 break; 388 default: 389 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 390 break; 391 392 } 393 return error; 394 } 395 396 void 397 ResetOptionValues () 398 { 399 Options::ResetOptionValues(); 400 m_avoid_no_debug = true; 401 m_run_mode = eOnlyDuringStepping; 402 } 403 404 const lldb::OptionDefinition* 405 GetDefinitions () 406 { 407 return g_option_table; 408 } 409 410 // Options table: Required for subclasses of Options. 411 412 static lldb::OptionDefinition g_option_table[]; 413 414 // Instance variables to hold the values for command options. 415 bool m_avoid_no_debug; 416 RunMode m_run_mode; 417 }; 418 419 CommandObjectThreadStepWithTypeAndScope (const char *name, 420 const char *help, 421 const char *syntax, 422 uint32_t flags, 423 StepType step_type, 424 StepScope step_scope) : 425 CommandObject (name, help, syntax, flags), 426 m_step_type (step_type), 427 m_step_scope (step_scope), 428 m_options () 429 { 430 } 431 432 virtual 433 ~CommandObjectThreadStepWithTypeAndScope () 434 { 435 } 436 437 virtual 438 Options * 439 GetOptions () 440 { 441 return &m_options; 442 } 443 444 virtual bool 445 Execute (Args& command, 446 CommandContext *context, 447 CommandInterpreter *interpreter, 448 CommandReturnObject &result) 449 { 450 Process *process = context->GetExecutionContext().process; 451 bool synchronous_execution = interpreter->GetSynchronous(); 452 453 if (process == NULL) 454 { 455 result.AppendError ("need a valid process to step"); 456 result.SetStatus (eReturnStatusFailed); 457 458 } 459 else 460 { 461 const uint32_t num_threads = process->GetThreadList().GetSize(); 462 Thread *thread = NULL; 463 464 if (command.GetArgumentCount() == 0) 465 { 466 thread = process->GetThreadList().GetCurrentThread().get(); 467 if (thread == NULL) 468 { 469 result.AppendError ("no current thread in process"); 470 result.SetStatus (eReturnStatusFailed); 471 return false; 472 } 473 } 474 else 475 { 476 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 477 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 478 if (step_thread_idx == LLDB_INVALID_INDEX32) 479 { 480 result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr); 481 result.SetStatus (eReturnStatusFailed); 482 return false; 483 } 484 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 485 if (thread == NULL) 486 { 487 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 488 step_thread_idx, 0, num_threads); 489 result.SetStatus (eReturnStatusFailed); 490 return false; 491 } 492 } 493 494 const bool abort_other_plans = false; 495 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 496 497 // This is a bit unfortunate, but not all the commands in this command object support 498 // only while stepping, so I use the bool for them. 499 bool bool_stop_other_threads; 500 if (m_options.m_run_mode == eAllThreads) 501 bool_stop_other_threads = false; 502 else 503 bool_stop_other_threads = true; 504 505 if (m_step_type == eStepTypeInto) 506 { 507 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 508 ThreadPlan *new_plan; 509 510 if (frame->HasDebugInformation ()) 511 { 512 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type, 513 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 514 frame->GetSymbolContext(eSymbolContextEverything), 515 stop_other_threads, 516 m_options.m_avoid_no_debug); 517 } 518 else 519 new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 520 521 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 522 process->Resume (); 523 } 524 else if (m_step_type == eStepTypeOver) 525 { 526 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 527 ThreadPlan *new_plan; 528 529 if (frame->HasDebugInformation()) 530 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, 531 m_step_type, 532 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 533 frame->GetSymbolContext(eSymbolContextEverything), 534 stop_other_threads, 535 false); 536 else 537 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, 538 abort_other_plans, 539 bool_stop_other_threads); 540 541 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 542 // Maybe there should be a parameter to control this. 543 new_plan->SetOkayToDiscard(false); 544 545 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 546 process->Resume (); 547 } 548 else if (m_step_type == eStepTypeTrace) 549 { 550 thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 551 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 552 process->Resume (); 553 } 554 else if (m_step_type == eStepTypeTraceOver) 555 { 556 thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 557 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 558 process->Resume (); 559 } 560 else if (m_step_type == eStepTypeOut) 561 { 562 ThreadPlan *new_plan; 563 564 new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion); 565 // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over. 566 // Maybe there should be a parameter to control this. 567 new_plan->SetOkayToDiscard(false); 568 569 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 570 process->Resume (); 571 } 572 else 573 { 574 result.AppendError ("step type is not supported"); 575 result.SetStatus (eReturnStatusFailed); 576 } 577 if (synchronous_execution) 578 { 579 StateType state = process->WaitForProcessToStop (NULL); 580 581 //EventSP event_sp; 582 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); 583 //while (! StateIsStoppedState (state)) 584 // { 585 // state = process->WaitForStateChangedEvents (NULL, event_sp); 586 // } 587 process->GetThreadList().SetCurrentThreadByID (thread->GetID()); 588 result.SetDidChangeProcessState (true); 589 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 590 result.SetStatus (eReturnStatusSuccessFinishNoResult); 591 } 592 } 593 return result.Succeeded(); 594 } 595 596 protected: 597 StepType m_step_type; 598 StepScope m_step_scope; 599 CommandOptions m_options; 600 }; 601 602 static lldb::OptionEnumValueElement 603 g_tri_running_mode[] = 604 { 605 { eOnlyThisThread, "thisThread", "Run only this thread"}, 606 { eAllThreads, "allThreads", "Run all threads"}, 607 { eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"}, 608 { 0, NULL, NULL } 609 }; 610 611 static lldb::OptionEnumValueElement 612 g_duo_running_mode[] = 613 { 614 { eOnlyThisThread, "thisThread", "Run only this thread"}, 615 { eAllThreads, "allThreads", "Run all threads"}, 616 { 0, NULL, NULL } 617 }; 618 619 lldb::OptionDefinition 620 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 621 { 622 { LLDB_OPT_SET_1, true, "avoid_no_debug", 'a', required_argument, NULL, 0, "<avoid_no_debug>", "Should step-in step over functions with no debug information"}, 623 { LLDB_OPT_SET_1, true, "run_mode", 'm', required_argument, g_tri_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"}, 624 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 625 }; 626 627 628 //------------------------------------------------------------------------- 629 // CommandObjectThreadContinue 630 //------------------------------------------------------------------------- 631 632 class CommandObjectThreadContinue : public CommandObject 633 { 634 public: 635 636 CommandObjectThreadContinue () : 637 CommandObject ("thread continue", 638 "Continues execution of one or more threads in an active process.", 639 "thread continue <thread-index> [<thread-index> ...]", 640 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 641 { 642 } 643 644 645 virtual 646 ~CommandObjectThreadContinue () 647 { 648 } 649 650 virtual bool 651 Execute (Args& command, 652 CommandContext *context, 653 CommandInterpreter *interpreter, 654 CommandReturnObject &result) 655 { 656 bool synchronous_execution = interpreter->GetSynchronous (); 657 658 if (!context->GetTarget()) 659 { 660 result.AppendError ("invalid target, set executable file using 'file' command"); 661 result.SetStatus (eReturnStatusFailed); 662 return false; 663 } 664 665 Process *process = context->GetExecutionContext().process; 666 if (process == NULL) 667 { 668 result.AppendError ("no process exists. Cannot continue"); 669 result.SetStatus (eReturnStatusFailed); 670 return false; 671 } 672 673 StateType state = process->GetState(); 674 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 675 { 676 const uint32_t num_threads = process->GetThreadList().GetSize(); 677 uint32_t idx; 678 const size_t argc = command.GetArgumentCount(); 679 if (argc > 0) 680 { 681 std::vector<uint32_t> resume_thread_indexes; 682 for (uint32_t i=0; i<argc; ++i) 683 { 684 idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32); 685 if (idx < num_threads) 686 resume_thread_indexes.push_back(idx); 687 else 688 result.AppendWarningWithFormat("Thread index %u out of range.\n", idx); 689 } 690 691 if (resume_thread_indexes.empty()) 692 { 693 result.AppendError ("no valid thread indexes were specified"); 694 result.SetStatus (eReturnStatusFailed); 695 return false; 696 } 697 else 698 { 699 result.AppendMessage ("Resuming thread "); 700 for (idx=0; idx<num_threads; ++idx) 701 { 702 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 703 if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end()) 704 { 705 result.AppendMessageWithFormat ("%u ", idx); 706 thread->SetResumeState (eStateRunning); 707 } 708 else 709 { 710 thread->SetResumeState (eStateSuspended); 711 } 712 } 713 result.AppendMessageWithFormat ("in process %i\n", process->GetID()); 714 } 715 } 716 else 717 { 718 Thread *current_thread = process->GetThreadList().GetCurrentThread().get(); 719 if (current_thread == NULL) 720 { 721 result.AppendError ("the process doesn't have a current thread"); 722 result.SetStatus (eReturnStatusFailed); 723 return false; 724 } 725 // Set the actions that the threads should each take when resuming 726 for (idx=0; idx<num_threads; ++idx) 727 { 728 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 729 if (thread == current_thread) 730 { 731 result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID()); 732 thread->SetResumeState (eStateRunning); 733 } 734 else 735 { 736 thread->SetResumeState (eStateSuspended); 737 } 738 } 739 } 740 741 Error error (process->Resume()); 742 if (error.Success()) 743 { 744 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 745 if (synchronous_execution) 746 { 747 StateType state = process->WaitForProcessToStop (NULL); 748 749 result.SetDidChangeProcessState (true); 750 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 751 result.SetStatus (eReturnStatusSuccessFinishNoResult); 752 } 753 else 754 { 755 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 756 } 757 } 758 else 759 { 760 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 761 result.SetStatus (eReturnStatusFailed); 762 } 763 } 764 else 765 { 766 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 767 StateAsCString(state)); 768 result.SetStatus (eReturnStatusFailed); 769 } 770 771 return result.Succeeded(); 772 } 773 774 }; 775 776 //------------------------------------------------------------------------- 777 // CommandObjectThreadUntil 778 //------------------------------------------------------------------------- 779 780 class CommandObjectThreadUntil : public CommandObject 781 { 782 public: 783 784 class CommandOptions : public Options 785 { 786 public: 787 uint32_t m_thread_idx; 788 uint32_t m_frame_idx; 789 790 CommandOptions () : 791 Options(), 792 m_thread_idx(LLDB_INVALID_THREAD_ID), 793 m_frame_idx(LLDB_INVALID_FRAME_ID) 794 { 795 // Keep default values of all options in one place: ResetOptionValues () 796 ResetOptionValues (); 797 } 798 799 virtual 800 ~CommandOptions () 801 { 802 } 803 804 virtual Error 805 SetOptionValue (int option_idx, const char *option_arg) 806 { 807 Error error; 808 char short_option = (char) m_getopt_table[option_idx].val; 809 810 switch (short_option) 811 { 812 case 't': 813 { 814 uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); 815 if (m_thread_idx == LLDB_INVALID_INDEX32) 816 { 817 error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg); 818 } 819 } 820 break; 821 case 'f': 822 { 823 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 824 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 825 { 826 error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg); 827 } 828 } 829 break; 830 case 'm': 831 { 832 bool found_one = false; 833 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 834 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one); 835 836 if (!found_one) 837 error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option); 838 else if (run_mode == eAllThreads) 839 m_stop_others = false; 840 else 841 m_stop_others = true; 842 843 } 844 break; 845 default: 846 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 847 break; 848 849 } 850 return error; 851 } 852 853 void 854 ResetOptionValues () 855 { 856 Options::ResetOptionValues(); 857 m_thread_idx = LLDB_INVALID_THREAD_ID; 858 m_frame_idx = 0; 859 m_stop_others = false; 860 } 861 862 const lldb::OptionDefinition* 863 GetDefinitions () 864 { 865 return g_option_table; 866 } 867 868 uint32_t m_step_thread_idx; 869 bool m_stop_others; 870 871 // Options table: Required for subclasses of Options. 872 873 static lldb::OptionDefinition g_option_table[]; 874 875 // Instance variables to hold the values for command options. 876 }; 877 878 CommandObjectThreadUntil () : 879 CommandObject ("thread until", 880 "Runs the current or specified thread until it reaches a given line number or leaves the current function.", 881 "thread until [<cmd-options>] <line-number>", 882 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 883 m_options () 884 { 885 } 886 887 888 virtual 889 ~CommandObjectThreadUntil () 890 { 891 } 892 893 virtual 894 Options * 895 GetOptions () 896 { 897 return &m_options; 898 } 899 900 virtual bool 901 Execute (Args& command, 902 CommandContext *context, 903 CommandInterpreter *interpreter, 904 CommandReturnObject &result) 905 { 906 bool synchronous_execution = interpreter->GetSynchronous (); 907 908 if (!context->GetTarget()) 909 { 910 result.AppendError ("invalid target, set executable file using 'file' command"); 911 result.SetStatus (eReturnStatusFailed); 912 return false; 913 } 914 915 Process *process = context->GetExecutionContext().process; 916 if (process == NULL) 917 { 918 result.AppendError ("need a valid process to step"); 919 result.SetStatus (eReturnStatusFailed); 920 921 } 922 else 923 { 924 Thread *thread = NULL; 925 uint32_t line_number; 926 927 if (command.GetArgumentCount() != 1) 928 { 929 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); 930 result.SetStatus (eReturnStatusFailed); 931 return false; 932 } 933 934 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 935 if (line_number == UINT32_MAX) 936 { 937 result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 938 result.SetStatus (eReturnStatusFailed); 939 return false; 940 } 941 942 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 943 { 944 thread = process->GetThreadList().GetCurrentThread().get(); 945 } 946 else 947 { 948 thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get(); 949 } 950 951 if (thread == NULL) 952 { 953 const uint32_t num_threads = process->GetThreadList().GetSize(); 954 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads); 955 result.SetStatus (eReturnStatusFailed); 956 return false; 957 } 958 959 const bool abort_other_plans = true; 960 961 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 962 if (frame == NULL) 963 { 964 965 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx); 966 result.SetStatus (eReturnStatusFailed); 967 return false; 968 } 969 970 ThreadPlan *new_plan; 971 972 if (frame->HasDebugInformation ()) 973 { 974 // Finally we got here... Translate the given line number to a bunch of addresses: 975 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 976 LineTable *line_table = NULL; 977 if (sc.comp_unit) 978 line_table = sc.comp_unit->GetLineTable(); 979 980 if (line_table == NULL) 981 { 982 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 983 m_options.m_frame_idx, m_options.m_thread_idx); 984 result.SetStatus (eReturnStatusFailed); 985 return false; 986 } 987 988 LineEntry function_start; 989 uint32_t index_ptr = 0, end_ptr; 990 std::vector<addr_t> address_list; 991 992 // Find the beginning & end index of the 993 AddressRange fun_addr_range = sc.function->GetAddressRange(); 994 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 995 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 996 997 Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 998 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 999 1000 while (index_ptr <= end_ptr) 1001 { 1002 LineEntry line_entry; 1003 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry); 1004 if (index_ptr == UINT32_MAX) 1005 break; 1006 1007 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process); 1008 if (address != LLDB_INVALID_ADDRESS) 1009 address_list.push_back (address); 1010 index_ptr++; 1011 } 1012 1013 new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others); 1014 new_plan->SetOkayToDiscard(false); 1015 } 1016 else 1017 { 1018 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx); 1019 result.SetStatus (eReturnStatusFailed); 1020 return false; 1021 1022 } 1023 1024 process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx); 1025 Error error (process->Resume ()); 1026 if (error.Success()) 1027 { 1028 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 1029 if (synchronous_execution) 1030 { 1031 StateType state = process->WaitForProcessToStop (NULL); 1032 1033 result.SetDidChangeProcessState (true); 1034 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 1035 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1036 } 1037 else 1038 { 1039 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1040 } 1041 } 1042 else 1043 { 1044 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1045 result.SetStatus (eReturnStatusFailed); 1046 } 1047 1048 } 1049 return result.Succeeded(); 1050 } 1051 protected: 1052 CommandOptions m_options; 1053 1054 }; 1055 1056 lldb::OptionDefinition 1057 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1058 { 1059 { LLDB_OPT_SET_1, true, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"}, 1060 { LLDB_OPT_SET_1, true, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"}, 1061 { LLDB_OPT_SET_1, true, "run_mode", 'm', required_argument, g_duo_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"}, 1062 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 1063 }; 1064 1065 1066 //------------------------------------------------------------------------- 1067 // CommandObjectThreadSelect 1068 //------------------------------------------------------------------------- 1069 1070 class CommandObjectThreadSelect : public CommandObject 1071 { 1072 public: 1073 1074 CommandObjectThreadSelect () : 1075 CommandObject ("thread select", 1076 "Selects a threads as the currently active thread.", 1077 "thread select <thread-index>", 1078 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1079 { 1080 } 1081 1082 1083 virtual 1084 ~CommandObjectThreadSelect () 1085 { 1086 } 1087 1088 virtual bool 1089 Execute (Args& command, 1090 CommandContext *context, 1091 CommandInterpreter *interpreter, 1092 CommandReturnObject &result) 1093 { 1094 Process *process = context->GetExecutionContext().process; 1095 if (process == NULL) 1096 { 1097 result.AppendError ("no process"); 1098 result.SetStatus (eReturnStatusFailed); 1099 return false; 1100 } 1101 else if (command.GetArgumentCount() != 1) 1102 { 1103 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1104 result.SetStatus (eReturnStatusFailed); 1105 return false; 1106 } 1107 1108 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1109 1110 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1111 if (new_thread == NULL) 1112 { 1113 result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1114 result.SetStatus (eReturnStatusFailed); 1115 return false; 1116 } 1117 1118 process->GetThreadList().SetCurrentThreadByID(new_thread->GetID()); 1119 1120 DisplayThreadInfo (interpreter, 1121 result.GetOutputStream(), 1122 new_thread, 1123 false, 1124 true); 1125 1126 return result.Succeeded(); 1127 } 1128 1129 }; 1130 1131 1132 //------------------------------------------------------------------------- 1133 // CommandObjectThreadList 1134 //------------------------------------------------------------------------- 1135 1136 CommandObjectThreadList::CommandObjectThreadList (): 1137 CommandObject ("thread list", 1138 "Shows a summary of all current threads in a process.", 1139 "thread list", 1140 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1141 { 1142 } 1143 1144 CommandObjectThreadList::~CommandObjectThreadList() 1145 { 1146 } 1147 1148 bool 1149 CommandObjectThreadList::Execute 1150 ( 1151 Args& command, 1152 CommandContext *context, 1153 CommandInterpreter *interpreter, 1154 CommandReturnObject &result 1155 ) 1156 { 1157 StreamString &strm = result.GetOutputStream(); 1158 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1159 ExecutionContext exe_ctx(context->GetExecutionContext()); 1160 if (exe_ctx.process) 1161 { 1162 const StateType state = exe_ctx.process->GetState(); 1163 1164 if (StateIsStoppedState(state)) 1165 { 1166 if (state == eStateExited) 1167 { 1168 int exit_status = exe_ctx.process->GetExitStatus(); 1169 const char *exit_description = exe_ctx.process->GetExitDescription(); 1170 strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1171 exe_ctx.process->GetID(), 1172 exit_status, 1173 exit_status, 1174 exit_description ? exit_description : ""); 1175 } 1176 else 1177 { 1178 strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1179 if (exe_ctx.thread == NULL) 1180 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1181 if (exe_ctx.thread != NULL) 1182 { 1183 DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false); 1184 } 1185 else 1186 { 1187 result.AppendError ("no valid thread found in current process"); 1188 result.SetStatus (eReturnStatusFailed); 1189 } 1190 } 1191 } 1192 else 1193 { 1194 result.AppendError ("process is currently running"); 1195 result.SetStatus (eReturnStatusFailed); 1196 } 1197 } 1198 else 1199 { 1200 result.AppendError ("no current location or status available"); 1201 result.SetStatus (eReturnStatusFailed); 1202 } 1203 return result.Succeeded(); 1204 } 1205 1206 //------------------------------------------------------------------------- 1207 // CommandObjectMultiwordThread 1208 //------------------------------------------------------------------------- 1209 1210 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter *interpreter) : 1211 CommandObjectMultiword ("thread", 1212 "A set of commands for operating on one or more thread within a running process.", 1213 "thread <subcommand> [<subcommand-options>]") 1214 { 1215 LoadSubCommand (CommandObjectSP (new CommandObjectThreadBacktrace ()), "backtrace", interpreter); 1216 LoadSubCommand (CommandObjectSP (new CommandObjectThreadContinue ()), "continue", interpreter); 1217 LoadSubCommand (CommandObjectSP (new CommandObjectThreadList ()), "list", interpreter); 1218 LoadSubCommand (CommandObjectSP (new CommandObjectThreadSelect ()), "select", interpreter); 1219 LoadSubCommand (CommandObjectSP (new CommandObjectThreadUntil ()), "until", interpreter); 1220 LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-in", 1221 "Source level single step in in specified thread (current thread, if none specified).", 1222 "thread step-in [<thread-id>]", 1223 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1224 eStepTypeInto, 1225 eStepScopeSource)), 1226 "step-in", interpreter); 1227 1228 LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out", 1229 "Source level single step out in specified thread (current thread, if none specified).", 1230 "thread step-out [<thread-id>]", 1231 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1232 eStepTypeOut, 1233 eStepScopeSource)), 1234 "step-out", interpreter); 1235 1236 LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over", 1237 "Source level single step over in specified thread (current thread, if none specified).", 1238 "thread step-over [<thread-id>]", 1239 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1240 eStepTypeOver, 1241 eStepScopeSource)), 1242 "step-over", interpreter); 1243 1244 LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst", 1245 "Single step one instruction in specified thread (current thread, if none specified).", 1246 "thread step-inst [<thread-id>]", 1247 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1248 eStepTypeTrace, 1249 eStepScopeInstruction)), 1250 "step-inst", interpreter); 1251 LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over", 1252 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 1253 "thread step-inst-over [<thread-id>]", 1254 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused, 1255 eStepTypeTraceOver, 1256 eStepScopeInstruction)), 1257 "step-inst-over", interpreter); 1258 } 1259 1260 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 1261 { 1262 } 1263 1264 1265