//===-- 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/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/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"
#include "llvm/Support/Errno.h"

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

// We expect that [command] only contains register names to be printed.
static size_t ComputeLongestRegisterName(Args &command,
                                         RegisterContext *reg_ctx,
                                         bool use_primary_name) {
  size_t name_right_align_at = 0;

  // Loop through all the arguments to find the longest register name.
  for (auto &entry : command) {
    // In most LLDB commands we accept '$<register>' as well as '<register>'
    // for example '$rbx' for 'rbx'. However internally the name does not have
    // '$'.
    llvm::StringRef arg_str = entry.ref();
    arg_str.consume_front("$");

    if (const RegisterInfo *reg_info =
            reg_ctx->GetRegisterInfoByName(arg_str)) {
      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;
  }

  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 {
        int reg_name_right_align_at = ComputeLongestRegisterName(
            command, reg_ctx, !m_command_options.alternate_name);
        // Extra ident to be consistent with register sets dumping.
        strm.IndentMore();
        for (auto &entry : command) {
          // 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 read $rbx -
          // internally, however, we should be strict and not allow ourselves
          // to call our registers $rbx in our own API
          auto arg_str = entry.ref();
          arg_str.consume_front("$");

          if (const RegisterInfo *reg_info =
                  reg_ctx->GetRegisterInfoByName(arg_str)) {
            // 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, *reg_info, print_type,
                              reg_name_right_align_at))
              strm.Printf("%-12s = error: unavailable\n", reg_info->name);
          } else {
            result.AppendErrorWithFormat("Invalid register name '%s'",
                                         arg_str.str().c_str());
          }
        }
        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;
