//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CommandObjectFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"

#include <memory>
#include <string>

using namespace lldb;
using namespace lldb_private;

#pragma mark CommandObjectFrameDiagnose

//-------------------------------------------------------------------------
// CommandObjectFrameInfo
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
// CommandObjectFrameDiagnose
//-------------------------------------------------------------------------

static constexpr OptionDefinition g_frame_diag_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName,    "A register to diagnose." },
  { LLDB_OPT_SET_1, false, "address",  'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress,         "An address to diagnose." },
  { LLDB_OPT_SET_1, false, "offset",   'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset,          "An optional offset.  Requires --register." }
    // clang-format on
};

class CommandObjectFrameDiagnose : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r':
        reg = ConstString(option_arg);
        break;

      case 'a': {
        address.emplace();
        if (option_arg.getAsInteger(0, *address)) {
          address.reset();
          error.SetErrorStringWithFormat("invalid address argument '%s'",
                                         option_arg.str().c_str());
        }
      } break;

      case 'o': {
        offset.emplace();
        if (option_arg.getAsInteger(0, *offset)) {
          offset.reset();
          error.SetErrorStringWithFormat("invalid offset argument '%s'",
                                         option_arg.str().c_str());
        }
      } break;

      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      address.reset();
      reg.reset();
      offset.reset();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_frame_diag_options);
    }

    // Options.
    llvm::Optional<lldb::addr_t> address;
    llvm::Optional<ConstString> reg;
    llvm::Optional<int64_t> offset;
  };

  CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame diagnose",
                            "Try to determine what path path the current stop "
                            "location used to get to a register or address",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused),
        m_options() {
    CommandArgumentEntry arg;
    CommandArgumentData index_arg;

    // Define the first (and only) variant of this arg.
    index_arg.arg_type = eArgTypeFrameIndex;
    index_arg.arg_repetition = eArgRepeatOptional;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(index_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectFrameDiagnose() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Thread *thread = m_exe_ctx.GetThreadPtr();
    StackFrameSP frame_sp = thread->GetSelectedFrame();

    ValueObjectSP valobj_sp;

    if (m_options.address.hasValue()) {
      if (m_options.reg.hasValue() || m_options.offset.hasValue()) {
        result.AppendError(
            "`frame diagnose --address` is incompatible with other arguments.");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue());
    } else if (m_options.reg.hasValue()) {
      valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
          m_options.reg.getValue(), m_options.offset.getValueOr(0));
    } else {
      StopInfoSP stop_info_sp = thread->GetStopInfo();
      if (!stop_info_sp) {
        result.AppendError("No arguments provided, and no stop info.");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
    }

    if (!valobj_sp) {
      result.AppendError("No diagnosis available.");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }


    DumpValueObjectOptions::DeclPrintingHelper helper = [&valobj_sp](
        ConstString type, ConstString var, const DumpValueObjectOptions &opts,
        Stream &stream) -> bool {
      const ValueObject::GetExpressionPathFormat format = ValueObject::
          GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
      const bool qualify_cxx_base_classes = false;
      valobj_sp->GetExpressionPath(stream, qualify_cxx_base_classes, format);
      stream.PutCString(" =");
      return true;
    };

    DumpValueObjectOptions options;
    options.SetDeclPrintingHelper(helper);
    ValueObjectPrinter printer(valobj_sp.get(), &result.GetOutputStream(),
                               options);
    printer.PrintValueObject();

    return true;
  }

protected:
  CommandOptions m_options;
};

#pragma mark CommandObjectFrameInfo

//-------------------------------------------------------------------------
// CommandObjectFrameInfo
//-------------------------------------------------------------------------

class CommandObjectFrameInfo : public CommandObjectParsed {
public:
  CommandObjectFrameInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame info", "List information about the current "
                                       "stack frame in the current thread.",
            "frame info",
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}

  ~CommandObjectFrameInfo() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

