//===-- CommandObjectReproducer.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 "CommandObjectReproducer.h"

#include "lldb/Host/HostInfo.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/Reproducer.h"

#include <csignal>

using namespace lldb;
using namespace llvm;
using namespace lldb_private;
using namespace lldb_private::repro;

enum ReproducerProvider {
  eReproducerProviderCommands,
  eReproducerProviderFiles,
  eReproducerProviderSymbolFiles,
  eReproducerProviderGDB,
  eReproducerProviderProcessInfo,
  eReproducerProviderVersion,
  eReproducerProviderWorkingDirectory,
  eReproducerProviderHomeDirectory,
  eReproducerProviderNone
};

static constexpr OptionEnumValueElement g_reproducer_provider_type[] = {
    {
        eReproducerProviderCommands,
        "commands",
        "Command Interpreter Commands",
    },
    {
        eReproducerProviderFiles,
        "files",
        "Files",
    },
    {
        eReproducerProviderSymbolFiles,
        "symbol-files",
        "Symbol Files",
    },
    {
        eReproducerProviderGDB,
        "gdb",
        "GDB Remote Packets",
    },
    {
        eReproducerProviderProcessInfo,
        "processes",
        "Process Info",
    },
    {
        eReproducerProviderVersion,
        "version",
        "Version",
    },
    {
        eReproducerProviderWorkingDirectory,
        "cwd",
        "Working Directory",
    },
    {
        eReproducerProviderHomeDirectory,
        "home",
        "Home Directory",
    },
    {
        eReproducerProviderNone,
        "none",
        "None",
    },
};

static constexpr OptionEnumValues ReproducerProviderType() {
  return OptionEnumValues(g_reproducer_provider_type);
}

#define LLDB_OPTIONS_reproducer_dump
#include "CommandOptions.inc"

enum ReproducerCrashSignal {
  eReproducerCrashSigill,
  eReproducerCrashSigsegv,
};

static constexpr OptionEnumValueElement g_reproducer_signaltype[] = {
    {
        eReproducerCrashSigill,
        "SIGILL",
        "Illegal instruction",
    },
    {
        eReproducerCrashSigsegv,
        "SIGSEGV",
        "Segmentation fault",
    },
};

static constexpr OptionEnumValues ReproducerSignalType() {
  return OptionEnumValues(g_reproducer_signaltype);
}

#define LLDB_OPTIONS_reproducer_xcrash
#include "CommandOptions.inc"

#define LLDB_OPTIONS_reproducer_verify
#include "CommandOptions.inc"

template <typename T>
llvm::Expected<T> static ReadFromYAML(StringRef filename) {
  auto error_or_file = MemoryBuffer::getFile(filename);
  if (auto err = error_or_file.getError()) {
    return errorCodeToError(err);
  }

  T t;
  yaml::Input yin((*error_or_file)->getBuffer());
  yin >> t;

  if (auto err = yin.error()) {
    return errorCodeToError(err);
  }

  return t;
}

static void SetError(CommandReturnObject &result, Error err) {
  result.GetErrorStream().Printf("error: %s\n",
                                 toString(std::move(err)).c_str());
  result.SetStatus(eReturnStatusFailed);
}

/// Create a loader from the given path if specified. Otherwise use the current
/// loader used for replay.
static Loader *
GetLoaderFromPathOrCurrent(llvm::Optional<Loader> &loader_storage,
                           CommandReturnObject &result,
                           FileSpec reproducer_path) {
  if (reproducer_path) {
    loader_storage.emplace(reproducer_path);
    Loader *loader = &(*loader_storage);
    if (Error err = loader->LoadIndex()) {
      // This is a hard error and will set the result to eReturnStatusFailed.
      SetError(result, std::move(err));
      return nullptr;
    }
    return loader;
  }

  if (Loader *loader = Reproducer::Instance().GetLoader())
    return loader;

  // This is a soft error because this is expected to fail during capture.
  result.SetError("Not specifying a reproducer is only support during replay.");
  result.SetStatus(eReturnStatusSuccessFinishNoResult);
  return nullptr;
}

