//===-- CommandObjectFrame.cpp --------------------------------------------===//
//
// 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/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.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/ValueObject/ValueObject.h"

#include <memory>
#include <optional>
#include <string>

using namespace lldb;
using namespace lldb_private;

#pragma mark CommandObjectFrameDiagnose

// CommandObjectFrameInfo

// CommandObjectFrameDiagnose

#define LLDB_OPTIONS_frame_diag
#include "CommandOptions.inc"

class CommandObjectFrameDiagnose : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { 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 = Status::FromErrorStringWithFormat(
              "invalid address argument '%s'", option_arg.str().c_str());
        }
      } break;

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

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

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

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

    // Options.
    std::optional<lldb::addr_t> address;
    std::optional<ConstString> reg;
    std::optional<int64_t> offset;
  };

  CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame diagnose",
                            "Try to determine what path the current stop "
                            "location used to get to a register or address",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameDiagnose() override = default;

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

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

    ValueObjectSP valobj_sp;

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

      valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
    }

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

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

    DumpValueObjectOptions options;
    options.SetDeclPrintingHelper(helper);
    // We've already handled the case where the value object sp is null, so
    // this is just to make sure future changes don't skip that:
    assert(valobj_sp.get() && "Must have a valid ValueObject to print");
    ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
    if (llvm::Error error = printer.PrintValueObject())
      result.AppendError(toString(std::move(error)));
  }

  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:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectFrameSelect

// CommandObjectFrameSelect

#define LLDB_OPTIONS_frame_select
#include "CommandOptions.inc"

class CommandObjectFrameSelect : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { 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': {
        int32_t offset = 0;
        if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
          error = Status::FromErrorStringWithFormat(
              "invalid frame offset argument '%s'", option_arg.str().c_str());
        } else
          relative_frame_offset = offset;
        break;
      }

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      relative_frame_offset.reset();
    }

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

    std::optional<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) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameSelect() override = default;

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