#pragma mark CommandObjectFrameSelect

//-------------------------------------------------------------------------
// CommandObjectFrameSelect
//-------------------------------------------------------------------------

static OptionDefinition g_frame_select_options[] = {
    // clang-format off
  { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." },
    // clang-format on
};

class CommandObjectFrameSelect : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r':
        if (option_arg.getAsInteger(0, relative_frame_offset)) {
          relative_frame_offset = INT32_MIN;
          error.SetErrorStringWithFormat("invalid frame offset argument '%s'",
                                         option_arg.str().c_str());
        }
        break;

      default:
        error.SetErrorStringWithFormat("invalid short option character '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      relative_frame_offset = INT32_MIN;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_frame_select_options);
    }

    int32_t relative_frame_offset;
  };

  CommandObjectFrameSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame select", "Select the current stack frame by "
                                         "index from within the current thread "
                                         "(see 'thread backtrace'.)",
            nullptr,
            eCommandRequiresThread | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
        m_options() {
    CommandArgumentEntry arg;
    CommandArgumentData index_arg;

    // Define the first (and only) variant of this arg.
    index_arg.arg_type = eArgTypeFrameIndex;
    index_arg.arg_repetition = eArgRepeatOptional;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(index_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectFrameSelect() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "thread" for validity as eCommandRequiresThread ensures
    // it is valid
    Thread *thread = m_exe_ctx.GetThreadPtr();

    uint32_t frame_idx = UINT32_MAX;
    if (m_options.relative_frame_offset != INT32_MIN) {
      // The one and only argument is a signed relative frame index
      frame_idx = thread->GetSelectedFrameIndex();
      if (frame_idx == UINT32_MAX)
        frame_idx = 0;

      if (m_options.relative_frame_offset < 0) {
        if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset)
          frame_idx += m_options.relative_frame_offset;
        else {
          if (frame_idx == 0) {
            // If you are already at the bottom of the stack, then just warn
            // and don't reset the frame.
            result.AppendError("Already at the bottom of the stack.");
            result.SetStatus(eReturnStatusFailed);
            return false;
          } else
            frame_idx = 0;
        }
      } else if (m_options.relative_frame_offset > 0) {
        // I don't want "up 20" where "20" takes you past the top of the stack
        // to produce
        // an error, but rather to just go to the top.  So I have to count the
        // stack here...
        const uint32_t num_frames = thread->GetStackFrameCount();
        if (static_cast<int32_t>(num_frames - frame_idx) >
            m_options.relative_frame_offset)
          frame_idx += m_options.relative_frame_offset;
        else {
          if (frame_idx == num_frames - 1) {
            // If we are already at the top of the stack, just warn and don't
            // reset the frame.
            result.AppendError("Already at the top of the stack.");
            result.SetStatus(eReturnStatusFailed);
            return false;
          } else
            frame_idx = num_frames - 1;
        }
      }
    } else {
      if (command.GetArgumentCount() > 1) {
        result.AppendErrorWithFormat(
            "too many arguments; expected frame-index, saw '%s'.\n",
            command[0].c_str());
        m_options.GenerateOptionUsage(
            result.GetErrorStream(), this,
            GetCommandInterpreter().GetDebugger().GetTerminalWidth());
        return false;
      }

      if (command.GetArgumentCount() == 1) {
        if (command[0].ref.getAsInteger(0, frame_idx)) {
          result.AppendErrorWithFormat("invalid frame index argument '%s'.",
                                       command[0].c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
      } else if (command.GetArgumentCount() == 0) {
        frame_idx = thread->GetSelectedFrameIndex();
        if (frame_idx == UINT32_MAX) {
          frame_idx = 0;
        }
      }
    }

    bool success = thread->SetSelectedFrameByIndexNoisily(
        frame_idx, result.GetOutputStream());
    if (success) {
      m_exe_ctx.SetFrameSP(thread->GetSelectedFrame());
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Frame index (%u) out of range.\n",
                                   frame_idx);
      result.SetStatus(eReturnStatusFailed);
    }

    return result.Succeeded();
  }

protected:
  CommandOptions m_options;
};

