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