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