1 //===-- CommandObjectThread.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CommandObjectThread.h" 10 11 #include <memory> 12 #include <sstream> 13 14 #include "CommandObjectThreadUtil.h" 15 #include "CommandObjectTrace.h" 16 #include "lldb/Core/PluginManager.h" 17 #include "lldb/Core/ValueObject.h" 18 #include "lldb/Host/OptionParser.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandOptionArgumentTable.h" 21 #include "lldb/Interpreter/CommandReturnObject.h" 22 #include "lldb/Interpreter/OptionArgParser.h" 23 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Symbol/CompileUnit.h" 26 #include "lldb/Symbol/Function.h" 27 #include "lldb/Symbol/LineEntry.h" 28 #include "lldb/Symbol/LineTable.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/ThreadPlanStepInRange.h" 36 #include "lldb/Target/Trace.h" 37 #include "lldb/Target/TraceDumper.h" 38 #include "lldb/Utility/State.h" 39 40 using namespace lldb; 41 using namespace lldb_private; 42 43 // CommandObjectThreadBacktrace 44 #define LLDB_OPTIONS_thread_backtrace 45 #include "CommandOptions.inc" 46 47 class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { 48 public: 49 class CommandOptions : public Options { 50 public: 51 CommandOptions() { 52 // Keep default values of all options in one place: OptionParsingStarting 53 // () 54 OptionParsingStarting(nullptr); 55 } 56 57 ~CommandOptions() override = default; 58 59 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 60 ExecutionContext *execution_context) override { 61 Status error; 62 const int short_option = m_getopt_table[option_idx].val; 63 64 switch (short_option) { 65 case 'c': 66 if (option_arg.getAsInteger(0, m_count)) { 67 m_count = UINT32_MAX; 68 error.SetErrorStringWithFormat( 69 "invalid integer value for option '%c'", short_option); 70 } 71 break; 72 case 's': 73 if (option_arg.getAsInteger(0, m_start)) 74 error.SetErrorStringWithFormat( 75 "invalid integer value for option '%c'", short_option); 76 break; 77 case 'e': { 78 bool success; 79 m_extended_backtrace = 80 OptionArgParser::ToBoolean(option_arg, false, &success); 81 if (!success) 82 error.SetErrorStringWithFormat( 83 "invalid boolean value for option '%c'", short_option); 84 } break; 85 default: 86 llvm_unreachable("Unimplemented option"); 87 } 88 return error; 89 } 90 91 void OptionParsingStarting(ExecutionContext *execution_context) override { 92 m_count = UINT32_MAX; 93 m_start = 0; 94 m_extended_backtrace = false; 95 } 96 97 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 98 return llvm::makeArrayRef(g_thread_backtrace_options); 99 } 100 101 // Instance variables to hold the values for command options. 102 uint32_t m_count; 103 uint32_t m_start; 104 bool m_extended_backtrace; 105 }; 106 107 CommandObjectThreadBacktrace(CommandInterpreter &interpreter) 108 : CommandObjectIterateOverThreads( 109 interpreter, "thread backtrace", 110 "Show thread call stacks. Defaults to the current thread, thread " 111 "indexes can be specified as arguments.\n" 112 "Use the thread-index \"all\" to see all threads.\n" 113 "Use the thread-index \"unique\" to see threads grouped by unique " 114 "call stacks.\n" 115 "Use 'settings set frame-format' to customize the printing of " 116 "frames in the backtrace and 'settings set thread-format' to " 117 "customize the thread header.", 118 nullptr, 119 eCommandRequiresProcess | eCommandRequiresThread | 120 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 121 eCommandProcessMustBePaused) {} 122 123 ~CommandObjectThreadBacktrace() override = default; 124 125 Options *GetOptions() override { return &m_options; } 126 127 llvm::Optional<std::string> GetRepeatCommand(Args ¤t_args, 128 uint32_t idx) override { 129 llvm::StringRef count_opt("--count"); 130 llvm::StringRef start_opt("--start"); 131 132 // If no "count" was provided, we are dumping the entire backtrace, so 133 // there isn't a repeat command. So we search for the count option in 134 // the args, and if we find it, we make a copy and insert or modify the 135 // start option's value to start count indices greater. 136 137 Args copy_args(current_args); 138 size_t num_entries = copy_args.GetArgumentCount(); 139 // These two point at the index of the option value if found. 140 size_t count_idx = 0; 141 size_t start_idx = 0; 142 size_t count_val = 0; 143 size_t start_val = 0; 144 145 for (size_t idx = 0; idx < num_entries; idx++) { 146 llvm::StringRef arg_string = copy_args[idx].ref(); 147 if (arg_string.equals("-c") || count_opt.startswith(arg_string)) { 148 idx++; 149 if (idx == num_entries) 150 return llvm::None; 151 count_idx = idx; 152 if (copy_args[idx].ref().getAsInteger(0, count_val)) 153 return llvm::None; 154 } else if (arg_string.equals("-s") || start_opt.startswith(arg_string)) { 155 idx++; 156 if (idx == num_entries) 157 return llvm::None; 158 start_idx = idx; 159 if (copy_args[idx].ref().getAsInteger(0, start_val)) 160 return llvm::None; 161 } 162 } 163 if (count_idx == 0) 164 return llvm::None; 165 166 std::string new_start_val = llvm::formatv("{0}", start_val + count_val); 167 if (start_idx == 0) { 168 copy_args.AppendArgument(start_opt); 169 copy_args.AppendArgument(new_start_val); 170 } else { 171 copy_args.ReplaceArgumentAtIndex(start_idx, new_start_val); 172 } 173 std::string repeat_command; 174 if (!copy_args.GetQuotedCommandString(repeat_command)) 175 return llvm::None; 176 return repeat_command; 177 } 178 179 protected: 180 void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) { 181 SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); 182 if (runtime) { 183 Stream &strm = result.GetOutputStream(); 184 const std::vector<ConstString> &types = 185 runtime->GetExtendedBacktraceTypes(); 186 for (auto type : types) { 187 ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread( 188 thread->shared_from_this(), type); 189 if (ext_thread_sp && ext_thread_sp->IsValid()) { 190 const uint32_t num_frames_with_source = 0; 191 const bool stop_format = false; 192 if (ext_thread_sp->GetStatus(strm, m_options.m_start, 193 m_options.m_count, 194 num_frames_with_source, stop_format)) { 195 DoExtendedBacktrace(ext_thread_sp.get(), result); 196 } 197 } 198 } 199 } 200 } 201 202 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 203 ThreadSP thread_sp = 204 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 205 if (!thread_sp) { 206 result.AppendErrorWithFormat( 207 "thread disappeared while computing backtraces: 0x%" PRIx64 "\n", 208 tid); 209 return false; 210 } 211 212 Thread *thread = thread_sp.get(); 213 214 Stream &strm = result.GetOutputStream(); 215 216 // Only dump stack info if we processing unique stacks. 217 const bool only_stacks = m_unique_stacks; 218 219 // Don't show source context when doing backtraces. 220 const uint32_t num_frames_with_source = 0; 221 const bool stop_format = true; 222 if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count, 223 num_frames_with_source, stop_format, only_stacks)) { 224 result.AppendErrorWithFormat( 225 "error displaying backtrace for thread: \"0x%4.4x\"\n", 226 thread->GetIndexID()); 227 return false; 228 } 229 if (m_options.m_extended_backtrace) { 230 DoExtendedBacktrace(thread, result); 231 } 232 233 return true; 234 } 235 236 CommandOptions m_options; 237 }; 238 239 enum StepScope { eStepScopeSource, eStepScopeInstruction }; 240 241 #define LLDB_OPTIONS_thread_step_scope 242 #include "CommandOptions.inc" 243 244 class ThreadStepScopeOptionGroup : public OptionGroup { 245 public: 246 ThreadStepScopeOptionGroup() { 247 // Keep default values of all options in one place: OptionParsingStarting 248 // () 249 OptionParsingStarting(nullptr); 250 } 251 252 ~ThreadStepScopeOptionGroup() override = default; 253 254 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 255 return llvm::makeArrayRef(g_thread_step_scope_options); 256 } 257 258 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 259 ExecutionContext *execution_context) override { 260 Status error; 261 const int short_option = 262 g_thread_step_scope_options[option_idx].short_option; 263 264 switch (short_option) { 265 case 'a': { 266 bool success; 267 bool avoid_no_debug = 268 OptionArgParser::ToBoolean(option_arg, true, &success); 269 if (!success) 270 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", 271 short_option); 272 else { 273 m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 274 } 275 } break; 276 277 case 'A': { 278 bool success; 279 bool avoid_no_debug = 280 OptionArgParser::ToBoolean(option_arg, true, &success); 281 if (!success) 282 error.SetErrorStringWithFormat("invalid boolean value for option '%c'", 283 short_option); 284 else { 285 m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; 286 } 287 } break; 288 289 case 'c': 290 if (option_arg.getAsInteger(0, m_step_count)) 291 error.SetErrorStringWithFormat("invalid step count '%s'", 292 option_arg.str().c_str()); 293 break; 294 295 case 'm': { 296 auto enum_values = GetDefinitions()[option_idx].enum_values; 297 m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( 298 option_arg, enum_values, eOnlyDuringStepping, error); 299 } break; 300 301 case 'e': 302 if (option_arg == "block") { 303 m_end_line_is_block_end = true; 304 break; 305 } 306 if (option_arg.getAsInteger(0, m_end_line)) 307 error.SetErrorStringWithFormat("invalid end line number '%s'", 308 option_arg.str().c_str()); 309 break; 310 311 case 'r': 312 m_avoid_regexp.clear(); 313 m_avoid_regexp.assign(std::string(option_arg)); 314 break; 315 316 case 't': 317 m_step_in_target.clear(); 318 m_step_in_target.assign(std::string(option_arg)); 319 break; 320 321 default: 322 llvm_unreachable("Unimplemented option"); 323 } 324 return error; 325 } 326 327 void OptionParsingStarting(ExecutionContext *execution_context) override { 328 m_step_in_avoid_no_debug = eLazyBoolCalculate; 329 m_step_out_avoid_no_debug = eLazyBoolCalculate; 330 m_run_mode = eOnlyDuringStepping; 331 332 // Check if we are in Non-Stop mode 333 TargetSP target_sp = 334 execution_context ? execution_context->GetTargetSP() : TargetSP(); 335 ProcessSP process_sp = 336 execution_context ? execution_context->GetProcessSP() : ProcessSP(); 337 if (process_sp && process_sp->GetSteppingRunsAllThreads()) 338 m_run_mode = eAllThreads; 339 340 m_avoid_regexp.clear(); 341 m_step_in_target.clear(); 342 m_step_count = 1; 343 m_end_line = LLDB_INVALID_LINE_NUMBER; 344 m_end_line_is_block_end = false; 345 } 346 347 // Instance variables to hold the values for command options. 348 LazyBool m_step_in_avoid_no_debug; 349 LazyBool m_step_out_avoid_no_debug; 350 RunMode m_run_mode; 351 std::string m_avoid_regexp; 352 std::string m_step_in_target; 353 uint32_t m_step_count; 354 uint32_t m_end_line; 355 bool m_end_line_is_block_end; 356 }; 357 358 class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { 359 public: 360 CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, 361 const char *name, const char *help, 362 const char *syntax, 363 StepType step_type, 364 StepScope step_scope) 365 : CommandObjectParsed(interpreter, name, help, syntax, 366 eCommandRequiresProcess | eCommandRequiresThread | 367 eCommandTryTargetAPILock | 368 eCommandProcessMustBeLaunched | 369 eCommandProcessMustBePaused), 370 m_step_type(step_type), m_step_scope(step_scope), 371 m_class_options("scripted step") { 372 CommandArgumentEntry arg; 373 CommandArgumentData thread_id_arg; 374 375 // Define the first (and only) variant of this arg. 376 thread_id_arg.arg_type = eArgTypeThreadID; 377 thread_id_arg.arg_repetition = eArgRepeatOptional; 378 379 // There is only one variant this argument could be; put it into the 380 // argument entry. 381 arg.push_back(thread_id_arg); 382 383 // Push the data for the first argument into the m_arguments vector. 384 m_arguments.push_back(arg); 385 386 if (step_type == eStepTypeScripted) { 387 m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2, 388 LLDB_OPT_SET_1); 389 } 390 m_all_options.Append(&m_options); 391 m_all_options.Finalize(); 392 } 393 394 ~CommandObjectThreadStepWithTypeAndScope() override = default; 395 396 void 397 HandleArgumentCompletion(CompletionRequest &request, 398 OptionElementVector &opt_element_vector) override { 399 if (request.GetCursorIndex()) 400 return; 401 402 CommandCompletions::InvokeCommonCompletionCallbacks( 403 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 404 request, nullptr); 405 } 406 407 Options *GetOptions() override { return &m_all_options; } 408 409 protected: 410 bool DoExecute(Args &command, CommandReturnObject &result) override { 411 Process *process = m_exe_ctx.GetProcessPtr(); 412 bool synchronous_execution = m_interpreter.GetSynchronous(); 413 414 const uint32_t num_threads = process->GetThreadList().GetSize(); 415 Thread *thread = nullptr; 416 417 if (command.GetArgumentCount() == 0) { 418 thread = GetDefaultThread(); 419 420 if (thread == nullptr) { 421 result.AppendError("no selected thread in process"); 422 return false; 423 } 424 } else { 425 const char *thread_idx_cstr = command.GetArgumentAtIndex(0); 426 uint32_t step_thread_idx; 427 428 if (!llvm::to_integer(thread_idx_cstr, step_thread_idx)) { 429 result.AppendErrorWithFormat("invalid thread index '%s'.\n", 430 thread_idx_cstr); 431 return false; 432 } 433 thread = 434 process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); 435 if (thread == nullptr) { 436 result.AppendErrorWithFormat( 437 "Thread index %u is out of range (valid values are 0 - %u).\n", 438 step_thread_idx, num_threads); 439 return false; 440 } 441 } 442 443 if (m_step_type == eStepTypeScripted) { 444 if (m_class_options.GetName().empty()) { 445 result.AppendErrorWithFormat("empty class name for scripted step."); 446 return false; 447 } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( 448 m_class_options.GetName().c_str())) { 449 result.AppendErrorWithFormat( 450 "class for scripted step: \"%s\" does not exist.", 451 m_class_options.GetName().c_str()); 452 return false; 453 } 454 } 455 456 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER && 457 m_step_type != eStepTypeInto) { 458 result.AppendErrorWithFormat( 459 "end line option is only valid for step into"); 460 return false; 461 } 462 463 const bool abort_other_plans = false; 464 const lldb::RunMode stop_other_threads = m_options.m_run_mode; 465 466 // This is a bit unfortunate, but not all the commands in this command 467 // object support only while stepping, so I use the bool for them. 468 bool bool_stop_other_threads; 469 if (m_options.m_run_mode == eAllThreads) 470 bool_stop_other_threads = false; 471 else if (m_options.m_run_mode == eOnlyDuringStepping) 472 bool_stop_other_threads = (m_step_type != eStepTypeOut); 473 else 474 bool_stop_other_threads = true; 475 476 ThreadPlanSP new_plan_sp; 477 Status new_plan_status; 478 479 if (m_step_type == eStepTypeInto) { 480 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 481 assert(frame != nullptr); 482 483 if (frame->HasDebugInformation()) { 484 AddressRange range; 485 SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); 486 if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) { 487 Status error; 488 if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, 489 error)) { 490 result.AppendErrorWithFormat("invalid end-line option: %s.", 491 error.AsCString()); 492 return false; 493 } 494 } else if (m_options.m_end_line_is_block_end) { 495 Status error; 496 Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; 497 if (!block) { 498 result.AppendErrorWithFormat("Could not find the current block."); 499 return false; 500 } 501 502 AddressRange block_range; 503 Address pc_address = frame->GetFrameCodeAddress(); 504 block->GetRangeContainingAddress(pc_address, block_range); 505 if (!block_range.GetBaseAddress().IsValid()) { 506 result.AppendErrorWithFormat( 507 "Could not find the current block address."); 508 return false; 509 } 510 lldb::addr_t pc_offset_in_block = 511 pc_address.GetFileAddress() - 512 block_range.GetBaseAddress().GetFileAddress(); 513 lldb::addr_t range_length = 514 block_range.GetByteSize() - pc_offset_in_block; 515 range = AddressRange(pc_address, range_length); 516 } else { 517 range = sc.line_entry.range; 518 } 519 520 new_plan_sp = thread->QueueThreadPlanForStepInRange( 521 abort_other_plans, range, 522 frame->GetSymbolContext(eSymbolContextEverything), 523 m_options.m_step_in_target.c_str(), stop_other_threads, 524 new_plan_status, m_options.m_step_in_avoid_no_debug, 525 m_options.m_step_out_avoid_no_debug); 526 527 if (new_plan_sp && !m_options.m_avoid_regexp.empty()) { 528 ThreadPlanStepInRange *step_in_range_plan = 529 static_cast<ThreadPlanStepInRange *>(new_plan_sp.get()); 530 step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); 531 } 532 } else 533 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 534 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 535 } else if (m_step_type == eStepTypeOver) { 536 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 537 538 if (frame->HasDebugInformation()) 539 new_plan_sp = thread->QueueThreadPlanForStepOverRange( 540 abort_other_plans, 541 frame->GetSymbolContext(eSymbolContextEverything).line_entry, 542 frame->GetSymbolContext(eSymbolContextEverything), 543 stop_other_threads, new_plan_status, 544 m_options.m_step_out_avoid_no_debug); 545 else 546 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 547 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 548 } else if (m_step_type == eStepTypeTrace) { 549 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 550 false, abort_other_plans, bool_stop_other_threads, new_plan_status); 551 } else if (m_step_type == eStepTypeTraceOver) { 552 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( 553 true, abort_other_plans, bool_stop_other_threads, new_plan_status); 554 } else if (m_step_type == eStepTypeOut) { 555 new_plan_sp = thread->QueueThreadPlanForStepOut( 556 abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, 557 eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status, 558 m_options.m_step_out_avoid_no_debug); 559 } else if (m_step_type == eStepTypeScripted) { 560 new_plan_sp = thread->QueueThreadPlanForStepScripted( 561 abort_other_plans, m_class_options.GetName().c_str(), 562 m_class_options.GetStructuredData(), bool_stop_other_threads, 563 new_plan_status); 564 } else { 565 result.AppendError("step type is not supported"); 566 return false; 567 } 568 569 // If we got a new plan, then set it to be a controlling plan (User level 570 // Plans should be controlling plans so that they can be interruptible). 571 // Then resume the process. 572 573 if (new_plan_sp) { 574 new_plan_sp->SetIsControllingPlan(true); 575 new_plan_sp->SetOkayToDiscard(false); 576 577 if (m_options.m_step_count > 1) { 578 if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) { 579 result.AppendWarning( 580 "step operation does not support iteration count."); 581 } 582 } 583 584 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 585 586 const uint32_t iohandler_id = process->GetIOHandlerID(); 587 588 StreamString stream; 589 Status error; 590 if (synchronous_execution) 591 error = process->ResumeSynchronous(&stream); 592 else 593 error = process->Resume(); 594 595 if (!error.Success()) { 596 result.AppendMessage(error.AsCString()); 597 return false; 598 } 599 600 // There is a race condition where this thread will return up the call 601 // stack to the main command handler and show an (lldb) prompt before 602 // HandlePrivateEvent (from PrivateStateThread) has a chance to call 603 // PushProcessIOHandler(). 604 process->SyncIOHandler(iohandler_id, std::chrono::seconds(2)); 605 606 if (synchronous_execution) { 607 // If any state changed events had anything to say, add that to the 608 // result 609 if (stream.GetSize() > 0) 610 result.AppendMessage(stream.GetString()); 611 612 process->GetThreadList().SetSelectedThreadByID(thread->GetID()); 613 result.SetDidChangeProcessState(true); 614 result.SetStatus(eReturnStatusSuccessFinishNoResult); 615 } else { 616 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 617 } 618 } else { 619 result.SetError(new_plan_status); 620 } 621 return result.Succeeded(); 622 } 623 624 StepType m_step_type; 625 StepScope m_step_scope; 626 ThreadStepScopeOptionGroup m_options; 627 OptionGroupPythonClassWithDict m_class_options; 628 OptionGroupOptions m_all_options; 629 }; 630 631 // CommandObjectThreadContinue 632 633 class CommandObjectThreadContinue : public CommandObjectParsed { 634 public: 635 CommandObjectThreadContinue(CommandInterpreter &interpreter) 636 : CommandObjectParsed( 637 interpreter, "thread continue", 638 "Continue execution of the current target process. One " 639 "or more threads may be specified, by default all " 640 "threads continue.", 641 nullptr, 642 eCommandRequiresThread | eCommandTryTargetAPILock | 643 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 644 CommandArgumentEntry arg; 645 CommandArgumentData thread_idx_arg; 646 647 // Define the first (and only) variant of this arg. 648 thread_idx_arg.arg_type = eArgTypeThreadIndex; 649 thread_idx_arg.arg_repetition = eArgRepeatPlus; 650 651 // There is only one variant this argument could be; put it into the 652 // argument entry. 653 arg.push_back(thread_idx_arg); 654 655 // Push the data for the first argument into the m_arguments vector. 656 m_arguments.push_back(arg); 657 } 658 659 ~CommandObjectThreadContinue() override = default; 660 661 void 662 HandleArgumentCompletion(CompletionRequest &request, 663 OptionElementVector &opt_element_vector) override { 664 CommandCompletions::InvokeCommonCompletionCallbacks( 665 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 666 request, nullptr); 667 } 668 669 bool DoExecute(Args &command, CommandReturnObject &result) override { 670 bool synchronous_execution = m_interpreter.GetSynchronous(); 671 672 Process *process = m_exe_ctx.GetProcessPtr(); 673 if (process == nullptr) { 674 result.AppendError("no process exists. Cannot continue"); 675 return false; 676 } 677 678 StateType state = process->GetState(); 679 if ((state == eStateCrashed) || (state == eStateStopped) || 680 (state == eStateSuspended)) { 681 const size_t argc = command.GetArgumentCount(); 682 if (argc > 0) { 683 // These two lines appear at the beginning of both blocks in this 684 // if..else, but that is because we need to release the lock before 685 // calling process->Resume below. 686 std::lock_guard<std::recursive_mutex> guard( 687 process->GetThreadList().GetMutex()); 688 const uint32_t num_threads = process->GetThreadList().GetSize(); 689 std::vector<Thread *> resume_threads; 690 for (auto &entry : command.entries()) { 691 uint32_t thread_idx; 692 if (entry.ref().getAsInteger(0, thread_idx)) { 693 result.AppendErrorWithFormat( 694 "invalid thread index argument: \"%s\".\n", entry.c_str()); 695 return false; 696 } 697 Thread *thread = 698 process->GetThreadList().FindThreadByIndexID(thread_idx).get(); 699 700 if (thread) { 701 resume_threads.push_back(thread); 702 } else { 703 result.AppendErrorWithFormat("invalid thread index %u.\n", 704 thread_idx); 705 return false; 706 } 707 } 708 709 if (resume_threads.empty()) { 710 result.AppendError("no valid thread indexes were specified"); 711 return false; 712 } else { 713 if (resume_threads.size() == 1) 714 result.AppendMessageWithFormat("Resuming thread: "); 715 else 716 result.AppendMessageWithFormat("Resuming threads: "); 717 718 for (uint32_t idx = 0; idx < num_threads; ++idx) { 719 Thread *thread = 720 process->GetThreadList().GetThreadAtIndex(idx).get(); 721 std::vector<Thread *>::iterator this_thread_pos = 722 find(resume_threads.begin(), resume_threads.end(), thread); 723 724 if (this_thread_pos != resume_threads.end()) { 725 resume_threads.erase(this_thread_pos); 726 if (!resume_threads.empty()) 727 result.AppendMessageWithFormat("%u, ", thread->GetIndexID()); 728 else 729 result.AppendMessageWithFormat("%u ", thread->GetIndexID()); 730 731 const bool override_suspend = true; 732 thread->SetResumeState(eStateRunning, override_suspend); 733 } else { 734 thread->SetResumeState(eStateSuspended); 735 } 736 } 737 result.AppendMessageWithFormat("in process %" PRIu64 "\n", 738 process->GetID()); 739 } 740 } else { 741 // These two lines appear at the beginning of both blocks in this 742 // if..else, but that is because we need to release the lock before 743 // calling process->Resume below. 744 std::lock_guard<std::recursive_mutex> guard( 745 process->GetThreadList().GetMutex()); 746 const uint32_t num_threads = process->GetThreadList().GetSize(); 747 Thread *current_thread = GetDefaultThread(); 748 if (current_thread == nullptr) { 749 result.AppendError("the process doesn't have a current thread"); 750 return false; 751 } 752 // Set the actions that the threads should each take when resuming 753 for (uint32_t idx = 0; idx < num_threads; ++idx) { 754 Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); 755 if (thread == current_thread) { 756 result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64 757 " in process %" PRIu64 "\n", 758 thread->GetID(), process->GetID()); 759 const bool override_suspend = true; 760 thread->SetResumeState(eStateRunning, override_suspend); 761 } else { 762 thread->SetResumeState(eStateSuspended); 763 } 764 } 765 } 766 767 StreamString stream; 768 Status error; 769 if (synchronous_execution) 770 error = process->ResumeSynchronous(&stream); 771 else 772 error = process->Resume(); 773 774 // We should not be holding the thread list lock when we do this. 775 if (error.Success()) { 776 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 777 process->GetID()); 778 if (synchronous_execution) { 779 // If any state changed events had anything to say, add that to the 780 // result 781 if (stream.GetSize() > 0) 782 result.AppendMessage(stream.GetString()); 783 784 result.SetDidChangeProcessState(true); 785 result.SetStatus(eReturnStatusSuccessFinishNoResult); 786 } else { 787 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 788 } 789 } else { 790 result.AppendErrorWithFormat("Failed to resume process: %s\n", 791 error.AsCString()); 792 } 793 } else { 794 result.AppendErrorWithFormat( 795 "Process cannot be continued from its current state (%s).\n", 796 StateAsCString(state)); 797 } 798 799 return result.Succeeded(); 800 } 801 }; 802 803 // CommandObjectThreadUntil 804 805 #define LLDB_OPTIONS_thread_until 806 #include "CommandOptions.inc" 807 808 class CommandObjectThreadUntil : public CommandObjectParsed { 809 public: 810 class CommandOptions : public Options { 811 public: 812 uint32_t m_thread_idx = LLDB_INVALID_THREAD_ID; 813 uint32_t m_frame_idx = LLDB_INVALID_FRAME_ID; 814 815 CommandOptions() { 816 // Keep default values of all options in one place: OptionParsingStarting 817 // () 818 OptionParsingStarting(nullptr); 819 } 820 821 ~CommandOptions() override = default; 822 823 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 824 ExecutionContext *execution_context) override { 825 Status error; 826 const int short_option = m_getopt_table[option_idx].val; 827 828 switch (short_option) { 829 case 'a': { 830 lldb::addr_t tmp_addr = OptionArgParser::ToAddress( 831 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); 832 if (error.Success()) 833 m_until_addrs.push_back(tmp_addr); 834 } break; 835 case 't': 836 if (option_arg.getAsInteger(0, m_thread_idx)) { 837 m_thread_idx = LLDB_INVALID_INDEX32; 838 error.SetErrorStringWithFormat("invalid thread index '%s'", 839 option_arg.str().c_str()); 840 } 841 break; 842 case 'f': 843 if (option_arg.getAsInteger(0, m_frame_idx)) { 844 m_frame_idx = LLDB_INVALID_FRAME_ID; 845 error.SetErrorStringWithFormat("invalid frame index '%s'", 846 option_arg.str().c_str()); 847 } 848 break; 849 case 'm': { 850 auto enum_values = GetDefinitions()[option_idx].enum_values; 851 lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( 852 option_arg, enum_values, eOnlyDuringStepping, error); 853 854 if (error.Success()) { 855 if (run_mode == eAllThreads) 856 m_stop_others = false; 857 else 858 m_stop_others = true; 859 } 860 } break; 861 default: 862 llvm_unreachable("Unimplemented option"); 863 } 864 return error; 865 } 866 867 void OptionParsingStarting(ExecutionContext *execution_context) override { 868 m_thread_idx = LLDB_INVALID_THREAD_ID; 869 m_frame_idx = 0; 870 m_stop_others = false; 871 m_until_addrs.clear(); 872 } 873 874 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 875 return llvm::makeArrayRef(g_thread_until_options); 876 } 877 878 uint32_t m_step_thread_idx = LLDB_INVALID_THREAD_ID; 879 bool m_stop_others = false; 880 std::vector<lldb::addr_t> m_until_addrs; 881 882 // Instance variables to hold the values for command options. 883 }; 884 885 CommandObjectThreadUntil(CommandInterpreter &interpreter) 886 : CommandObjectParsed( 887 interpreter, "thread until", 888 "Continue until a line number or address is reached by the " 889 "current or specified thread. Stops when returning from " 890 "the current function as a safety measure. " 891 "The target line number(s) are given as arguments, and if more " 892 "than one" 893 " is provided, stepping will stop when the first one is hit.", 894 nullptr, 895 eCommandRequiresThread | eCommandTryTargetAPILock | 896 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 897 CommandArgumentEntry arg; 898 CommandArgumentData line_num_arg; 899 900 // Define the first (and only) variant of this arg. 901 line_num_arg.arg_type = eArgTypeLineNum; 902 line_num_arg.arg_repetition = eArgRepeatPlain; 903 904 // There is only one variant this argument could be; put it into the 905 // argument entry. 906 arg.push_back(line_num_arg); 907 908 // Push the data for the first argument into the m_arguments vector. 909 m_arguments.push_back(arg); 910 } 911 912 ~CommandObjectThreadUntil() override = default; 913 914 Options *GetOptions() override { return &m_options; } 915 916 protected: 917 bool DoExecute(Args &command, CommandReturnObject &result) override { 918 bool synchronous_execution = m_interpreter.GetSynchronous(); 919 920 Target *target = &GetSelectedTarget(); 921 922 Process *process = m_exe_ctx.GetProcessPtr(); 923 if (process == nullptr) { 924 result.AppendError("need a valid process to step"); 925 } else { 926 Thread *thread = nullptr; 927 std::vector<uint32_t> line_numbers; 928 929 if (command.GetArgumentCount() >= 1) { 930 size_t num_args = command.GetArgumentCount(); 931 for (size_t i = 0; i < num_args; i++) { 932 uint32_t line_number; 933 if (!llvm::to_integer(command.GetArgumentAtIndex(i), line_number)) { 934 result.AppendErrorWithFormat("invalid line number: '%s'.\n", 935 command.GetArgumentAtIndex(i)); 936 return false; 937 } else 938 line_numbers.push_back(line_number); 939 } 940 } else if (m_options.m_until_addrs.empty()) { 941 result.AppendErrorWithFormat("No line number or address provided:\n%s", 942 GetSyntax().str().c_str()); 943 return false; 944 } 945 946 if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { 947 thread = GetDefaultThread(); 948 } else { 949 thread = process->GetThreadList() 950 .FindThreadByIndexID(m_options.m_thread_idx) 951 .get(); 952 } 953 954 if (thread == nullptr) { 955 const uint32_t num_threads = process->GetThreadList().GetSize(); 956 result.AppendErrorWithFormat( 957 "Thread index %u is out of range (valid values are 0 - %u).\n", 958 m_options.m_thread_idx, num_threads); 959 return false; 960 } 961 962 const bool abort_other_plans = false; 963 964 StackFrame *frame = 965 thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); 966 if (frame == nullptr) { 967 result.AppendErrorWithFormat( 968 "Frame index %u is out of range for thread id %" PRIu64 ".\n", 969 m_options.m_frame_idx, thread->GetID()); 970 return false; 971 } 972 973 ThreadPlanSP new_plan_sp; 974 Status new_plan_status; 975 976 if (frame->HasDebugInformation()) { 977 // Finally we got here... Translate the given line number to a bunch 978 // of addresses: 979 SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit)); 980 LineTable *line_table = nullptr; 981 if (sc.comp_unit) 982 line_table = sc.comp_unit->GetLineTable(); 983 984 if (line_table == nullptr) { 985 result.AppendErrorWithFormat("Failed to resolve the line table for " 986 "frame %u of thread id %" PRIu64 ".\n", 987 m_options.m_frame_idx, thread->GetID()); 988 return false; 989 } 990 991 LineEntry function_start; 992 uint32_t index_ptr = 0, end_ptr = UINT32_MAX; 993 std::vector<addr_t> address_list; 994 995 // Find the beginning & end index of the function, but first make 996 // sure it is valid: 997 if (!sc.function) { 998 result.AppendErrorWithFormat("Have debug information but no " 999 "function info - can't get until range."); 1000 return false; 1001 } 1002 1003 AddressRange fun_addr_range = sc.function->GetAddressRange(); 1004 Address fun_start_addr = fun_addr_range.GetBaseAddress(); 1005 line_table->FindLineEntryByAddress(fun_start_addr, function_start, 1006 &index_ptr); 1007 1008 Address fun_end_addr(fun_start_addr.GetSection(), 1009 fun_start_addr.GetOffset() + 1010 fun_addr_range.GetByteSize()); 1011 1012 bool all_in_function = true; 1013 1014 line_table->FindLineEntryByAddress(fun_end_addr, function_start, 1015 &end_ptr); 1016 1017 // Since not all source lines will contribute code, check if we are 1018 // setting the breakpoint on the exact line number or the nearest 1019 // subsequent line number and set breakpoints at all the line table 1020 // entries of the chosen line number (exact or nearest subsequent). 1021 for (uint32_t line_number : line_numbers) { 1022 LineEntry line_entry; 1023 bool exact = false; 1024 uint32_t start_idx_ptr = index_ptr; 1025 start_idx_ptr = sc.comp_unit->FindLineEntry( 1026 index_ptr, line_number, nullptr, exact, &line_entry); 1027 if (start_idx_ptr != UINT32_MAX) 1028 line_number = line_entry.line; 1029 exact = true; 1030 start_idx_ptr = index_ptr; 1031 while (start_idx_ptr <= end_ptr) { 1032 start_idx_ptr = sc.comp_unit->FindLineEntry( 1033 start_idx_ptr, line_number, nullptr, exact, &line_entry); 1034 if (start_idx_ptr == UINT32_MAX) 1035 break; 1036 1037 addr_t address = 1038 line_entry.range.GetBaseAddress().GetLoadAddress(target); 1039 if (address != LLDB_INVALID_ADDRESS) { 1040 if (fun_addr_range.ContainsLoadAddress(address, target)) 1041 address_list.push_back(address); 1042 else 1043 all_in_function = false; 1044 } 1045 start_idx_ptr++; 1046 } 1047 } 1048 1049 for (lldb::addr_t address : m_options.m_until_addrs) { 1050 if (fun_addr_range.ContainsLoadAddress(address, target)) 1051 address_list.push_back(address); 1052 else 1053 all_in_function = false; 1054 } 1055 1056 if (address_list.empty()) { 1057 if (all_in_function) 1058 result.AppendErrorWithFormat( 1059 "No line entries matching until target.\n"); 1060 else 1061 result.AppendErrorWithFormat( 1062 "Until target outside of the current function.\n"); 1063 1064 return false; 1065 } 1066 1067 new_plan_sp = thread->QueueThreadPlanForStepUntil( 1068 abort_other_plans, &address_list.front(), address_list.size(), 1069 m_options.m_stop_others, m_options.m_frame_idx, new_plan_status); 1070 if (new_plan_sp) { 1071 // User level plans should be controlling plans so they can be 1072 // interrupted 1073 // (e.g. by hitting a breakpoint) and other plans executed by the 1074 // user (stepping around the breakpoint) and then a "continue" will 1075 // resume the original plan. 1076 new_plan_sp->SetIsControllingPlan(true); 1077 new_plan_sp->SetOkayToDiscard(false); 1078 } else { 1079 result.SetError(new_plan_status); 1080 return false; 1081 } 1082 } else { 1083 result.AppendErrorWithFormat("Frame index %u of thread id %" PRIu64 1084 " has no debug information.\n", 1085 m_options.m_frame_idx, thread->GetID()); 1086 return false; 1087 } 1088 1089 if (!process->GetThreadList().SetSelectedThreadByID(thread->GetID())) { 1090 result.AppendErrorWithFormat( 1091 "Failed to set the selected thread to thread id %" PRIu64 ".\n", 1092 thread->GetID()); 1093 return false; 1094 } 1095 1096 StreamString stream; 1097 Status error; 1098 if (synchronous_execution) 1099 error = process->ResumeSynchronous(&stream); 1100 else 1101 error = process->Resume(); 1102 1103 if (error.Success()) { 1104 result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", 1105 process->GetID()); 1106 if (synchronous_execution) { 1107 // If any state changed events had anything to say, add that to the 1108 // result 1109 if (stream.GetSize() > 0) 1110 result.AppendMessage(stream.GetString()); 1111 1112 result.SetDidChangeProcessState(true); 1113 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1114 } else { 1115 result.SetStatus(eReturnStatusSuccessContinuingNoResult); 1116 } 1117 } else { 1118 result.AppendErrorWithFormat("Failed to resume process: %s.\n", 1119 error.AsCString()); 1120 } 1121 } 1122 return result.Succeeded(); 1123 } 1124 1125 CommandOptions m_options; 1126 }; 1127 1128 // CommandObjectThreadSelect 1129 1130 class CommandObjectThreadSelect : public CommandObjectParsed { 1131 public: 1132 CommandObjectThreadSelect(CommandInterpreter &interpreter) 1133 : CommandObjectParsed(interpreter, "thread select", 1134 "Change the currently selected thread.", nullptr, 1135 eCommandRequiresProcess | eCommandTryTargetAPILock | 1136 eCommandProcessMustBeLaunched | 1137 eCommandProcessMustBePaused) { 1138 CommandArgumentEntry arg; 1139 CommandArgumentData thread_idx_arg; 1140 1141 // Define the first (and only) variant of this arg. 1142 thread_idx_arg.arg_type = eArgTypeThreadIndex; 1143 thread_idx_arg.arg_repetition = eArgRepeatPlain; 1144 1145 // There is only one variant this argument could be; put it into the 1146 // argument entry. 1147 arg.push_back(thread_idx_arg); 1148 1149 // Push the data for the first argument into the m_arguments vector. 1150 m_arguments.push_back(arg); 1151 } 1152 1153 ~CommandObjectThreadSelect() override = default; 1154 1155 void 1156 HandleArgumentCompletion(CompletionRequest &request, 1157 OptionElementVector &opt_element_vector) override { 1158 if (request.GetCursorIndex()) 1159 return; 1160 1161 CommandCompletions::InvokeCommonCompletionCallbacks( 1162 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 1163 request, nullptr); 1164 } 1165 1166 protected: 1167 bool DoExecute(Args &command, CommandReturnObject &result) override { 1168 Process *process = m_exe_ctx.GetProcessPtr(); 1169 if (process == nullptr) { 1170 result.AppendError("no process"); 1171 return false; 1172 } else if (command.GetArgumentCount() != 1) { 1173 result.AppendErrorWithFormat( 1174 "'%s' takes exactly one thread index argument:\nUsage: %s\n", 1175 m_cmd_name.c_str(), m_cmd_syntax.c_str()); 1176 return false; 1177 } 1178 1179 uint32_t index_id; 1180 if (!llvm::to_integer(command.GetArgumentAtIndex(0), index_id)) { 1181 result.AppendErrorWithFormat("Invalid thread index '%s'", 1182 command.GetArgumentAtIndex(0)); 1183 return false; 1184 } 1185 1186 Thread *new_thread = 1187 process->GetThreadList().FindThreadByIndexID(index_id).get(); 1188 if (new_thread == nullptr) { 1189 result.AppendErrorWithFormat("invalid thread #%s.\n", 1190 command.GetArgumentAtIndex(0)); 1191 return false; 1192 } 1193 1194 process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); 1195 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1196 1197 return result.Succeeded(); 1198 } 1199 }; 1200 1201 // CommandObjectThreadList 1202 1203 class CommandObjectThreadList : public CommandObjectParsed { 1204 public: 1205 CommandObjectThreadList(CommandInterpreter &interpreter) 1206 : CommandObjectParsed( 1207 interpreter, "thread list", 1208 "Show a summary of each thread in the current target process. " 1209 "Use 'settings set thread-format' to customize the individual " 1210 "thread listings.", 1211 "thread list", 1212 eCommandRequiresProcess | eCommandTryTargetAPILock | 1213 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1214 1215 ~CommandObjectThreadList() override = default; 1216 1217 protected: 1218 bool DoExecute(Args &command, CommandReturnObject &result) override { 1219 Stream &strm = result.GetOutputStream(); 1220 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1221 Process *process = m_exe_ctx.GetProcessPtr(); 1222 const bool only_threads_with_stop_reason = false; 1223 const uint32_t start_frame = 0; 1224 const uint32_t num_frames = 0; 1225 const uint32_t num_frames_with_source = 0; 1226 process->GetStatus(strm); 1227 process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, 1228 num_frames, num_frames_with_source, false); 1229 return result.Succeeded(); 1230 } 1231 }; 1232 1233 // CommandObjectThreadInfo 1234 #define LLDB_OPTIONS_thread_info 1235 #include "CommandOptions.inc" 1236 1237 class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { 1238 public: 1239 class CommandOptions : public Options { 1240 public: 1241 CommandOptions() { OptionParsingStarting(nullptr); } 1242 1243 ~CommandOptions() override = default; 1244 1245 void OptionParsingStarting(ExecutionContext *execution_context) override { 1246 m_json_thread = false; 1247 m_json_stopinfo = false; 1248 } 1249 1250 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1251 ExecutionContext *execution_context) override { 1252 const int short_option = m_getopt_table[option_idx].val; 1253 Status error; 1254 1255 switch (short_option) { 1256 case 'j': 1257 m_json_thread = true; 1258 break; 1259 1260 case 's': 1261 m_json_stopinfo = true; 1262 break; 1263 1264 default: 1265 llvm_unreachable("Unimplemented option"); 1266 } 1267 return error; 1268 } 1269 1270 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1271 return llvm::makeArrayRef(g_thread_info_options); 1272 } 1273 1274 bool m_json_thread; 1275 bool m_json_stopinfo; 1276 }; 1277 1278 CommandObjectThreadInfo(CommandInterpreter &interpreter) 1279 : CommandObjectIterateOverThreads( 1280 interpreter, "thread info", 1281 "Show an extended summary of one or " 1282 "more threads. Defaults to the " 1283 "current thread.", 1284 "thread info", 1285 eCommandRequiresProcess | eCommandTryTargetAPILock | 1286 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 1287 m_add_return = false; 1288 } 1289 1290 ~CommandObjectThreadInfo() override = default; 1291 1292 void 1293 HandleArgumentCompletion(CompletionRequest &request, 1294 OptionElementVector &opt_element_vector) override { 1295 CommandCompletions::InvokeCommonCompletionCallbacks( 1296 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 1297 request, nullptr); 1298 } 1299 1300 Options *GetOptions() override { return &m_options; } 1301 1302 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1303 ThreadSP thread_sp = 1304 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1305 if (!thread_sp) { 1306 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1307 tid); 1308 return false; 1309 } 1310 1311 Thread *thread = thread_sp.get(); 1312 1313 Stream &strm = result.GetOutputStream(); 1314 if (!thread->GetDescription(strm, eDescriptionLevelFull, 1315 m_options.m_json_thread, 1316 m_options.m_json_stopinfo)) { 1317 result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", 1318 thread->GetIndexID()); 1319 return false; 1320 } 1321 return true; 1322 } 1323 1324 CommandOptions m_options; 1325 }; 1326 1327 // CommandObjectThreadException 1328 1329 class CommandObjectThreadException : public CommandObjectIterateOverThreads { 1330 public: 1331 CommandObjectThreadException(CommandInterpreter &interpreter) 1332 : CommandObjectIterateOverThreads( 1333 interpreter, "thread exception", 1334 "Display the current exception object for a thread. Defaults to " 1335 "the current thread.", 1336 "thread exception", 1337 eCommandRequiresProcess | eCommandTryTargetAPILock | 1338 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1339 1340 ~CommandObjectThreadException() override = default; 1341 1342 void 1343 HandleArgumentCompletion(CompletionRequest &request, 1344 OptionElementVector &opt_element_vector) override { 1345 CommandCompletions::InvokeCommonCompletionCallbacks( 1346 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 1347 request, nullptr); 1348 } 1349 1350 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1351 ThreadSP thread_sp = 1352 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1353 if (!thread_sp) { 1354 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1355 tid); 1356 return false; 1357 } 1358 1359 Stream &strm = result.GetOutputStream(); 1360 ValueObjectSP exception_object_sp = thread_sp->GetCurrentException(); 1361 if (exception_object_sp) { 1362 exception_object_sp->Dump(strm); 1363 } 1364 1365 ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace(); 1366 if (exception_thread_sp && exception_thread_sp->IsValid()) { 1367 const uint32_t num_frames_with_source = 0; 1368 const bool stop_format = false; 1369 exception_thread_sp->GetStatus(strm, 0, UINT32_MAX, 1370 num_frames_with_source, stop_format); 1371 } 1372 1373 return true; 1374 } 1375 }; 1376 1377 class CommandObjectThreadSiginfo : public CommandObjectIterateOverThreads { 1378 public: 1379 CommandObjectThreadSiginfo(CommandInterpreter &interpreter) 1380 : CommandObjectIterateOverThreads( 1381 interpreter, "thread siginfo", 1382 "Display the current siginfo object for a thread. Defaults to " 1383 "the current thread.", 1384 "thread siginfo", 1385 eCommandRequiresProcess | eCommandTryTargetAPILock | 1386 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1387 1388 ~CommandObjectThreadSiginfo() override = default; 1389 1390 void 1391 HandleArgumentCompletion(CompletionRequest &request, 1392 OptionElementVector &opt_element_vector) override { 1393 CommandCompletions::InvokeCommonCompletionCallbacks( 1394 GetCommandInterpreter(), CommandCompletions::eThreadIndexCompletion, 1395 request, nullptr); 1396 } 1397 1398 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1399 ThreadSP thread_sp = 1400 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 1401 if (!thread_sp) { 1402 result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", 1403 tid); 1404 return false; 1405 } 1406 1407 Stream &strm = result.GetOutputStream(); 1408 if (!thread_sp->GetDescription(strm, eDescriptionLevelFull, false, false)) { 1409 result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", 1410 thread_sp->GetIndexID()); 1411 return false; 1412 } 1413 ValueObjectSP exception_object_sp = thread_sp->GetSiginfoValue(); 1414 if (exception_object_sp) 1415 exception_object_sp->Dump(strm); 1416 else 1417 strm.Printf("(no siginfo)\n"); 1418 strm.PutChar('\n'); 1419 1420 return true; 1421 } 1422 }; 1423 1424 // CommandObjectThreadReturn 1425 #define LLDB_OPTIONS_thread_return 1426 #include "CommandOptions.inc" 1427 1428 class CommandObjectThreadReturn : public CommandObjectRaw { 1429 public: 1430 class CommandOptions : public Options { 1431 public: 1432 CommandOptions() { 1433 // Keep default values of all options in one place: OptionParsingStarting 1434 // () 1435 OptionParsingStarting(nullptr); 1436 } 1437 1438 ~CommandOptions() override = default; 1439 1440 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1441 ExecutionContext *execution_context) override { 1442 Status error; 1443 const int short_option = m_getopt_table[option_idx].val; 1444 1445 switch (short_option) { 1446 case 'x': { 1447 bool success; 1448 bool tmp_value = 1449 OptionArgParser::ToBoolean(option_arg, false, &success); 1450 if (success) 1451 m_from_expression = tmp_value; 1452 else { 1453 error.SetErrorStringWithFormat( 1454 "invalid boolean value '%s' for 'x' option", 1455 option_arg.str().c_str()); 1456 } 1457 } break; 1458 default: 1459 llvm_unreachable("Unimplemented option"); 1460 } 1461 return error; 1462 } 1463 1464 void OptionParsingStarting(ExecutionContext *execution_context) override { 1465 m_from_expression = false; 1466 } 1467 1468 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1469 return llvm::makeArrayRef(g_thread_return_options); 1470 } 1471 1472 bool m_from_expression = false; 1473 1474 // Instance variables to hold the values for command options. 1475 }; 1476 1477 CommandObjectThreadReturn(CommandInterpreter &interpreter) 1478 : CommandObjectRaw(interpreter, "thread return", 1479 "Prematurely return from a stack frame, " 1480 "short-circuiting execution of newer frames " 1481 "and optionally yielding a specified value. Defaults " 1482 "to the exiting the current stack " 1483 "frame.", 1484 "thread return", 1485 eCommandRequiresFrame | eCommandTryTargetAPILock | 1486 eCommandProcessMustBeLaunched | 1487 eCommandProcessMustBePaused) { 1488 CommandArgumentEntry arg; 1489 CommandArgumentData expression_arg; 1490 1491 // Define the first (and only) variant of this arg. 1492 expression_arg.arg_type = eArgTypeExpression; 1493 expression_arg.arg_repetition = eArgRepeatOptional; 1494 1495 // There is only one variant this argument could be; put it into the 1496 // argument entry. 1497 arg.push_back(expression_arg); 1498 1499 // Push the data for the first argument into the m_arguments vector. 1500 m_arguments.push_back(arg); 1501 } 1502 1503 ~CommandObjectThreadReturn() override = default; 1504 1505 Options *GetOptions() override { return &m_options; } 1506 1507 protected: 1508 bool DoExecute(llvm::StringRef command, 1509 CommandReturnObject &result) override { 1510 // I am going to handle this by hand, because I don't want you to have to 1511 // say: 1512 // "thread return -- -5". 1513 if (command.startswith("-x")) { 1514 if (command.size() != 2U) 1515 result.AppendWarning("Return values ignored when returning from user " 1516 "called expressions"); 1517 1518 Thread *thread = m_exe_ctx.GetThreadPtr(); 1519 Status error; 1520 error = thread->UnwindInnermostExpression(); 1521 if (!error.Success()) { 1522 result.AppendErrorWithFormat("Unwinding expression failed - %s.", 1523 error.AsCString()); 1524 } else { 1525 bool success = 1526 thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); 1527 if (success) { 1528 m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); 1529 result.SetStatus(eReturnStatusSuccessFinishResult); 1530 } else { 1531 result.AppendErrorWithFormat( 1532 "Could not select 0th frame after unwinding expression."); 1533 } 1534 } 1535 return result.Succeeded(); 1536 } 1537 1538 ValueObjectSP return_valobj_sp; 1539 1540 StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); 1541 uint32_t frame_idx = frame_sp->GetFrameIndex(); 1542 1543 if (frame_sp->IsInlined()) { 1544 result.AppendError("Don't know how to return from inlined frames."); 1545 return false; 1546 } 1547 1548 if (!command.empty()) { 1549 Target *target = m_exe_ctx.GetTargetPtr(); 1550 EvaluateExpressionOptions options; 1551 1552 options.SetUnwindOnError(true); 1553 options.SetUseDynamic(eNoDynamicValues); 1554 1555 ExpressionResults exe_results = eExpressionSetupError; 1556 exe_results = target->EvaluateExpression(command, frame_sp.get(), 1557 return_valobj_sp, options); 1558 if (exe_results != eExpressionCompleted) { 1559 if (return_valobj_sp) 1560 result.AppendErrorWithFormat( 1561 "Error evaluating result expression: %s", 1562 return_valobj_sp->GetError().AsCString()); 1563 else 1564 result.AppendErrorWithFormat( 1565 "Unknown error evaluating result expression."); 1566 return false; 1567 } 1568 } 1569 1570 Status error; 1571 ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); 1572 const bool broadcast = true; 1573 error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast); 1574 if (!error.Success()) { 1575 result.AppendErrorWithFormat( 1576 "Error returning from frame %d of thread %d: %s.", frame_idx, 1577 thread_sp->GetIndexID(), error.AsCString()); 1578 return false; 1579 } 1580 1581 result.SetStatus(eReturnStatusSuccessFinishResult); 1582 return true; 1583 } 1584 1585 CommandOptions m_options; 1586 }; 1587 1588 // CommandObjectThreadJump 1589 #define LLDB_OPTIONS_thread_jump 1590 #include "CommandOptions.inc" 1591 1592 class CommandObjectThreadJump : public CommandObjectParsed { 1593 public: 1594 class CommandOptions : public Options { 1595 public: 1596 CommandOptions() { OptionParsingStarting(nullptr); } 1597 1598 ~CommandOptions() override = default; 1599 1600 void OptionParsingStarting(ExecutionContext *execution_context) override { 1601 m_filenames.Clear(); 1602 m_line_num = 0; 1603 m_line_offset = 0; 1604 m_load_addr = LLDB_INVALID_ADDRESS; 1605 m_force = false; 1606 } 1607 1608 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1609 ExecutionContext *execution_context) override { 1610 const int short_option = m_getopt_table[option_idx].val; 1611 Status error; 1612 1613 switch (short_option) { 1614 case 'f': 1615 m_filenames.AppendIfUnique(FileSpec(option_arg)); 1616 if (m_filenames.GetSize() > 1) 1617 return Status("only one source file expected."); 1618 break; 1619 case 'l': 1620 if (option_arg.getAsInteger(0, m_line_num)) 1621 return Status("invalid line number: '%s'.", option_arg.str().c_str()); 1622 break; 1623 case 'b': 1624 if (option_arg.getAsInteger(0, m_line_offset)) 1625 return Status("invalid line offset: '%s'.", option_arg.str().c_str()); 1626 break; 1627 case 'a': 1628 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 1629 LLDB_INVALID_ADDRESS, &error); 1630 break; 1631 case 'r': 1632 m_force = true; 1633 break; 1634 default: 1635 llvm_unreachable("Unimplemented option"); 1636 } 1637 return error; 1638 } 1639 1640 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1641 return llvm::makeArrayRef(g_thread_jump_options); 1642 } 1643 1644 FileSpecList m_filenames; 1645 uint32_t m_line_num; 1646 int32_t m_line_offset; 1647 lldb::addr_t m_load_addr; 1648 bool m_force; 1649 }; 1650 1651 CommandObjectThreadJump(CommandInterpreter &interpreter) 1652 : CommandObjectParsed( 1653 interpreter, "thread jump", 1654 "Sets the program counter to a new address.", "thread jump", 1655 eCommandRequiresFrame | eCommandTryTargetAPILock | 1656 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} 1657 1658 ~CommandObjectThreadJump() override = default; 1659 1660 Options *GetOptions() override { return &m_options; } 1661 1662 protected: 1663 bool DoExecute(Args &args, CommandReturnObject &result) override { 1664 RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); 1665 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1666 Thread *thread = m_exe_ctx.GetThreadPtr(); 1667 Target *target = m_exe_ctx.GetTargetPtr(); 1668 const SymbolContext &sym_ctx = 1669 frame->GetSymbolContext(eSymbolContextLineEntry); 1670 1671 if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) { 1672 // Use this address directly. 1673 Address dest = Address(m_options.m_load_addr); 1674 1675 lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); 1676 if (callAddr == LLDB_INVALID_ADDRESS) { 1677 result.AppendErrorWithFormat("Invalid destination address."); 1678 return false; 1679 } 1680 1681 if (!reg_ctx->SetPC(callAddr)) { 1682 result.AppendErrorWithFormat("Error changing PC value for thread %d.", 1683 thread->GetIndexID()); 1684 return false; 1685 } 1686 } else { 1687 // Pick either the absolute line, or work out a relative one. 1688 int32_t line = (int32_t)m_options.m_line_num; 1689 if (line == 0) 1690 line = sym_ctx.line_entry.line + m_options.m_line_offset; 1691 1692 // Try the current file, but override if asked. 1693 FileSpec file = sym_ctx.line_entry.file; 1694 if (m_options.m_filenames.GetSize() == 1) 1695 file = m_options.m_filenames.GetFileSpecAtIndex(0); 1696 1697 if (!file) { 1698 result.AppendErrorWithFormat( 1699 "No source file available for the current location."); 1700 return false; 1701 } 1702 1703 std::string warnings; 1704 Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings); 1705 1706 if (err.Fail()) { 1707 result.SetError(err); 1708 return false; 1709 } 1710 1711 if (!warnings.empty()) 1712 result.AppendWarning(warnings.c_str()); 1713 } 1714 1715 result.SetStatus(eReturnStatusSuccessFinishResult); 1716 return true; 1717 } 1718 1719 CommandOptions m_options; 1720 }; 1721 1722 // Next are the subcommands of CommandObjectMultiwordThreadPlan 1723 1724 // CommandObjectThreadPlanList 1725 #define LLDB_OPTIONS_thread_plan_list 1726 #include "CommandOptions.inc" 1727 1728 class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { 1729 public: 1730 class CommandOptions : public Options { 1731 public: 1732 CommandOptions() { 1733 // Keep default values of all options in one place: OptionParsingStarting 1734 // () 1735 OptionParsingStarting(nullptr); 1736 } 1737 1738 ~CommandOptions() override = default; 1739 1740 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1741 ExecutionContext *execution_context) override { 1742 const int short_option = m_getopt_table[option_idx].val; 1743 1744 switch (short_option) { 1745 case 'i': 1746 m_internal = true; 1747 break; 1748 case 't': 1749 lldb::tid_t tid; 1750 if (option_arg.getAsInteger(0, tid)) 1751 return Status("invalid tid: '%s'.", option_arg.str().c_str()); 1752 m_tids.push_back(tid); 1753 break; 1754 case 'u': 1755 m_unreported = false; 1756 break; 1757 case 'v': 1758 m_verbose = true; 1759 break; 1760 default: 1761 llvm_unreachable("Unimplemented option"); 1762 } 1763 return {}; 1764 } 1765 1766 void OptionParsingStarting(ExecutionContext *execution_context) override { 1767 m_verbose = false; 1768 m_internal = false; 1769 m_unreported = true; // The variable is "skip unreported" and we want to 1770 // skip unreported by default. 1771 m_tids.clear(); 1772 } 1773 1774 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1775 return llvm::makeArrayRef(g_thread_plan_list_options); 1776 } 1777 1778 // Instance variables to hold the values for command options. 1779 bool m_verbose; 1780 bool m_internal; 1781 bool m_unreported; 1782 std::vector<lldb::tid_t> m_tids; 1783 }; 1784 1785 CommandObjectThreadPlanList(CommandInterpreter &interpreter) 1786 : CommandObjectIterateOverThreads( 1787 interpreter, "thread plan list", 1788 "Show thread plans for one or more threads. If no threads are " 1789 "specified, show the " 1790 "current thread. Use the thread-index \"all\" to see all threads.", 1791 nullptr, 1792 eCommandRequiresProcess | eCommandRequiresThread | 1793 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 1794 eCommandProcessMustBePaused) {} 1795 1796 ~CommandObjectThreadPlanList() override = default; 1797 1798 Options *GetOptions() override { return &m_options; } 1799 1800 bool DoExecute(Args &command, CommandReturnObject &result) override { 1801 // If we are reporting all threads, dispatch to the Process to do that: 1802 if (command.GetArgumentCount() == 0 && m_options.m_tids.empty()) { 1803 Stream &strm = result.GetOutputStream(); 1804 DescriptionLevel desc_level = m_options.m_verbose 1805 ? eDescriptionLevelVerbose 1806 : eDescriptionLevelFull; 1807 m_exe_ctx.GetProcessPtr()->DumpThreadPlans( 1808 strm, desc_level, m_options.m_internal, true, m_options.m_unreported); 1809 result.SetStatus(eReturnStatusSuccessFinishResult); 1810 return true; 1811 } else { 1812 // Do any TID's that the user may have specified as TID, then do any 1813 // Thread Indexes... 1814 if (!m_options.m_tids.empty()) { 1815 Process *process = m_exe_ctx.GetProcessPtr(); 1816 StreamString tmp_strm; 1817 for (lldb::tid_t tid : m_options.m_tids) { 1818 bool success = process->DumpThreadPlansForTID( 1819 tmp_strm, tid, eDescriptionLevelFull, m_options.m_internal, 1820 true /* condense_trivial */, m_options.m_unreported); 1821 // If we didn't find a TID, stop here and return an error. 1822 if (!success) { 1823 result.AppendError("Error dumping plans:"); 1824 result.AppendError(tmp_strm.GetString()); 1825 return false; 1826 } 1827 // Otherwise, add our data to the output: 1828 result.GetOutputStream() << tmp_strm.GetString(); 1829 } 1830 } 1831 return CommandObjectIterateOverThreads::DoExecute(command, result); 1832 } 1833 } 1834 1835 protected: 1836 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 1837 // If we have already handled this from a -t option, skip it here. 1838 if (llvm::is_contained(m_options.m_tids, tid)) 1839 return true; 1840 1841 Process *process = m_exe_ctx.GetProcessPtr(); 1842 1843 Stream &strm = result.GetOutputStream(); 1844 DescriptionLevel desc_level = eDescriptionLevelFull; 1845 if (m_options.m_verbose) 1846 desc_level = eDescriptionLevelVerbose; 1847 1848 process->DumpThreadPlansForTID(strm, tid, desc_level, m_options.m_internal, 1849 true /* condense_trivial */, 1850 m_options.m_unreported); 1851 return true; 1852 } 1853 1854 CommandOptions m_options; 1855 }; 1856 1857 class CommandObjectThreadPlanDiscard : public CommandObjectParsed { 1858 public: 1859 CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) 1860 : CommandObjectParsed(interpreter, "thread plan discard", 1861 "Discards thread plans up to and including the " 1862 "specified index (see 'thread plan list'.) " 1863 "Only user visible plans can be discarded.", 1864 nullptr, 1865 eCommandRequiresProcess | eCommandRequiresThread | 1866 eCommandTryTargetAPILock | 1867 eCommandProcessMustBeLaunched | 1868 eCommandProcessMustBePaused) { 1869 CommandArgumentEntry arg; 1870 CommandArgumentData plan_index_arg; 1871 1872 // Define the first (and only) variant of this arg. 1873 plan_index_arg.arg_type = eArgTypeUnsignedInteger; 1874 plan_index_arg.arg_repetition = eArgRepeatPlain; 1875 1876 // There is only one variant this argument could be; put it into the 1877 // argument entry. 1878 arg.push_back(plan_index_arg); 1879 1880 // Push the data for the first argument into the m_arguments vector. 1881 m_arguments.push_back(arg); 1882 } 1883 1884 ~CommandObjectThreadPlanDiscard() override = default; 1885 1886 void 1887 HandleArgumentCompletion(CompletionRequest &request, 1888 OptionElementVector &opt_element_vector) override { 1889 if (!m_exe_ctx.HasThreadScope() || request.GetCursorIndex()) 1890 return; 1891 1892 m_exe_ctx.GetThreadPtr()->AutoCompleteThreadPlans(request); 1893 } 1894 1895 bool DoExecute(Args &args, CommandReturnObject &result) override { 1896 Thread *thread = m_exe_ctx.GetThreadPtr(); 1897 if (args.GetArgumentCount() != 1) { 1898 result.AppendErrorWithFormat("Too many arguments, expected one - the " 1899 "thread plan index - but got %zu.", 1900 args.GetArgumentCount()); 1901 return false; 1902 } 1903 1904 uint32_t thread_plan_idx; 1905 if (!llvm::to_integer(args.GetArgumentAtIndex(0), thread_plan_idx)) { 1906 result.AppendErrorWithFormat( 1907 "Invalid thread index: \"%s\" - should be unsigned int.", 1908 args.GetArgumentAtIndex(0)); 1909 return false; 1910 } 1911 1912 if (thread_plan_idx == 0) { 1913 result.AppendErrorWithFormat( 1914 "You wouldn't really want me to discard the base thread plan."); 1915 return false; 1916 } 1917 1918 if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { 1919 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1920 return true; 1921 } else { 1922 result.AppendErrorWithFormat( 1923 "Could not find User thread plan with index %s.", 1924 args.GetArgumentAtIndex(0)); 1925 return false; 1926 } 1927 } 1928 }; 1929 1930 class CommandObjectThreadPlanPrune : public CommandObjectParsed { 1931 public: 1932 CommandObjectThreadPlanPrune(CommandInterpreter &interpreter) 1933 : CommandObjectParsed(interpreter, "thread plan prune", 1934 "Removes any thread plans associated with " 1935 "currently unreported threads. " 1936 "Specify one or more TID's to remove, or if no " 1937 "TID's are provides, remove threads for all " 1938 "unreported threads", 1939 nullptr, 1940 eCommandRequiresProcess | 1941 eCommandTryTargetAPILock | 1942 eCommandProcessMustBeLaunched | 1943 eCommandProcessMustBePaused) { 1944 CommandArgumentEntry arg; 1945 CommandArgumentData tid_arg; 1946 1947 // Define the first (and only) variant of this arg. 1948 tid_arg.arg_type = eArgTypeThreadID; 1949 tid_arg.arg_repetition = eArgRepeatStar; 1950 1951 // There is only one variant this argument could be; put it into the 1952 // argument entry. 1953 arg.push_back(tid_arg); 1954 1955 // Push the data for the first argument into the m_arguments vector. 1956 m_arguments.push_back(arg); 1957 } 1958 1959 ~CommandObjectThreadPlanPrune() override = default; 1960 1961 bool DoExecute(Args &args, CommandReturnObject &result) override { 1962 Process *process = m_exe_ctx.GetProcessPtr(); 1963 1964 if (args.GetArgumentCount() == 0) { 1965 process->PruneThreadPlans(); 1966 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1967 return true; 1968 } 1969 1970 const size_t num_args = args.GetArgumentCount(); 1971 1972 std::lock_guard<std::recursive_mutex> guard( 1973 process->GetThreadList().GetMutex()); 1974 1975 for (size_t i = 0; i < num_args; i++) { 1976 lldb::tid_t tid; 1977 if (!llvm::to_integer(args.GetArgumentAtIndex(i), tid)) { 1978 result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", 1979 args.GetArgumentAtIndex(i)); 1980 return false; 1981 } 1982 if (!process->PruneThreadPlansForTID(tid)) { 1983 result.AppendErrorWithFormat("Could not find unreported tid: \"%s\"\n", 1984 args.GetArgumentAtIndex(i)); 1985 return false; 1986 } 1987 } 1988 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1989 return true; 1990 } 1991 }; 1992 1993 // CommandObjectMultiwordThreadPlan 1994 1995 class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { 1996 public: 1997 CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) 1998 : CommandObjectMultiword( 1999 interpreter, "plan", 2000 "Commands for managing thread plans that control execution.", 2001 "thread plan <subcommand> [<subcommand objects]") { 2002 LoadSubCommand( 2003 "list", CommandObjectSP(new CommandObjectThreadPlanList(interpreter))); 2004 LoadSubCommand( 2005 "discard", 2006 CommandObjectSP(new CommandObjectThreadPlanDiscard(interpreter))); 2007 LoadSubCommand( 2008 "prune", 2009 CommandObjectSP(new CommandObjectThreadPlanPrune(interpreter))); 2010 } 2011 2012 ~CommandObjectMultiwordThreadPlan() override = default; 2013 }; 2014 2015 // Next are the subcommands of CommandObjectMultiwordTrace 2016 2017 // CommandObjectTraceExport 2018 2019 class CommandObjectTraceExport : public CommandObjectMultiword { 2020 public: 2021 CommandObjectTraceExport(CommandInterpreter &interpreter) 2022 : CommandObjectMultiword( 2023 interpreter, "trace thread export", 2024 "Commands for exporting traces of the threads in the current " 2025 "process to different formats.", 2026 "thread trace export <export-plugin> [<subcommand objects>]") { 2027 2028 unsigned i = 0; 2029 for (llvm::StringRef plugin_name = 2030 PluginManager::GetTraceExporterPluginNameAtIndex(i); 2031 !plugin_name.empty(); 2032 plugin_name = PluginManager::GetTraceExporterPluginNameAtIndex(i++)) { 2033 if (ThreadTraceExportCommandCreator command_creator = 2034 PluginManager::GetThreadTraceExportCommandCreatorAtIndex(i)) { 2035 LoadSubCommand(plugin_name, command_creator(interpreter)); 2036 } 2037 } 2038 } 2039 }; 2040 2041 // CommandObjectTraceStart 2042 2043 class CommandObjectTraceStart : public CommandObjectTraceProxy { 2044 public: 2045 CommandObjectTraceStart(CommandInterpreter &interpreter) 2046 : CommandObjectTraceProxy( 2047 /*live_debug_session_only=*/true, interpreter, "thread trace start", 2048 "Start tracing threads with the corresponding trace " 2049 "plug-in for the current process.", 2050 "thread trace start [<trace-options>]") {} 2051 2052 protected: 2053 lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override { 2054 return trace.GetThreadTraceStartCommand(m_interpreter); 2055 } 2056 }; 2057 2058 // CommandObjectTraceStop 2059 2060 class CommandObjectTraceStop : public CommandObjectMultipleThreads { 2061 public: 2062 CommandObjectTraceStop(CommandInterpreter &interpreter) 2063 : CommandObjectMultipleThreads( 2064 interpreter, "thread trace stop", 2065 "Stop tracing threads, including the ones traced with the " 2066 "\"process trace start\" command." 2067 "Defaults to the current thread. Thread indices can be " 2068 "specified as arguments.\n Use the thread-index \"all\" to stop " 2069 "tracing " 2070 "for all existing threads.", 2071 "thread trace stop [<thread-index> <thread-index> ...]", 2072 eCommandRequiresProcess | eCommandTryTargetAPILock | 2073 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 2074 eCommandProcessMustBeTraced) {} 2075 2076 ~CommandObjectTraceStop() override = default; 2077 2078 bool DoExecuteOnThreads(Args &command, CommandReturnObject &result, 2079 llvm::ArrayRef<lldb::tid_t> tids) override { 2080 ProcessSP process_sp = m_exe_ctx.GetProcessSP(); 2081 2082 TraceSP trace_sp = process_sp->GetTarget().GetTrace(); 2083 2084 if (llvm::Error err = trace_sp->Stop(tids)) 2085 result.AppendError(toString(std::move(err))); 2086 else 2087 result.SetStatus(eReturnStatusSuccessFinishResult); 2088 2089 return result.Succeeded(); 2090 } 2091 }; 2092 2093 static ThreadSP GetSingleThreadFromArgs(ExecutionContext &exe_ctx, Args &args, 2094 CommandReturnObject &result) { 2095 if (args.GetArgumentCount() == 0) 2096 return exe_ctx.GetThreadSP(); 2097 2098 const char *arg = args.GetArgumentAtIndex(0); 2099 uint32_t thread_idx; 2100 2101 if (!llvm::to_integer(arg, thread_idx)) { 2102 result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg); 2103 return nullptr; 2104 } 2105 ThreadSP thread_sp = 2106 exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx); 2107 if (!thread_sp) 2108 result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg); 2109 return thread_sp; 2110 } 2111 2112 // CommandObjectTraceDumpFunctionCalls 2113 #define LLDB_OPTIONS_thread_trace_dump_function_calls 2114 #include "CommandOptions.inc" 2115 2116 class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed { 2117 public: 2118 class CommandOptions : public Options { 2119 public: 2120 CommandOptions() { OptionParsingStarting(nullptr); } 2121 2122 ~CommandOptions() override = default; 2123 2124 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2125 ExecutionContext *execution_context) override { 2126 Status error; 2127 const int short_option = m_getopt_table[option_idx].val; 2128 2129 switch (short_option) { 2130 case 'j': { 2131 m_dumper_options.json = true; 2132 break; 2133 } 2134 case 'J': { 2135 m_dumper_options.json = true; 2136 m_dumper_options.pretty_print_json = true; 2137 break; 2138 } 2139 case 'F': { 2140 m_output_file.emplace(option_arg); 2141 break; 2142 } 2143 default: 2144 llvm_unreachable("Unimplemented option"); 2145 } 2146 return error; 2147 } 2148 2149 void OptionParsingStarting(ExecutionContext *execution_context) override { 2150 m_dumper_options = {}; 2151 m_output_file = llvm::None; 2152 } 2153 2154 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2155 return llvm::makeArrayRef(g_thread_trace_dump_function_calls_options); 2156 } 2157 2158 static const size_t kDefaultCount = 20; 2159 2160 // Instance variables to hold the values for command options. 2161 TraceDumperOptions m_dumper_options; 2162 llvm::Optional<FileSpec> m_output_file; 2163 }; 2164 2165 CommandObjectTraceDumpFunctionCalls(CommandInterpreter &interpreter) 2166 : CommandObjectParsed( 2167 interpreter, "thread trace dump function-calls", 2168 "Dump the traced function-calls for one thread. If no " 2169 "thread is specified, the current thread is used.", 2170 nullptr, 2171 eCommandRequiresProcess | eCommandRequiresThread | 2172 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 2173 eCommandProcessMustBePaused | eCommandProcessMustBeTraced) { 2174 CommandArgumentData thread_arg{eArgTypeThreadIndex, eArgRepeatOptional}; 2175 m_arguments.push_back({thread_arg}); 2176 } 2177 2178 ~CommandObjectTraceDumpFunctionCalls() override = default; 2179 2180 Options *GetOptions() override { return &m_options; } 2181 2182 protected: 2183 bool DoExecute(Args &args, CommandReturnObject &result) override { 2184 ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); 2185 if (!thread_sp) { 2186 result.AppendError("invalid thread\n"); 2187 return false; 2188 } 2189 2190 llvm::Expected<TraceCursorSP> cursor_or_error = 2191 m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp); 2192 2193 if (!cursor_or_error) { 2194 result.AppendError(llvm::toString(cursor_or_error.takeError())); 2195 return false; 2196 } 2197 TraceCursorSP &cursor_sp = *cursor_or_error; 2198 2199 llvm::Optional<StreamFile> out_file; 2200 if (m_options.m_output_file) { 2201 out_file.emplace(m_options.m_output_file->GetPath().c_str(), 2202 File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | 2203 File::eOpenOptionTruncate); 2204 } 2205 2206 m_options.m_dumper_options.forwards = true; 2207 2208 TraceDumper dumper(std::move(cursor_sp), 2209 out_file ? *out_file : result.GetOutputStream(), 2210 m_options.m_dumper_options); 2211 2212 dumper.DumpFunctionCalls(); 2213 return true; 2214 } 2215 2216 CommandOptions m_options; 2217 }; 2218 2219 // CommandObjectTraceDumpInstructions 2220 #define LLDB_OPTIONS_thread_trace_dump_instructions 2221 #include "CommandOptions.inc" 2222 2223 class CommandObjectTraceDumpInstructions : public CommandObjectParsed { 2224 public: 2225 class CommandOptions : public Options { 2226 public: 2227 CommandOptions() { OptionParsingStarting(nullptr); } 2228 2229 ~CommandOptions() override = default; 2230 2231 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2232 ExecutionContext *execution_context) override { 2233 Status error; 2234 const int short_option = m_getopt_table[option_idx].val; 2235 2236 switch (short_option) { 2237 case 'c': { 2238 int32_t count; 2239 if (option_arg.empty() || option_arg.getAsInteger(0, count) || 2240 count < 0) 2241 error.SetErrorStringWithFormat( 2242 "invalid integer value for option '%s'", 2243 option_arg.str().c_str()); 2244 else 2245 m_count = count; 2246 break; 2247 } 2248 case 'a': { 2249 m_count = std::numeric_limits<decltype(m_count)>::max(); 2250 break; 2251 } 2252 case 's': { 2253 int32_t skip; 2254 if (option_arg.empty() || option_arg.getAsInteger(0, skip) || skip < 0) 2255 error.SetErrorStringWithFormat( 2256 "invalid integer value for option '%s'", 2257 option_arg.str().c_str()); 2258 else 2259 m_dumper_options.skip = skip; 2260 break; 2261 } 2262 case 'i': { 2263 uint64_t id; 2264 if (option_arg.empty() || option_arg.getAsInteger(0, id)) 2265 error.SetErrorStringWithFormat( 2266 "invalid integer value for option '%s'", 2267 option_arg.str().c_str()); 2268 else 2269 m_dumper_options.id = id; 2270 break; 2271 } 2272 case 'F': { 2273 m_output_file.emplace(option_arg); 2274 break; 2275 } 2276 case 'r': { 2277 m_dumper_options.raw = true; 2278 break; 2279 } 2280 case 'f': { 2281 m_dumper_options.forwards = true; 2282 break; 2283 } 2284 case 'k': { 2285 m_dumper_options.show_control_flow_kind = true; 2286 break; 2287 } 2288 case 't': { 2289 m_dumper_options.show_timestamps = true; 2290 break; 2291 } 2292 case 'e': { 2293 m_dumper_options.show_events = true; 2294 break; 2295 } 2296 case 'j': { 2297 m_dumper_options.json = true; 2298 break; 2299 } 2300 case 'J': { 2301 m_dumper_options.pretty_print_json = true; 2302 m_dumper_options.json = true; 2303 break; 2304 } 2305 case 'E': { 2306 m_dumper_options.only_events = true; 2307 m_dumper_options.show_events = true; 2308 break; 2309 } 2310 case 'C': { 2311 m_continue = true; 2312 break; 2313 } 2314 default: 2315 llvm_unreachable("Unimplemented option"); 2316 } 2317 return error; 2318 } 2319 2320 void OptionParsingStarting(ExecutionContext *execution_context) override { 2321 m_count = kDefaultCount; 2322 m_continue = false; 2323 m_output_file = llvm::None; 2324 m_dumper_options = {}; 2325 } 2326 2327 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2328 return llvm::makeArrayRef(g_thread_trace_dump_instructions_options); 2329 } 2330 2331 static const size_t kDefaultCount = 20; 2332 2333 // Instance variables to hold the values for command options. 2334 size_t m_count; 2335 size_t m_continue; 2336 llvm::Optional<FileSpec> m_output_file; 2337 TraceDumperOptions m_dumper_options; 2338 }; 2339 2340 CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter) 2341 : CommandObjectParsed( 2342 interpreter, "thread trace dump instructions", 2343 "Dump the traced instructions for one thread. If no " 2344 "thread is specified, show the current thread.", 2345 nullptr, 2346 eCommandRequiresProcess | eCommandRequiresThread | 2347 eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | 2348 eCommandProcessMustBePaused | eCommandProcessMustBeTraced) { 2349 CommandArgumentData thread_arg{eArgTypeThreadIndex, eArgRepeatOptional}; 2350 m_arguments.push_back({thread_arg}); 2351 } 2352 2353 ~CommandObjectTraceDumpInstructions() override = default; 2354 2355 Options *GetOptions() override { return &m_options; } 2356 2357 llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, 2358 uint32_t index) override { 2359 std::string cmd; 2360 current_command_args.GetCommandString(cmd); 2361 if (cmd.find(" --continue") == std::string::npos) 2362 cmd += " --continue"; 2363 return cmd; 2364 } 2365 2366 protected: 2367 bool DoExecute(Args &args, CommandReturnObject &result) override { 2368 ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result); 2369 if (!thread_sp) { 2370 result.AppendError("invalid thread\n"); 2371 return false; 2372 } 2373 2374 if (m_options.m_continue && m_last_id) { 2375 // We set up the options to continue one instruction past where 2376 // the previous iteration stopped. 2377 m_options.m_dumper_options.skip = 1; 2378 m_options.m_dumper_options.id = m_last_id; 2379 } 2380 2381 llvm::Expected<TraceCursorSP> cursor_or_error = 2382 m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp); 2383 2384 if (!cursor_or_error) { 2385 result.AppendError(llvm::toString(cursor_or_error.takeError())); 2386 return false; 2387 } 2388 TraceCursorSP &cursor_sp = *cursor_or_error; 2389 2390 if (m_options.m_dumper_options.id && 2391 !cursor_sp->HasId(*m_options.m_dumper_options.id)) { 2392 result.AppendError("invalid instruction id\n"); 2393 return false; 2394 } 2395 2396 llvm::Optional<StreamFile> out_file; 2397 if (m_options.m_output_file) { 2398 out_file.emplace(m_options.m_output_file->GetPath().c_str(), 2399 File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | 2400 File::eOpenOptionTruncate); 2401 } 2402 2403 if (m_options.m_continue && !m_last_id) { 2404 // We need to stop processing data when we already ran out of instructions 2405 // in a previous command. We can fake this by setting the cursor past the 2406 // end of the trace. 2407 cursor_sp->Seek(1, lldb::eTraceCursorSeekTypeEnd); 2408 } 2409 2410 TraceDumper dumper(std::move(cursor_sp), 2411 out_file ? *out_file : result.GetOutputStream(), 2412 m_options.m_dumper_options); 2413 2414 m_last_id = dumper.DumpInstructions(m_options.m_count); 2415 return true; 2416 } 2417 2418 CommandOptions m_options; 2419 // Last traversed id used to continue a repeat command. None means 2420 // that all the trace has been consumed. 2421 llvm::Optional<lldb::user_id_t> m_last_id; 2422 }; 2423 2424 // CommandObjectTraceDumpInfo 2425 #define LLDB_OPTIONS_thread_trace_dump_info 2426 #include "CommandOptions.inc" 2427 2428 class CommandObjectTraceDumpInfo : public CommandObjectIterateOverThreads { 2429 public: 2430 class CommandOptions : public Options { 2431 public: 2432 CommandOptions() { OptionParsingStarting(nullptr); } 2433 2434 ~CommandOptions() override = default; 2435 2436 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2437 ExecutionContext *execution_context) override { 2438 Status error; 2439 const int short_option = m_getopt_table[option_idx].val; 2440 2441 switch (short_option) { 2442 case 'v': { 2443 m_verbose = true; 2444 break; 2445 } 2446 case 'j': { 2447 m_json = true; 2448 break; 2449 } 2450 default: 2451 llvm_unreachable("Unimplemented option"); 2452 } 2453 return error; 2454 } 2455 2456 void OptionParsingStarting(ExecutionContext *execution_context) override { 2457 m_verbose = false; 2458 m_json = false; 2459 } 2460 2461 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2462 return llvm::makeArrayRef(g_thread_trace_dump_info_options); 2463 } 2464 2465 // Instance variables to hold the values for command options. 2466 bool m_verbose; 2467 bool m_json; 2468 }; 2469 2470 CommandObjectTraceDumpInfo(CommandInterpreter &interpreter) 2471 : CommandObjectIterateOverThreads( 2472 interpreter, "thread trace dump info", 2473 "Dump the traced information for one or more threads. If no " 2474 "threads are specified, show the current thread. Use the " 2475 "thread-index \"all\" to see all threads.", 2476 nullptr, 2477 eCommandRequiresProcess | eCommandTryTargetAPILock | 2478 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused | 2479 eCommandProcessMustBeTraced) {} 2480 2481 ~CommandObjectTraceDumpInfo() override = default; 2482 2483 Options *GetOptions() override { return &m_options; } 2484 2485 protected: 2486 bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { 2487 const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace(); 2488 ThreadSP thread_sp = 2489 m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); 2490 trace_sp->DumpTraceInfo(*thread_sp, result.GetOutputStream(), 2491 m_options.m_verbose, m_options.m_json); 2492 return true; 2493 } 2494 2495 CommandOptions m_options; 2496 }; 2497 2498 // CommandObjectMultiwordTraceDump 2499 class CommandObjectMultiwordTraceDump : public CommandObjectMultiword { 2500 public: 2501 CommandObjectMultiwordTraceDump(CommandInterpreter &interpreter) 2502 : CommandObjectMultiword( 2503 interpreter, "dump", 2504 "Commands for displaying trace information of the threads " 2505 "in the current process.", 2506 "thread trace dump <subcommand> [<subcommand objects>]") { 2507 LoadSubCommand( 2508 "instructions", 2509 CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter))); 2510 LoadSubCommand( 2511 "function-calls", 2512 CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter))); 2513 LoadSubCommand( 2514 "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter))); 2515 } 2516 ~CommandObjectMultiwordTraceDump() override = default; 2517 }; 2518 2519 // CommandObjectMultiwordTrace 2520 class CommandObjectMultiwordTrace : public CommandObjectMultiword { 2521 public: 2522 CommandObjectMultiwordTrace(CommandInterpreter &interpreter) 2523 : CommandObjectMultiword( 2524 interpreter, "trace", 2525 "Commands for operating on traces of the threads in the current " 2526 "process.", 2527 "thread trace <subcommand> [<subcommand objects>]") { 2528 LoadSubCommand("dump", CommandObjectSP(new CommandObjectMultiwordTraceDump( 2529 interpreter))); 2530 LoadSubCommand("start", 2531 CommandObjectSP(new CommandObjectTraceStart(interpreter))); 2532 LoadSubCommand("stop", 2533 CommandObjectSP(new CommandObjectTraceStop(interpreter))); 2534 LoadSubCommand("export", 2535 CommandObjectSP(new CommandObjectTraceExport(interpreter))); 2536 } 2537 2538 ~CommandObjectMultiwordTrace() override = default; 2539 }; 2540 2541 // CommandObjectMultiwordThread 2542 2543 CommandObjectMultiwordThread::CommandObjectMultiwordThread( 2544 CommandInterpreter &interpreter) 2545 : CommandObjectMultiword(interpreter, "thread", 2546 "Commands for operating on " 2547 "one or more threads in " 2548 "the current process.", 2549 "thread <subcommand> [<subcommand-options>]") { 2550 LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace( 2551 interpreter))); 2552 LoadSubCommand("continue", 2553 CommandObjectSP(new CommandObjectThreadContinue(interpreter))); 2554 LoadSubCommand("list", 2555 CommandObjectSP(new CommandObjectThreadList(interpreter))); 2556 LoadSubCommand("return", 2557 CommandObjectSP(new CommandObjectThreadReturn(interpreter))); 2558 LoadSubCommand("jump", 2559 CommandObjectSP(new CommandObjectThreadJump(interpreter))); 2560 LoadSubCommand("select", 2561 CommandObjectSP(new CommandObjectThreadSelect(interpreter))); 2562 LoadSubCommand("until", 2563 CommandObjectSP(new CommandObjectThreadUntil(interpreter))); 2564 LoadSubCommand("info", 2565 CommandObjectSP(new CommandObjectThreadInfo(interpreter))); 2566 LoadSubCommand("exception", CommandObjectSP(new CommandObjectThreadException( 2567 interpreter))); 2568 LoadSubCommand("siginfo", 2569 CommandObjectSP(new CommandObjectThreadSiginfo(interpreter))); 2570 LoadSubCommand("step-in", 2571 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2572 interpreter, "thread step-in", 2573 "Source level single step, stepping into calls. Defaults " 2574 "to current thread unless specified.", 2575 nullptr, eStepTypeInto, eStepScopeSource))); 2576 2577 LoadSubCommand("step-out", 2578 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2579 interpreter, "thread step-out", 2580 "Finish executing the current stack frame and stop after " 2581 "returning. Defaults to current thread unless specified.", 2582 nullptr, eStepTypeOut, eStepScopeSource))); 2583 2584 LoadSubCommand("step-over", 2585 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2586 interpreter, "thread step-over", 2587 "Source level single step, stepping over calls. Defaults " 2588 "to current thread unless specified.", 2589 nullptr, eStepTypeOver, eStepScopeSource))); 2590 2591 LoadSubCommand("step-inst", 2592 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2593 interpreter, "thread step-inst", 2594 "Instruction level single step, stepping into calls. " 2595 "Defaults to current thread unless specified.", 2596 nullptr, eStepTypeTrace, eStepScopeInstruction))); 2597 2598 LoadSubCommand("step-inst-over", 2599 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2600 interpreter, "thread step-inst-over", 2601 "Instruction level single step, stepping over calls. " 2602 "Defaults to current thread unless specified.", 2603 nullptr, eStepTypeTraceOver, eStepScopeInstruction))); 2604 2605 LoadSubCommand( 2606 "step-scripted", 2607 CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( 2608 interpreter, "thread step-scripted", 2609 "Step as instructed by the script class passed in the -C option. " 2610 "You can also specify a dictionary of key (-k) and value (-v) pairs " 2611 "that will be used to populate an SBStructuredData Dictionary, which " 2612 "will be passed to the constructor of the class implementing the " 2613 "scripted step. See the Python Reference for more details.", 2614 nullptr, eStepTypeScripted, eStepScopeSource))); 2615 2616 LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( 2617 interpreter))); 2618 LoadSubCommand("trace", 2619 CommandObjectSP(new CommandObjectMultiwordTrace(interpreter))); 2620 } 2621 2622 CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; 2623