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