brintos

brintos / llvm-project-archived public Read only

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