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