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 "lldb/lldb-python.h" 11 12 #include "CommandObjectThread.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/lldb-private.h" 19 #include "lldb/Core/State.h" 20 #include "lldb/Core/SourceManager.h" 21 #include "lldb/Host/Host.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Interpreter/CommandReturnObject.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Symbol/CompileUnit.h" 26 #include "lldb/Symbol/Function.h" 27 #include "lldb/Symbol/LineTable.h" 28 #include "lldb/Symbol/LineEntry.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/RegisterContext.h" 31 #include "lldb/Target/SystemRuntime.h" 32 #include "lldb/Target/Target.h" 33 #include "lldb/Target/Thread.h" 34 #include "lldb/Target/ThreadPlan.h" 35 #include "lldb/Target/ThreadPlanStepInstruction.h" 36 #include "lldb/Target/ThreadPlanStepOut.h" 37 #include "lldb/Target/ThreadPlanStepRange.h" 38 #include "lldb/Target/ThreadPlanStepInRange.h" 39 40 41 using namespace lldb; 42 using namespace lldb_private; 43 44 45 //------------------------------------------------------------------------- 46 // CommandObjectThreadBacktrace 47 //------------------------------------------------------------------------- 48 49 class CommandObjectIterateOverThreads : public CommandObjectParsed 50 { 51 public: 52 CommandObjectIterateOverThreads (CommandInterpreter &interpreter, 53 const char *name, 54 const char *help, 55 const char *syntax, 56 uint32_t flags) : 57 CommandObjectParsed (interpreter, name, help, syntax, flags) 58 { 59 } 60 61 virtual ~CommandObjectIterateOverThreads() {} 62 virtual bool 63 DoExecute (Args& command, CommandReturnObject &result) 64 { 65 result.SetStatus (m_success_return); 66 67 if (command.GetArgumentCount() == 0) 68 { 69 Thread *thread = m_exe_ctx.GetThreadPtr(); 70 if (!HandleOneThread (*thread, result)) 71 return false; 72 } 73 else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0) 74 { 75 Process *process = m_exe_ctx.GetProcessPtr(); 76 uint32_t idx = 0; 77 for (ThreadSP thread_sp : process->Threads()) 78 { 79 if (idx != 0 && m_add_return) 80 result.AppendMessage(""); 81 82 if (!HandleOneThread(*(thread_sp.get()), result)) 83 return false; 84 ++idx; 85 } 86 } 87 else 88 { 89 const size_t num_args = command.GetArgumentCount(); 90 Process *process = m_exe_ctx.GetProcessPtr(); 91 Mutex::Locker locker (process->GetThreadList().GetMutex()); 92 std::vector<ThreadSP> thread_sps; 93 94 for (size_t i = 0; i < num_args; i++) 95 { 96 bool success; 97 98 uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); 99 if (!success) 100 { 101 result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); 102 result.SetStatus (eReturnStatusFailed); 103 return false; 104 } 105 106 thread_sps.push_back(process->GetThreadList().FindThreadByIndexID(thread_idx)); 107 108 if (!thread_sps[i]) 109 { 110 result.AppendErrorWithFormat ("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); 111 result.SetStatus (eReturnStatusFailed); 112 return false; 113 } 114 115 } 116 117 for (uint32_t i = 0; i < num_args; i++) 118 { 119 if (!HandleOneThread (*(thread_sps[i].get()), result)) 120 return false; 121 122 if (i < num_args - 1 && m_add_return) 123 result.AppendMessage(""); 124 } 125 } 126 return result.Succeeded(); 127 } 128 129 protected: 130 131 // Override this to do whatever you need to do for one thread. 132 // 133 // If you return false, the iteration will stop, otherwise it will proceed. 134 // The result is set to m_success_return (defaults to eReturnStatusSuccessFinishResult) before the iteration, 135 // so you only need to set the return status in HandleOneThread if you want to indicate an error. 136 // If m_add_return is true, a blank line will be inserted between each of the listings (except the last one.) 137 138 virtual bool 139 HandleOneThread (Thread &thread, CommandReturnObject &result) = 0; 140 141 ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; 142 bool m_add_return = true; 143 144 }; 145 146 //------------------------------------------------------------------------- 147 // CommandObjectThreadBacktrace 148 //------------------------------------------------------------------------- 149 150 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads 151 { 152 public: 153 154 class CommandOptions : public Options 155 { 156 public: 157 158 CommandOptions (CommandInterpreter &interpreter) : 159 Options(interpreter) 160 { 161 // Keep default values of all options in one place: OptionParsingStarting () 162 OptionParsingStarting (); 163 } 164 165 virtual 166 ~CommandOptions () 167 { 168 } 169 170 virtual Error 171 SetOptionValue (uint32_t option_idx, const char *option_arg) 172 { 173 Error error; 174 const int short_option = m_getopt_table[option_idx].val; 175 176 switch (short_option) 177 { 178 case 'c': 179 { 180 bool success; 181 int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success); 182 if (!success) 183 error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 184 if (input_count < -1) 185 m_count = UINT32_MAX; 186 else 187 m_count = input_count; 188 } 189 break; 190 case 's': 191 { 192 bool success; 193 m_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 194 if (!success) 195 error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); 196 } 197 case 'e': 198 { 199 bool success; 200 m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success); 201 if (!success) 202 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 203 } 204 break; 205 default: 206 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 207 break; 208 209 } 210 return error; 211 } 212 213 void 214 OptionParsingStarting () 215 { 216 m_count = UINT32_MAX; 217 m_start = 0; 218 m_extended_backtrace = false; 219 } 220 221 const OptionDefinition* 222 GetDefinitions () 223 { 224 return g_option_table; 225 } 226 227 // Options table: Required for subclasses of Options. 228 229 static OptionDefinition g_option_table[]; 230 231 // Instance variables to hold the values for command options. 232 uint32_t m_count; 233 uint32_t m_start; 234 bool m_extended_backtrace; 235 }; 236 237 CommandObjectThreadBacktrace (CommandInterpreter &interpreter) : 238 CommandObjectIterateOverThreads (interpreter, 239 "thread backtrace", 240 "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.", 241 NULL, 242 eFlagRequiresProcess | 243 eFlagRequiresThread | 244 eFlagTryTargetAPILock | 245 eFlagProcessMustBeLaunched | 246 eFlagProcessMustBePaused ), 247 m_options(interpreter) 248 { 249 } 250 251 ~CommandObjectThreadBacktrace() 252 { 253 } 254 255 virtual Options * 256 GetOptions () 257 { 258 return &m_options; 259 } 260 261 protected: 262 void 263 DoExtendedBacktrace (Thread *thread, CommandReturnObject &result) 264 { 265 SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 266 if (runtime) 267 { 268 Stream &strm = result.GetOutputStream(); 269 const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes(); 270 for (auto type : types) 271 { 272 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type); 273 if (ext_thread_sp && ext_thread_sp->IsValid ()) 274 { 275 const uint32_t num_frames_with_source = 0; 276 if (ext_thread_sp->GetStatus (strm, 277 m_options.m_start, 278 m_options.m_count, 279 num_frames_with_source)) 280 { 281 DoExtendedBacktrace (ext_thread_sp.get(), result); 282 } 283 } 284 } 285 } 286 } 287 288 virtual bool 289 HandleOneThread (Thread &thread, CommandReturnObject &result) 290 { 291 Stream &strm = result.GetOutputStream(); 292 293 // Don't show source context when doing backtraces. 294 const uint32_t num_frames_with_source = 0; 295 296 if (!thread.GetStatus (strm, 297 m_options.m_start, 298 m_options.m_count, 299 num_frames_with_source)) 300 { 301 result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", thread.GetIndexID()); 302 result.SetStatus (eReturnStatusFailed); 303 return false; 304 } 305 if (m_options.m_extended_backtrace) 306 { 307 DoExtendedBacktrace (&thread, result); 308 } 309 310 return true; 311 } 312 313 CommandOptions m_options; 314 }; 315 316 OptionDefinition 317 CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = 318 { 319 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, 320 { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, 321 { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"}, 322 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 323 }; 324 325 enum StepScope 326 { 327 eStepScopeSource, 328 eStepScopeInstruction 329 }; 330 331 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed 332 { 333 public: 334 335 class CommandOptions : public Options 336 { 337 public: 338 339 CommandOptions (CommandInterpreter &interpreter) : 340 Options (interpreter) 341 { 342 // Keep default values of all options in one place: OptionParsingStarting () 343 OptionParsingStarting (); 344 } 345 346 virtual 347 ~CommandOptions () 348 { 349 } 350 351 virtual Error 352 SetOptionValue (uint32_t option_idx, const char *option_arg) 353 { 354 Error error; 355 const int short_option = m_getopt_table[option_idx].val; 356 357 switch (short_option) 358 { 359 case 'a': 360 { 361 bool success; 362 bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 363 if (!success) 364 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 365 else 366 { 367 m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 368 } 369 } 370 break; 371 372 case 'A': 373 { 374 bool success; 375 bool avoid_no_debug = Args::StringToBoolean (option_arg, true, &success); 376 if (!success) 377 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option); 378 else 379 { 380 m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 381 } 382 } 383 break; 384 385 case 'c': 386 { 387 m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 388 if (m_step_count == UINT32_MAX) 389 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 390 break; 391 } 392 break; 393 case 'C': 394 { 395 m_class_name.clear(); 396 m_class_name.assign(option_arg); 397 } 398 break; 399 case 'm': 400 { 401 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 402 m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 403 } 404 break; 405 406 case 'r': 407 { 408 m_avoid_regexp.clear(); 409 m_avoid_regexp.assign(option_arg); 410 } 411 break; 412 413 case 't': 414 { 415 m_step_in_target.clear(); 416 m_step_in_target.assign(option_arg); 417 418 } 419 break; 420 default: 421 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 422 break; 423 424 } 425 return error; 426 } 427 428 void 429 OptionParsingStarting () 430 { 431 m_step_in_avoid_no_debug = eLazyBoolCalculate; 432 m_step_out_avoid_no_debug = eLazyBoolCalculate; 433 m_run_mode = eOnlyDuringStepping; 434 m_avoid_regexp.clear(); 435 m_step_in_target.clear(); 436 m_class_name.clear(); 437 m_step_count = 1; 438 } 439 440 const OptionDefinition* 441 GetDefinitions () 442 { 443 return g_option_table; 444 } 445 446 // Options table: Required for subclasses of Options. 447 448 static OptionDefinition g_option_table[]; 449 450 // Instance variables to hold the values for command options. 451 LazyBool m_step_in_avoid_no_debug; 452 LazyBool m_step_out_avoid_no_debug; 453 RunMode m_run_mode; 454 std::string m_avoid_regexp; 455 std::string m_step_in_target; 456 std::string m_class_name; 457 int32_t m_step_count; 458 }; 459 460 CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, 461 const char *name, 462 const char *help, 463 const char *syntax, 464 StepType step_type, 465 StepScope step_scope) : 466 CommandObjectParsed (interpreter, name, help, syntax, 467 eFlagRequiresProcess | 468 eFlagRequiresThread | 469 eFlagTryTargetAPILock | 470 eFlagProcessMustBeLaunched | 471 eFlagProcessMustBePaused ), 472 m_step_type (step_type), 473 m_step_scope (step_scope), 474 m_options (interpreter) 475 { 476 CommandArgumentEntry arg; 477 CommandArgumentData thread_id_arg; 478 479 // Define the first (and only) variant of this arg. 480 thread_id_arg.arg_type = eArgTypeThreadID; 481 thread_id_arg.arg_repetition = eArgRepeatOptional; 482 483 // There is only one variant this argument could be; put it into the argument entry. 484 arg.push_back (thread_id_arg); 485 486 // Push the data for the first argument into the m_arguments vector. 487 m_arguments.push_back (arg); 488 } 489 490 virtual 491 ~CommandObjectThreadStepWithTypeAndScope () 492 { 493 } 494 495 virtual 496 Options * 497 GetOptions () 498 { 499 return &m_options; 500 } 501 502 protected: 503 virtual bool 504 DoExecute (Args& command, CommandReturnObject &result) 505 { 506 Process *process = m_exe_ctx.GetProcessPtr(); 507 bool synchronous_execution = m_interpreter.GetSynchronous(); 508 509 const uint32_t num_threads = process->GetThreadList().GetSize(); 510 Thread *thread = NULL; 511 512 if (command.GetArgumentCount() == 0) 513 { 514 thread = process->GetThreadList().GetSelectedThread().get(); 515 if (thread == NULL) 516 { 517 result.AppendError ("no selected thread in process"); 518 result.SetStatus (eReturnStatusFailed); 519 return false; 520 } 521 } 522 else 523 { 524 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 525 uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); 526 if (step_thread_idx == LLDB_INVALID_INDEX32) 527 { 528 result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); 529 result.SetStatus (eReturnStatusFailed); 530 return false; 531 } 532 thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 533 if (thread == NULL) 534 { 535 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 536 step_thread_idx, num_threads); 537 result.SetStatus (eReturnStatusFailed); 538 return false; 539 } 540 } 541 542 if (m_step_type == eStepTypeScripted) 543 { 544 if (m_options.m_class_name.empty()) 545 { 546 result.AppendErrorWithFormat ("empty class name for scripted step."); 547 result.SetStatus(eReturnStatusFailed); 548 return false; 549 } 550 else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists(m_options.m_class_name.c_str())) 551 { 552 result.AppendErrorWithFormat ("class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); 553 result.SetStatus(eReturnStatusFailed); 554 return false; 555 } 556 } 557 558 const bool abort_other_plans = false; 559 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 560 561 // This is a bit unfortunate, but not all the commands in this command object support 562 // only while stepping, so I use the bool for them. 563 bool bool_stop_other_threads; 564 if (m_options.m_run_mode == eAllThreads) 565 bool_stop_other_threads = false; 566 else if (m_options.m_run_mode == eOnlyDuringStepping) 567 { 568 if (m_step_type == eStepTypeOut || m_step_type == eStepTypeScripted) 569 bool_stop_other_threads = false; 570 else 571 bool_stop_other_threads = true; 572 } 573 else 574 bool_stop_other_threads = true; 575 576 ThreadPlanSP new_plan_sp; 577 578 if (m_step_type == eStepTypeInto) 579 { 580 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 581 582 if (frame->HasDebugInformation ()) 583 { 584 new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, 585 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 586 frame->GetSymbolContext(eSymbolContextEverything), 587 m_options.m_step_in_target.c_str(), 588 stop_other_threads, 589 m_options.m_step_in_avoid_no_debug, 590 m_options.m_step_out_avoid_no_debug); 591 592 if (new_plan_sp && !m_options.m_avoid_regexp.empty()) 593 { 594 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan_sp.get()); 595 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 596 } 597 } 598 else 599 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 600 601 } 602 else if (m_step_type == eStepTypeOver) 603 { 604 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 605 606 if (frame->HasDebugInformation()) 607 new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, 608 frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, 609 frame->GetSymbolContext(eSymbolContextEverything), 610 stop_other_threads, 611 m_options.m_step_out_avoid_no_debug); 612 else 613 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, 614 abort_other_plans, 615 bool_stop_other_threads); 616 617 } 618 else if (m_step_type == eStepTypeTrace) 619 { 620 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads); 621 } 622 else if (m_step_type == eStepTypeTraceOver) 623 { 624 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads); 625 } 626 else if (m_step_type == eStepTypeOut) 627 { 628 new_plan_sp = thread->QueueThreadPlanForStepOut (abort_other_plans, 629 NULL, 630 false, 631 bool_stop_other_threads, 632 eVoteYes, 633 eVoteNoOpinion, 634 thread->GetSelectedFrameIndex(), 635 m_options.m_step_out_avoid_no_debug); 636 } 637 else if (m_step_type == eStepTypeScripted) 638 { 639 new_plan_sp = thread->QueueThreadPlanForStepScripted (abort_other_plans, 640 m_options.m_class_name.c_str(), 641 bool_stop_other_threads); 642 } 643 else 644 { 645 result.AppendError ("step type is not supported"); 646 result.SetStatus (eReturnStatusFailed); 647 return false; 648 } 649 650 // If we got a new plan, then set it to be a master plan (User level Plans should be master plans 651 // so that they can be interruptible). Then resume the process. 652 653 if (new_plan_sp) 654 { 655 new_plan_sp->SetIsMasterPlan (true); 656 new_plan_sp->SetOkayToDiscard (false); 657 658 if (m_options.m_step_count > 1) 659 { 660 if (new_plan_sp->SetIterationCount(m_options.m_step_count)) 661 { 662 result.AppendWarning ("step operation does not support iteration count."); 663 } 664 } 665 666 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 667 process->Resume (); 668 669 // There is a race condition where this thread will return up the call stack to the main command handler 670 // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 671 // a chance to call PushProcessIOHandler(). 672 process->SyncIOHandler(2000); 673 674 if (synchronous_execution) 675 { 676 StateType state = process->WaitForProcessToStop (NULL); 677 678 //EventSP event_sp; 679 //StateType state = process->WaitForStateChangedEvents (NULL, event_sp); 680 //while (! StateIsStoppedState (state)) 681 // { 682 // state = process->WaitForStateChangedEvents (NULL, event_sp); 683 // } 684 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 685 result.SetDidChangeProcessState (true); 686 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 687 result.SetStatus (eReturnStatusSuccessFinishNoResult); 688 } 689 else 690 { 691 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 692 } 693 } 694 else 695 { 696 result.AppendError ("Couldn't find thread plan to implement step type."); 697 result.SetStatus (eReturnStatusFailed); 698 } 699 return result.Succeeded(); 700 } 701 702 protected: 703 StepType m_step_type; 704 StepScope m_step_scope; 705 CommandOptions m_options; 706 }; 707 708 static OptionEnumValueElement 709 g_tri_running_mode[] = 710 { 711 { eOnlyThisThread, "this-thread", "Run only this thread"}, 712 { eAllThreads, "all-threads", "Run all threads"}, 713 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 714 { 0, NULL, NULL } 715 }; 716 717 static OptionEnumValueElement 718 g_duo_running_mode[] = 719 { 720 { eOnlyThisThread, "this-thread", "Run only this thread"}, 721 { eAllThreads, "all-threads", "Run all threads"}, 722 { 0, NULL, NULL } 723 }; 724 725 OptionDefinition 726 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 727 { 728 { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, 729 { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, 730 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, 731 { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, NULL, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, 732 { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, 733 { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, 734 { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step."}, 735 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 736 }; 737 738 739 //------------------------------------------------------------------------- 740 // CommandObjectThreadContinue 741 //------------------------------------------------------------------------- 742 743 class CommandObjectThreadContinue : public CommandObjectParsed 744 { 745 public: 746 747 CommandObjectThreadContinue (CommandInterpreter &interpreter) : 748 CommandObjectParsed (interpreter, 749 "thread continue", 750 "Continue execution of one or more threads in an active process.", 751 NULL, 752 eFlagRequiresThread | 753 eFlagTryTargetAPILock | 754 eFlagProcessMustBeLaunched | 755 eFlagProcessMustBePaused) 756 { 757 CommandArgumentEntry arg; 758 CommandArgumentData thread_idx_arg; 759 760 // Define the first (and only) variant of this arg. 761 thread_idx_arg.arg_type = eArgTypeThreadIndex; 762 thread_idx_arg.arg_repetition = eArgRepeatPlus; 763 764 // There is only one variant this argument could be; put it into the argument entry. 765 arg.push_back (thread_idx_arg); 766 767 // Push the data for the first argument into the m_arguments vector. 768 m_arguments.push_back (arg); 769 } 770 771 772 virtual 773 ~CommandObjectThreadContinue () 774 { 775 } 776 777 virtual bool 778 DoExecute (Args& command, CommandReturnObject &result) 779 { 780 bool synchronous_execution = m_interpreter.GetSynchronous (); 781 782 if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 783 { 784 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 785 result.SetStatus (eReturnStatusFailed); 786 return false; 787 } 788 789 Process *process = m_exe_ctx.GetProcessPtr(); 790 if (process == NULL) 791 { 792 result.AppendError ("no process exists. Cannot continue"); 793 result.SetStatus (eReturnStatusFailed); 794 return false; 795 } 796 797 StateType state = process->GetState(); 798 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 799 { 800 const size_t argc = command.GetArgumentCount(); 801 if (argc > 0) 802 { 803 // These two lines appear at the beginning of both blocks in 804 // this if..else, but that is because we need to release the 805 // lock before calling process->Resume below. 806 Mutex::Locker locker (process->GetThreadList().GetMutex()); 807 const uint32_t num_threads = process->GetThreadList().GetSize(); 808 std::vector<Thread *> resume_threads; 809 for (uint32_t i=0; i<argc; ++i) 810 { 811 bool success; 812 const int base = 0; 813 uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); 814 if (success) 815 { 816 Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 817 818 if (thread) 819 { 820 resume_threads.push_back(thread); 821 } 822 else 823 { 824 result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); 825 result.SetStatus (eReturnStatusFailed); 826 return false; 827 } 828 } 829 else 830 { 831 result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); 832 result.SetStatus (eReturnStatusFailed); 833 return false; 834 } 835 } 836 837 if (resume_threads.empty()) 838 { 839 result.AppendError ("no valid thread indexes were specified"); 840 result.SetStatus (eReturnStatusFailed); 841 return false; 842 } 843 else 844 { 845 if (resume_threads.size() == 1) 846 result.AppendMessageWithFormat ("Resuming thread: "); 847 else 848 result.AppendMessageWithFormat ("Resuming threads: "); 849 850 for (uint32_t idx=0; idx<num_threads; ++idx) 851 { 852 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 853 std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); 854 855 if (this_thread_pos != resume_threads.end()) 856 { 857 resume_threads.erase(this_thread_pos); 858 if (resume_threads.size() > 0) 859 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); 860 else 861 result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); 862 863 const bool override_suspend = true; 864 thread->SetResumeState (eStateRunning, override_suspend); 865 } 866 else 867 { 868 thread->SetResumeState (eStateSuspended); 869 } 870 } 871 result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); 872 } 873 } 874 else 875 { 876 // These two lines appear at the beginning of both blocks in 877 // this if..else, but that is because we need to release the 878 // lock before calling process->Resume below. 879 Mutex::Locker locker (process->GetThreadList().GetMutex()); 880 const uint32_t num_threads = process->GetThreadList().GetSize(); 881 Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 882 if (current_thread == NULL) 883 { 884 result.AppendError ("the process doesn't have a current thread"); 885 result.SetStatus (eReturnStatusFailed); 886 return false; 887 } 888 // Set the actions that the threads should each take when resuming 889 for (uint32_t idx=0; idx<num_threads; ++idx) 890 { 891 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 892 if (thread == current_thread) 893 { 894 result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); 895 const bool override_suspend = true; 896 thread->SetResumeState (eStateRunning, override_suspend); 897 } 898 else 899 { 900 thread->SetResumeState (eStateSuspended); 901 } 902 } 903 } 904 905 // We should not be holding the thread list lock when we do this. 906 Error error (process->Resume()); 907 if (error.Success()) 908 { 909 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 910 if (synchronous_execution) 911 { 912 state = process->WaitForProcessToStop (NULL); 913 914 result.SetDidChangeProcessState (true); 915 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 916 result.SetStatus (eReturnStatusSuccessFinishNoResult); 917 } 918 else 919 { 920 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 921 } 922 } 923 else 924 { 925 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 926 result.SetStatus (eReturnStatusFailed); 927 } 928 } 929 else 930 { 931 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 932 StateAsCString(state)); 933 result.SetStatus (eReturnStatusFailed); 934 } 935 936 return result.Succeeded(); 937 } 938 939 }; 940 941 //------------------------------------------------------------------------- 942 // CommandObjectThreadUntil 943 //------------------------------------------------------------------------- 944 945 class CommandObjectThreadUntil : public CommandObjectParsed 946 { 947 public: 948 949 class CommandOptions : public Options 950 { 951 public: 952 uint32_t m_thread_idx; 953 uint32_t m_frame_idx; 954 955 CommandOptions (CommandInterpreter &interpreter) : 956 Options (interpreter), 957 m_thread_idx(LLDB_INVALID_THREAD_ID), 958 m_frame_idx(LLDB_INVALID_FRAME_ID) 959 { 960 // Keep default values of all options in one place: OptionParsingStarting () 961 OptionParsingStarting (); 962 } 963 964 virtual 965 ~CommandOptions () 966 { 967 } 968 969 virtual Error 970 SetOptionValue (uint32_t option_idx, const char *option_arg) 971 { 972 Error error; 973 const int short_option = m_getopt_table[option_idx].val; 974 975 switch (short_option) 976 { 977 case 't': 978 { 979 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); 980 if (m_thread_idx == LLDB_INVALID_INDEX32) 981 { 982 error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); 983 } 984 } 985 break; 986 case 'f': 987 { 988 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 989 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 990 { 991 error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); 992 } 993 } 994 break; 995 case 'm': 996 { 997 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 998 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 999 1000 if (error.Success()) 1001 { 1002 if (run_mode == eAllThreads) 1003 m_stop_others = false; 1004 else 1005 m_stop_others = true; 1006 } 1007 } 1008 break; 1009 default: 1010 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1011 break; 1012 1013 } 1014 return error; 1015 } 1016 1017 void 1018 OptionParsingStarting () 1019 { 1020 m_thread_idx = LLDB_INVALID_THREAD_ID; 1021 m_frame_idx = 0; 1022 m_stop_others = false; 1023 } 1024 1025 const OptionDefinition* 1026 GetDefinitions () 1027 { 1028 return g_option_table; 1029 } 1030 1031 uint32_t m_step_thread_idx; 1032 bool m_stop_others; 1033 1034 // Options table: Required for subclasses of Options. 1035 1036 static OptionDefinition g_option_table[]; 1037 1038 // Instance variables to hold the values for command options. 1039 }; 1040 1041 CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1042 CommandObjectParsed (interpreter, 1043 "thread until", 1044 "Run the current or specified thread until it reaches a given line number or leaves the current function.", 1045 NULL, 1046 eFlagRequiresThread | 1047 eFlagTryTargetAPILock | 1048 eFlagProcessMustBeLaunched | 1049 eFlagProcessMustBePaused ), 1050 m_options (interpreter) 1051 { 1052 CommandArgumentEntry arg; 1053 CommandArgumentData line_num_arg; 1054 1055 // Define the first (and only) variant of this arg. 1056 line_num_arg.arg_type = eArgTypeLineNum; 1057 line_num_arg.arg_repetition = eArgRepeatPlain; 1058 1059 // There is only one variant this argument could be; put it into the argument entry. 1060 arg.push_back (line_num_arg); 1061 1062 // Push the data for the first argument into the m_arguments vector. 1063 m_arguments.push_back (arg); 1064 } 1065 1066 1067 virtual 1068 ~CommandObjectThreadUntil () 1069 { 1070 } 1071 1072 virtual 1073 Options * 1074 GetOptions () 1075 { 1076 return &m_options; 1077 } 1078 1079 protected: 1080 virtual bool 1081 DoExecute (Args& command, CommandReturnObject &result) 1082 { 1083 bool synchronous_execution = m_interpreter.GetSynchronous (); 1084 1085 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1086 if (target == NULL) 1087 { 1088 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1089 result.SetStatus (eReturnStatusFailed); 1090 return false; 1091 } 1092 1093 Process *process = m_exe_ctx.GetProcessPtr(); 1094 if (process == NULL) 1095 { 1096 result.AppendError ("need a valid process to step"); 1097 result.SetStatus (eReturnStatusFailed); 1098 1099 } 1100 else 1101 { 1102 Thread *thread = NULL; 1103 uint32_t line_number; 1104 1105 if (command.GetArgumentCount() != 1) 1106 { 1107 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); 1108 result.SetStatus (eReturnStatusFailed); 1109 return false; 1110 } 1111 1112 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1113 if (line_number == UINT32_MAX) 1114 { 1115 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1116 result.SetStatus (eReturnStatusFailed); 1117 return false; 1118 } 1119 1120 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1121 { 1122 thread = process->GetThreadList().GetSelectedThread().get(); 1123 } 1124 else 1125 { 1126 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); 1127 } 1128 1129 if (thread == NULL) 1130 { 1131 const uint32_t num_threads = process->GetThreadList().GetSize(); 1132 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 1133 m_options.m_thread_idx, 1134 num_threads); 1135 result.SetStatus (eReturnStatusFailed); 1136 return false; 1137 } 1138 1139 const bool abort_other_plans = false; 1140 1141 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1142 if (frame == NULL) 1143 { 1144 1145 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 1146 m_options.m_frame_idx, 1147 m_options.m_thread_idx); 1148 result.SetStatus (eReturnStatusFailed); 1149 return false; 1150 } 1151 1152 ThreadPlanSP new_plan_sp; 1153 1154 if (frame->HasDebugInformation ()) 1155 { 1156 // Finally we got here... Translate the given line number to a bunch of addresses: 1157 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1158 LineTable *line_table = NULL; 1159 if (sc.comp_unit) 1160 line_table = sc.comp_unit->GetLineTable(); 1161 1162 if (line_table == NULL) 1163 { 1164 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1165 m_options.m_frame_idx, m_options.m_thread_idx); 1166 result.SetStatus (eReturnStatusFailed); 1167 return false; 1168 } 1169 1170 LineEntry function_start; 1171 uint32_t index_ptr = 0, end_ptr; 1172 std::vector<addr_t> address_list; 1173 1174 // Find the beginning & end index of the 1175 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1176 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1177 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1178 1179 Address fun_end_addr(fun_start_addr.GetSection(), 1180 fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1181 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 1182 1183 bool all_in_function = true; 1184 1185 while (index_ptr <= end_ptr) 1186 { 1187 LineEntry line_entry; 1188 const bool exact = false; 1189 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry); 1190 if (index_ptr == UINT32_MAX) 1191 break; 1192 1193 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1194 if (address != LLDB_INVALID_ADDRESS) 1195 { 1196 if (fun_addr_range.ContainsLoadAddress (address, target)) 1197 address_list.push_back (address); 1198 else 1199 all_in_function = false; 1200 } 1201 index_ptr++; 1202 } 1203 1204 if (address_list.size() == 0) 1205 { 1206 if (all_in_function) 1207 result.AppendErrorWithFormat ("No line entries matching until target.\n"); 1208 else 1209 result.AppendErrorWithFormat ("Until target outside of the current function.\n"); 1210 1211 result.SetStatus (eReturnStatusFailed); 1212 return false; 1213 } 1214 1215 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, 1216 &address_list.front(), 1217 address_list.size(), 1218 m_options.m_stop_others, 1219 m_options.m_frame_idx); 1220 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) 1221 // and other plans executed by the user (stepping around the breakpoint) and then a "continue" 1222 // will resume the original plan. 1223 new_plan_sp->SetIsMasterPlan (true); 1224 new_plan_sp->SetOkayToDiscard(false); 1225 } 1226 else 1227 { 1228 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 1229 m_options.m_frame_idx, 1230 m_options.m_thread_idx); 1231 result.SetStatus (eReturnStatusFailed); 1232 return false; 1233 1234 } 1235 1236 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 1237 Error error (process->Resume ()); 1238 if (error.Success()) 1239 { 1240 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1241 if (synchronous_execution) 1242 { 1243 StateType state = process->WaitForProcessToStop (NULL); 1244 1245 result.SetDidChangeProcessState (true); 1246 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 1247 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1248 } 1249 else 1250 { 1251 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1252 } 1253 } 1254 else 1255 { 1256 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1257 result.SetStatus (eReturnStatusFailed); 1258 } 1259 1260 } 1261 return result.Succeeded(); 1262 } 1263 1264 CommandOptions m_options; 1265 1266 }; 1267 1268 OptionDefinition 1269 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1270 { 1271 { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 1272 { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 1273 { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, 1274 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1275 }; 1276 1277 1278 //------------------------------------------------------------------------- 1279 // CommandObjectThreadSelect 1280 //------------------------------------------------------------------------- 1281 1282 class CommandObjectThreadSelect : public CommandObjectParsed 1283 { 1284 public: 1285 1286 CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1287 CommandObjectParsed (interpreter, 1288 "thread select", 1289 "Select a thread as the currently active thread.", 1290 NULL, 1291 eFlagRequiresProcess | 1292 eFlagTryTargetAPILock | 1293 eFlagProcessMustBeLaunched | 1294 eFlagProcessMustBePaused ) 1295 { 1296 CommandArgumentEntry arg; 1297 CommandArgumentData thread_idx_arg; 1298 1299 // Define the first (and only) variant of this arg. 1300 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1301 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1302 1303 // There is only one variant this argument could be; put it into the argument entry. 1304 arg.push_back (thread_idx_arg); 1305 1306 // Push the data for the first argument into the m_arguments vector. 1307 m_arguments.push_back (arg); 1308 } 1309 1310 1311 virtual 1312 ~CommandObjectThreadSelect () 1313 { 1314 } 1315 1316 protected: 1317 virtual bool 1318 DoExecute (Args& command, CommandReturnObject &result) 1319 { 1320 Process *process = m_exe_ctx.GetProcessPtr(); 1321 if (process == NULL) 1322 { 1323 result.AppendError ("no process"); 1324 result.SetStatus (eReturnStatusFailed); 1325 return false; 1326 } 1327 else if (command.GetArgumentCount() != 1) 1328 { 1329 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1330 result.SetStatus (eReturnStatusFailed); 1331 return false; 1332 } 1333 1334 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1335 1336 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1337 if (new_thread == NULL) 1338 { 1339 result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1340 result.SetStatus (eReturnStatusFailed); 1341 return false; 1342 } 1343 1344 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1345 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1346 1347 return result.Succeeded(); 1348 } 1349 1350 }; 1351 1352 1353 //------------------------------------------------------------------------- 1354 // CommandObjectThreadList 1355 //------------------------------------------------------------------------- 1356 1357 class CommandObjectThreadList : public CommandObjectParsed 1358 { 1359 public: 1360 1361 1362 CommandObjectThreadList (CommandInterpreter &interpreter): 1363 CommandObjectParsed (interpreter, 1364 "thread list", 1365 "Show a summary of all current threads in a process.", 1366 "thread list", 1367 eFlagRequiresProcess | 1368 eFlagTryTargetAPILock | 1369 eFlagProcessMustBeLaunched | 1370 eFlagProcessMustBePaused ) 1371 { 1372 } 1373 1374 ~CommandObjectThreadList() 1375 { 1376 } 1377 1378 protected: 1379 bool 1380 DoExecute (Args& command, CommandReturnObject &result) 1381 { 1382 Stream &strm = result.GetOutputStream(); 1383 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1384 Process *process = m_exe_ctx.GetProcessPtr(); 1385 const bool only_threads_with_stop_reason = false; 1386 const uint32_t start_frame = 0; 1387 const uint32_t num_frames = 0; 1388 const uint32_t num_frames_with_source = 0; 1389 process->GetStatus(strm); 1390 process->GetThreadStatus (strm, 1391 only_threads_with_stop_reason, 1392 start_frame, 1393 num_frames, 1394 num_frames_with_source); 1395 return result.Succeeded(); 1396 } 1397 }; 1398 1399 //------------------------------------------------------------------------- 1400 // CommandObjectThreadInfo 1401 //------------------------------------------------------------------------- 1402 1403 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads 1404 { 1405 public: 1406 1407 CommandObjectThreadInfo (CommandInterpreter &interpreter) : 1408 CommandObjectIterateOverThreads (interpreter, 1409 "thread info", 1410 "Show an extended summary of information about thread(s) in a process.", 1411 "thread info", 1412 eFlagRequiresProcess | 1413 eFlagTryTargetAPILock | 1414 eFlagProcessMustBeLaunched | 1415 eFlagProcessMustBePaused), 1416 m_options (interpreter) 1417 { 1418 m_add_return = false; 1419 } 1420 1421 class CommandOptions : public Options 1422 { 1423 public: 1424 1425 CommandOptions (CommandInterpreter &interpreter) : 1426 Options (interpreter) 1427 { 1428 OptionParsingStarting (); 1429 } 1430 1431 void 1432 OptionParsingStarting () 1433 { 1434 m_json_thread = false; 1435 m_json_stopinfo = false; 1436 } 1437 1438 virtual 1439 ~CommandOptions () 1440 { 1441 } 1442 1443 virtual Error 1444 SetOptionValue (uint32_t option_idx, const char *option_arg) 1445 { 1446 const int short_option = m_getopt_table[option_idx].val; 1447 Error error; 1448 1449 switch (short_option) 1450 { 1451 case 'j': 1452 m_json_thread = true; 1453 break; 1454 1455 case 's': 1456 m_json_stopinfo = true; 1457 break; 1458 1459 default: 1460 return Error("invalid short option character '%c'", short_option); 1461 1462 } 1463 return error; 1464 } 1465 1466 const OptionDefinition* 1467 GetDefinitions () 1468 { 1469 return g_option_table; 1470 } 1471 1472 bool m_json_thread; 1473 bool m_json_stopinfo; 1474 1475 static OptionDefinition g_option_table[]; 1476 }; 1477 1478 virtual 1479 Options * 1480 GetOptions () 1481 { 1482 return &m_options; 1483 } 1484 1485 1486 virtual 1487 ~CommandObjectThreadInfo () 1488 { 1489 } 1490 1491 virtual bool 1492 HandleOneThread (Thread &thread, CommandReturnObject &result) 1493 { 1494 Stream &strm = result.GetOutputStream(); 1495 if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) 1496 { 1497 result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); 1498 result.SetStatus (eReturnStatusFailed); 1499 return false; 1500 } 1501 return true; 1502 } 1503 1504 CommandOptions m_options; 1505 1506 }; 1507 1508 OptionDefinition 1509 CommandObjectThreadInfo::CommandOptions::g_option_table[] = 1510 { 1511 { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, 1512 { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, 1513 1514 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1515 }; 1516 1517 1518 //------------------------------------------------------------------------- 1519 // CommandObjectThreadReturn 1520 //------------------------------------------------------------------------- 1521 1522 class CommandObjectThreadReturn : public CommandObjectRaw 1523 { 1524 public: 1525 class CommandOptions : public Options 1526 { 1527 public: 1528 1529 CommandOptions (CommandInterpreter &interpreter) : 1530 Options (interpreter), 1531 m_from_expression (false) 1532 { 1533 // Keep default values of all options in one place: OptionParsingStarting () 1534 OptionParsingStarting (); 1535 } 1536 1537 virtual 1538 ~CommandOptions () 1539 { 1540 } 1541 1542 virtual Error 1543 SetOptionValue (uint32_t option_idx, const char *option_arg) 1544 { 1545 Error error; 1546 const int short_option = m_getopt_table[option_idx].val; 1547 1548 switch (short_option) 1549 { 1550 case 'x': 1551 { 1552 bool success; 1553 bool tmp_value = Args::StringToBoolean (option_arg, false, &success); 1554 if (success) 1555 m_from_expression = tmp_value; 1556 else 1557 { 1558 error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); 1559 } 1560 } 1561 break; 1562 default: 1563 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1564 break; 1565 1566 } 1567 return error; 1568 } 1569 1570 void 1571 OptionParsingStarting () 1572 { 1573 m_from_expression = false; 1574 } 1575 1576 const OptionDefinition* 1577 GetDefinitions () 1578 { 1579 return g_option_table; 1580 } 1581 1582 bool m_from_expression; 1583 1584 // Options table: Required for subclasses of Options. 1585 1586 static OptionDefinition g_option_table[]; 1587 1588 // Instance variables to hold the values for command options. 1589 }; 1590 1591 virtual 1592 Options * 1593 GetOptions () 1594 { 1595 return &m_options; 1596 } 1597 1598 CommandObjectThreadReturn (CommandInterpreter &interpreter) : 1599 CommandObjectRaw (interpreter, 1600 "thread return", 1601 "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value," 1602 " or with the -x option from the innermost function evaluation.", 1603 "thread return", 1604 eFlagRequiresFrame | 1605 eFlagTryTargetAPILock | 1606 eFlagProcessMustBeLaunched | 1607 eFlagProcessMustBePaused ), 1608 m_options (interpreter) 1609 { 1610 CommandArgumentEntry arg; 1611 CommandArgumentData expression_arg; 1612 1613 // Define the first (and only) variant of this arg. 1614 expression_arg.arg_type = eArgTypeExpression; 1615 expression_arg.arg_repetition = eArgRepeatOptional; 1616 1617 // There is only one variant this argument could be; put it into the argument entry. 1618 arg.push_back (expression_arg); 1619 1620 // Push the data for the first argument into the m_arguments vector. 1621 m_arguments.push_back (arg); 1622 1623 1624 } 1625 1626 ~CommandObjectThreadReturn() 1627 { 1628 } 1629 1630 protected: 1631 1632 bool DoExecute 1633 ( 1634 const char *command, 1635 CommandReturnObject &result 1636 ) 1637 { 1638 // I am going to handle this by hand, because I don't want you to have to say: 1639 // "thread return -- -5". 1640 if (command[0] == '-' && command[1] == 'x') 1641 { 1642 if (command && command[2] != '\0') 1643 result.AppendWarning("Return values ignored when returning from user called expressions"); 1644 1645 Thread *thread = m_exe_ctx.GetThreadPtr(); 1646 Error error; 1647 error = thread->UnwindInnermostExpression(); 1648 if (!error.Success()) 1649 { 1650 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); 1651 result.SetStatus (eReturnStatusFailed); 1652 } 1653 else 1654 { 1655 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); 1656 if (success) 1657 { 1658 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); 1659 result.SetStatus (eReturnStatusSuccessFinishResult); 1660 } 1661 else 1662 { 1663 result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); 1664 result.SetStatus (eReturnStatusFailed); 1665 } 1666 } 1667 return result.Succeeded(); 1668 } 1669 1670 ValueObjectSP return_valobj_sp; 1671 1672 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1673 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1674 1675 if (frame_sp->IsInlined()) 1676 { 1677 result.AppendError("Don't know how to return from inlined frames."); 1678 result.SetStatus (eReturnStatusFailed); 1679 return false; 1680 } 1681 1682 if (command && command[0] != '\0') 1683 { 1684 Target *target = m_exe_ctx.GetTargetPtr(); 1685 EvaluateExpressionOptions options; 1686 1687 options.SetUnwindOnError(true); 1688 options.SetUseDynamic(eNoDynamicValues); 1689 1690 ExpressionResults exe_results = eExpressionSetupError; 1691 exe_results = target->EvaluateExpression (command, 1692 frame_sp.get(), 1693 return_valobj_sp, 1694 options); 1695 if (exe_results != eExpressionCompleted) 1696 { 1697 if (return_valobj_sp) 1698 result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); 1699 else 1700 result.AppendErrorWithFormat("Unknown error evaluating result expression."); 1701 result.SetStatus (eReturnStatusFailed); 1702 return false; 1703 1704 } 1705 } 1706 1707 Error error; 1708 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1709 const bool broadcast = true; 1710 error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); 1711 if (!error.Success()) 1712 { 1713 result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); 1714 result.SetStatus (eReturnStatusFailed); 1715 return false; 1716 } 1717 1718 result.SetStatus (eReturnStatusSuccessFinishResult); 1719 return true; 1720 } 1721 1722 CommandOptions m_options; 1723 1724 }; 1725 OptionDefinition 1726 CommandObjectThreadReturn::CommandOptions::g_option_table[] = 1727 { 1728 { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, 1729 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1730 }; 1731 1732 //------------------------------------------------------------------------- 1733 // CommandObjectThreadJump 1734 //------------------------------------------------------------------------- 1735 1736 class CommandObjectThreadJump : public CommandObjectParsed 1737 { 1738 public: 1739 class CommandOptions : public Options 1740 { 1741 public: 1742 1743 CommandOptions (CommandInterpreter &interpreter) : 1744 Options (interpreter) 1745 { 1746 OptionParsingStarting (); 1747 } 1748 1749 void 1750 OptionParsingStarting () 1751 { 1752 m_filenames.Clear(); 1753 m_line_num = 0; 1754 m_line_offset = 0; 1755 m_load_addr = LLDB_INVALID_ADDRESS; 1756 m_force = false; 1757 } 1758 1759 virtual 1760 ~CommandOptions () 1761 { 1762 } 1763 1764 virtual Error 1765 SetOptionValue (uint32_t option_idx, const char *option_arg) 1766 { 1767 bool success; 1768 const int short_option = m_getopt_table[option_idx].val; 1769 Error error; 1770 1771 switch (short_option) 1772 { 1773 case 'f': 1774 m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 1775 if (m_filenames.GetSize() > 1) 1776 return Error("only one source file expected."); 1777 break; 1778 case 'l': 1779 m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success); 1780 if (!success || m_line_num == 0) 1781 return Error("invalid line number: '%s'.", option_arg); 1782 break; 1783 case 'b': 1784 m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success); 1785 if (!success) 1786 return Error("invalid line offset: '%s'.", option_arg); 1787 break; 1788 case 'a': 1789 { 1790 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 1791 m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 1792 } 1793 break; 1794 case 'r': 1795 m_force = true; 1796 break; 1797 1798 default: 1799 return Error("invalid short option character '%c'", short_option); 1800 1801 } 1802 return error; 1803 } 1804 1805 const OptionDefinition* 1806 GetDefinitions () 1807 { 1808 return g_option_table; 1809 } 1810 1811 FileSpecList m_filenames; 1812 uint32_t m_line_num; 1813 int32_t m_line_offset; 1814 lldb::addr_t m_load_addr; 1815 bool m_force; 1816 1817 static OptionDefinition g_option_table[]; 1818 }; 1819 1820 virtual 1821 Options * 1822 GetOptions () 1823 { 1824 return &m_options; 1825 } 1826 1827 CommandObjectThreadJump (CommandInterpreter &interpreter) : 1828 CommandObjectParsed (interpreter, 1829 "thread jump", 1830 "Sets the program counter to a new address.", 1831 "thread jump", 1832 eFlagRequiresFrame | 1833 eFlagTryTargetAPILock | 1834 eFlagProcessMustBeLaunched | 1835 eFlagProcessMustBePaused ), 1836 m_options (interpreter) 1837 { 1838 } 1839 1840 ~CommandObjectThreadJump() 1841 { 1842 } 1843 1844 protected: 1845 1846 bool DoExecute (Args& args, CommandReturnObject &result) 1847 { 1848 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1849 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1850 Thread *thread = m_exe_ctx.GetThreadPtr(); 1851 Target *target = m_exe_ctx.GetTargetPtr(); 1852 const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); 1853 1854 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 1855 { 1856 // Use this address directly. 1857 Address dest = Address(m_options.m_load_addr); 1858 1859 lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); 1860 if (callAddr == LLDB_INVALID_ADDRESS) 1861 { 1862 result.AppendErrorWithFormat ("Invalid destination address."); 1863 result.SetStatus (eReturnStatusFailed); 1864 return false; 1865 } 1866 1867 if (!reg_ctx->SetPC (callAddr)) 1868 { 1869 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); 1870 result.SetStatus (eReturnStatusFailed); 1871 return false; 1872 } 1873 } 1874 else 1875 { 1876 // Pick either the absolute line, or work out a relative one. 1877 int32_t line = (int32_t)m_options.m_line_num; 1878 if (line == 0) 1879 line = sym_ctx.line_entry.line + m_options.m_line_offset; 1880 1881 // Try the current file, but override if asked. 1882 FileSpec file = sym_ctx.line_entry.file; 1883 if (m_options.m_filenames.GetSize() == 1) 1884 file = m_options.m_filenames.GetFileSpecAtIndex(0); 1885 1886 if (!file) 1887 { 1888 result.AppendErrorWithFormat ("No source file available for the current location."); 1889 result.SetStatus (eReturnStatusFailed); 1890 return false; 1891 } 1892 1893 std::string warnings; 1894 Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); 1895 1896 if (err.Fail()) 1897 { 1898 result.SetError (err); 1899 return false; 1900 } 1901 1902 if (!warnings.empty()) 1903 result.AppendWarning (warnings.c_str()); 1904 } 1905 1906 result.SetStatus (eReturnStatusSuccessFinishResult); 1907 return true; 1908 } 1909 1910 CommandOptions m_options; 1911 }; 1912 OptionDefinition 1913 CommandObjectThreadJump::CommandOptions::g_option_table[] = 1914 { 1915 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 1916 "Specifies the source file to jump to."}, 1917 1918 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, 1919 "Specifies the line number to jump to."}, 1920 1921 { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, 1922 "Jumps by a relative line offset from the current line."}, 1923 1924 { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, 1925 "Jumps to a specific address."}, 1926 1927 { LLDB_OPT_SET_1| 1928 LLDB_OPT_SET_2| 1929 LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."}, 1930 1931 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1932 }; 1933 1934 //------------------------------------------------------------------------- 1935 // Next are the subcommands of CommandObjectMultiwordThreadPlan 1936 //------------------------------------------------------------------------- 1937 1938 1939 //------------------------------------------------------------------------- 1940 // CommandObjectThreadPlanList 1941 //------------------------------------------------------------------------- 1942 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads 1943 { 1944 public: 1945 1946 class CommandOptions : public Options 1947 { 1948 public: 1949 1950 CommandOptions (CommandInterpreter &interpreter) : 1951 Options(interpreter) 1952 { 1953 // Keep default values of all options in one place: OptionParsingStarting () 1954 OptionParsingStarting (); 1955 } 1956 1957 virtual 1958 ~CommandOptions () 1959 { 1960 } 1961 1962 virtual Error 1963 SetOptionValue (uint32_t option_idx, const char *option_arg) 1964 { 1965 Error error; 1966 const int short_option = m_getopt_table[option_idx].val; 1967 1968 switch (short_option) 1969 { 1970 case 'i': 1971 { 1972 m_internal = true; 1973 } 1974 break; 1975 case 'v': 1976 { 1977 m_verbose = true; 1978 } 1979 break; 1980 default: 1981 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1982 break; 1983 1984 } 1985 return error; 1986 } 1987 1988 void 1989 OptionParsingStarting () 1990 { 1991 m_verbose = false; 1992 m_internal = false; 1993 } 1994 1995 const OptionDefinition* 1996 GetDefinitions () 1997 { 1998 return g_option_table; 1999 } 2000 2001 // Options table: Required for subclasses of Options. 2002 2003 static OptionDefinition g_option_table[]; 2004 2005 // Instance variables to hold the values for command options. 2006 bool m_verbose; 2007 bool m_internal; 2008 }; 2009 2010 CommandObjectThreadPlanList (CommandInterpreter &interpreter) : 2011 CommandObjectIterateOverThreads (interpreter, 2012 "thread plan list", 2013 "Show thread plans for one or more threads. If no threads are specified, show the " 2014 "currently selected thread. Use the thread-index \"all\" to see all threads.", 2015 NULL, 2016 eFlagRequiresProcess | 2017 eFlagRequiresThread | 2018 eFlagTryTargetAPILock | 2019 eFlagProcessMustBeLaunched | 2020 eFlagProcessMustBePaused ), 2021 m_options(interpreter) 2022 { 2023 } 2024 2025 ~CommandObjectThreadPlanList () 2026 { 2027 } 2028 2029 virtual Options * 2030 GetOptions () 2031 { 2032 return &m_options; 2033 } 2034 2035 protected: 2036 virtual bool 2037 HandleOneThread (Thread &thread, CommandReturnObject &result) 2038 { 2039 Stream &strm = result.GetOutputStream(); 2040 DescriptionLevel desc_level = eDescriptionLevelFull; 2041 if (m_options.m_verbose) 2042 desc_level = eDescriptionLevelVerbose; 2043 2044 thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); 2045 return true; 2046 } 2047 CommandOptions m_options; 2048 }; 2049 2050 OptionDefinition 2051 CommandObjectThreadPlanList::CommandOptions::g_option_table[] = 2052 { 2053 { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, 2054 { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, 2055 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2056 }; 2057 2058 class CommandObjectThreadPlanDiscard : public CommandObjectParsed 2059 { 2060 public: 2061 CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : 2062 CommandObjectParsed (interpreter, 2063 "thread plan discard", 2064 "Discards thread plans up to and including the plan passed as the command argument." 2065 "Only user visible plans can be discarded, use the index from \"thread plan list\"" 2066 " without the \"-i\" argument.", 2067 NULL, 2068 eFlagRequiresProcess | 2069 eFlagRequiresThread | 2070 eFlagTryTargetAPILock | 2071 eFlagProcessMustBeLaunched | 2072 eFlagProcessMustBePaused ) 2073 { 2074 CommandArgumentEntry arg; 2075 CommandArgumentData plan_index_arg; 2076 2077 // Define the first (and only) variant of this arg. 2078 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 2079 plan_index_arg.arg_repetition = eArgRepeatPlain; 2080 2081 // There is only one variant this argument could be; put it into the argument entry. 2082 arg.push_back (plan_index_arg); 2083 2084 // Push the data for the first argument into the m_arguments vector. 2085 m_arguments.push_back (arg); 2086 } 2087 2088 virtual ~CommandObjectThreadPlanDiscard () {} 2089 2090 bool 2091 DoExecute (Args& args, CommandReturnObject &result) 2092 { 2093 Thread *thread = m_exe_ctx.GetThreadPtr(); 2094 if (args.GetArgumentCount() != 1) 2095 { 2096 result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", 2097 args.GetArgumentCount()); 2098 result.SetStatus (eReturnStatusFailed); 2099 return false; 2100 } 2101 2102 bool success; 2103 uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 2104 if (!success) 2105 { 2106 result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", 2107 args.GetArgumentAtIndex(0)); 2108 result.SetStatus (eReturnStatusFailed); 2109 return false; 2110 } 2111 2112 if (thread_plan_idx == 0) 2113 { 2114 result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); 2115 result.SetStatus (eReturnStatusFailed); 2116 return false; 2117 } 2118 2119 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) 2120 { 2121 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2122 return true; 2123 } 2124 else 2125 { 2126 result.AppendErrorWithFormat("Could not find User thread plan with index %s.", 2127 args.GetArgumentAtIndex(0)); 2128 result.SetStatus (eReturnStatusFailed); 2129 return false; 2130 } 2131 } 2132 }; 2133 2134 //------------------------------------------------------------------------- 2135 // CommandObjectMultiwordThreadPlan 2136 //------------------------------------------------------------------------- 2137 2138 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword 2139 { 2140 public: 2141 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : 2142 CommandObjectMultiword (interpreter, 2143 "plan", 2144 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", 2145 "thread plan <subcommand> [<subcommand objects]") 2146 { 2147 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); 2148 LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); 2149 } 2150 2151 virtual ~CommandObjectMultiwordThreadPlan () {} 2152 2153 2154 }; 2155 2156 //------------------------------------------------------------------------- 2157 // CommandObjectMultiwordThread 2158 //------------------------------------------------------------------------- 2159 2160 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 2161 CommandObjectMultiword (interpreter, 2162 "thread", 2163 "A set of commands for operating on one or more threads within a running process.", 2164 "thread <subcommand> [<subcommand-options>]") 2165 { 2166 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 2167 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 2168 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 2169 LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); 2170 LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); 2171 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 2172 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 2173 LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); 2174 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2175 interpreter, 2176 "thread step-in", 2177 "Source level single step in specified thread (current thread, if none specified).", 2178 NULL, 2179 eStepTypeInto, 2180 eStepScopeSource))); 2181 2182 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2183 interpreter, 2184 "thread step-out", 2185 "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).", 2186 NULL, 2187 eStepTypeOut, 2188 eStepScopeSource))); 2189 2190 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2191 interpreter, 2192 "thread step-over", 2193 "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 2194 NULL, 2195 eStepTypeOver, 2196 eStepScopeSource))); 2197 2198 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2199 interpreter, 2200 "thread step-inst", 2201 "Single step one instruction in specified thread (current thread, if none specified).", 2202 NULL, 2203 eStepTypeTrace, 2204 eStepScopeInstruction))); 2205 2206 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2207 interpreter, 2208 "thread step-inst-over", 2209 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 2210 NULL, 2211 eStepTypeTraceOver, 2212 eStepScopeInstruction))); 2213 2214 LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2215 interpreter, 2216 "thread step-scripted", 2217 "Step as instructed by the script class passed in the -C option.", 2218 NULL, 2219 eStepTypeScripted, 2220 eStepScopeSource))); 2221 2222 LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); 2223 } 2224 2225 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 2226 { 2227 } 2228 2229 2230