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