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