#pragma mark CommandObjectFrameVariable
//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
class CommandObjectFrameVariable : public CommandObjectParsed {
public:
  CommandObjectFrameVariable(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame variable",
            "Show variables for the current stack frame. Defaults to all "
            "arguments and local variables in scope. Names of argument, "
            "local, file static and file global variables can be specified. "
            "Children of aggregate variables can be specified such as "
            "'var->child.x'.  The -> and [] operators in 'frame variable' do "
            "not invoke operator overloads if they exist, but directly access "
            "the specified element.  If you want to trigger operator overloads "
            "use the expression command to print the variable instead."
            "\nIt is worth noting that except for overloaded "
            "operators, when printing local variables 'expr local_var' and "
            "'frame var local_var' produce the same "
            "results.  However, 'frame variable' is more efficient, since it "
            "uses debug information and memory reads directly, rather than "
            "parsing and evaluating an expression, which may even involve "
            "JITing and running code in the target program.",
            nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
                         eCommandProcessMustBeLaunched |
                         eCommandProcessMustBePaused | eCommandRequiresProcess),
        m_option_group(),
        m_option_variable(
            true), // Include the frame specific options by passing "true"
        m_option_format(eFormatDefault),
        m_varobj_options() {
    CommandArgumentEntry arg;
    CommandArgumentData var_name_arg;

    // Define the first (and only) variant of this arg.
    var_name_arg.arg_type = eArgTypeVarName;
    var_name_arg.arg_repetition = eArgRepeatStar;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(var_name_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);

    m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_format,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectFrameVariable() override = default;

  Options *GetOptions() override { return &m_option_group; }

  int HandleArgumentCompletion(
      CompletionRequest &request,
      OptionElementVector &opt_element_vector) override {
    // Arguments are the standard source file completer.
    CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
        request, nullptr);
    return request.GetNumberOfMatches();
  }

protected:
  llvm::StringRef GetScopeString(VariableSP var_sp) {
    if (!var_sp)
      return llvm::StringRef::withNullAsEmpty(nullptr);

    switch (var_sp->GetScope()) {
    case eValueTypeVariableGlobal:
      return "GLOBAL: ";
    case eValueTypeVariableStatic:
      return "STATIC: ";
    case eValueTypeVariableArgument:
      return "ARG: ";
    case eValueTypeVariableLocal:
      return "LOCAL: ";
    case eValueTypeVariableThreadLocal:
      return "THREAD: ";
    default:
      break;
    }

    return llvm::StringRef::withNullAsEmpty(nullptr);
  }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "frame" for validity as eCommandRequiresFrame ensures
    // it is valid
    StackFrame *frame = m_exe_ctx.GetFramePtr();

    Stream &s = result.GetOutputStream();

    // Be careful about the stack frame, if any summary formatter runs code, it
    // might clear the StackFrameList for the thread.  So hold onto a shared
    // pointer to the frame so it stays alive.

    VariableList *variable_list =
        frame->GetVariableList(m_option_variable.show_globals);

    VariableSP var_sp;
    ValueObjectSP valobj_sp;

    TypeSummaryImplSP summary_format_sp;
    if (!m_option_variable.summary.IsCurrentValueEmpty())
      DataVisualization::NamedSummaryFormats::GetSummaryFormat(
          ConstString(m_option_variable.summary.GetCurrentValue()),
          summary_format_sp);
    else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
      summary_format_sp = std::make_shared<StringSummaryFormat>(
          TypeSummaryImpl::Flags(),
          m_option_variable.summary_string.GetCurrentValue());

    DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
        eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
        summary_format_sp));

    const SymbolContext &sym_ctx =
        frame->GetSymbolContext(eSymbolContextFunction);
    if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
      m_option_variable.show_globals = true;

    if (variable_list) {
      const Format format = m_option_format.GetFormat();
      options.SetFormat(format);

      if (!command.empty()) {
        VariableList regex_var_list;

        // If we have any args to the variable command, we will make variable
        // objects from them...
        for (auto &entry : command) {
          if (m_option_variable.use_regex) {
            const size_t regex_start_index = regex_var_list.GetSize();
            llvm::StringRef name_str = entry.ref;
            RegularExpression regex(name_str);
            if (regex.Compile(name_str)) {
              size_t num_matches = 0;
              const size_t num_new_regex_vars =
                  variable_list->AppendVariablesIfUnique(regex, regex_var_list,
                                                         num_matches);
              if (num_new_regex_vars > 0) {
                for (size_t regex_idx = regex_start_index,
                            end_index = regex_var_list.GetSize();
                     regex_idx < end_index; ++regex_idx) {
                  var_sp = regex_var_list.GetVariableAtIndex(regex_idx);
                  if (var_sp) {
                    valobj_sp = frame->GetValueObjectForFrameVariable(
                        var_sp, m_varobj_options.use_dynamic);
                    if (valobj_sp) {
                      std::string scope_string;
                      if (m_option_variable.show_scope)
                        scope_string = GetScopeString(var_sp).str();

                      if (!scope_string.empty())
                        s.PutCString(scope_string);

                      if (m_option_variable.show_decl &&
                          var_sp->GetDeclaration().GetFile()) {
                        bool show_fullpaths = false;
                        bool show_module = true;
                        if (var_sp->DumpDeclaration(&s, show_fullpaths,
                                                    show_module))
                          s.PutCString(": ");
                      }
                      valobj_sp->Dump(result.GetOutputStream(), options);
                    }
                  }
                }
              } else if (num_matches == 0) {
                result.GetErrorStream().Printf("error: no variables matched "
                                               "the regular expression '%s'.\n",
                                               entry.c_str());
              }
            } else {
              char regex_error[1024];
              if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
                result.GetErrorStream().Printf("error: %s\n", regex_error);
              else
                result.GetErrorStream().Printf(
                    "error: unknown regex error when compiling '%s'\n",
                    entry.c_str());
            }
          } else // No regex, either exact variable names or variable
                 // expressions.
          {
            Status error;
            uint32_t expr_path_options =
                StackFrame::eExpressionPathOptionCheckPtrVsMember |
                StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
                StackFrame::eExpressionPathOptionsInspectAnonymousUnions;
            lldb::VariableSP var_sp;
            valobj_sp = frame->GetValueForVariableExpressionPath(
                entry.ref, m_varobj_options.use_dynamic, expr_path_options,
                var_sp, error);
            if (valobj_sp) {
              std::string scope_string;
              if (m_option_variable.show_scope)
                scope_string = GetScopeString(var_sp).str();

              if (!scope_string.empty())
                s.PutCString(scope_string);
              if (m_option_variable.show_decl && var_sp &&
                  var_sp->GetDeclaration().GetFile()) {
                var_sp->GetDeclaration().DumpStopContext(&s, false);
                s.PutCString(": ");
              }

              options.SetFormat(format);
              options.SetVariableFormatDisplayLanguage(
                  valobj_sp->GetPreferredDisplayLanguage());

              Stream &output_stream = result.GetOutputStream();
              options.SetRootValueObjectName(
                  valobj_sp->GetParent() ? entry.c_str() : nullptr);
              valobj_sp->Dump(output_stream, options);
            } else {
              const char *error_cstr = error.AsCString(nullptr);
              if (error_cstr)
                result.GetErrorStream().Printf("error: %s\n", error_cstr);
              else
                result.GetErrorStream().Printf("error: unable to find any "
                                               "variable expression path that "
                                               "matches '%s'.\n",
                                               entry.c_str());
            }
          }
        }
      } else // No command arg specified.  Use variable_list, instead.
      {
        const size_t num_variables = variable_list->GetSize();
        if (num_variables > 0) {
          for (size_t i = 0; i < num_variables; i++) {
            var_sp = variable_list->GetVariableAtIndex(i);
            switch (var_sp->GetScope()) {
            case eValueTypeVariableGlobal:
              if (!m_option_variable.show_globals)
                continue;
              break;
            case eValueTypeVariableStatic:
              if (!m_option_variable.show_globals)
                continue;
              break;
            case eValueTypeVariableArgument:
              if (!m_option_variable.show_args)
                continue;
              break;
            case eValueTypeVariableLocal:
              if (!m_option_variable.show_locals)
                continue;
              break;
            default:
              continue;
              break;
            }
            std::string scope_string;
            if (m_option_variable.show_scope)
              scope_string = GetScopeString(var_sp).str();

            // Use the variable object code to make sure we are using the same
            // APIs as the public API will be using...
            valobj_sp = frame->GetValueObjectForFrameVariable(
                var_sp, m_varobj_options.use_dynamic);
            if (valobj_sp) {
              // When dumping all variables, don't print any variables that are
              // not in scope to avoid extra unneeded output
              if (valobj_sp->IsInScope()) {
                if (!valobj_sp->GetTargetSP()
                         ->GetDisplayRuntimeSupportValues() &&
                    valobj_sp->IsRuntimeSupportValue())
                  continue;

                if (!scope_string.empty())
                  s.PutCString(scope_string);

                if (m_option_variable.show_decl &&
                    var_sp->GetDeclaration().GetFile()) {
                  var_sp->GetDeclaration().DumpStopContext(&s, false);
                  s.PutCString(": ");
                }

                options.SetFormat(format);
                options.SetVariableFormatDisplayLanguage(
                    valobj_sp->GetPreferredDisplayLanguage());
                options.SetRootValueObjectName(
                    var_sp ? var_sp->GetName().AsCString() : nullptr);
                valobj_sp->Dump(result.GetOutputStream(), options);
              }
            }
          }
        }
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
    }

    if (m_option_variable.show_recognized_args) {
      auto recognized_frame = frame->GetRecognizedFrame();
      if (recognized_frame) {
        ValueObjectListSP recognized_arg_list =
            recognized_frame->GetRecognizedArguments();
        if (recognized_arg_list) {
          for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
            options.SetFormat(m_option_format.GetFormat());
            options.SetVariableFormatDisplayLanguage(
                rec_value_sp->GetPreferredDisplayLanguage());
            options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
            rec_value_sp->Dump(result.GetOutputStream(), options);
          }
        }
      }
    }

    if (m_interpreter.TruncationWarningNecessary()) {
      result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
                                      m_cmd_name.c_str());
      m_interpreter.TruncationWarningGiven();
    }

    // Increment statistics.
    bool res = result.Succeeded();
    Target *target = GetSelectedOrDummyTarget();
    if (res)
      target->IncrementStats(StatisticKind::FrameVarSuccess);
    else
      target->IncrementStats(StatisticKind::FrameVarFailure);
    return res;
  }

