//===-- CommandObjectRegister.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 "CommandObjectRegister.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpRegisterInfo.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionValueArray.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObject.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Error.h"

#include <string>
#include <vector>

using namespace lldb;
using namespace lldb_private;

// "register read"
#define LLDB_OPTIONS_register_read
#include "CommandOptions.inc"

static size_t GetNameSize(const RegisterInfo *reg_info, bool use_primary_name) {
  const char *reg_name = use_primary_name ? reg_info->name : reg_info->alt_name;
  return reg_name ? strlen(reg_name) : 0;
}

static size_t ComputeLongestRegisterName(RegisterContext *reg_ctx,
                                         const RegisterSet &reg_set,
                                         bool use_primary_name,
                                         bool primitive_only) {
  const size_t num_registers = reg_set.num_registers;
  size_t name_right_align_at = 0;

  // Loop through all the registers to find the longest register name.
  for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
    const size_t reg = reg_set.registers[reg_idx];
    if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg)) {
      // Derived registers are skipped if primitive_only is true.
      if (primitive_only && reg_info->value_regs)
        continue;

      name_right_align_at = std::max(name_right_align_at,
                                     GetNameSize(reg_info, use_primary_name));
    }
  }

  return name_right_align_at;
}

class CommandObjectRegisterRead : public CommandObjectParsed {
public:
  CommandObjectRegisterRead(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "register read",
            "Dump the contents of one or more register values from the current "
            "frame.  If no register is specified, dumps them all.",
            nullptr,
            eCommandRequiresFrame | eCommandRequiresRegContext |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
        m_format_options(eFormatDefault, UINT64_MAX, UINT64_MAX,
                         {{CommandArgumentType::eArgTypeFormat,
                           "Specify a format to be used for display. This "
                           "overrides any other register type information."}}) {
    AddSimpleArgumentList(eArgTypeRegisterName, eArgRepeatStar);

    // Add the "--format"
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_ALL);
    m_option_group.Append(&m_command_options);
    m_option_group.Finalize();
  }