protected:
  void 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) {
      // The one and only argument is a signed relative frame index
      frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
      if (frame_idx == UINT32_MAX)
        frame_idx = 0;

      // If moving up/down by one, skip over hidden frames.
      if (*m_options.relative_frame_offset == 1 ||
          *m_options.relative_frame_offset == -1) {
        uint32_t candidate_idx = frame_idx;
        const unsigned max_depth = 12;
        for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
          if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
            candidate_idx = UINT32_MAX;
            break;
          }
          candidate_idx += *m_options.relative_frame_offset;
          if (auto candidate_sp = thread->GetStackFrameAtIndex(candidate_idx)) {
            if (candidate_sp->IsHidden())
              continue;
            // Now candidate_idx is the first non-hidden frame.
            break;
          }
          candidate_idx = UINT32_MAX;
          break;
        };
        if (candidate_idx != UINT32_MAX)
          m_options.relative_frame_offset = candidate_idx - frame_idx;
      }

      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.");
            return;
          } 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.  OTOH, start
        // by seeing if the requested frame exists, in which case we can avoid
        // counting the stack here...
        const uint32_t frame_requested =
            frame_idx + *m_options.relative_frame_offset;
        StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
        if (frame_sp)
          frame_idx = frame_requested;
        else {
          // The request went past the stack, so handle that case:
          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.");
              return;
            } 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;
      }

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

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

  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.",
            nullptr,
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
                eCommandRequiresProcess),
        m_option_variable(
            true), // Include the frame specific options by passing "true"
        m_option_format(eFormatDefault) {
    SetHelpLong(R"(
Children of aggregate variables can be specified such as 'var->child.x'.  In
'frame variable', the operators -> and [] 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.

It 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.)");

    AddSimpleArgumentList(eArgTypeVarName, eArgRepeatStar);

    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; }

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

    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();
  }

  /// Returns true if `scope` matches any of the options in `m_option_variable`.
  bool ScopeRequested(lldb::ValueType scope) {
    switch (scope) {
    case eValueTypeVariableGlobal:
    case eValueTypeVariableStatic:
      return m_option_variable.show_globals;
    case eValueTypeVariableArgument:
      return m_option_variable.show_args;
    case eValueTypeVariableLocal:
      return m_option_variable.show_locals;
    case eValueTypeInvalid:
    case eValueTypeRegister:
    case eValueTypeRegisterSet:
    case eValueTypeConstResult:
    case eValueTypeVariableThreadLocal:
    case eValueTypeVTable:
    case eValueTypeVTableEntry:
      return false;
    }
    llvm_unreachable("Unexpected scope value");
  }

  /// Finds all the variables in `all_variables` whose name matches `regex`,
  /// inserting them into `matches`. Variables already contained in `matches`
  /// are not inserted again.
  /// Nullopt is returned in case of no matches.
  /// A sub-range of `matches` with all newly inserted variables is returned.
  /// This may be empty if all matches were already contained in `matches`.
  std::optional<llvm::ArrayRef<VariableSP>>
  findUniqueRegexMatches(RegularExpression &regex,
                         VariableList &matches,
                         const VariableList &all_variables) {
    bool any_matches = false;
    const size_t previous_num_vars = matches.GetSize();

    for (const VariableSP &var : all_variables) {
      if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
        continue;
      any_matches = true;
      matches.AddVariableIfUnique(var);
    }

    if (any_matches)
      return matches.toArrayRef().drop_front(previous_num_vars);
    return std::nullopt;
  }

  void 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();

    // Using a regex should behave like looking for an exact name match: it
    // also finds globals.
    m_option_variable.show_globals |= m_option_variable.use_regex;

    // 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.

    Status error;
    VariableList *variable_list =
        frame->GetVariableList(m_option_variable.show_globals, &error);

    if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
      result.AppendError(error.AsCString());
    }

    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) {
            llvm::StringRef name_str = entry.ref();
            RegularExpression regex(name_str);
            if (regex.IsValid()) {
              std::optional<llvm::ArrayRef<VariableSP>> results =
                  findUniqueRegexMatches(regex, regex_var_list, *variable_list);
              if (!results) {
                result.AppendErrorWithFormat(
                    "no variables matched the regular expression '%s'.",
                    entry.c_str());
                continue;
              }
              for (const VariableSP &var_sp : *results) {
                valobj_sp = frame->GetValueObjectForFrameVariable(
                    var_sp, m_varobj_options.use_dynamic);
                if (valobj_sp) {
                  result.GetValueObjectList().Append(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(": ");
                  }
                  auto &strm = result.GetOutputStream();
                  if (llvm::Error error = valobj_sp->Dump(strm, options))
                    result.AppendError(toString(std::move(error)));
                }
              }
            } else {
              if (llvm::Error err = regex.GetError())
                result.AppendError(llvm::toString(std::move(err)));
              else
                result.AppendErrorWithFormat(
                    "unknown regex error when compiling '%s'", 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) {
              result.GetValueObjectList().Append(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);
              if (llvm::Error error = valobj_sp->Dump(output_stream, options))
                result.AppendError(toString(std::move(error)));
            } else {
              if (auto error_cstr = error.AsCString(nullptr))
                result.AppendError(error_cstr);
              else
                result.AppendErrorWithFormat(
                    "unable to find any variable expression path that matches "
                    "'%s'.",
                    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++) {
            VariableSP var_sp = variable_list->GetVariableAtIndex(i);
            if (!ScopeRequested(var_sp->GetScope()))
                continue;
            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) {
              result.GetValueObjectList().Append(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);
                if (llvm::Error error =
                        valobj_sp->Dump(result.GetOutputStream(), options))
                  result.AppendError(toString(std::move(error)));
              }
            }
          }
        }
      }
      if (result.GetStatus() != eReturnStatusFailed)
        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()) {
            result.GetValueObjectList().Append(rec_value_sp);
            options.SetFormat(m_option_format.GetFormat());
            options.SetVariableFormatDisplayLanguage(
                rec_value_sp->GetPreferredDisplayLanguage());
            options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
            if (llvm::Error error =
                    rec_value_sp->Dump(result.GetOutputStream(), options))
              result.AppendError(toString(std::move(error)));
          }
        }
      }
    }

    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
                                           m_cmd_name);

    // Increment statistics.
    TargetStats &target_stats = GetTarget().GetStatistics();
    if (result.Succeeded())
      target_stats.GetFrameVariableStats().NotifySuccess();
    else
      target_stats.GetFrameVariableStats().NotifyFailure();
  }

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

#pragma mark CommandObjectFrameRecognizer

#define LLDB_OPTIONS_frame_recognizer_add
#include "CommandOptions.inc"

class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~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 'f': {
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, true, &success);
        if (success) {
          m_first_instruction_only = value;
        } else {
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value '%s' passed for -f option",
              option_arg.str().c_str());
        }
      } break;
      case 'l':
        m_class_name = std::string(option_arg);
        break;
      case 's':
        m_module = std::string(option_arg);
        break;
      case 'n':
        m_symbols.push_back(std::string(option_arg));
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_module = "";
      m_symbols.clear();
      m_class_name = "";
      m_regex = false;
      m_first_instruction_only = true;
    }

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

    // Instance variables to hold the values for command options.
    std::string m_class_name;
    std::string m_module;
    std::vector<std::string> m_symbols;
    bool m_regex;
    bool m_first_instruction_only;
  };

  CommandOptions m_options;

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

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

public:
  CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer add",
                            "Add a new frame recognizer.", nullptr) {
    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
        target = frame.thread.process.target
        value = 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;
};

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

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

  if (m_options.m_symbols.empty()) {
    result.AppendErrorWithFormat(
        "%s needs at least one symbol name (-n argument).\n",
        m_cmd_name.c_str());
    return;
  }

  if (m_options.m_regex && m_options.m_symbols.size() > 1) {
    result.AppendErrorWithFormat(
        "%s needs only one symbol regular expression (-n argument).\n",
        m_cmd_name.c_str());
    return;
  }

  ScriptInterpreter *interpreter = GetDebugger().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_symbols.front()));
    GetTarget().GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  } else {
    auto module = ConstString(m_options.m_module);
    std::vector<ConstString> symbols(m_options.m_symbols.begin(),
                                     m_options.m_symbols.end());
    GetTarget().GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, symbols,
        Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  }
