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 uint32_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 667 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 668 669 StreamString stream; 670 Error error; 671 if (synchronous_execution) 672 error = process->ResumeSynchronous (&stream); 673 else 674 error = process->Resume (); 675 676 // There is a race condition where this thread will return up the call stack to the main command handler 677 // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has 678 // a chance to call PushProcessIOHandler(). 679 process->SyncIOHandler(2000); 680 681 if (synchronous_execution) 682 { 683 // If any state changed events had anything to say, add that to the result 684 if (stream.GetData()) 685 result.AppendMessage(stream.GetData()); 686 687 process->GetThreadList().SetSelectedThreadByID (thread->GetID()); 688 result.SetDidChangeProcessState (true); 689 result.SetStatus (eReturnStatusSuccessFinishNoResult); 690 } 691 else 692 { 693 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 694 } 695 } 696 else 697 { 698 result.AppendError ("Couldn't find thread plan to implement step type."); 699 result.SetStatus (eReturnStatusFailed); 700 } 701 return result.Succeeded(); 702 } 703 704 protected: 705 StepType m_step_type; 706 StepScope m_step_scope; 707 CommandOptions m_options; 708 }; 709 710 static OptionEnumValueElement 711 g_tri_running_mode[] = 712 { 713 { eOnlyThisThread, "this-thread", "Run only this thread"}, 714 { eAllThreads, "all-threads", "Run all threads"}, 715 { eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, 716 { 0, NULL, NULL } 717 }; 718 719 static OptionEnumValueElement 720 g_duo_running_mode[] = 721 { 722 { eOnlyThisThread, "this-thread", "Run only this thread"}, 723 { eAllThreads, "all-threads", "Run all threads"}, 724 { 0, NULL, NULL } 725 }; 726 727 OptionDefinition 728 CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = 729 { 730 { 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."}, 731 { 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."}, 732 { 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."}, 733 { 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."}, 734 { 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."}, 735 { 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."}, 736 { 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."}, 737 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 738 }; 739 740 741 //------------------------------------------------------------------------- 742 // CommandObjectThreadContinue 743 //------------------------------------------------------------------------- 744 745 class CommandObjectThreadContinue : public CommandObjectParsed 746 { 747 public: 748 749 CommandObjectThreadContinue (CommandInterpreter &interpreter) : 750 CommandObjectParsed (interpreter, 751 "thread continue", 752 "Continue execution of one or more threads in an active process.", 753 NULL, 754 eFlagRequiresThread | 755 eFlagTryTargetAPILock | 756 eFlagProcessMustBeLaunched | 757 eFlagProcessMustBePaused) 758 { 759 CommandArgumentEntry arg; 760 CommandArgumentData thread_idx_arg; 761 762 // Define the first (and only) variant of this arg. 763 thread_idx_arg.arg_type = eArgTypeThreadIndex; 764 thread_idx_arg.arg_repetition = eArgRepeatPlus; 765 766 // There is only one variant this argument could be; put it into the argument entry. 767 arg.push_back (thread_idx_arg); 768 769 // Push the data for the first argument into the m_arguments vector. 770 m_arguments.push_back (arg); 771 } 772 773 774 virtual 775 ~CommandObjectThreadContinue () 776 { 777 } 778 779 virtual bool 780 DoExecute (Args& command, CommandReturnObject &result) 781 { 782 bool synchronous_execution = m_interpreter.GetSynchronous (); 783 784 if (!m_interpreter.GetDebugger().GetSelectedTarget().get()) 785 { 786 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 787 result.SetStatus (eReturnStatusFailed); 788 return false; 789 } 790 791 Process *process = m_exe_ctx.GetProcessPtr(); 792 if (process == NULL) 793 { 794 result.AppendError ("no process exists. Cannot continue"); 795 result.SetStatus (eReturnStatusFailed); 796 return false; 797 } 798 799 StateType state = process->GetState(); 800 if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) 801 { 802 const size_t argc = command.GetArgumentCount(); 803 if (argc > 0) 804 { 805 // These two lines appear at the beginning of both blocks in 806 // this if..else, but that is because we need to release the 807 // lock before calling process->Resume below. 808 Mutex::Locker locker (process->GetThreadList().GetMutex()); 809 const uint32_t num_threads = process->GetThreadList().GetSize(); 810 std::vector<Thread *> resume_threads; 811 for (uint32_t i=0; i<argc; ++i) 812 { 813 bool success; 814 const int base = 0; 815 uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); 816 if (success) 817 { 818 Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 819 820 if (thread) 821 { 822 resume_threads.push_back(thread); 823 } 824 else 825 { 826 result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); 827 result.SetStatus (eReturnStatusFailed); 828 return false; 829 } 830 } 831 else 832 { 833 result.AppendErrorWithFormat ("invalid thread index argument: \"%s\".\n", command.GetArgumentAtIndex(i)); 834 result.SetStatus (eReturnStatusFailed); 835 return false; 836 } 837 } 838 839 if (resume_threads.empty()) 840 { 841 result.AppendError ("no valid thread indexes were specified"); 842 result.SetStatus (eReturnStatusFailed); 843 return false; 844 } 845 else 846 { 847 if (resume_threads.size() == 1) 848 result.AppendMessageWithFormat ("Resuming thread: "); 849 else 850 result.AppendMessageWithFormat ("Resuming threads: "); 851 852 for (uint32_t idx=0; idx<num_threads; ++idx) 853 { 854 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 855 std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); 856 857 if (this_thread_pos != resume_threads.end()) 858 { 859 resume_threads.erase(this_thread_pos); 860 if (resume_threads.size() > 0) 861 result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); 862 else 863 result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); 864 865 const bool override_suspend = true; 866 thread->SetResumeState (eStateRunning, override_suspend); 867 } 868 else 869 { 870 thread->SetResumeState (eStateSuspended); 871 } 872 } 873 result.AppendMessageWithFormat ("in process %" PRIu64 "\n", process->GetID()); 874 } 875 } 876 else 877 { 878 // These two lines appear at the beginning of both blocks in 879 // this if..else, but that is because we need to release the 880 // lock before calling process->Resume below. 881 Mutex::Locker locker (process->GetThreadList().GetMutex()); 882 const uint32_t num_threads = process->GetThreadList().GetSize(); 883 Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); 884 if (current_thread == NULL) 885 { 886 result.AppendError ("the process doesn't have a current thread"); 887 result.SetStatus (eReturnStatusFailed); 888 return false; 889 } 890 // Set the actions that the threads should each take when resuming 891 for (uint32_t idx=0; idx<num_threads; ++idx) 892 { 893 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 894 if (thread == current_thread) 895 { 896 result.AppendMessageWithFormat ("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); 897 const bool override_suspend = true; 898 thread->SetResumeState (eStateRunning, override_suspend); 899 } 900 else 901 { 902 thread->SetResumeState (eStateSuspended); 903 } 904 } 905 } 906 907 908 StreamString stream; 909 Error error; 910 if (synchronous_execution) 911 error = process->ResumeSynchronous (&stream); 912 else 913 error = process->Resume (); 914 915 // We should not be holding the thread list lock when we do this. 916 if (error.Success()) 917 { 918 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 919 if (synchronous_execution) 920 { 921 // If any state changed events had anything to say, add that to the result 922 if (stream.GetData()) 923 result.AppendMessage(stream.GetData()); 924 925 result.SetDidChangeProcessState (true); 926 result.SetStatus (eReturnStatusSuccessFinishNoResult); 927 } 928 else 929 { 930 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 931 } 932 } 933 else 934 { 935 result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); 936 result.SetStatus (eReturnStatusFailed); 937 } 938 } 939 else 940 { 941 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 942 StateAsCString(state)); 943 result.SetStatus (eReturnStatusFailed); 944 } 945 946 return result.Succeeded(); 947 } 948 949 }; 950 951 //------------------------------------------------------------------------- 952 // CommandObjectThreadUntil 953 //------------------------------------------------------------------------- 954 955 class CommandObjectThreadUntil : public CommandObjectParsed 956 { 957 public: 958 959 class CommandOptions : public Options 960 { 961 public: 962 uint32_t m_thread_idx; 963 uint32_t m_frame_idx; 964 965 CommandOptions (CommandInterpreter &interpreter) : 966 Options (interpreter), 967 m_thread_idx(LLDB_INVALID_THREAD_ID), 968 m_frame_idx(LLDB_INVALID_FRAME_ID) 969 { 970 // Keep default values of all options in one place: OptionParsingStarting () 971 OptionParsingStarting (); 972 } 973 974 virtual 975 ~CommandOptions () 976 { 977 } 978 979 virtual Error 980 SetOptionValue (uint32_t option_idx, const char *option_arg) 981 { 982 Error error; 983 const int short_option = m_getopt_table[option_idx].val; 984 985 switch (short_option) 986 { 987 case 't': 988 { 989 m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); 990 if (m_thread_idx == LLDB_INVALID_INDEX32) 991 { 992 error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); 993 } 994 } 995 break; 996 case 'f': 997 { 998 m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); 999 if (m_frame_idx == LLDB_INVALID_FRAME_ID) 1000 { 1001 error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); 1002 } 1003 } 1004 break; 1005 case 'm': 1006 { 1007 OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; 1008 lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, error); 1009 1010 if (error.Success()) 1011 { 1012 if (run_mode == eAllThreads) 1013 m_stop_others = false; 1014 else 1015 m_stop_others = true; 1016 } 1017 } 1018 break; 1019 default: 1020 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1021 break; 1022 1023 } 1024 return error; 1025 } 1026 1027 void 1028 OptionParsingStarting () 1029 { 1030 m_thread_idx = LLDB_INVALID_THREAD_ID; 1031 m_frame_idx = 0; 1032 m_stop_others = false; 1033 } 1034 1035 const OptionDefinition* 1036 GetDefinitions () 1037 { 1038 return g_option_table; 1039 } 1040 1041 uint32_t m_step_thread_idx; 1042 bool m_stop_others; 1043 1044 // Options table: Required for subclasses of Options. 1045 1046 static OptionDefinition g_option_table[]; 1047 1048 // Instance variables to hold the values for command options. 1049 }; 1050 1051 CommandObjectThreadUntil (CommandInterpreter &interpreter) : 1052 CommandObjectParsed (interpreter, 1053 "thread until", 1054 "Run the current or specified thread until it reaches a given line number or leaves the current function.", 1055 NULL, 1056 eFlagRequiresThread | 1057 eFlagTryTargetAPILock | 1058 eFlagProcessMustBeLaunched | 1059 eFlagProcessMustBePaused ), 1060 m_options (interpreter) 1061 { 1062 CommandArgumentEntry arg; 1063 CommandArgumentData line_num_arg; 1064 1065 // Define the first (and only) variant of this arg. 1066 line_num_arg.arg_type = eArgTypeLineNum; 1067 line_num_arg.arg_repetition = eArgRepeatPlain; 1068 1069 // There is only one variant this argument could be; put it into the argument entry. 1070 arg.push_back (line_num_arg); 1071 1072 // Push the data for the first argument into the m_arguments vector. 1073 m_arguments.push_back (arg); 1074 } 1075 1076 1077 virtual 1078 ~CommandObjectThreadUntil () 1079 { 1080 } 1081 1082 virtual 1083 Options * 1084 GetOptions () 1085 { 1086 return &m_options; 1087 } 1088 1089 protected: 1090 virtual bool 1091 DoExecute (Args& command, CommandReturnObject &result) 1092 { 1093 bool synchronous_execution = m_interpreter.GetSynchronous (); 1094 1095 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1096 if (target == NULL) 1097 { 1098 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1099 result.SetStatus (eReturnStatusFailed); 1100 return false; 1101 } 1102 1103 Process *process = m_exe_ctx.GetProcessPtr(); 1104 if (process == NULL) 1105 { 1106 result.AppendError ("need a valid process to step"); 1107 result.SetStatus (eReturnStatusFailed); 1108 1109 } 1110 else 1111 { 1112 Thread *thread = NULL; 1113 uint32_t line_number; 1114 1115 if (command.GetArgumentCount() != 1) 1116 { 1117 result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); 1118 result.SetStatus (eReturnStatusFailed); 1119 return false; 1120 } 1121 1122 line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); 1123 if (line_number == UINT32_MAX) 1124 { 1125 result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); 1126 result.SetStatus (eReturnStatusFailed); 1127 return false; 1128 } 1129 1130 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) 1131 { 1132 thread = process->GetThreadList().GetSelectedThread().get(); 1133 } 1134 else 1135 { 1136 thread = process->GetThreadList().FindThreadByIndexID(m_options.m_thread_idx).get(); 1137 } 1138 1139 if (thread == NULL) 1140 { 1141 const uint32_t num_threads = process->GetThreadList().GetSize(); 1142 result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", 1143 m_options.m_thread_idx, 1144 num_threads); 1145 result.SetStatus (eReturnStatusFailed); 1146 return false; 1147 } 1148 1149 const bool abort_other_plans = false; 1150 1151 StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 1152 if (frame == NULL) 1153 { 1154 1155 result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", 1156 m_options.m_frame_idx, 1157 m_options.m_thread_idx); 1158 result.SetStatus (eReturnStatusFailed); 1159 return false; 1160 } 1161 1162 ThreadPlanSP new_plan_sp; 1163 1164 if (frame->HasDebugInformation ()) 1165 { 1166 // Finally we got here... Translate the given line number to a bunch of addresses: 1167 SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit)); 1168 LineTable *line_table = NULL; 1169 if (sc.comp_unit) 1170 line_table = sc.comp_unit->GetLineTable(); 1171 1172 if (line_table == NULL) 1173 { 1174 result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n", 1175 m_options.m_frame_idx, m_options.m_thread_idx); 1176 result.SetStatus (eReturnStatusFailed); 1177 return false; 1178 } 1179 1180 LineEntry function_start; 1181 uint32_t index_ptr = 0, end_ptr; 1182 std::vector<addr_t> address_list; 1183 1184 // Find the beginning & end index of the 1185 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1186 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1187 line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr); 1188 1189 Address fun_end_addr(fun_start_addr.GetSection(), 1190 fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); 1191 line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); 1192 1193 bool all_in_function = true; 1194 1195 while (index_ptr <= end_ptr) 1196 { 1197 LineEntry line_entry; 1198 const bool exact = false; 1199 index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry); 1200 if (index_ptr == UINT32_MAX) 1201 break; 1202 1203 addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); 1204 if (address != LLDB_INVALID_ADDRESS) 1205 { 1206 if (fun_addr_range.ContainsLoadAddress (address, target)) 1207 address_list.push_back (address); 1208 else 1209 all_in_function = false; 1210 } 1211 index_ptr++; 1212 } 1213 1214 if (address_list.size() == 0) 1215 { 1216 if (all_in_function) 1217 result.AppendErrorWithFormat ("No line entries matching until target.\n"); 1218 else 1219 result.AppendErrorWithFormat ("Until target outside of the current function.\n"); 1220 1221 result.SetStatus (eReturnStatusFailed); 1222 return false; 1223 } 1224 1225 new_plan_sp = thread->QueueThreadPlanForStepUntil (abort_other_plans, 1226 &address_list.front(), 1227 address_list.size(), 1228 m_options.m_stop_others, 1229 m_options.m_frame_idx); 1230 // User level plans should be master plans so they can be interrupted (e.g. by hitting a breakpoint) 1231 // and other plans executed by the user (stepping around the breakpoint) and then a "continue" 1232 // will resume the original plan. 1233 new_plan_sp->SetIsMasterPlan (true); 1234 new_plan_sp->SetOkayToDiscard(false); 1235 } 1236 else 1237 { 1238 result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", 1239 m_options.m_frame_idx, 1240 m_options.m_thread_idx); 1241 result.SetStatus (eReturnStatusFailed); 1242 return false; 1243 1244 } 1245 1246 1247 1248 process->GetThreadList().SetSelectedThreadByID (m_options.m_thread_idx); 1249 1250 StreamString stream; 1251 Error error; 1252 if (synchronous_execution) 1253 error = process->ResumeSynchronous (&stream); 1254 else 1255 error = process->Resume (); 1256 1257 if (error.Success()) 1258 { 1259 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 1260 if (synchronous_execution) 1261 { 1262 // If any state changed events had anything to say, add that to the result 1263 if (stream.GetData()) 1264 result.AppendMessage(stream.GetData()); 1265 1266 result.SetDidChangeProcessState (true); 1267 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1268 } 1269 else 1270 { 1271 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 1272 } 1273 } 1274 else 1275 { 1276 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 1277 result.SetStatus (eReturnStatusFailed); 1278 } 1279 1280 } 1281 return result.Succeeded(); 1282 } 1283 1284 CommandOptions m_options; 1285 1286 }; 1287 1288 OptionDefinition 1289 CommandObjectThreadUntil::CommandOptions::g_option_table[] = 1290 { 1291 { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, 1292 { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, 1293 { 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"}, 1294 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1295 }; 1296 1297 1298 //------------------------------------------------------------------------- 1299 // CommandObjectThreadSelect 1300 //------------------------------------------------------------------------- 1301 1302 class CommandObjectThreadSelect : public CommandObjectParsed 1303 { 1304 public: 1305 1306 CommandObjectThreadSelect (CommandInterpreter &interpreter) : 1307 CommandObjectParsed (interpreter, 1308 "thread select", 1309 "Select a thread as the currently active thread.", 1310 NULL, 1311 eFlagRequiresProcess | 1312 eFlagTryTargetAPILock | 1313 eFlagProcessMustBeLaunched | 1314 eFlagProcessMustBePaused ) 1315 { 1316 CommandArgumentEntry arg; 1317 CommandArgumentData thread_idx_arg; 1318 1319 // Define the first (and only) variant of this arg. 1320 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1321 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1322 1323 // There is only one variant this argument could be; put it into the argument entry. 1324 arg.push_back (thread_idx_arg); 1325 1326 // Push the data for the first argument into the m_arguments vector. 1327 m_arguments.push_back (arg); 1328 } 1329 1330 1331 virtual 1332 ~CommandObjectThreadSelect () 1333 { 1334 } 1335 1336 protected: 1337 virtual bool 1338 DoExecute (Args& command, CommandReturnObject &result) 1339 { 1340 Process *process = m_exe_ctx.GetProcessPtr(); 1341 if (process == NULL) 1342 { 1343 result.AppendError ("no process"); 1344 result.SetStatus (eReturnStatusFailed); 1345 return false; 1346 } 1347 else if (command.GetArgumentCount() != 1) 1348 { 1349 result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1350 result.SetStatus (eReturnStatusFailed); 1351 return false; 1352 } 1353 1354 uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); 1355 1356 Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); 1357 if (new_thread == NULL) 1358 { 1359 result.AppendErrorWithFormat ("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); 1360 result.SetStatus (eReturnStatusFailed); 1361 return false; 1362 } 1363 1364 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1365 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1366 1367 return result.Succeeded(); 1368 } 1369 1370 }; 1371 1372 1373 //------------------------------------------------------------------------- 1374 // CommandObjectThreadList 1375 //------------------------------------------------------------------------- 1376 1377 class CommandObjectThreadList : public CommandObjectParsed 1378 { 1379 public: 1380 1381 1382 CommandObjectThreadList (CommandInterpreter &interpreter): 1383 CommandObjectParsed (interpreter, 1384 "thread list", 1385 "Show a summary of all current threads in a process.", 1386 "thread list", 1387 eFlagRequiresProcess | 1388 eFlagTryTargetAPILock | 1389 eFlagProcessMustBeLaunched | 1390 eFlagProcessMustBePaused ) 1391 { 1392 } 1393 1394 ~CommandObjectThreadList() 1395 { 1396 } 1397 1398 protected: 1399 bool 1400 DoExecute (Args& command, CommandReturnObject &result) 1401 { 1402 Stream &strm = result.GetOutputStream(); 1403 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1404 Process *process = m_exe_ctx.GetProcessPtr(); 1405 const bool only_threads_with_stop_reason = false; 1406 const uint32_t start_frame = 0; 1407 const uint32_t num_frames = 0; 1408 const uint32_t num_frames_with_source = 0; 1409 process->GetStatus(strm); 1410 process->GetThreadStatus (strm, 1411 only_threads_with_stop_reason, 1412 start_frame, 1413 num_frames, 1414 num_frames_with_source); 1415 return result.Succeeded(); 1416 } 1417 }; 1418 1419 //------------------------------------------------------------------------- 1420 // CommandObjectThreadInfo 1421 //------------------------------------------------------------------------- 1422 1423 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads 1424 { 1425 public: 1426 1427 CommandObjectThreadInfo (CommandInterpreter &interpreter) : 1428 CommandObjectIterateOverThreads (interpreter, 1429 "thread info", 1430 "Show an extended summary of information about thread(s) in a process.", 1431 "thread info", 1432 eFlagRequiresProcess | 1433 eFlagTryTargetAPILock | 1434 eFlagProcessMustBeLaunched | 1435 eFlagProcessMustBePaused), 1436 m_options (interpreter) 1437 { 1438 m_add_return = false; 1439 } 1440 1441 class CommandOptions : public Options 1442 { 1443 public: 1444 1445 CommandOptions (CommandInterpreter &interpreter) : 1446 Options (interpreter) 1447 { 1448 OptionParsingStarting (); 1449 } 1450 1451 void 1452 OptionParsingStarting () 1453 { 1454 m_json_thread = false; 1455 m_json_stopinfo = false; 1456 } 1457 1458 virtual 1459 ~CommandOptions () 1460 { 1461 } 1462 1463 virtual Error 1464 SetOptionValue (uint32_t option_idx, const char *option_arg) 1465 { 1466 const int short_option = m_getopt_table[option_idx].val; 1467 Error error; 1468 1469 switch (short_option) 1470 { 1471 case 'j': 1472 m_json_thread = true; 1473 break; 1474 1475 case 's': 1476 m_json_stopinfo = true; 1477 break; 1478 1479 default: 1480 return Error("invalid short option character '%c'", short_option); 1481 1482 } 1483 return error; 1484 } 1485 1486 const OptionDefinition* 1487 GetDefinitions () 1488 { 1489 return g_option_table; 1490 } 1491 1492 bool m_json_thread; 1493 bool m_json_stopinfo; 1494 1495 static OptionDefinition g_option_table[]; 1496 }; 1497 1498 virtual 1499 Options * 1500 GetOptions () 1501 { 1502 return &m_options; 1503 } 1504 1505 1506 virtual 1507 ~CommandObjectThreadInfo () 1508 { 1509 } 1510 1511 virtual bool 1512 HandleOneThread (Thread &thread, CommandReturnObject &result) 1513 { 1514 Stream &strm = result.GetOutputStream(); 1515 if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) 1516 { 1517 result.AppendErrorWithFormat ("error displaying info for thread: \"%d\"\n", thread.GetIndexID()); 1518 result.SetStatus (eReturnStatusFailed); 1519 return false; 1520 } 1521 return true; 1522 } 1523 1524 CommandOptions m_options; 1525 1526 }; 1527 1528 OptionDefinition 1529 CommandObjectThreadInfo::CommandOptions::g_option_table[] = 1530 { 1531 { LLDB_OPT_SET_ALL, false, "json",'j', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the thread info in JSON format."}, 1532 { LLDB_OPT_SET_ALL, false, "stop-info",'s', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display the extended stop info in JSON format."}, 1533 1534 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1535 }; 1536 1537 1538 //------------------------------------------------------------------------- 1539 // CommandObjectThreadReturn 1540 //------------------------------------------------------------------------- 1541 1542 class CommandObjectThreadReturn : public CommandObjectRaw 1543 { 1544 public: 1545 class CommandOptions : public Options 1546 { 1547 public: 1548 1549 CommandOptions (CommandInterpreter &interpreter) : 1550 Options (interpreter), 1551 m_from_expression (false) 1552 { 1553 // Keep default values of all options in one place: OptionParsingStarting () 1554 OptionParsingStarting (); 1555 } 1556 1557 virtual 1558 ~CommandOptions () 1559 { 1560 } 1561 1562 virtual Error 1563 SetOptionValue (uint32_t option_idx, const char *option_arg) 1564 { 1565 Error error; 1566 const int short_option = m_getopt_table[option_idx].val; 1567 1568 switch (short_option) 1569 { 1570 case 'x': 1571 { 1572 bool success; 1573 bool tmp_value = Args::StringToBoolean (option_arg, false, &success); 1574 if (success) 1575 m_from_expression = tmp_value; 1576 else 1577 { 1578 error.SetErrorStringWithFormat ("invalid boolean value '%s' for 'x' option", option_arg); 1579 } 1580 } 1581 break; 1582 default: 1583 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1584 break; 1585 1586 } 1587 return error; 1588 } 1589 1590 void 1591 OptionParsingStarting () 1592 { 1593 m_from_expression = false; 1594 } 1595 1596 const OptionDefinition* 1597 GetDefinitions () 1598 { 1599 return g_option_table; 1600 } 1601 1602 bool m_from_expression; 1603 1604 // Options table: Required for subclasses of Options. 1605 1606 static OptionDefinition g_option_table[]; 1607 1608 // Instance variables to hold the values for command options. 1609 }; 1610 1611 virtual 1612 Options * 1613 GetOptions () 1614 { 1615 return &m_options; 1616 } 1617 1618 CommandObjectThreadReturn (CommandInterpreter &interpreter) : 1619 CommandObjectRaw (interpreter, 1620 "thread return", 1621 "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value," 1622 " or with the -x option from the innermost function evaluation.", 1623 "thread return", 1624 eFlagRequiresFrame | 1625 eFlagTryTargetAPILock | 1626 eFlagProcessMustBeLaunched | 1627 eFlagProcessMustBePaused ), 1628 m_options (interpreter) 1629 { 1630 CommandArgumentEntry arg; 1631 CommandArgumentData expression_arg; 1632 1633 // Define the first (and only) variant of this arg. 1634 expression_arg.arg_type = eArgTypeExpression; 1635 expression_arg.arg_repetition = eArgRepeatOptional; 1636 1637 // There is only one variant this argument could be; put it into the argument entry. 1638 arg.push_back (expression_arg); 1639 1640 // Push the data for the first argument into the m_arguments vector. 1641 m_arguments.push_back (arg); 1642 1643 1644 } 1645 1646 ~CommandObjectThreadReturn() 1647 { 1648 } 1649 1650 protected: 1651 1652 bool DoExecute 1653 ( 1654 const char *command, 1655 CommandReturnObject &result 1656 ) 1657 { 1658 // I am going to handle this by hand, because I don't want you to have to say: 1659 // "thread return -- -5". 1660 if (command[0] == '-' && command[1] == 'x') 1661 { 1662 if (command && command[2] != '\0') 1663 result.AppendWarning("Return values ignored when returning from user called expressions"); 1664 1665 Thread *thread = m_exe_ctx.GetThreadPtr(); 1666 Error error; 1667 error = thread->UnwindInnermostExpression(); 1668 if (!error.Success()) 1669 { 1670 result.AppendErrorWithFormat ("Unwinding expression failed - %s.", error.AsCString()); 1671 result.SetStatus (eReturnStatusFailed); 1672 } 1673 else 1674 { 1675 bool success = thread->SetSelectedFrameByIndexNoisily (0, result.GetOutputStream()); 1676 if (success) 1677 { 1678 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ()); 1679 result.SetStatus (eReturnStatusSuccessFinishResult); 1680 } 1681 else 1682 { 1683 result.AppendErrorWithFormat ("Could not select 0th frame after unwinding expression."); 1684 result.SetStatus (eReturnStatusFailed); 1685 } 1686 } 1687 return result.Succeeded(); 1688 } 1689 1690 ValueObjectSP return_valobj_sp; 1691 1692 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1693 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1694 1695 if (frame_sp->IsInlined()) 1696 { 1697 result.AppendError("Don't know how to return from inlined frames."); 1698 result.SetStatus (eReturnStatusFailed); 1699 return false; 1700 } 1701 1702 if (command && command[0] != '\0') 1703 { 1704 Target *target = m_exe_ctx.GetTargetPtr(); 1705 EvaluateExpressionOptions options; 1706 1707 options.SetUnwindOnError(true); 1708 options.SetUseDynamic(eNoDynamicValues); 1709 1710 ExpressionResults exe_results = eExpressionSetupError; 1711 exe_results = target->EvaluateExpression (command, 1712 frame_sp.get(), 1713 return_valobj_sp, 1714 options); 1715 if (exe_results != eExpressionCompleted) 1716 { 1717 if (return_valobj_sp) 1718 result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); 1719 else 1720 result.AppendErrorWithFormat("Unknown error evaluating result expression."); 1721 result.SetStatus (eReturnStatusFailed); 1722 return false; 1723 1724 } 1725 } 1726 1727 Error error; 1728 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1729 const bool broadcast = true; 1730 error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast); 1731 if (!error.Success()) 1732 { 1733 result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); 1734 result.SetStatus (eReturnStatusFailed); 1735 return false; 1736 } 1737 1738 result.SetStatus (eReturnStatusSuccessFinishResult); 1739 return true; 1740 } 1741 1742 CommandOptions m_options; 1743 1744 }; 1745 OptionDefinition 1746 CommandObjectThreadReturn::CommandOptions::g_option_table[] = 1747 { 1748 { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, 1749 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1750 }; 1751 1752 //------------------------------------------------------------------------- 1753 // CommandObjectThreadJump 1754 //------------------------------------------------------------------------- 1755 1756 class CommandObjectThreadJump : public CommandObjectParsed 1757 { 1758 public: 1759 class CommandOptions : public Options 1760 { 1761 public: 1762 1763 CommandOptions (CommandInterpreter &interpreter) : 1764 Options (interpreter) 1765 { 1766 OptionParsingStarting (); 1767 } 1768 1769 void 1770 OptionParsingStarting () 1771 { 1772 m_filenames.Clear(); 1773 m_line_num = 0; 1774 m_line_offset = 0; 1775 m_load_addr = LLDB_INVALID_ADDRESS; 1776 m_force = false; 1777 } 1778 1779 virtual 1780 ~CommandOptions () 1781 { 1782 } 1783 1784 virtual Error 1785 SetOptionValue (uint32_t option_idx, const char *option_arg) 1786 { 1787 bool success; 1788 const int short_option = m_getopt_table[option_idx].val; 1789 Error error; 1790 1791 switch (short_option) 1792 { 1793 case 'f': 1794 m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 1795 if (m_filenames.GetSize() > 1) 1796 return Error("only one source file expected."); 1797 break; 1798 case 'l': 1799 m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success); 1800 if (!success || m_line_num == 0) 1801 return Error("invalid line number: '%s'.", option_arg); 1802 break; 1803 case 'b': 1804 m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success); 1805 if (!success) 1806 return Error("invalid line offset: '%s'.", option_arg); 1807 break; 1808 case 'a': 1809 { 1810 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 1811 m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); 1812 } 1813 break; 1814 case 'r': 1815 m_force = true; 1816 break; 1817 1818 default: 1819 return Error("invalid short option character '%c'", short_option); 1820 1821 } 1822 return error; 1823 } 1824 1825 const OptionDefinition* 1826 GetDefinitions () 1827 { 1828 return g_option_table; 1829 } 1830 1831 FileSpecList m_filenames; 1832 uint32_t m_line_num; 1833 int32_t m_line_offset; 1834 lldb::addr_t m_load_addr; 1835 bool m_force; 1836 1837 static OptionDefinition g_option_table[]; 1838 }; 1839 1840 virtual 1841 Options * 1842 GetOptions () 1843 { 1844 return &m_options; 1845 } 1846 1847 CommandObjectThreadJump (CommandInterpreter &interpreter) : 1848 CommandObjectParsed (interpreter, 1849 "thread jump", 1850 "Sets the program counter to a new address.", 1851 "thread jump", 1852 eFlagRequiresFrame | 1853 eFlagTryTargetAPILock | 1854 eFlagProcessMustBeLaunched | 1855 eFlagProcessMustBePaused ), 1856 m_options (interpreter) 1857 { 1858 } 1859 1860 ~CommandObjectThreadJump() 1861 { 1862 } 1863 1864 protected: 1865 1866 bool DoExecute (Args& args, CommandReturnObject &result) 1867 { 1868 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1869 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1870 Thread *thread = m_exe_ctx.GetThreadPtr(); 1871 Target *target = m_exe_ctx.GetTargetPtr(); 1872 const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); 1873 1874 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 1875 { 1876 // Use this address directly. 1877 Address dest = Address(m_options.m_load_addr); 1878 1879 lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); 1880 if (callAddr == LLDB_INVALID_ADDRESS) 1881 { 1882 result.AppendErrorWithFormat ("Invalid destination address."); 1883 result.SetStatus (eReturnStatusFailed); 1884 return false; 1885 } 1886 1887 if (!reg_ctx->SetPC (callAddr)) 1888 { 1889 result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); 1890 result.SetStatus (eReturnStatusFailed); 1891 return false; 1892 } 1893 } 1894 else 1895 { 1896 // Pick either the absolute line, or work out a relative one. 1897 int32_t line = (int32_t)m_options.m_line_num; 1898 if (line == 0) 1899 line = sym_ctx.line_entry.line + m_options.m_line_offset; 1900 1901 // Try the current file, but override if asked. 1902 FileSpec file = sym_ctx.line_entry.file; 1903 if (m_options.m_filenames.GetSize() == 1) 1904 file = m_options.m_filenames.GetFileSpecAtIndex(0); 1905 1906 if (!file) 1907 { 1908 result.AppendErrorWithFormat ("No source file available for the current location."); 1909 result.SetStatus (eReturnStatusFailed); 1910 return false; 1911 } 1912 1913 std::string warnings; 1914 Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); 1915 1916 if (err.Fail()) 1917 { 1918 result.SetError (err); 1919 return false; 1920 } 1921 1922 if (!warnings.empty()) 1923 result.AppendWarning (warnings.c_str()); 1924 } 1925 1926 result.SetStatus (eReturnStatusSuccessFinishResult); 1927 return true; 1928 } 1929 1930 CommandOptions m_options; 1931 }; 1932 OptionDefinition 1933 CommandObjectThreadJump::CommandOptions::g_option_table[] = 1934 { 1935 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 1936 "Specifies the source file to jump to."}, 1937 1938 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLineNum, 1939 "Specifies the line number to jump to."}, 1940 1941 { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, 1942 "Jumps by a relative line offset from the current line."}, 1943 1944 { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, 1945 "Jumps to a specific address."}, 1946 1947 { LLDB_OPT_SET_1| 1948 LLDB_OPT_SET_2| 1949 LLDB_OPT_SET_3, false, "force",'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,"Allows the PC to leave the current function."}, 1950 1951 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1952 }; 1953 1954 //------------------------------------------------------------------------- 1955 // Next are the subcommands of CommandObjectMultiwordThreadPlan 1956 //------------------------------------------------------------------------- 1957 1958 1959 //------------------------------------------------------------------------- 1960 // CommandObjectThreadPlanList 1961 //------------------------------------------------------------------------- 1962 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads 1963 { 1964 public: 1965 1966 class CommandOptions : public Options 1967 { 1968 public: 1969 1970 CommandOptions (CommandInterpreter &interpreter) : 1971 Options(interpreter) 1972 { 1973 // Keep default values of all options in one place: OptionParsingStarting () 1974 OptionParsingStarting (); 1975 } 1976 1977 virtual 1978 ~CommandOptions () 1979 { 1980 } 1981 1982 virtual Error 1983 SetOptionValue (uint32_t option_idx, const char *option_arg) 1984 { 1985 Error error; 1986 const int short_option = m_getopt_table[option_idx].val; 1987 1988 switch (short_option) 1989 { 1990 case 'i': 1991 { 1992 m_internal = true; 1993 } 1994 break; 1995 case 'v': 1996 { 1997 m_verbose = true; 1998 } 1999 break; 2000 default: 2001 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 2002 break; 2003 2004 } 2005 return error; 2006 } 2007 2008 void 2009 OptionParsingStarting () 2010 { 2011 m_verbose = false; 2012 m_internal = false; 2013 } 2014 2015 const OptionDefinition* 2016 GetDefinitions () 2017 { 2018 return g_option_table; 2019 } 2020 2021 // Options table: Required for subclasses of Options. 2022 2023 static OptionDefinition g_option_table[]; 2024 2025 // Instance variables to hold the values for command options. 2026 bool m_verbose; 2027 bool m_internal; 2028 }; 2029 2030 CommandObjectThreadPlanList (CommandInterpreter &interpreter) : 2031 CommandObjectIterateOverThreads (interpreter, 2032 "thread plan list", 2033 "Show thread plans for one or more threads. If no threads are specified, show the " 2034 "currently selected thread. Use the thread-index \"all\" to see all threads.", 2035 NULL, 2036 eFlagRequiresProcess | 2037 eFlagRequiresThread | 2038 eFlagTryTargetAPILock | 2039 eFlagProcessMustBeLaunched | 2040 eFlagProcessMustBePaused ), 2041 m_options(interpreter) 2042 { 2043 } 2044 2045 ~CommandObjectThreadPlanList () 2046 { 2047 } 2048 2049 virtual Options * 2050 GetOptions () 2051 { 2052 return &m_options; 2053 } 2054 2055 protected: 2056 virtual bool 2057 HandleOneThread (Thread &thread, CommandReturnObject &result) 2058 { 2059 Stream &strm = result.GetOutputStream(); 2060 DescriptionLevel desc_level = eDescriptionLevelFull; 2061 if (m_options.m_verbose) 2062 desc_level = eDescriptionLevelVerbose; 2063 2064 thread.DumpThreadPlans (&strm, desc_level, m_options.m_internal, true); 2065 return true; 2066 } 2067 CommandOptions m_options; 2068 }; 2069 2070 OptionDefinition 2071 CommandObjectThreadPlanList::CommandOptions::g_option_table[] = 2072 { 2073 { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display more information about the thread plans"}, 2074 { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display internal as well as user thread plans"}, 2075 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2076 }; 2077 2078 class CommandObjectThreadPlanDiscard : public CommandObjectParsed 2079 { 2080 public: 2081 CommandObjectThreadPlanDiscard (CommandInterpreter &interpreter) : 2082 CommandObjectParsed (interpreter, 2083 "thread plan discard", 2084 "Discards thread plans up to and including the plan passed as the command argument." 2085 "Only user visible plans can be discarded, use the index from \"thread plan list\"" 2086 " without the \"-i\" argument.", 2087 NULL, 2088 eFlagRequiresProcess | 2089 eFlagRequiresThread | 2090 eFlagTryTargetAPILock | 2091 eFlagProcessMustBeLaunched | 2092 eFlagProcessMustBePaused ) 2093 { 2094 CommandArgumentEntry arg; 2095 CommandArgumentData plan_index_arg; 2096 2097 // Define the first (and only) variant of this arg. 2098 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 2099 plan_index_arg.arg_repetition = eArgRepeatPlain; 2100 2101 // There is only one variant this argument could be; put it into the argument entry. 2102 arg.push_back (plan_index_arg); 2103 2104 // Push the data for the first argument into the m_arguments vector. 2105 m_arguments.push_back (arg); 2106 } 2107 2108 virtual ~CommandObjectThreadPlanDiscard () {} 2109 2110 bool 2111 DoExecute (Args& args, CommandReturnObject &result) 2112 { 2113 Thread *thread = m_exe_ctx.GetThreadPtr(); 2114 if (args.GetArgumentCount() != 1) 2115 { 2116 result.AppendErrorWithFormat("Too many arguments, expected one - the thread plan index - but got %zu.", 2117 args.GetArgumentCount()); 2118 result.SetStatus (eReturnStatusFailed); 2119 return false; 2120 } 2121 2122 bool success; 2123 uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); 2124 if (!success) 2125 { 2126 result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", 2127 args.GetArgumentAtIndex(0)); 2128 result.SetStatus (eReturnStatusFailed); 2129 return false; 2130 } 2131 2132 if (thread_plan_idx == 0) 2133 { 2134 result.AppendErrorWithFormat("You wouldn't really want me to discard the base thread plan."); 2135 result.SetStatus (eReturnStatusFailed); 2136 return false; 2137 } 2138 2139 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) 2140 { 2141 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2142 return true; 2143 } 2144 else 2145 { 2146 result.AppendErrorWithFormat("Could not find User thread plan with index %s.", 2147 args.GetArgumentAtIndex(0)); 2148 result.SetStatus (eReturnStatusFailed); 2149 return false; 2150 } 2151 } 2152 }; 2153 2154 //------------------------------------------------------------------------- 2155 // CommandObjectMultiwordThreadPlan 2156 //------------------------------------------------------------------------- 2157 2158 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword 2159 { 2160 public: 2161 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : 2162 CommandObjectMultiword (interpreter, 2163 "plan", 2164 "A set of subcommands for accessing the thread plans controlling execution control on one or more threads.", 2165 "thread plan <subcommand> [<subcommand objects]") 2166 { 2167 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadPlanList (interpreter))); 2168 LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); 2169 } 2170 2171 virtual ~CommandObjectMultiwordThreadPlan () {} 2172 2173 2174 }; 2175 2176 //------------------------------------------------------------------------- 2177 // CommandObjectMultiwordThread 2178 //------------------------------------------------------------------------- 2179 2180 CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &interpreter) : 2181 CommandObjectMultiword (interpreter, 2182 "thread", 2183 "A set of commands for operating on one or more threads within a running process.", 2184 "thread <subcommand> [<subcommand-options>]") 2185 { 2186 LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter))); 2187 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter))); 2188 LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter))); 2189 LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter))); 2190 LoadSubCommand ("jump", CommandObjectSP (new CommandObjectThreadJump (interpreter))); 2191 LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter))); 2192 LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter))); 2193 LoadSubCommand ("info", CommandObjectSP (new CommandObjectThreadInfo (interpreter))); 2194 LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2195 interpreter, 2196 "thread step-in", 2197 "Source level single step in specified thread (current thread, if none specified).", 2198 NULL, 2199 eStepTypeInto, 2200 eStepScopeSource))); 2201 2202 LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2203 interpreter, 2204 "thread step-out", 2205 "Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).", 2206 NULL, 2207 eStepTypeOut, 2208 eStepScopeSource))); 2209 2210 LoadSubCommand ("step-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2211 interpreter, 2212 "thread step-over", 2213 "Source level single step in specified thread (current thread, if none specified), stepping over calls.", 2214 NULL, 2215 eStepTypeOver, 2216 eStepScopeSource))); 2217 2218 LoadSubCommand ("step-inst", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2219 interpreter, 2220 "thread step-inst", 2221 "Single step one instruction in specified thread (current thread, if none specified).", 2222 NULL, 2223 eStepTypeTrace, 2224 eStepScopeInstruction))); 2225 2226 LoadSubCommand ("step-inst-over", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2227 interpreter, 2228 "thread step-inst-over", 2229 "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.", 2230 NULL, 2231 eStepTypeTraceOver, 2232 eStepScopeInstruction))); 2233 2234 LoadSubCommand ("step-scripted", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ( 2235 interpreter, 2236 "thread step-scripted", 2237 "Step as instructed by the script class passed in the -C option.", 2238 NULL, 2239 eStepTypeScripted, 2240 eStepScopeSource))); 2241 2242 LoadSubCommand ("plan", CommandObjectSP (new CommandObjectMultiwordThreadPlan(interpreter))); 2243 } 2244 2245 CommandObjectMultiwordThread::~CommandObjectMultiwordThread () 2246 { 2247 } 2248 2249 2250