//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <inttypes.h>

// C++ Includes
// Other libraries and framework includes
#include "clang/AST/Decl.h"

// Project includes
#include "CommandObjectMemory.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupOutputFile.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/StreamString.h"

#include "lldb/lldb-private.h"

using namespace lldb;
using namespace lldb_private;

static OptionDefinition g_read_memory_options[] = {
    // clang-format off
  {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine, "The number of items per line to display." },
  {LLDB_OPT_SET_2, false, "binary",       'b', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,          "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that "
                                                                                                                            "uses the format, size, count and number per line settings." },
  {LLDB_OPT_SET_3, true , "type",         't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone,          "The name of a type to view memory as." },
  {LLDB_OPT_SET_3, false, "offset",       'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,         "How many elements of the specified type to skip before starting to display data." },
  {LLDB_OPT_SET_1 |
   LLDB_OPT_SET_2 |
   LLDB_OPT_SET_3, false, "force",        'r', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,          "Necessary if reading over target.max-memory-read-size bytes." },
    // clang-format on
};

class OptionGroupReadMemory : public OptionGroup {
public:
  OptionGroupReadMemory()
      : m_num_per_line(1, 1), m_output_as_binary(false), m_view_as_type(),
        m_offset(0, 0) {}

  ~OptionGroupReadMemory() override = default;

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

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

    switch (short_option) {
    case 'l':
      error = m_num_per_line.SetValueFromString(option_value);
      if (m_num_per_line.GetCurrentValue() == 0)
        error.SetErrorStringWithFormat(
            "invalid value for --num-per-line option '%s'",
            option_value.str().c_str());
      break;

    case 'b':
      m_output_as_binary = true;
      break;

    case 't':
      error = m_view_as_type.SetValueFromString(option_value);
      break;

    case 'r':
      m_force = true;
      break;

    case 'E':
      error = m_offset.SetValueFromString(option_value);
      break;

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

  void OptionParsingStarting(ExecutionContext *execution_context) override {
    m_num_per_line.Clear();
    m_output_as_binary = false;
    m_view_as_type.Clear();
    m_force = false;
    m_offset.Clear();
  }

  Status FinalizeSettings(Target *target, OptionGroupFormat &format_options) {
    Status error;
    OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
    OptionValueUInt64 &count_value = format_options.GetCountValue();
    const bool byte_size_option_set = byte_size_value.OptionWasSet();
    const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
    const bool count_option_set = format_options.GetCountValue().OptionWasSet();

    switch (format_options.GetFormat()) {
    default:
      break;

    case eFormatBoolean:
      if (!byte_size_option_set)
        byte_size_value = 1;
      if (!num_per_line_option_set)
        m_num_per_line = 1;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatCString:
      break;

    case eFormatInstruction:
      if (count_option_set)
        byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
      m_num_per_line = 1;
      break;

    case eFormatAddressInfo:
      if (!byte_size_option_set)
        byte_size_value = target->GetArchitecture().GetAddressByteSize();
      m_num_per_line = 1;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatPointer:
      byte_size_value = target->GetArchitecture().GetAddressByteSize();
      if (!num_per_line_option_set)
        m_num_per_line = 4;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatBinary:
    case eFormatFloat:
    case eFormatOctal:
    case eFormatDecimal:
    case eFormatEnum:
    case eFormatUnicode16:
    case eFormatUnicode32:
    case eFormatUnsigned:
    case eFormatHexFloat:
      if (!byte_size_option_set)
        byte_size_value = 4;
      if (!num_per_line_option_set)
        m_num_per_line = 1;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatBytes:
    case eFormatBytesWithASCII:
      if (byte_size_option_set) {
        if (byte_size_value > 1)
          error.SetErrorStringWithFormat(
              "display format (bytes/bytes with ASCII) conflicts with the "
              "specified byte size %" PRIu64 "\n"
              "\tconsider using a different display format or don't specify "
              "the byte size.",
              byte_size_value.GetCurrentValue());
      } else
        byte_size_value = 1;
      if (!num_per_line_option_set)
        m_num_per_line = 16;
      if (!count_option_set)
        format_options.GetCountValue() = 32;
      break;

    case eFormatCharArray:
    case eFormatChar:
    case eFormatCharPrintable:
      if (!byte_size_option_set)
        byte_size_value = 1;
      if (!num_per_line_option_set)
        m_num_per_line = 32;
      if (!count_option_set)
        format_options.GetCountValue() = 64;
      break;

    case eFormatComplex:
      if (!byte_size_option_set)
        byte_size_value = 8;
      if (!num_per_line_option_set)
        m_num_per_line = 1;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatComplexInteger:
      if (!byte_size_option_set)
        byte_size_value = 8;
      if (!num_per_line_option_set)
        m_num_per_line = 1;
      if (!count_option_set)
        format_options.GetCountValue() = 8;
      break;

    case eFormatHex:
      if (!byte_size_option_set)
        byte_size_value = 4;
      if (!num_per_line_option_set) {
        switch (byte_size_value) {
        case 1:
        case 2:
          m_num_per_line = 8;
          break;
        case 4:
          m_num_per_line = 4;
          break;
        case 8:
          m_num_per_line = 2;
          break;
        default:
          m_num_per_line = 1;
          break;
        }
      }
      if (!count_option_set)
        count_value = 8;
      break;

    case eFormatVectorOfChar:
    case eFormatVectorOfSInt8:
    case eFormatVectorOfUInt8:
    case eFormatVectorOfSInt16:
    case eFormatVectorOfUInt16:
    case eFormatVectorOfSInt32:
    case eFormatVectorOfUInt32:
    case eFormatVectorOfSInt64:
    case eFormatVectorOfUInt64:
    case eFormatVectorOfFloat16:
    case eFormatVectorOfFloat32:
    case eFormatVectorOfFloat64:
    case eFormatVectorOfUInt128:
      if (!byte_size_option_set)
        byte_size_value = 128;
      if (!num_per_line_option_set)
        m_num_per_line = 1;
      if (!count_option_set)
        count_value = 4;
      break;
    }
    return error;
  }

  bool AnyOptionWasSet() const {
    return m_num_per_line.OptionWasSet() || m_output_as_binary ||
           m_view_as_type.OptionWasSet() || m_offset.OptionWasSet();
  }

  OptionValueUInt64 m_num_per_line;
  bool m_output_as_binary;
  OptionValueString m_view_as_type;
  bool m_force;
  OptionValueUInt64 m_offset;
};

//----------------------------------------------------------------------
// Read memory from the inferior process
//----------------------------------------------------------------------
class CommandObjectMemoryRead : public CommandObjectParsed {
public:
  CommandObjectMemoryRead(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "memory read",
            "Read from the memory of the current target process.", nullptr,
            eCommandRequiresTarget | eCommandProcessMustBePaused),
        m_option_group(), m_format_options(eFormatBytesWithASCII, 1, 8),
        m_memory_options(), m_outfile_options(), m_varobj_options(),
        m_next_addr(LLDB_INVALID_ADDRESS), m_prev_byte_size(0),
        m_prev_format_options(eFormatBytesWithASCII, 1, 8),
        m_prev_memory_options(), m_prev_outfile_options(),
        m_prev_varobj_options() {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData start_addr_arg;
    CommandArgumentData end_addr_arg;

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

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

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

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

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

    // Add the "--format" and "--count" options to group 1 and 3
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_COUNT,
                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
    // Add the "--size" option to group 1 and 2
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_SIZE,
                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
    m_option_group.Append(&m_memory_options);
    m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL,
                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
    m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
    m_option_group.Finalize();
  }

  ~CommandObjectMemoryRead() override = default;

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

  const char *GetRepeatCommand(Args &current_command_args,
                               uint32_t index) override {
    return m_cmd_name.c_str();
  }

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

    const size_t argc = command.GetArgumentCount();

    if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) {
      result.AppendErrorWithFormat("%s takes a start address expression with "
                                   "an optional end address expression.\n",
                                   m_cmd_name.c_str());
      result.AppendRawWarning("Expressions should be quoted if they contain "
                              "spaces or other special characters.\n");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    CompilerType clang_ast_type;
    Status error;

    const char *view_as_type_cstr =
        m_memory_options.m_view_as_type.GetCurrentValue();
    if (view_as_type_cstr && view_as_type_cstr[0]) {
      // We are viewing memory as a type

      SymbolContext sc;
      const bool exact_match = false;
      TypeList type_list;
      uint32_t reference_count = 0;
      uint32_t pointer_count = 0;
      size_t idx;

#define ALL_KEYWORDS                                                           \
  KEYWORD("const")                                                             \
  KEYWORD("volatile")                                                          \
  KEYWORD("restrict")                                                          \
  KEYWORD("struct")                                                            \
  KEYWORD("class")                                                             \
  KEYWORD("union")

#define KEYWORD(s) s,
      static const char *g_keywords[] = {ALL_KEYWORDS};
#undef KEYWORD

#define KEYWORD(s) (sizeof(s) - 1),
      static const int g_keyword_lengths[] = {ALL_KEYWORDS};
#undef KEYWORD

#undef ALL_KEYWORDS

      static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
      std::string type_str(view_as_type_cstr);

      // Remove all instances of g_keywords that are followed by spaces
      for (size_t i = 0; i < g_num_keywords; ++i) {
        const char *keyword = g_keywords[i];
        int keyword_len = g_keyword_lengths[i];

        idx = 0;
        while ((idx = type_str.find(keyword, idx)) != std::string::npos) {
          if (type_str[idx + keyword_len] == ' ' ||
              type_str[idx + keyword_len] == '\t') {
            type_str.erase(idx, keyword_len + 1);
            idx = 0;
          } else {
            idx += keyword_len;
          }
        }
      }
      bool done = type_str.empty();
      //
      idx = type_str.find_first_not_of(" \t");
      if (idx > 0 && idx != std::string::npos)
        type_str.erase(0, idx);
      while (!done) {
        // Strip trailing spaces
        if (type_str.empty())
          done = true;
        else {
          switch (type_str[type_str.size() - 1]) {
          case '*':
            ++pointer_count;
            LLVM_FALLTHROUGH;
          case ' ':
          case '\t':
            type_str.erase(type_str.size() - 1);
            break;

          case '&':
            if (reference_count == 0) {
              reference_count = 1;
              type_str.erase(type_str.size() - 1);
            } else {
              result.AppendErrorWithFormat("invalid type string: '%s'\n",
                                           view_as_type_cstr);
              result.SetStatus(eReturnStatusFailed);
              return false;
            }
            break;

          default:
            done = true;
            break;
          }
        }
      }

      llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
      ConstString lookup_type_name(type_str.c_str());
      StackFrame *frame = m_exe_ctx.GetFramePtr();
      if (frame) {
        sc = frame->GetSymbolContext(eSymbolContextModule);
        if (sc.module_sp) {
          sc.module_sp->FindTypes(sc, lookup_type_name, exact_match, 1,
                                  searched_symbol_files, type_list);
        }
      }
      if (type_list.GetSize() == 0) {
        target->GetImages().FindTypes(sc, lookup_type_name, exact_match, 1,
                                      searched_symbol_files, type_list);
      }

      if (type_list.GetSize() == 0 && lookup_type_name.GetCString() &&
          *lookup_type_name.GetCString() == '$') {
        if (ClangPersistentVariables *persistent_vars =
                llvm::dyn_cast_or_null<ClangPersistentVariables>(
                    target->GetPersistentExpressionStateForLanguage(
                        lldb::eLanguageTypeC))) {
          clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(
              persistent_vars->GetPersistentDecl(
                  ConstString(lookup_type_name)));

          if (tdecl) {
            clang_ast_type.SetCompilerType(
                ClangASTContext::GetASTContext(&tdecl->getASTContext()),
                reinterpret_cast<lldb::opaque_compiler_type_t>(
                    const_cast<clang::Type *>(tdecl->getTypeForDecl())));
          }
        }
      }

      if (!clang_ast_type.IsValid()) {
        if (type_list.GetSize() == 0) {
          result.AppendErrorWithFormat("unable to find any types that match "
                                       "the raw type '%s' for full type '%s'\n",
                                       lookup_type_name.GetCString(),
                                       view_as_type_cstr);
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else {
          TypeSP type_sp(type_list.GetTypeAtIndex(0));
          clang_ast_type = type_sp->GetFullCompilerType();
        }
      }

      while (pointer_count > 0) {
        CompilerType pointer_type = clang_ast_type.GetPointerType();
        if (pointer_type.IsValid())
          clang_ast_type = pointer_type;
        else {
          result.AppendError("unable make a pointer type\n");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        --pointer_count;
      }

      m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);

      if (m_format_options.GetByteSizeValue() == 0) {
        result.AppendErrorWithFormat(
            "unable to get the byte size of the type '%s'\n",
            view_as_type_cstr);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      if (!m_format_options.GetCountValue().OptionWasSet())
        m_format_options.GetCountValue() = 1;
    } else {
      error = m_memory_options.FinalizeSettings(target, m_format_options);
    }

    // Look for invalid combinations of settings
    if (error.Fail()) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    lldb::addr_t addr;
    size_t total_byte_size = 0;
    if (argc == 0) {
      // Use the last address and byte size and all options as they were
      // if no options have been set
      addr = m_next_addr;
      total_byte_size = m_prev_byte_size;
      clang_ast_type = m_prev_clang_ast_type;
      if (!m_format_options.AnyOptionWasSet() &&
          !m_memory_options.AnyOptionWasSet() &&
          !m_outfile_options.AnyOptionWasSet() &&
          !m_varobj_options.AnyOptionWasSet()) {
        m_format_options = m_prev_format_options;
        m_memory_options = m_prev_memory_options;
        m_outfile_options = m_prev_outfile_options;
        m_varobj_options = m_prev_varobj_options;
      }
    }

    size_t item_count = m_format_options.GetCountValue().GetCurrentValue();

    // TODO For non-8-bit byte addressable architectures this needs to be
    // revisited to fully support all lldb's range of formatting options.
    // Furthermore code memory reads (for those architectures) will not
    // be correctly formatted even w/o formatting options.
    size_t item_byte_size =
        target->GetArchitecture().GetDataByteSize() > 1
            ? target->GetArchitecture().GetDataByteSize()
            : m_format_options.GetByteSizeValue().GetCurrentValue();

    const size_t num_per_line =
        m_memory_options.m_num_per_line.GetCurrentValue();

    if (total_byte_size == 0) {
      total_byte_size = item_count * item_byte_size;
      if (total_byte_size == 0)
        total_byte_size = 32;
    }

    if (argc > 0)
      addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
                                   LLDB_INVALID_ADDRESS, &error);

    if (addr == LLDB_INVALID_ADDRESS) {
      result.AppendError("invalid start address expression.");
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (argc == 2) {
      lldb::addr_t end_addr = Args::StringToAddress(
          &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, nullptr);
      if (end_addr == LLDB_INVALID_ADDRESS) {
        result.AppendError("invalid end address expression.");
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
      } else if (end_addr <= addr) {
        result.AppendErrorWithFormat(
            "end address (0x%" PRIx64
            ") must be greater that the start address (0x%" PRIx64 ").\n",
            end_addr, addr);
        result.SetStatus(eReturnStatusFailed);
        return false;
      } else if (m_format_options.GetCountValue().OptionWasSet()) {
        result.AppendErrorWithFormat(
            "specify either the end address (0x%" PRIx64
            ") or the count (--count %" PRIu64 "), not both.\n",
            end_addr, (uint64_t)item_count);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      total_byte_size = end_addr - addr;
      item_count = total_byte_size / item_byte_size;
    }

    uint32_t max_unforced_size = target->GetMaximumMemReadSize();

    if (total_byte_size > max_unforced_size && !m_memory_options.m_force) {
      result.AppendErrorWithFormat(
          "Normally, \'memory read\' will not read over %" PRIu32
          " bytes of data.\n",
          max_unforced_size);
      result.AppendErrorWithFormat(
          "Please use --force to override this restriction just once.\n");
      result.AppendErrorWithFormat("or set target.max-memory-read-size if you "
                                   "will often need a larger limit.\n");
      return false;
    }

    DataBufferSP data_sp;
    size_t bytes_read = 0;
    if (clang_ast_type.GetOpaqueQualType()) {
      // Make sure we don't display our type as ASCII bytes like the default
      // memory read
      if (!m_format_options.GetFormatValue().OptionWasSet())
        m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);

      bytes_read = clang_ast_type.GetByteSize(nullptr) *
                   m_format_options.GetCountValue().GetCurrentValue();

      if (argc > 0)
        addr = addr + (clang_ast_type.GetByteSize(nullptr) *
                       m_memory_options.m_offset.GetCurrentValue());
    } else if (m_format_options.GetFormatValue().GetCurrentValue() !=
               eFormatCString) {
      data_sp.reset(new DataBufferHeap(total_byte_size, '\0'));
      if (data_sp->GetBytes() == nullptr) {
        result.AppendErrorWithFormat(
            "can't allocate 0x%" PRIx32
            " bytes for the memory read buffer, specify a smaller size to read",
            (uint32_t)total_byte_size);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      Address address(addr, nullptr);
      bytes_read = target->ReadMemory(address, false, data_sp->GetBytes(),
                                      data_sp->GetByteSize(), error);
      if (bytes_read == 0) {
        const char *error_cstr = error.AsCString();
        if (error_cstr && error_cstr[0]) {
          result.AppendError(error_cstr);
        } else {
          result.AppendErrorWithFormat(
              "failed to read memory from 0x%" PRIx64 ".\n", addr);
        }
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      if (bytes_read < total_byte_size)
        result.AppendWarningWithFormat(
            "Not all bytes (%" PRIu64 "/%" PRIu64
            ") were able to be read from 0x%" PRIx64 ".\n",
            (uint64_t)bytes_read, (uint64_t)total_byte_size, addr);
    } else {
      // we treat c-strings as a special case because they do not have a fixed
      // size
      if (m_format_options.GetByteSizeValue().OptionWasSet() &&
          !m_format_options.HasGDBFormat())
        item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
      else
        item_byte_size = target->GetMaximumSizeOfStringSummary();
      if (!m_format_options.GetCountValue().OptionWasSet())
        item_count = 1;
      data_sp.reset(new DataBufferHeap((item_byte_size + 1) * item_count,
                                       '\0')); // account for NULLs as necessary
      if (data_sp->GetBytes() == nullptr) {
        result.AppendErrorWithFormat(
            "can't allocate 0x%" PRIx64
            " bytes for the memory read buffer, specify a smaller size to read",
            (uint64_t)((item_byte_size + 1) * item_count));
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      uint8_t *data_ptr = data_sp->GetBytes();
      auto data_addr = addr;
      auto count = item_count;
      item_count = 0;
      bool break_on_no_NULL = false;
      while (item_count < count) {
        std::string buffer;
        buffer.resize(item_byte_size + 1, 0);
        Status error;
        size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0],
                                                    item_byte_size + 1, error);
        if (error.Fail()) {
          result.AppendErrorWithFormat(
              "failed to read memory from 0x%" PRIx64 ".\n", addr);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }

        if (item_byte_size == read) {
          result.AppendWarningWithFormat(
              "unable to find a NULL terminated string at 0x%" PRIx64
              ".Consider increasing the maximum read length.\n",
              data_addr);
          --read;
          break_on_no_NULL = true;
        } else
          ++read; // account for final NULL byte

        memcpy(data_ptr, &buffer[0], read);
        data_ptr += read;
        data_addr += read;
        bytes_read += read;
        item_count++; // if we break early we know we only read item_count
                      // strings

        if (break_on_no_NULL)
          break;
      }
      data_sp.reset(new DataBufferHeap(data_sp->GetBytes(), bytes_read + 1));
    }

    m_next_addr = addr + bytes_read;
    m_prev_byte_size = bytes_read;
    m_prev_format_options = m_format_options;
    m_prev_memory_options = m_memory_options;
    m_prev_outfile_options = m_outfile_options;
    m_prev_varobj_options = m_varobj_options;
    m_prev_clang_ast_type = clang_ast_type;

    StreamFile outfile_stream;
    Stream *output_stream = nullptr;
    const FileSpec &outfile_spec =
        m_outfile_options.GetFile().GetCurrentValue();
    if (outfile_spec) {
      char path[PATH_MAX];
      outfile_spec.GetPath(path, sizeof(path));

      uint32_t open_options =
          File::eOpenOptionWrite | File::eOpenOptionCanCreate;
      const bool append = m_outfile_options.GetAppend().GetCurrentValue();
      if (append)
        open_options |= File::eOpenOptionAppend;

      if (outfile_stream.GetFile().Open(path, open_options).Success()) {
        if (m_memory_options.m_output_as_binary) {
          const size_t bytes_written =
              outfile_stream.Write(data_sp->GetBytes(), bytes_read);
          if (bytes_written > 0) {
            result.GetOutputStream().Printf(
                "%zi bytes %s to '%s'\n", bytes_written,
                append ? "appended" : "written", path);
            return true;
          } else {
            result.AppendErrorWithFormat("Failed to write %" PRIu64
                                         " bytes to '%s'.\n",
                                         (uint64_t)bytes_read, path);
            result.SetStatus(eReturnStatusFailed);
            return false;
          }
        } else {
          // We are going to write ASCII to the file just point the
          // output_stream to our outfile_stream...
          output_stream = &outfile_stream;
        }
      } else {
        result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path,
                                     append ? "append" : "write");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    } else {
      output_stream = &result.GetOutputStream();
    }

    ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
    if (clang_ast_type.GetOpaqueQualType()) {
      for (uint32_t i = 0; i < item_count; ++i) {
        addr_t item_addr = addr + (i * item_byte_size);
        Address address(item_addr);
        StreamString name_strm;
        name_strm.Printf("0x%" PRIx64, item_addr);
        ValueObjectSP valobj_sp(ValueObjectMemory::Create(
            exe_scope, name_strm.GetString(), address, clang_ast_type));
        if (valobj_sp) {
          Format format = m_format_options.GetFormat();
          if (format != eFormatDefault)
            valobj_sp->SetFormat(format);

          DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
              eLanguageRuntimeDescriptionDisplayVerbosityFull, format));

          valobj_sp->Dump(*output_stream, options);
        } else {
          result.AppendErrorWithFormat(
              "failed to create a value object for: (%s) %s\n",
              view_as_type_cstr, name_strm.GetData());
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
      }
      return true;
    }

    result.SetStatus(eReturnStatusSuccessFinishResult);
    DataExtractor data(data_sp, target->GetArchitecture().GetByteOrder(),
                       target->GetArchitecture().GetAddressByteSize(),
                       target->GetArchitecture().GetDataByteSize());

    Format format = m_format_options.GetFormat();
    if (((format == eFormatChar) || (format == eFormatCharPrintable)) &&
        (item_byte_size != 1)) {
      // if a count was not passed, or it is 1
      if (!m_format_options.GetCountValue().OptionWasSet() || item_count == 1) {
        // this turns requests such as
        // memory read -fc -s10 -c1 *charPtrPtr
        // which make no sense (what is a char of size 10?)
        // into a request for fetching 10 chars of size 1 from the same memory
        // location
        format = eFormatCharArray;
        item_count = item_byte_size;
        item_byte_size = 1;
      } else {
        // here we passed a count, and it was not 1
        // so we have a byte_size and a count
        // we could well multiply those, but instead let's just fail
        result.AppendErrorWithFormat(
            "reading memory as characters of size %" PRIu64 " is not supported",
            (uint64_t)item_byte_size);
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }

    assert(output_stream);
    size_t bytes_dumped = DumpDataExtractor(
        data, output_stream, 0, format, item_byte_size, item_count,
        num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0,
        exe_scope);
    m_next_addr = addr + bytes_dumped;
    output_stream->EOL();
    return true;
  }

  OptionGroupOptions m_option_group;
  OptionGroupFormat m_format_options;
  OptionGroupReadMemory m_memory_options;
  OptionGroupOutputFile m_outfile_options;
  OptionGroupValueObjectDisplay m_varobj_options;
  lldb::addr_t m_next_addr;
  lldb::addr_t m_prev_byte_size;
  OptionGroupFormat m_prev_format_options;
  OptionGroupReadMemory m_prev_memory_options;
  OptionGroupOutputFile m_prev_outfile_options;
  OptionGroupValueObjectDisplay m_prev_varobj_options;
  CompilerType m_prev_clang_ast_type;
};

OptionDefinition g_memory_find_option_table[] = {
    // clang-format off
  {LLDB_OPT_SET_1,   true,  "expression",  'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
  {LLDB_OPT_SET_2,   true,  "string",      's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,       "Use text to find a byte pattern."},
  {LLDB_OPT_SET_ALL, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,      "How many times to perform the search."},
  {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,     "When dumping memory for a match, an offset from the match location to start dumping from."},
    // clang-format on
};

//----------------------------------------------------------------------
// Find the specified data in memory
//----------------------------------------------------------------------
class CommandObjectMemoryFind : public CommandObjectParsed {
public:
  class OptionGroupFindMemory : public OptionGroup {
  public:
    OptionGroupFindMemory() : OptionGroup(), m_count(1), m_offset(0) {}

    ~OptionGroupFindMemory() override = default;

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

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

      switch (short_option) {
      case 'e':
        m_expr.SetValueFromString(option_value);
        break;

      case 's':
        m_string.SetValueFromString(option_value);
        break;

      case 'c':
        if (m_count.SetValueFromString(option_value).Fail())
          error.SetErrorString("unrecognized value for count");
        break;

      case 'o':
        if (m_offset.SetValueFromString(option_value).Fail())
          error.SetErrorString("unrecognized value for dump-offset");
        break;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_expr.Clear();
      m_string.Clear();
      m_count.Clear();
    }

    OptionValueString m_expr;
    OptionValueString m_string;
    OptionValueUInt64 m_count;
    OptionValueUInt64 m_offset;
  };

  CommandObjectMemoryFind(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "memory find",
            "Find a value in the memory of the current target process.",
            nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched),
        m_option_group(), m_memory_options() {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData addr_arg;
    CommandArgumentData value_arg;

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

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

    // Define the first (and only) variant of this arg.
    value_arg.arg_type = eArgTypeAddressOrExpression;
    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);

    m_option_group.Append(&m_memory_options);
    m_option_group.Finalize();
  }

  ~CommandObjectMemoryFind() override = default;

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

protected:
  class ProcessMemoryIterator {
  public:
    ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base)
        : m_process_sp(process_sp), m_base_addr(base), m_is_valid(true) {
      lldbassert(process_sp.get() != nullptr);
    }

    bool IsValid() { return m_is_valid; }

    uint8_t operator[](lldb::addr_t offset) {
      if (!IsValid())
        return 0;

      uint8_t retval = 0;
      Status error;
      if (0 ==
          m_process_sp->ReadMemory(m_base_addr + offset, &retval, 1, error)) {
        m_is_valid = false;
        return 0;
      }

      return retval;
    }

  private:
    ProcessSP m_process_sp;
    lldb::addr_t m_base_addr;
    bool m_is_valid;
  };
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "process" for validity as eCommandRequiresProcess
    // ensures it is valid
    Process *process = m_exe_ctx.GetProcessPtr();

    const size_t argc = command.GetArgumentCount();

    if (argc != 2) {
      result.AppendError("two addresses needed for memory find");
      return false;
    }

    Status error;
    lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
                                                  LLDB_INVALID_ADDRESS, &error);
    if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
      result.AppendError("invalid low address");
      return false;
    }
    lldb::addr_t high_addr = Args::StringToAddress(
        &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, &error);
    if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
      result.AppendError("invalid high address");
      return false;
    }

    if (high_addr <= low_addr) {
      result.AppendError(
          "starting address must be smaller than ending address");
      return false;
    }

    lldb::addr_t found_location = LLDB_INVALID_ADDRESS;

    DataBufferHeap buffer;

    if (m_memory_options.m_string.OptionWasSet())
      buffer.CopyData(m_memory_options.m_string.GetStringValue());
    else if (m_memory_options.m_expr.OptionWasSet()) {
      StackFrame *frame = m_exe_ctx.GetFramePtr();
      ValueObjectSP result_sp;
      if ((eExpressionCompleted ==
           process->GetTarget().EvaluateExpression(
               m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
          result_sp) {
        uint64_t value = result_sp->GetValueAsUnsigned(0);
        switch (result_sp->GetCompilerType().GetByteSize(nullptr)) {
        case 1: {
          uint8_t byte = (uint8_t)value;
          buffer.CopyData(&byte, 1);
        } break;
        case 2: {
          uint16_t word = (uint16_t)value;
          buffer.CopyData(&word, 2);
        } break;
        case 4: {
          uint32_t lword = (uint32_t)value;
          buffer.CopyData(&lword, 4);
        } break;
        case 8: {
          buffer.CopyData(&value, 8);
        } break;
        case 3:
        case 5:
        case 6:
        case 7:
          result.AppendError("unknown type. pass a string instead");
          return false;
        default:
          result.AppendError(
              "result size larger than 8 bytes. pass a string instead");
          return false;
        }
      } else {
        result.AppendError(
            "expression evaluation failed. pass a string instead");
        return false;
      }
    } else {
      result.AppendError(
          "please pass either a block of text, or an expression to evaluate.");
      return false;
    }

    size_t count = m_memory_options.m_count.GetCurrentValue();
    found_location = low_addr;
    bool ever_found = false;
    while (count) {
      found_location = FastSearch(found_location, high_addr, buffer.GetBytes(),
                                  buffer.GetByteSize());
      if (found_location == LLDB_INVALID_ADDRESS) {
        if (!ever_found) {
          result.AppendMessage("data not found within the range.\n");
          result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
        } else
          result.AppendMessage("no more matches within the range.\n");
        break;
      }
      result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n",
                                     found_location);

      DataBufferHeap dumpbuffer(32, 0);
      process->ReadMemory(
          found_location + m_memory_options.m_offset.GetCurrentValue(),
          dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
      if (!error.Fail()) {
        DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
                           process->GetByteOrder(),
                           process->GetAddressByteSize());
        DumpDataExtractor(
            data, &result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1,
            dumpbuffer.GetByteSize(), 16,
            found_location + m_memory_options.m_offset.GetCurrentValue(), 0, 0);
        result.GetOutputStream().EOL();
      }

      --count;
      found_location++;
      ever_found = true;
    }

    result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
    return true;
  }

  lldb::addr_t FastSearch(lldb::addr_t low, lldb::addr_t high, uint8_t *buffer,
                          size_t buffer_size) {
    const size_t region_size = high - low;

    if (region_size < buffer_size)
      return LLDB_INVALID_ADDRESS;

    std::vector<size_t> bad_char_heuristic(256, buffer_size);
    ProcessSP process_sp = m_exe_ctx.GetProcessSP();
    ProcessMemoryIterator iterator(process_sp, low);

    for (size_t idx = 0; idx < buffer_size - 1; idx++) {
      decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx];
      bad_char_heuristic[bcu_idx] = buffer_size - idx - 1;
    }
    for (size_t s = 0; s <= (region_size - buffer_size);) {
      int64_t j = buffer_size - 1;
      while (j >= 0 && buffer[j] == iterator[s + j])
        j--;
      if (j < 0)
        return low + s;
      else
        s += bad_char_heuristic[iterator[s + buffer_size - 1]];
    }

    return LLDB_INVALID_ADDRESS;
  }

  OptionGroupOptions m_option_group;
  OptionGroupFindMemory m_memory_options;
};

OptionDefinition g_memory_write_option_table[] = {
    // clang-format off
  {LLDB_OPT_SET_1, true,  "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."},
  {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset,   "Start writing bytes from an offset within the input file."},
    // clang-format on
};

//----------------------------------------------------------------------
// Write memory to the inferior process
//----------------------------------------------------------------------
class CommandObjectMemoryWrite : public CommandObjectParsed {
public:
  class OptionGroupWriteMemory : public OptionGroup {
  public:
    OptionGroupWriteMemory() : OptionGroup() {}

    ~OptionGroupWriteMemory() override = default;

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

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

      switch (short_option) {
      case 'i':
        m_infile.SetFile(option_value, true);
        if (!m_infile.Exists()) {
          m_infile.Clear();
          error.SetErrorStringWithFormat("input file does not exist: '%s'",
                                         option_value.str().c_str());
        }
        break;

      case 'o': {
        if (option_value.getAsInteger(0, m_infile_offset)) {
          m_infile_offset = 0;
          error.SetErrorStringWithFormat("invalid offset string '%s'",
                                         option_value.str().c_str());
        }
      } break;

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

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_infile.Clear();
      m_infile_offset = 0;
    }

    FileSpec m_infile;
    off_t m_infile_offset;
  };

  CommandObjectMemoryWrite(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "memory write",
            "Write to the memory of the current target process.", nullptr,
            eCommandRequiresProcess | eCommandProcessMustBeLaunched),
        m_option_group(), m_format_options(eFormatBytes, 1, UINT64_MAX),
        m_memory_options() {
    CommandArgumentEntry arg1;
    CommandArgumentEntry arg2;
    CommandArgumentData addr_arg;
    CommandArgumentData value_arg;

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

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

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

    // 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);

    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_FORMAT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_format_options,
                          OptionGroupFormat::OPTION_GROUP_SIZE,
                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
    m_option_group.Append(&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
    m_option_group.Finalize();
  }

  ~CommandObjectMemoryWrite() override = default;

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

  bool UIntValueIsValidForSize(uint64_t uval64, size_t total_byte_size) {
    if (total_byte_size > 8)
      return false;

    if (total_byte_size == 8)
      return true;

    const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
    return uval64 <= max;
  }

  bool SIntValueIsValidForSize(int64_t sval64, size_t total_byte_size) {
    if (total_byte_size > 8)
      return false;

    if (total_byte_size == 8)
      return true;

    const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
    const int64_t min = ~(max);
    return min <= sval64 && sval64 <= max;
  }

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

    const size_t argc = command.GetArgumentCount();

    if (m_memory_options.m_infile) {
      if (argc < 1) {
        result.AppendErrorWithFormat(
            "%s takes a destination address when writing file contents.\n",
            m_cmd_name.c_str());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    } else if (argc < 2) {
      result.AppendErrorWithFormat(
          "%s takes a destination address and at least one value.\n",
          m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    StreamString buffer(
        Stream::eBinary,
        process->GetTarget().GetArchitecture().GetAddressByteSize(),
        process->GetTarget().GetArchitecture().GetByteOrder());

    OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
    size_t item_byte_size = byte_size_value.GetCurrentValue();

    Status error;
    lldb::addr_t addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
                                              LLDB_INVALID_ADDRESS, &error);

    if (addr == LLDB_INVALID_ADDRESS) {
      result.AppendError("invalid address expression\n");
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    if (m_memory_options.m_infile) {
      size_t length = SIZE_MAX;
      if (item_byte_size > 1)
        length = item_byte_size;
      auto data_sp = DataBufferLLVM::CreateSliceFromPath(
          m_memory_options.m_infile.GetPath(), length,
          m_memory_options.m_infile_offset);
      if (data_sp) {
        length = data_sp->GetByteSize();
        if (length > 0) {
          Status error;
          size_t bytes_written =
              process->WriteMemory(addr, data_sp->GetBytes(), length, error);

          if (bytes_written == length) {
            // All bytes written
            result.GetOutputStream().Printf(
                "%" PRIu64 " bytes were written to 0x%" PRIx64 "\n",
                (uint64_t)bytes_written, addr);
            result.SetStatus(eReturnStatusSuccessFinishResult);
          } else if (bytes_written > 0) {
            // Some byte written
            result.GetOutputStream().Printf(
                "%" PRIu64 " bytes of %" PRIu64
                " requested were written to 0x%" PRIx64 "\n",
                (uint64_t)bytes_written, (uint64_t)length, addr);
            result.SetStatus(eReturnStatusSuccessFinishResult);
          } else {
            result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
                                         " failed: %s.\n",
                                         addr, error.AsCString());
            result.SetStatus(eReturnStatusFailed);
          }
        }
      } else {
        result.AppendErrorWithFormat("Unable to read contents of file.\n");
        result.SetStatus(eReturnStatusFailed);
      }
      return result.Succeeded();
    } else if (item_byte_size == 0) {
      if (m_format_options.GetFormat() == eFormatPointer)
        item_byte_size = buffer.GetAddressByteSize();
      else
        item_byte_size = 1;
    }

    command.Shift(); // shift off the address argument
    uint64_t uval64;
    int64_t sval64;
    bool success = false;
    for (auto &entry : command) {
      switch (m_format_options.GetFormat()) {
      case kNumFormats:
      case eFormatFloat: // TODO: add support for floats soon
      case eFormatCharPrintable:
      case eFormatBytesWithASCII:
      case eFormatComplex:
      case eFormatEnum:
      case eFormatUnicode16:
      case eFormatUnicode32:
      case eFormatVectorOfChar:
      case eFormatVectorOfSInt8:
      case eFormatVectorOfUInt8:
      case eFormatVectorOfSInt16:
      case eFormatVectorOfUInt16:
      case eFormatVectorOfSInt32:
      case eFormatVectorOfUInt32:
      case eFormatVectorOfSInt64:
      case eFormatVectorOfUInt64:
      case eFormatVectorOfFloat16:
      case eFormatVectorOfFloat32:
      case eFormatVectorOfFloat64:
      case eFormatVectorOfUInt128:
      case eFormatOSType:
      case eFormatComplexInteger:
      case eFormatAddressInfo:
      case eFormatHexFloat:
      case eFormatInstruction:
      case eFormatVoid:
        result.AppendError("unsupported format for writing memory");
        result.SetStatus(eReturnStatusFailed);
        return false;

      case eFormatDefault:
      case eFormatBytes:
      case eFormatHex:
      case eFormatHexUppercase:
      case eFormatPointer:
      {
        // Decode hex bytes
        // Be careful, getAsInteger with a radix of 16 rejects "0xab" so we
        // have to special case that:
        bool success = false;
        if (entry.ref.startswith("0x"))
          success = !entry.ref.getAsInteger(0, uval64);
        if (!success)
          success = !entry.ref.getAsInteger(16, uval64);
        if (!success) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid hex string value.\n", entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) {
          result.AppendErrorWithFormat("Value 0x%" PRIx64
                                       " is too large to fit in a %" PRIu64
                                       " byte unsigned integer value.\n",
                                       uval64, (uint64_t)item_byte_size);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(uval64, item_byte_size);
        break;
      }
      case eFormatBoolean:
        uval64 = Args::StringToBoolean(entry.ref, false, &success);
        if (!success) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid boolean string value.\n", entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(uval64, item_byte_size);
        break;

      case eFormatBinary:
        if (entry.ref.getAsInteger(2, uval64)) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid binary string value.\n", entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) {
          result.AppendErrorWithFormat("Value 0x%" PRIx64
                                       " is too large to fit in a %" PRIu64
                                       " byte unsigned integer value.\n",
                                       uval64, (uint64_t)item_byte_size);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(uval64, item_byte_size);
        break;

      case eFormatCharArray:
      case eFormatChar:
      case eFormatCString: {
        if (entry.ref.empty())
          break;

        size_t len = entry.ref.size();
        // Include the NULL for C strings...
        if (m_format_options.GetFormat() == eFormatCString)
          ++len;
        Status error;
        if (process->WriteMemory(addr, entry.c_str(), len, error) == len) {
          addr += len;
        } else {
          result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
                                       " failed: %s.\n",
                                       addr, error.AsCString());
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        break;
      }
      case eFormatDecimal:
        if (entry.ref.getAsInteger(0, sval64)) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid signed decimal value.\n", entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else if (!SIntValueIsValidForSize(sval64, item_byte_size)) {
          result.AppendErrorWithFormat(
              "Value %" PRIi64 " is too large or small to fit in a %" PRIu64
              " byte signed integer value.\n",
              sval64, (uint64_t)item_byte_size);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(sval64, item_byte_size);
        break;

      case eFormatUnsigned:

        if (!entry.ref.getAsInteger(0, uval64)) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid unsigned decimal string value.\n",
              entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) {
          result.AppendErrorWithFormat("Value %" PRIu64
                                       " is too large to fit in a %" PRIu64
                                       " byte unsigned integer value.\n",
                                       uval64, (uint64_t)item_byte_size);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(uval64, item_byte_size);
        break;

      case eFormatOctal:
        if (entry.ref.getAsInteger(8, uval64)) {
          result.AppendErrorWithFormat(
              "'%s' is not a valid octal string value.\n", entry.c_str());
          result.SetStatus(eReturnStatusFailed);
          return false;
        } else if (!UIntValueIsValidForSize(uval64, item_byte_size)) {
          result.AppendErrorWithFormat("Value %" PRIo64
                                       " is too large to fit in a %" PRIu64
                                       " byte unsigned integer value.\n",
                                       uval64, (uint64_t)item_byte_size);
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        buffer.PutMaxHex64(uval64, item_byte_size);
        break;
      }
    }

    if (!buffer.GetString().empty()) {
      Status error;
      if (process->WriteMemory(addr, buffer.GetString().data(),
                               buffer.GetString().size(),
                               error) == buffer.GetString().size())
        return true;
      else {
        result.AppendErrorWithFormat("Memory write to 0x%" PRIx64
                                     " failed: %s.\n",
                                     addr, error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
    }
    return true;
  }

  OptionGroupOptions m_option_group;
  OptionGroupFormat m_format_options;
  OptionGroupWriteMemory m_memory_options;
};

//----------------------------------------------------------------------
// Get malloc/free history of a memory address.
//----------------------------------------------------------------------
class CommandObjectMemoryHistory : public CommandObjectParsed {
public:
  CommandObjectMemoryHistory(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "memory history", "Print recorded stack traces for "
                                           "allocation/deallocation events "
                                           "associated with an address.",
            nullptr,
            eCommandRequiresTarget | eCommandRequiresProcess |
                eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) {
    CommandArgumentEntry arg1;
    CommandArgumentData addr_arg;

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

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

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

  ~CommandObjectMemoryHistory() override = default;

  const char *GetRepeatCommand(Args &current_command_args,
                               uint32_t index) override {
    return m_cmd_name.c_str();
  }

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();

    if (argc == 0 || argc > 1) {
      result.AppendErrorWithFormat("%s takes an address expression",
                                   m_cmd_name.c_str());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    Status error;
    lldb::addr_t addr = Args::StringToAddress(&m_exe_ctx, command[0].ref,
                                              LLDB_INVALID_ADDRESS, &error);

    if (addr == LLDB_INVALID_ADDRESS) {
      result.AppendError("invalid address expression");
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    Stream *output_stream = &result.GetOutputStream();

    const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
    const MemoryHistorySP &memory_history =
        MemoryHistory::FindPlugin(process_sp);

    if (!memory_history) {
      result.AppendError("no available memory history provider");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);

    const bool stop_format = false;
    for (auto thread : thread_list) {
      thread->GetStatus(*output_stream, 0, UINT32_MAX, 0, stop_format);
    }

    result.SetStatus(eReturnStatusSuccessFinishResult);

    return true;
  }
};

//-------------------------------------------------------------------------
// CommandObjectMemoryRegion
//-------------------------------------------------------------------------
#pragma mark CommandObjectMemoryRegion

class CommandObjectMemoryRegion : public CommandObjectParsed {
public:
  CommandObjectMemoryRegion(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "memory region",
                            "Get information on the memory region containing "
                            "an address in the current target process.",
                            "memory region ADDR",
                            eCommandRequiresProcess | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched),
        m_prev_end_addr(LLDB_INVALID_ADDRESS) {}

  ~CommandObjectMemoryRegion() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    ProcessSP process_sp = m_exe_ctx.GetProcessSP();
    if (process_sp) {
      Status error;
      lldb::addr_t load_addr = m_prev_end_addr;
      m_prev_end_addr = LLDB_INVALID_ADDRESS;

      const size_t argc = command.GetArgumentCount();
      if (argc > 1 || (argc == 0 && load_addr == LLDB_INVALID_ADDRESS)) {
        result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n",
                                     m_cmd_name.c_str(), m_cmd_syntax.c_str());
        result.SetStatus(eReturnStatusFailed);
      } else {
        auto load_addr_str = command[0].ref;
        if (command.GetArgumentCount() == 1) {
          load_addr = Args::StringToAddress(&m_exe_ctx, load_addr_str,
                                            LLDB_INVALID_ADDRESS, &error);
          if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) {
            result.AppendErrorWithFormat(
                "invalid address argument \"%s\": %s\n", command[0].c_str(),
                error.AsCString());
            result.SetStatus(eReturnStatusFailed);
          }
        }

        lldb_private::MemoryRegionInfo range_info;
        error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
        if (error.Success()) {
          lldb_private::Address addr;
          ConstString section_name;
          if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) {
            SectionSP section_sp(addr.GetSection());
            if (section_sp) {
              // Got the top most section, not the deepest section
              while (section_sp->GetParent())
                section_sp = section_sp->GetParent();
              section_name = section_sp->GetName();
            }
          }
          result.AppendMessageWithFormat(
              "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n",
              range_info.GetRange().GetRangeBase(),
              range_info.GetRange().GetRangeEnd(),
              range_info.GetReadable() ? 'r' : '-',
              range_info.GetWritable() ? 'w' : '-',
              range_info.GetExecutable() ? 'x' : '-', section_name ? " " : "",
              section_name ? section_name.AsCString() : "");
          m_prev_end_addr = range_info.GetRange().GetRangeEnd();
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.SetStatus(eReturnStatusFailed);
          result.AppendErrorWithFormat("%s\n", error.AsCString());
        }
      }
    } else {
      m_prev_end_addr = LLDB_INVALID_ADDRESS;
      result.AppendError("invalid process");
      result.SetStatus(eReturnStatusFailed);
    }
    return result.Succeeded();
  }

  const char *GetRepeatCommand(Args &current_command_args,
                               uint32_t index) override {
    // If we repeat this command, repeat it without any arguments so we can
    // show the next memory range
    return m_cmd_name.c_str();
  }

  lldb::addr_t m_prev_end_addr;
};

//-------------------------------------------------------------------------
// CommandObjectMemory
//-------------------------------------------------------------------------

CommandObjectMemory::CommandObjectMemory(CommandInterpreter &interpreter)
    : CommandObjectMultiword(
          interpreter, "memory",
          "Commands for operating on memory in the current target process.",
          "memory <subcommand> [<subcommand-options>]") {
  LoadSubCommand("find",
                 CommandObjectSP(new CommandObjectMemoryFind(interpreter)));
  LoadSubCommand("read",
                 CommandObjectSP(new CommandObjectMemoryRead(interpreter)));
  LoadSubCommand("write",
                 CommandObjectSP(new CommandObjectMemoryWrite(interpreter)));
  LoadSubCommand("history",
                 CommandObjectSP(new CommandObjectMemoryHistory(interpreter)));
  LoadSubCommand("region",
                 CommandObjectSP(new CommandObjectMemoryRegion(interpreter)));
}

CommandObjectMemory::~CommandObjectMemory() = default;