#endif

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

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

  ~CommandObjectFrameRecognizerClear() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    GetTarget().GetFrameRecognizerManager().RemoveAllRecognizers();
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

static void
PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
                       const std::string &module,
                       llvm::ArrayRef<lldb_private::ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
  if (!enabled)
    strm << "[disabled] ";

  strm << name << ", ";

  if (!module.empty())
    strm << "module " << module << ", ";

  switch (symbol_mangling) {
  case Mangled::NamePreference ::ePreferMangled:
    strm << "mangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangled:
    strm << "demangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
    strm << "demangled (no args) symbol ";
    break;
  }

  if (regexp)
    strm << "regex ";

  llvm::interleaveComma(symbols, strm);
}

// Base class for commands which accept a single frame recognizer as an argument
class CommandObjectWithFrameRecognizerArg : public CommandObjectParsed {
public:
  CommandObjectWithFrameRecognizerArg(CommandInterpreter &interpreter,
                                      const char *name,
                                      const char *help = nullptr,
                                      const char *syntax = nullptr,
                                      uint32_t flags = 0)
      : CommandObjectParsed(interpreter, name, help, syntax, flags) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex() != 0)
      return;

    GetTarget().GetFrameRecognizerManager().ForEach(
        [&request](uint32_t rid, bool enabled, std::string rname,
                   std::string module,
                   llvm::ArrayRef<lldb_private::ConstString> symbols,
                   Mangled::NamePreference symbol_mangling, bool regexp) {
          StreamString strm;
          if (rname.empty())
            rname = "(internal)";

          PrintRecognizerDetails(strm, rname, enabled, module, symbols,
                                 symbol_mangling, regexp);

          request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
        });
  }

  virtual void DoExecuteWithId(CommandReturnObject &result,
                               uint32_t recognizer_id) = 0;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    uint32_t recognizer_id;
    if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
      result.AppendErrorWithFormat("'%s' is not a valid recognizer id.\n",
                                   command.GetArgumentAtIndex(0));
      return;
    }

    DoExecuteWithId(result, recognizer_id);
  }
};

class CommandObjectFrameRecognizerEnable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerEnable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer enable",
            "Enable a frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerEnable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDisable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDisable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer disable",
            "Disable a frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDisable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDelete
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer delete",
            "Delete an existing frame recognizer by id.", nullptr) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDelete() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget().GetFrameRecognizerManager();
    if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id.\n",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

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:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    bool any_printed = false;
    GetTarget().GetFrameRecognizerManager().ForEach(
        [&result,
         &any_printed](uint32_t recognizer_id, bool enabled, std::string name,
                       std::string module, llvm::ArrayRef<ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
          Stream &stream = result.GetOutputStream();

          if (name.empty())
            name = "(internal)";

          stream << std::to_string(recognizer_id) << ": ";
          PrintRecognizerDetails(stream, name, enabled, module, symbols,
                                 symbol_mangling, regexp);

          stream.EOL();
          stream.Flush();

          any_printed = true;
        });

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

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) {
    AddSimpleArgumentList(eArgTypeFrameIndex);
  }

  ~CommandObjectFrameRecognizerInfo() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    const char *frame_index_str = command.GetArgumentAtIndex(0);
    uint32_t frame_index;
    if (!llvm::to_integer(frame_index_str, frame_index)) {
      result.AppendErrorWithFormat("'%s' is not a valid frame index.",
                                   frame_index_str);
      return;
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process");
      return;
    }
    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (thread == nullptr) {
      result.AppendError("no thread");
      return;
    }
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
      return;
    }

    StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
    if (!frame_sp) {
      result.AppendErrorWithFormat("no frame with index %u", frame_index);
      return;
    }

    auto recognizer =
        GetTarget().GetFrameRecognizerManager().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);
  }
};

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("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
                               interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
                               interpreter)));
    LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
                              interpreter)));
    LoadSubCommand(
        "enable",
        CommandObjectSP(new CommandObjectFrameRecognizerEnable(interpreter)));
    LoadSubCommand(
        "disable",
        CommandObjectSP(new CommandObjectFrameRecognizerDisable(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
    LoadSubCommand(
        "clear",
        CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
  }

  ~CommandObjectFrameRecognizer() override = default;
};

#pragma mark CommandObjectMultiwordFrame

// CommandObjectMultiwordFrame

CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "frame",
                             "Commands for selecting and "
                             "examining 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)));
#if LLDB_ENABLE_PYTHON
  LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
                                   interpreter)));
#endif
}

CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