protected:
  OptionGroupOptions m_option_group;
  OptionGroupVariable m_option_variable;
  OptionGroupFormat m_option_format;
  OptionGroupValueObjectDisplay m_varobj_options;
};

#pragma mark CommandObjectFrameRecognizer

static OptionDefinition g_frame_recognizer_add_options[] = {
    // clang-format off
  { LLDB_OPT_SET_ALL, false, "shlib",         's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName,   "Name of the module or shared library that this recognizer applies to." },
  { LLDB_OPT_SET_ALL, false, "function",      'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeName,        "Name of the function that this recognizer applies to." },
  { LLDB_OPT_SET_2,   false, "python-class",  'l', OptionParser::eRequiredArgument, nullptr, {}, 0,                                     eArgTypePythonClass, "Give the name of a Python class to use for this frame recognizer." },
  { LLDB_OPT_SET_ALL, false, "regex",         'x', OptionParser::eNoArgument,       nullptr, {}, 0,                                     eArgTypeNone,        "Function name and module name are actually regular expressions." }
    // clang-format on
};

class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}
    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'l':
        m_class_name = std::string(option_arg);
        break;
      case 's':
        m_module = std::string(option_arg);
        break;
      case 'n':
        m_function = std::string(option_arg);
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        error.SetErrorStringWithFormat("unrecognized option '%c'",
                                       short_option);
        break;
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_module = "";
      m_function = "";
      m_class_name = "";
      m_regex = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_frame_recognizer_add_options);
    }

    // Instance variables to hold the values for command options.
    std::string m_class_name;
    std::string m_module;
    std::string m_function;
    bool m_regex;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override;