  ~CommandObjectRegisterRead() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (!m_exe_ctx.HasProcessScope())
      return;
    CommandObject::HandleArgumentCompletion(request, opt_element_vector);
  }

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

  bool DumpRegister(const ExecutionContext &exe_ctx, Stream &strm,
                    RegisterContext &reg_ctx, const RegisterInfo &reg_info,
                    bool print_type, size_t reg_name_right_align_at) {
    RegisterValue reg_value;
    if (!reg_ctx.ReadRegister(&reg_info, reg_value))
      return false;

    strm.Indent();

    bool prefix_with_altname = (bool)m_command_options.alternate_name;
    bool prefix_with_name = !prefix_with_altname;
    DumpRegisterValue(reg_value, strm, reg_info, prefix_with_name,
                      prefix_with_altname, m_format_options.GetFormat(),
                      reg_name_right_align_at,
                      exe_ctx.GetBestExecutionContextScope(), print_type,
                      exe_ctx.GetTargetSP());
    if ((reg_info.encoding == eEncodingUint) ||
        (reg_info.encoding == eEncodingSint)) {
      Process *process = exe_ctx.GetProcessPtr();
      if (process && reg_info.byte_size == process->GetAddressByteSize()) {
        addr_t reg_addr = reg_value.GetAsUInt64(LLDB_INVALID_ADDRESS);
        if (reg_addr != LLDB_INVALID_ADDRESS) {
          Address so_reg_addr;
          if (exe_ctx.GetTargetRef().ResolveLoadAddress(reg_addr,
                                                        so_reg_addr)) {
            strm.PutCString("  ");
            so_reg_addr.Dump(&strm, exe_ctx.GetBestExecutionContextScope(),
                             Address::DumpStyleResolvedDescription);
          }
        }
      }
    }
    strm.EOL();
    return true;
  }

  void DumpRegisterField(Stream &strm, const RegisterInfo &reg_info,
                         const ValueObjectSP &value_sp,
                         size_t reg_name_right_align_at,
                         CommandReturnObject &result) {
    DumpValueObjectOptions options(*value_sp);
    options.SetHideRootType(true)
        .SetHideRootName(true)
        .SetHideName(true)
        .SetAllowOnelinerMode(true);
    if (m_format_options.GetFormatValue().OptionWasSet())
      options.SetFormat(m_format_options.GetFormatValue().GetCurrentValue());

    StreamString value_stream;
    if (llvm::Error error = value_sp->Dump(value_stream, options)) {
      result.AppendError(toString(std::move(error)));
      return;
    }

    llvm::StringRef value = value_stream.GetString();
    value.consume_back("\n");
    const char *register_name =
        m_command_options.alternate_name && reg_info.alt_name
            ? reg_info.alt_name
            : reg_info.name;

    StreamString expression_stream;
    value_sp->GetExpressionPath(expression_stream);
    llvm::StringRef expression = expression_stream.GetString();
    expression.consume_front("$");
    llvm::StringRef expression_path = expression;

    strm.Indent();
    // Keep the resolved suffix while allowing an alternate register name.
    if (expression_path.consume_front(reg_info.name))
      strm.Printf("%*s%s = ", static_cast<int>(reg_name_right_align_at),
                  register_name, expression_path.str().c_str());
    else
      strm.Printf("%*s = ", static_cast<int>(reg_name_right_align_at),
                  expression.str().c_str());
    strm << value << '\n';
  }

  bool DumpRegisterSet(const ExecutionContext &exe_ctx, Stream &strm,
                       RegisterContext *reg_ctx, size_t set_idx,
                       bool primitive_only = false) {
    uint32_t unavailable_count = 0;
    uint32_t available_count = 0;

    if (!reg_ctx)
      return false; // thread has no registers (i.e. core files are corrupt,
                    // incomplete crash logs...)

    const RegisterSet *const reg_set = reg_ctx->GetRegisterSet(set_idx);
    if (reg_set) {
      strm.Printf("%s:\n", (reg_set->name ? reg_set->name : "unknown"));
      strm.IndentMore();
      const size_t num_registers = reg_set->num_registers;
      size_t reg_name_right_align_at = ComputeLongestRegisterName(
          reg_ctx, *reg_set, !m_command_options.alternate_name, primitive_only);
      for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
        const uint32_t reg = reg_set->registers[reg_idx];
        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg);
        // Skip the dumping of derived register if primitive_only is true.
        if (primitive_only && reg_info && reg_info->value_regs)
          continue;

        if (reg_info &&
            DumpRegister(exe_ctx, strm, *reg_ctx, *reg_info,
                         /*print_type=*/false, reg_name_right_align_at))
          ++available_count;
        else
          ++unavailable_count;
      }
      strm.IndentLess();
      if (unavailable_count) {
        strm.Indent();
        strm.Printf("%u registers were unavailable.\n", unavailable_count);
      }
      strm.EOL();
    }
    return available_count > 0;
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Stream &strm = result.GetOutputStream();
    RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();

    if (command.GetArgumentCount() == 0) {
      size_t set_idx;

      size_t num_register_sets = 1;
      const size_t set_array_size = m_command_options.set_indexes.GetSize();
      if (set_array_size > 0) {
        for (size_t i = 0; i < set_array_size; ++i) {
          set_idx =
              m_command_options.set_indexes[i]->GetValueAs<uint64_t>().value_or(
                  UINT32_MAX);
          if (set_idx < reg_ctx->GetRegisterSetCount()) {
            if (!DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx)) {
              if (errno)
                result.AppendErrorWithFormatv("register read failed: {0}\n",
                                              llvm::sys::StrError());
              else
                result.AppendError("unknown error while reading registers.\n");
              break;
            }
          } else {
            result.AppendErrorWithFormat("invalid register set index: %" PRIu64,
                                         (uint64_t)set_idx);
            break;
          }
        }
      } else {
        if (m_command_options.dump_all_sets)
          num_register_sets = reg_ctx->GetRegisterSetCount();

        for (set_idx = 0; set_idx < num_register_sets; ++set_idx) {
          // When dump_all_sets option is set, dump primitive as well as
          // derived registers.
          DumpRegisterSet(m_exe_ctx, strm, reg_ctx, set_idx,
                          !m_command_options.dump_all_sets.GetCurrentValue());
        }
      }
    } else {
      if (m_command_options.dump_all_sets) {
        result.AppendError("the --all option can't be used when registers "
                           "names are supplied as arguments\n");
      } else if (m_command_options.set_indexes.GetSize() > 0) {
        result.AppendError("the --set <set> option can't be used when "
                           "registers names are supplied as arguments\n");
      } else {
        struct RegisterArgument {
          std::string expression;
          const RegisterInfo *reg_info = nullptr;
          ValueObjectSP value_sp;
          Status error;
        };

        StackFrame *frame = m_exe_ctx.GetFramePtr();
        if (!frame) {
          result.AppendError("no frame");
          return;
        }
        std::vector<RegisterArgument> register_arguments;
        register_arguments.reserve(command.GetArgumentCount());
        size_t reg_name_right_align_at = 0;

        for (auto &entry : command) {
          RegisterArgument argument;
          argument.expression = entry.ref().str();

          llvm::StringRef expression = entry.ref();
          expression.consume_front("$");
          std::string variable_path = "$" + expression.str();
          VariableSP variable_sp;
          argument.value_sp = frame->GetValueForVariableExpressionPath(
              variable_path, eNoDynamicValues,
              StackFrame::eExpressionPathOptionCheckPtrVsMember, variable_sp,
              argument.error, eDILModeLegacy);
          if (argument.error.Fail() &&
              expression.find_first_of(".[") == llvm::StringRef::npos &&
              !expression.contains("->")) {
            argument.error = Status::FromErrorStringWithFormat(
                "Invalid register name or identifier '%s'",
                argument.expression.c_str());
          }
          if (argument.error.Success()) {
            ValueObject *root = argument.value_sp->GetRoot();
            if (root && root->GetValueType() == eValueTypeRegister)
              argument.reg_info = reg_ctx->GetRegisterInfoByName(
                  root->GetName().GetStringRef());
          }

          if (argument.error.Success() && !argument.reg_info)
            argument.error = Status::FromErrorStringWithFormat(
                "Invalid register expression '%s'",
                argument.expression.c_str());
          else if (argument.error.Success())
            reg_name_right_align_at =
                std::max(reg_name_right_align_at,
                         GetNameSize(argument.reg_info,
                                     !m_command_options.alternate_name));
          register_arguments.push_back(std::move(argument));
        }

        // Extra ident to be consistent with register sets dumping.
        strm.IndentMore();
        for (const RegisterArgument &argument : register_arguments) {
          if (argument.error.Fail()) {
            result.AppendError(argument.error.AsCString());
            continue;
          }

          if (argument.value_sp.get() == argument.value_sp->GetRoot()) {
            // If they have asked for a specific format don't obscure that by
            // printing a structured value afterwards.
            bool print_type = !m_format_options.GetFormatValue().OptionWasSet();
            if (!DumpRegister(m_exe_ctx, strm, *reg_ctx, *argument.reg_info,
                              print_type, reg_name_right_align_at))
              strm.Printf("%-12s = error: unavailable\n",
                          argument.reg_info->name);
          } else {
            DumpRegisterField(strm, *argument.reg_info, argument.value_sp,
                              reg_name_right_align_at, result);
          }
        }
        strm.IndentLess();
      }
    }
    if (result.GetStatus() != eReturnStatusFailed)
      result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  class CommandOptions : public OptionGroup {
  public:
    CommandOptions()
        : set_indexes(OptionValue::ConvertTypeToMask(OptionValue::eTypeUInt64)),
          dump_all_sets(false, false), // Initial and default values are false
          alternate_name(false, false) {}

    ~CommandOptions() override = default;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      set_indexes.Clear();
      dump_all_sets.Clear();
      alternate_name.Clear();
    }

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = GetDefinitions()[option_idx].short_option;
      switch (short_option) {
      case 's': {
        OptionValueSP value_sp(OptionValueUInt64::Create(option_value, error));
        if (value_sp)
          set_indexes.AppendValue(value_sp);
      } break;

      case 'a':
        // When we don't use OptionValue::SetValueFromCString(const char *) to
        // set an option value, it won't be marked as being set in the options
        // so we make a call to let users know the value was set via option
        dump_all_sets.SetCurrentValue(true);
        dump_all_sets.SetOptionWasSet();
        break;

      case 'A':
        // When we don't use OptionValue::SetValueFromCString(const char *) to
        // set an option value, it won't be marked as being set in the options
        // so we make a call to let users know the value was set via option
        alternate_name.SetCurrentValue(true);
        dump_all_sets.SetOptionWasSet();
        break;

      default:
        llvm_unreachable("Unimplemented option");
      }
      return error;
    }

    // Instance variables to hold the values for command options.
    OptionValueArray set_indexes;
    OptionValueBoolean dump_all_sets;
    OptionValueBoolean alternate_name;
  };

  OptionGroupOptions m_option_group;
  OptionGroupFormat m_format_options;
  CommandOptions m_command_options;
};

