//===-- 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/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Queue.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/Utility/State.h"

#include <mutex>

LLDB_PLUGIN_DEFINE(ScriptedProcess)

using namespace lldb;
using namespace lldb_private;

llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
  return "Scripted Process plug-in.";
}

static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
    ScriptLanguage::eScriptLanguagePython,
};

bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
  llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
      llvm::ArrayRef(g_supported_script_languages);

  return llvm::is_contained(supported_languages, language);
}

lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
                                                lldb::ListenerSP listener_sp,
                                                const FileSpec *file,
                                                bool can_connect) {
  if (!target_sp ||
      !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
    return nullptr;

  ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo());

  Status error;
  auto process_sp = std::shared_ptr<ScriptedProcess>(
      new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error));

  if (error.Fail() || !process_sp || !process_sp->m_interface_up) {
    LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
    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 ScriptedMetadata &scripted_metadata,
                                 Status &error)
    : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) {

  if (!target_sp) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, "Invalid target");
    return;
  }

  ScriptInterpreter *interpreter =
      target_sp->GetDebugger().GetScriptInterpreter();

  if (!interpreter) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
        "Debugger has no Script Interpreter");
    return;
  }

  // Create process instance interface
  m_interface_up = interpreter->CreateScriptedProcessInterface();
  if (!m_interface_up) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
        "Script interpreter couldn't create Scripted Process Interface");
    return;
  }

  ExecutionContext exe_ctx(target_sp, /*get_process=*/false);

  // Create process script object
  auto obj_or_err = GetInterface().CreatePluginObject(
      m_scripted_metadata.GetClassName(), exe_ctx,
      m_scripted_metadata.GetArgsSP());

  if (!obj_or_err) {
    llvm::consumeError(obj_or_err.takeError());
    error = Status::FromErrorString("Failed to create script object.");
    return;
  }

  StructuredData::GenericSP object_sp = *obj_or_err;

  if (!object_sp || !object_sp->IsValid()) {
    error = Status::FromErrorStringWithFormat(
        "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
        "Failed to create valid script object");
    return;
  }
}

ScriptedProcess::~ScriptedProcess() {
  Clear();
  // If the interface is not valid, we can't call Finalize(). When that happens
  // it means that the Scripted Process instanciation failed and the
  // CreateProcess function returns a nullptr, so no one besides this class
  // should have access to that bogus process object.
  if (!m_interface_up)
    return;
  // 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(true /* destructing */);
}

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

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

  return DoLaunch(nullptr, launch_info);
}

Status ScriptedProcess::DoLaunch(Module *exe_module,
                                 ProcessLaunchInfo &launch_info) {
  LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
  
  /* MARK: This doesn't reflect how lldb actually launches a process.
           In reality, it attaches to debugserver, then resume the process.
           That's not true in all cases.  If debugserver is remote, lldb
           asks debugserver to launch the process for it. */
  Status error = GetInterface().Launch();
  SetPrivateState(eStateStopped);
  return error;
}

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

void ScriptedProcess::DidResume() {
  // Update the PID again, in case the user provided a placeholder pid at launch
  m_pid = GetInterface().GetProcessID();
}

Status ScriptedProcess::DoResume() {
  LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);

  return GetInterface().Resume();
}

Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
  Status error = GetInterface().Attach(attach_info);
  SetPrivateState(eStateRunning);
  SetPrivateState(eStateStopped);
  if (error.Fail())
    return error;
  // NOTE: We need to set the PID before finishing to attach otherwise we will
  // hit an assert when calling the attach completion handler.
  DidLaunch();

  return {};
}

Status
ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
                                         const ProcessAttachInfo &attach_info) {
  return DoAttach(attach_info);
}

Status ScriptedProcess::DoAttachToProcessWithName(
    const char *process_name, const ProcessAttachInfo &attach_info) {
  return DoAttach(attach_info);
}

void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
  process_arch = GetArchitecture();
}

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

bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }

