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