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

#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"

#include "lldb/Host/OptionParser.h"

#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/MemoryRegionInfo.h"

LLDB_PLUGIN_DEFINE(ScriptedProcess)

using namespace lldb;
using namespace lldb_private;

ConstString ScriptedProcess::GetPluginNameStatic() {
  static ConstString g_name("ScriptedProcess");
  return g_name;
}

const char *ScriptedProcess::GetPluginDescriptionStatic() {
  return "Scripted Process plug-in.";
}

lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
                                                lldb::ListenerSP listener_sp,
                                                const FileSpec *file,
                                                bool can_connect) {
  ScriptedProcess::LaunchInfo launch_info(target_sp->GetProcessLaunchInfo());

  auto process_sp =
      std::make_shared<ScriptedProcess>(target_sp, listener_sp, launch_info);

  if (!process_sp || !process_sp->m_script_object_sp ||
      !process_sp->m_script_object_sp->IsValid())
    return nullptr;

  return process_sp;
}

bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
                               bool plugin_specified_by_name) {
  return true;
}

ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
                                 lldb::ListenerSP listener_sp,
                                 const ScriptedProcess::LaunchInfo &launch_info)
    : Process(target_sp, listener_sp), m_launch_info(launch_info),
      m_interpreter(nullptr), m_script_object_sp(nullptr) {
  if (!target_sp)
    return;

  m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();

  if (!m_interpreter)
    return;

  StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
      m_launch_info.GetClassName().c_str(), target_sp,
      m_launch_info.GetDictionarySP());

  if (object_sp && object_sp->IsValid())
    m_script_object_sp = object_sp;
}

ScriptedProcess::~ScriptedProcess() {
  Clear();
  // We need to call finalize on the process before destroying ourselves to
  // make sure all of the broadcaster cleanup goes as planned. If we destruct
  // this class, then Process::~Process() might have problems trying to fully
  // destroy the broadcaster.
  Finalize();
}

void ScriptedProcess::Initialize() {
  static llvm::once_flag g_once_flag;

  llvm::call_once(g_once_flag, []() {
    PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                  GetPluginDescriptionStatic(), CreateInstance);
  });
}

void ScriptedProcess::Terminate() {
  PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
}

ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }

uint32_t ScriptedProcess::GetPluginVersion() { return 1; }

Status ScriptedProcess::DoLoadCore() {
  ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();

  return DoLaunch(nullptr, launch_info);
}

Status ScriptedProcess::DoLaunch(Module *exe_module,
                                 ProcessLaunchInfo &launch_info) {
  if (!m_interpreter)
    return Status("No interpreter.");

  if (!m_script_object_sp)
    return Status("No python object.");

  Status status = GetInterface().Launch();

  if (status.Success()) {
    SetPrivateState(eStateRunning);
    SetPrivateState(eStateStopped);
  }

  return status;
}

void ScriptedProcess::DidLaunch() {
  if (m_interpreter)
    m_pid = GetInterface().GetProcessID();
}

Status ScriptedProcess::DoResume() {
  if (!m_interpreter)
    return Status("No interpreter.");

  if (!m_script_object_sp)
    return Status("No python object.");

  Status status = GetInterface().Resume();

  if (status.Success()) {
    SetPrivateState(eStateRunning);
    SetPrivateState(eStateStopped);
  }

  return status;
}

Status ScriptedProcess::DoDestroy() { return Status(); }

bool ScriptedProcess::IsAlive() {
  if (!m_interpreter)
    return false;

  return GetInterface().IsAlive();
}

size_t ScriptedProcess::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
                                   Status &error) {
  return DoReadMemory(addr, buf, size, error);
}

size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
                                     Status &error) {

  auto error_with_message = [&error](llvm::StringRef message) {
    error.SetErrorString(message);
    return LLDB_INVALID_ADDRESS;
  };

  if (!m_interpreter)
    return error_with_message("No interpreter.");

  lldb::DataExtractorSP data_extractor_sp =
      GetInterface().ReadMemoryAtAddress(addr, size, error);

  if (!data_extractor_sp || error.Fail())
    return LLDB_INVALID_ADDRESS;

  if (data_extractor_sp->GetByteSize() != size)
    return error_with_message("Failed to read requested memory size.");

  offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
      0, size, buf, size, GetByteOrder());

  if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
    return error_with_message("Failed to copy read memory to buffer.");

  return size;
}

ArchSpec ScriptedProcess::GetArchitecture() {
  return GetTarget().GetArchitecture();
}

Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
                                            MemoryRegionInfo &region) {
  return Status();
}

Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
  Status error;

  if (!m_interpreter) {
    error.SetErrorString("No interpreter.");
    return error;
  }

  lldb::addr_t address = 0;
  lldb::MemoryRegionInfoSP mem_region_sp = nullptr;

  while ((mem_region_sp =
              GetInterface().GetMemoryRegionContainingAddress(address))) {
    auto range = mem_region_sp->GetRange();
    address += range.GetRangeBase() + range.GetByteSize();
    region_list.push_back(*mem_region_sp.get());
  }

  return error;
}

void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }

bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
                                         ThreadList &new_thread_list) {
  return new_thread_list.GetSize(false) > 0;
}

bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
  info.Clear();
  info.SetProcessID(GetID());
  info.SetArchitecture(GetArchitecture());
  lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
  if (module_sp) {
    const bool add_exe_file_as_first_arg = false;
    info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
                           add_exe_file_as_first_arg);
  }
  return true;
}

ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
  return m_interpreter->GetScriptedProcessInterface();
}
