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