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