public:
  CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer add",
                            "Add a new frame recognizer.", nullptr),
        m_options() {
    SetHelpLong(R"(
Frame recognizers allow for retrieving information about special frames based on
ABI, arguments or other special properties of that frame, even without source
code or debug info. Currently, one use case is to extract function arguments
that would otherwise be unaccesible, or augment existing arguments.

Adding a custom frame recognizer is possible by implementing a Python class
and using the 'frame recognizer add' command. The Python class should have a
'get_recognized_arguments' method and it will receive an argument of type
lldb.SBFrame representing the current frame that we are trying to recognize.
The method should return a (possibly empty) list of lldb.SBValue objects that
represent the recognized arguments.

An example of a recognizer that retrieves the file descriptor values from libc
functions 'read', 'write' and 'close' follows:

  class LibcFdRecognizer(object):
    def get_recognized_arguments(self, frame):
      if frame.name in ["read", "write", "close"]:
        fd = frame.EvaluateExpression("$arg1").unsigned
        value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
        return [value]
      return []

The file containing this implementation can be imported via 'command script
import' and then we can register this recognizer with 'frame recognizer add'.
It's important to restrict the recognizer to the libc library (which is
libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
in other modules:

(lldb) command script import .../fd_recognizer.py
(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib

When the program is stopped at the beginning of the 'read' function in libc, we
can view the recognizer arguments in 'frame variable':

(lldb) b read
(lldb) r
Process 1234 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
    frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
(lldb) frame variable
(int) fd = 3

    )");
  }
  ~CommandObjectFrameRecognizerAdd() override = default;
};

bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
                                                CommandReturnObject &result) {
#ifndef LLDB_DISABLE_PYTHON
  if (m_options.m_class_name.empty()) {
    result.AppendErrorWithFormat(
        "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  if (m_options.m_module.empty()) {
    result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  if (m_options.m_function.empty()) {
    result.AppendErrorWithFormat("%s needs a function name (-n argument).\n",
                                 m_cmd_name.c_str());
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();

  if (interpreter &&
      !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
    result.AppendWarning(
        "The provided class does not exist - please define it "
        "before attempting to use this frame recognizer");
  }

  StackFrameRecognizerSP recognizer_sp =
      StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
          interpreter, m_options.m_class_name.c_str()));
  if (m_options.m_regex) {
    auto module =
        RegularExpressionSP(new RegularExpression(m_options.m_module));
    auto func =
        RegularExpressionSP(new RegularExpression(m_options.m_function));
    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
  } else {
    auto module = ConstString(m_options.m_module);
    auto func = ConstString(m_options.m_function);
    StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
  }
#endif

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
  return result.Succeeded();
}

class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer clear",
                           "Delete all frame recognizers.", nullptr) {}

  ~CommandObjectFrameRecognizerClear() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    StackFrameRecognizerManager::RemoveAllRecognizers();
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
 public:
  CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer delete",
                            "Delete an existing frame recognizer.", nullptr) {}

  ~CommandObjectFrameRecognizerDelete() override = default;

 protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() == 0) {
      if (!m_interpreter.Confirm(
              "About to delete all frame recognizers, do you want to do that?",
              true)) {
        result.AppendMessage("Operation cancelled...");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      StackFrameRecognizerManager::RemoveAllRecognizers();
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return result.Succeeded();
    }

    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    uint32_t recognizer_id =
        StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);

    StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id);
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

