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