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