class CommandObjectFrameRecognizerList : public CommandObjectParsed {
 public:
  CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer list",
                            "Show a list of active frame recognizers.",
                            nullptr) {}

  ~CommandObjectFrameRecognizerList() override = default;

 protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    bool any_printed = false;
    StackFrameRecognizerManager::ForEach(
        [&result, &any_printed](uint32_t recognizer_id, std::string name,
                                std::string function, std::string symbol,
                                bool regexp) {
          if (name == "") name = "(internal)";
          result.GetOutputStream().Printf(
              "%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(),
              function.c_str(), symbol.c_str(), regexp ? " (regexp)" : "");
          any_printed = true;
        });

    if (any_printed)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.GetOutputStream().PutCString("no matching results found.\n");
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
    return result.Succeeded();
  }
};

class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
 public:
  CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame recognizer info",
            "Show which frame recognizer is applied a stack frame (if any).",
            nullptr) {
    CommandArgumentEntry arg;
    CommandArgumentData index_arg;

    // Define the first (and only) variant of this arg.
    index_arg.arg_type = eArgTypeFrameIndex;
    index_arg.arg_repetition = eArgRepeatPlain;

    // There is only one variant this argument could be; put it into the
    // argument entry.
    arg.push_back(index_arg);

    // Push the data for the first argument into the m_arguments vector.
    m_arguments.push_back(arg);
  }

  ~CommandObjectFrameRecognizerInfo() override = default;

 protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (thread == nullptr) {
      result.AppendError("no thread");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    uint32_t frame_index =
        StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
    StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
    if (!frame_sp) {
      result.AppendErrorWithFormat("no frame with index %u", frame_index);
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    auto recognizer =
        StackFrameRecognizerManager::GetRecognizerForFrame(frame_sp);

    Stream &output_stream = result.GetOutputStream();
    output_stream.Printf("frame %d ", frame_index);
    if (recognizer) {
      output_stream << "is recognized by ";
      output_stream << recognizer->GetName();
    } else {
      output_stream << "not recognized by any recognizer";
    }
    output_stream.EOL();
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return result.Succeeded();
  }
};

class CommandObjectFrameRecognizer : public CommandObjectMultiword {
 public:
  CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "frame recognizer",
            "Commands for editing and viewing frame recognizers.",
            "frame recognizer [<sub-command-options>] ") {
    LoadSubCommand(
        "add",
        CommandObjectSP(new CommandObjectFrameRecognizerAdd(interpreter)));
    LoadSubCommand(
        "clear",
        CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
    LoadSubCommand(
        "list",
        CommandObjectSP(new CommandObjectFrameRecognizerList(interpreter)));
    LoadSubCommand(
        "info",
        CommandObjectSP(new CommandObjectFrameRecognizerInfo(interpreter)));
  }

  ~CommandObjectFrameRecognizer() override = default;
};

#pragma mark CommandObjectMultiwordFrame

//-------------------------------------------------------------------------
// CommandObjectMultiwordFrame
//-------------------------------------------------------------------------

CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "frame", "Commands for selecting and "
                                                   "examing the current "
                                                   "thread's stack frames.",
                             "frame <subcommand> [<subcommand-options>]") {
  LoadSubCommand("diagnose",
                 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
  LoadSubCommand("info",
                 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
  LoadSubCommand("variable",
                 CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
#ifndef LLDB_DISABLE_PYTHON
  LoadSubCommand(
      "recognizer",
      CommandObjectSP(new CommandObjectFrameRecognizer(interpreter)));
#endif
}

CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