size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
                                     Status &error) {
  lldb::DataExtractorSP data_extractor_sp =
      GetInterface().ReadMemoryAtAddress(addr, size, error);

  if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
    return 0;

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

  if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
    return ScriptedInterface::ErrorWithMessage<size_t>(
        LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);

  // FIXME: We should use the diagnostic system to report a warning if the
  // `bytes_copied` is different from `size`.

  return bytes_copied;
}

size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
                                      size_t size, Status &error) {
  lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
      buf, size, GetByteOrder(), GetAddressByteSize());

  if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
    return 0;

  lldb::offset_t bytes_written =
      GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);

  if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
    return ScriptedInterface::ErrorWithMessage<size_t>(
        LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);

  // FIXME: We should use the diagnostic system to report a warning if the
  // `bytes_written` is different from `size`.

  return bytes_written;
}

Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
  assert(bp_site != nullptr);

  if (bp_site->IsEnabled()) {
    return {};
  }

  if (bp_site->HardwareRequired()) {
    return Status::FromErrorString(
        "Scripted Processes don't support hardware breakpoints");
  }

  Status error;
  GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);

  return error;
}

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

Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
                                              MemoryRegionInfo &region) {
  Status error;
  if (auto region_or_err =
          GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
    region = *region_or_err;

  return error;
}

Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
  Status error;
  lldb::addr_t address = 0;

  while (auto region_or_err =
             GetInterface().GetMemoryRegionContainingAddress(address, error)) {
    if (error.Fail())
      break;

    MemoryRegionInfo &mem_region = *region_or_err;
    auto range = mem_region.GetRange();
    address += range.GetRangeBase() + range.GetByteSize();
    region_list.push_back(mem_region);
  }

  return error;
}

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

bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
                                         ThreadList &new_thread_list) {
  // TODO: Implement
  // This is supposed to get the current set of threads, if any of them are in
  // old_thread_list then they get copied to new_thread_list, and then any
  // actually new threads will get added to new_thread_list.
  m_thread_plans.ClearThreadCache();

  Status error;
  StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();

  if (!thread_info_sp)
    return ScriptedInterface::ErrorWithMessage<bool>(
        LLVM_PRETTY_FUNCTION,
        "Couldn't fetch thread list from Scripted Process.", error);

  // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
  // ObjectSP>` for storage, each item is sorted based on the key alphabetical
  // order. Since `GetThreadsInfo` provides thread indices as the key element,
  // thread info comes ordered alphabetically, instead of numerically, so we
  // need to sort the thread indices before creating thread.

  StructuredData::ArraySP keys = thread_info_sp->GetKeys();

  std::map<size_t, StructuredData::ObjectSP> sorted_threads;
  auto sort_keys = [&sorted_threads,
                    &thread_info_sp](StructuredData::Object *item) -> bool {
    if (!item)
      return false;

    llvm::StringRef key = item->GetStringValue();
    size_t idx = 0;

    // Make sure the provided index is actually an integer
    if (!llvm::to_integer(key, idx))
      return false;

    sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
    return true;
  };

  size_t thread_count = thread_info_sp->GetSize();

  if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
    // Might be worth showing the unsorted thread list instead of return early.
    return ScriptedInterface::ErrorWithMessage<bool>(
        LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);

  auto create_scripted_thread =
      [this, &error, &new_thread_list](
          const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
    size_t idx = pair.first;
    StructuredData::ObjectSP object_sp = pair.second;

    if (!object_sp)
      return ScriptedInterface::ErrorWithMessage<bool>(
          LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);

    auto thread_or_error =
        ScriptedThread::Create(*this, object_sp->GetAsGeneric());

    if (!thread_or_error)
      return ScriptedInterface::ErrorWithMessage<bool>(
          LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);

    ThreadSP thread_sp = thread_or_error.get();
    lldbassert(thread_sp && "Couldn't initialize scripted thread.");

    RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
    if (!reg_ctx_sp)
      return ScriptedInterface::ErrorWithMessage<bool>(
          LLVM_PRETTY_FUNCTION,
          llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
              .str(),
          error);

    new_thread_list.AddThread(thread_sp);

    return true;
  };

  llvm::for_each(sorted_threads, create_scripted_thread);

  return new_thread_list.GetSize(false) > 0;
}

