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