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