class CommandObjectReproducerGenerate : public CommandObjectParsed {
public:
  CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "reproducer generate",
            "Generate reproducer on disk. When the debugger is in capture "
            "mode, this command will output the reproducer to a directory on "
            "disk and quit. In replay mode this command in a no-op.",
            nullptr) {}

  ~CommandObjectReproducerGenerate() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (!command.empty()) {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
      return false;
    }

    auto &r = Reproducer::Instance();
    if (auto generator = r.GetGenerator()) {
      generator->Keep();
      if (llvm::Error e = repro::Finalize(r.GetReproducerPath())) {
        SetError(result, std::move(e));
        return result.Succeeded();
      }
    } else if (r.IsReplaying()) {
      // Make this operation a NO-OP in replay mode.
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return result.Succeeded();
    } else {
      result.AppendErrorWithFormat("Unable to get the reproducer generator");
      result.SetStatus(eReturnStatusFailed);
      return false;
    }

    result.GetOutputStream()
        << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
    result.GetOutputStream()
        << "Please have a look at the directory to assess if you're willing to "
           "share the contained information.\n";

    m_interpreter.BroadcastEvent(
        CommandInterpreter::eBroadcastBitQuitCommandReceived);
    result.SetStatus(eReturnStatusQuit);
    return result.Succeeded();
  }
};

class CommandObjectReproducerXCrash : public CommandObjectParsed {
public:
  CommandObjectReproducerXCrash(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "reproducer xcrash",
                            "Intentionally force  the debugger to crash in "
                            "order to trigger and test reproducer generation.",
                            nullptr) {}

  ~CommandObjectReproducerXCrash() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

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

      switch (short_option) {
      case 's':
        signal = (ReproducerCrashSignal)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
        if (!error.Success())
          error.SetErrorStringWithFormat("unrecognized value for signal '%s'",
                                         option_arg.str().c_str());
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      signal = eReproducerCrashSigsegv;
    }

    ArrayRef<OptionDefinition> GetDefinitions() override {
      return makeArrayRef(g_reproducer_xcrash_options);
    }

    ReproducerCrashSignal signal = eReproducerCrashSigsegv;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (!command.empty()) {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
      return false;
    }

    auto &r = Reproducer::Instance();

    if (!r.IsCapturing() && !r.IsReplaying()) {
      result.SetError(
          "forcing a crash is only supported when capturing a reproducer.");
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return false;
    }

    switch (m_options.signal) {
    case eReproducerCrashSigill:
      std::raise(SIGILL);
      break;
    case eReproducerCrashSigsegv:
      std::raise(SIGSEGV);
      break;
    }

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

private:
  CommandOptions m_options;
};

class CommandObjectReproducerStatus : public CommandObjectParsed {
public:
  CommandObjectReproducerStatus(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "reproducer status",
            "Show the current reproducer status. In capture mode the "
            "debugger "
            "is collecting all the information it needs to create a "
            "reproducer.  In replay mode the reproducer is replaying a "
            "reproducer. When the reproducers are off, no data is collected "
            "and no reproducer can be generated.",
            nullptr) {}

  ~CommandObjectReproducerStatus() override = default;

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (!command.empty()) {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
      return false;
    }

    auto &r = Reproducer::Instance();
    if (r.IsCapturing()) {
      result.GetOutputStream() << "Reproducer is in capture mode.\n";
    } else if (r.IsReplaying()) {
      result.GetOutputStream() << "Reproducer is in replay mode.\n";
    } else {
      result.GetOutputStream() << "Reproducer is off.\n";
    }

    if (r.IsCapturing() || r.IsReplaying()) {
      result.GetOutputStream()
          << "Path: " << r.GetReproducerPath().GetPath() << '\n';
    }

    // Auto generate is hidden unless enabled because this is mostly for
    // development and testing.
    if (Generator *g = r.GetGenerator()) {
      if (g->IsAutoGenerate())
        result.GetOutputStream() << "Auto generate: on\n";
    }

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

class CommandObjectReproducerDump : public CommandObjectParsed {
public:
  CommandObjectReproducerDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "reproducer dump",
                            "Dump the information contained in a reproducer. "
                            "If no reproducer is specified during replay, it "
                            "dumps the content of the current reproducer.",
                            nullptr) {}

