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