//===-- 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.AppendError(toString(std::move(err)));
}

/// 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.AppendError(
      "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 {
      result.AppendErrorWithFormat("Unable to get the reproducer generator");
      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() {}

    ~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()) {
      result.AppendError(
          "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";
      result.GetOutputStream()
          << "Path: " << r.GetReproducerPath().GetPath() << '\n';
    } else {
      result.GetOutputStream() << "Reproducer is off.\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() {}

    ~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.AppendError("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() {}

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