  ~CommandObjectReproducerDump() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), file() {}

    ~CommandOptions() override = default;

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

      switch (short_option) {
      case 'f':
        file.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(file);
        break;
      case 'p':
        provider = (ReproducerProvider)OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
        if (!error.Success())
          error.SetErrorStringWithFormat("unrecognized value for provider '%s'",
                                         option_arg.str().c_str());
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      file.Clear();
      provider = eReproducerProviderNone;
    }

    ArrayRef<OptionDefinition> GetDefinitions() override {
      return makeArrayRef(g_reproducer_dump_options);
    }

    FileSpec file;
    ReproducerProvider provider = eReproducerProviderNone;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (!command.empty()) {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
      return false;
    }

    llvm::Optional<Loader> loader_storage;
    Loader *loader =
        GetLoaderFromPathOrCurrent(loader_storage, result, m_options.file);
    if (!loader)
      return false;

    switch (m_options.provider) {
    case eReproducerProviderFiles: {
      FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>();

      // Read the VFS mapping.
      ErrorOr<std::unique_ptr<MemoryBuffer>> buffer =
          vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath());
      if (!buffer) {
        SetError(result, errorCodeToError(buffer.getError()));
        return false;
      }

      // Initialize a VFS from the given mapping.
      IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML(
          std::move(buffer.get()), nullptr, vfs_mapping.GetPath());

      // Dump the VFS to a buffer.
      std::string str;
      raw_string_ostream os(str);
      static_cast<vfs::RedirectingFileSystem &>(*vfs).dump(os);
      os.flush();

      // Return the string.
      result.AppendMessage(str);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderSymbolFiles: {
      Expected<std::string> symbol_files =
          loader->LoadBuffer<SymbolFileProvider>();
      if (!symbol_files) {
        SetError(result, symbol_files.takeError());
        return false;
      }

      std::vector<SymbolFileProvider::Entry> entries;
      llvm::yaml::Input yin(*symbol_files);
      yin >> entries;

      for (const auto &entry : entries) {
        result.AppendMessageWithFormat("- uuid:        %s\n",
                                       entry.uuid.c_str());
        result.AppendMessageWithFormat("  module path: %s\n",
                                       entry.module_path.c_str());
        result.AppendMessageWithFormat("  symbol path: %s\n",
                                       entry.symbol_path.c_str());
      }
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderVersion: {
      Expected<std::string> version = loader->LoadBuffer<VersionProvider>();
      if (!version) {
        SetError(result, version.takeError());
        return false;
      }
      result.AppendMessage(*version);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderWorkingDirectory: {
      Expected<std::string> cwd =
          repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader);
      if (!cwd) {
        SetError(result, cwd.takeError());
        return false;
      }
      result.AppendMessage(*cwd);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderHomeDirectory: {
      Expected<std::string> home =
          repro::GetDirectoryFrom<HomeDirectoryProvider>(loader);
      if (!home) {
        SetError(result, home.takeError());
        return false;
      }
      result.AppendMessage(*home);
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderCommands: {
      std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> multi_loader =
          repro::MultiLoader<repro::CommandProvider>::Create(loader);
      if (!multi_loader) {
        SetError(result,
                 make_error<StringError>("Unable to create command loader.",
                                         llvm::inconvertibleErrorCode()));
        return false;
      }

      // Iterate over the command files and dump them.
      llvm::Optional<std::string> command_file;
      while ((command_file = multi_loader->GetNextFile())) {
        if (!command_file)
          break;

        auto command_buffer = llvm::MemoryBuffer::getFile(*command_file);
        if (auto err = command_buffer.getError()) {
          SetError(result, errorCodeToError(err));
          return false;
        }
        result.AppendMessage((*command_buffer)->getBuffer());
      }

      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderGDB: {
      std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
          multi_loader =
              repro::MultiLoader<repro::GDBRemoteProvider>::Create(loader);

      if (!multi_loader) {
        SetError(result,
                 make_error<StringError>("Unable to create GDB loader.",
                                         llvm::inconvertibleErrorCode()));
        return false;
      }

      llvm::Optional<std::string> gdb_file;
      while ((gdb_file = multi_loader->GetNextFile())) {
        if (llvm::Expected<std::vector<GDBRemotePacket>> packets =
                ReadFromYAML<std::vector<GDBRemotePacket>>(*gdb_file)) {
          for (GDBRemotePacket &packet : *packets) {
            packet.Dump(result.GetOutputStream());
          }
        } else {
          SetError(result, packets.takeError());
          return false;
        }
      }

      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderProcessInfo: {
      std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>>
          multi_loader =
              repro::MultiLoader<repro::ProcessInfoProvider>::Create(loader);

      if (!multi_loader) {
        SetError(result, make_error<StringError>(
                             llvm::inconvertibleErrorCode(),
                             "Unable to create process info loader."));
        return false;
      }

      llvm::Optional<std::string> process_file;
      while ((process_file = multi_loader->GetNextFile())) {
        if (llvm::Expected<ProcessInstanceInfoList> infos =
                ReadFromYAML<ProcessInstanceInfoList>(*process_file)) {
          for (ProcessInstanceInfo info : *infos)
            info.Dump(result.GetOutputStream(), HostInfo::GetUserIDResolver());
        } else {
          SetError(result, infos.takeError());
          return false;
        }
      }

      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }
    case eReproducerProviderNone:
      result.SetError("No valid provider specified.");
      return false;
    }

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

private:
  CommandOptions m_options;
};

class CommandObjectReproducerVerify : public CommandObjectParsed {
public:
  CommandObjectReproducerVerify(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "reproducer verify",
                            "Verify the contents of a reproducer. "
                            "If no reproducer is specified during replay, it "
                            "verifies the content of the current reproducer.",
                            nullptr) {}

  ~CommandObjectReproducerVerify() override = default;

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

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options(), file() {}

    ~CommandOptions() override = default;

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

      switch (short_option) {
      case 'f':
        file.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(file);
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      file.Clear();
    }

    ArrayRef<OptionDefinition> GetDefinitions() override {
      return makeArrayRef(g_reproducer_verify_options);
    }

    FileSpec file;
  };

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    if (!command.empty()) {
      result.AppendErrorWithFormat("'%s' takes no arguments",
                                   m_cmd_name.c_str());
      return false;
    }

    llvm::Optional<Loader> loader_storage;
    Loader *loader =
        GetLoaderFromPathOrCurrent(loader_storage, result, m_options.file);
    if (!loader)
      return false;

    bool errors = false;
    auto error_callback = [&](llvm::StringRef error) {
      errors = true;
      result.AppendError(error);
    };

    bool warnings = false;
    auto warning_callback = [&](llvm::StringRef warning) {
      warnings = true;
      result.AppendWarning(warning);
    };

    auto note_callback = [&](llvm::StringRef warning) {
      result.AppendMessage(warning);
    };

    Verifier verifier(loader);
    verifier.Verify(error_callback, warning_callback, note_callback);

    if (warnings || errors) {
      result.AppendMessage("reproducer verification failed");
      result.SetStatus(eReturnStatusFailed);
    } else {
      result.AppendMessage("reproducer verification succeeded");
      result.SetStatus(eReturnStatusSuccessFinishResult);
    }

    return result.Succeeded();
  }

private:
  CommandOptions m_options;
};

CommandObjectReproducer::CommandObjectReproducer(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(
          interpreter, "reproducer",
          "Commands for manipulating reproducers. Reproducers make it "
          "possible "
          "to capture full debug sessions with all its dependencies. The "
          "resulting reproducer is used to replay the debug session while "
          "debugging the debugger.\n"
          "Because reproducers need the whole the debug session from "
          "beginning to end, you need to launch the debugger in capture or "
          "replay mode, commonly though the command line driver.\n"
          "Reproducers are unrelated record-replay debugging, as you cannot "
          "interact with the debugger during replay.\n",
          "reproducer <subcommand> [<subcommand-options>]") {
  LoadSubCommand(
      "generate",
      CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
  LoadSubCommand("status", CommandObjectSP(
                               new CommandObjectReproducerStatus(interpreter)));
  LoadSubCommand("dump",
                 CommandObjectSP(new CommandObjectReproducerDump(interpreter)));
  LoadSubCommand("verify", CommandObjectSP(
                               new CommandObjectReproducerVerify(interpreter)));
  LoadSubCommand("xcrash", CommandObjectSP(
                               new CommandObjectReproducerXCrash(interpreter)));
}

CommandObjectReproducer::~CommandObjectReproducer() = default;