void ScriptedProcess::RefreshStateAfterStop() {
  // Let all threads recover from stopping and do any clean up based on the
  // previous thread state (if any).
  m_thread_list.RefreshStateAfterStop();
}

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

lldb_private::StructuredData::ObjectSP
ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
  Status error;
  auto error_with_message = [&error](llvm::StringRef message) {
    return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
                                                     message.data(), error);
  };

  StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();

  if (!loaded_images_sp || !loaded_images_sp->GetSize())
    return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
        LLVM_PRETTY_FUNCTION, "No loaded images.", error);

  ModuleList module_list;
  Target &target = GetTarget();

  auto reload_image = [&target, &module_list, &error_with_message](
                          StructuredData::Object *obj) -> bool {
    StructuredData::Dictionary *dict = obj->GetAsDictionary();

    if (!dict)
      return error_with_message("Couldn't cast image object into dictionary.");

    ModuleSpec module_spec;
    llvm::StringRef value;

    bool has_path = dict->HasKey("path");
    bool has_uuid = dict->HasKey("uuid");
    if (!has_path && !has_uuid)
      return error_with_message("Dictionary should have key 'path' or 'uuid'");
    if (!dict->HasKey("load_addr"))
      return error_with_message("Dictionary is missing key 'load_addr'");

    if (has_path) {
      dict->GetValueForKeyAsString("path", value);
      module_spec.GetFileSpec().SetPath(value);
    }

    if (has_uuid) {
      dict->GetValueForKeyAsString("uuid", value);
      module_spec.GetUUID().SetFromStringRef(value);
    }
    module_spec.GetArchitecture() = target.GetArchitecture();

    ModuleSP module_sp =
        target.GetOrCreateModule(module_spec, true /* notify */);

    if (!module_sp)
      return error_with_message("Couldn't create or get module.");

    lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
    lldb::offset_t slide = LLDB_INVALID_OFFSET;
    dict->GetValueForKeyAsInteger("load_addr", load_addr);
    dict->GetValueForKeyAsInteger("slide", slide);
    if (load_addr == LLDB_INVALID_ADDRESS)
      return error_with_message(
          "Couldn't get valid load address or slide offset.");

    if (slide != LLDB_INVALID_OFFSET)
      load_addr += slide;

    bool changed = false;
    module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
                              changed);

    if (!changed && !module_sp->GetObjectFile())
      return error_with_message("Couldn't set the load address for module.");

    dict->GetValueForKeyAsString("path", value);
    FileSpec objfile(value);
    module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());

    return module_list.AppendIfNeeded(module_sp);
  };

  if (!loaded_images_sp->ForEach(reload_image))
    return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
        LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);

  target.ModulesDidLoad(module_list);

  return loaded_images_sp;
}

lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
  StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();

  Status error;
  if (!metadata_sp || !metadata_sp->GetSize())
    return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
        LLVM_PRETTY_FUNCTION, "No metadata.", error);

  return metadata_sp;
}

void ScriptedProcess::UpdateQueueListIfNeeded() {
  CheckScriptedInterface();
  for (ThreadSP thread_sp : Threads()) {
    if (const char *queue_name = thread_sp->GetQueueName()) {
      QueueSP queue_sp = std::make_shared<Queue>(
          m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
      m_queue_list.AddQueue(queue_sp);
    }
  }
}

ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
  CheckScriptedInterface();
  return *m_interface_up;
}

void *ScriptedProcess::GetImplementation() {
  StructuredData::GenericSP object_instance_sp =
      GetInterface().GetScriptObjectInstance();
  if (object_instance_sp &&
      object_instance_sp->GetType() == eStructuredDataTypeGeneric)
    return object_instance_sp->GetAsGeneric()->GetValue();
  return nullptr;
}