// "register write"
class CommandObjectRegisterWrite : public CommandObjectParsed {
public:
  CommandObjectRegisterWrite(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "register write",
                            "Modify a single register value.", nullptr,
                            eCommandRequiresFrame | eCommandRequiresRegContext |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData register_arg;
    CommandArgumentData value_arg;

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

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

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

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

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

  ~CommandObjectRegisterWrite() override = default;

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

    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        GetCommandInterpreter(), lldb::eRegisterCompletion, request, nullptr);
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    DataExtractor reg_data;
    RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();

    if (command.GetArgumentCount() != 2) {
      result.AppendError(
          "register write takes exactly 2 arguments: <reg-name> <value>");
    } else {
      auto reg_name = command[0].ref();
      auto value_str = command[1].ref();

      // in most LLDB commands we accept $rbx as the name for register RBX -
      // and here we would reject it and non-existant. we should be more
      // consistent towards the user and allow them to say reg write $rbx -
      // internally, however, we should be strict and not allow ourselves to
      // call our registers $rbx in our own API
      reg_name.consume_front("$");

      const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);

      if (reg_info) {
        RegisterValue reg_value;

        Status error(reg_value.SetValueFromString(reg_info, value_str));
        if (error.Success()) {
          if (reg_ctx->WriteRegister(reg_info, reg_value)) {
            // Toss all frames and anything else in the thread after a register
            // has been written.
            m_exe_ctx.GetThreadRef().Flush();
            result.SetStatus(eReturnStatusSuccessFinishNoResult);
            return;
          }
        }
        if (error.AsCString()) {
          result.AppendErrorWithFormat(
              "Failed to write register '%s' with value '%s': %s",
              reg_name.str().c_str(), value_str.str().c_str(),
              error.AsCString());
        } else {
          result.AppendErrorWithFormat(
              "Failed to write register '%s' with value '%s'",
              reg_name.str().c_str(), value_str.str().c_str());
        }
      } else {
        result.AppendErrorWithFormat("Register not found for '%s'",
                                     reg_name.str().c_str());
      }
    }
  }
};

