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