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