// "register info"
class CommandObjectRegisterInfo : public CommandObjectParsed {
public:
  CommandObjectRegisterInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "register info",
                            "View information about a register.", nullptr,
                            eCommandRequiresFrame | eCommandRequiresRegContext |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    SetHelpLong(R"(
Name             The name lldb uses for the register, optionally with an alias.
Size             The size of the register in bytes and again in bits.
Invalidates (*)  The registers that would be changed if you wrote this
                 register. For example, writing to a narrower alias of a wider
                 register would change the value of the wider register.
Read from   (*)  The registers that the value of this register is constructed
                 from. For example, a narrower alias of a wider register will be
                 read from the wider register.
In sets     (*)  The register sets that contain this register. For example the
                 PC will be in the "General Purpose Register" set.
Fields      (*)  A table of the names and bit positions of the values contained
                 in this register.

Fields marked with (*) may not always be present. Some information may be
different for the same register when connected to different debug servers.)");

    AddSimpleArgumentList(eArgTypeRegisterName);
  }

  ~CommandObjectRegisterInfo() override = default;

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
      return;
    CommandObject::HandleArgumentCompletion(request, opt_element_vector);
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    if (command.GetArgumentCount() != 1) {
      result.AppendError("register info takes exactly 1 argument: <reg-name>");
      return;
    }

    llvm::StringRef reg_name = command[0].ref();
    RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext();
    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
    if (reg_info) {
      DumpRegisterInfo(
          result.GetOutputStream(), *reg_ctx, *reg_info,
          GetCommandInterpreter().GetDebugger().GetTerminalWidth());
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else
      result.AppendErrorWithFormat("No register found with name '%s'",
                                   reg_name.str().c_str());
  }
};

// CommandObjectRegister constructor
CommandObjectRegister::CommandObjectRegister(CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "register",
                             "Commands to access registers for the current "
                             "thread and stack frame.",
                             "register [read|write|info] ...") {
  LoadSubCommand("read",
                 CommandObjectSP(new CommandObjectRegisterRead(interpreter)));
  LoadSubCommand("write",
                 CommandObjectSP(new CommandObjectRegisterWrite(interpreter)));
  LoadSubCommand("info",
                 CommandObjectSP(new CommandObjectRegisterInfo(interpreter)));
}

CommandObjectRegister::~CommandObjectRegister() = default;
