//===-- 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/AddressableBits.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/Utility/State.h"

#include "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h"

#include "llvm/Support/Error.h"

#include <string>

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(ScriptedProcess)

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

  if (!scripted_metadata)
    return nullptr;

  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) {
    // CreateInstance returns nullptr on failure with no Status output
    // parameter, so we must report the error via the diagnostic system for
    // users to see it.
    if (error.Fail()) {
      Debugger::ReportError(
          llvm::formatv("failed to create ScriptedProcess: {0}",
                        error.AsCString())
              .str(),
          target_sp->GetDebugger().GetID());
    }
    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, exe_ctx);

  if (!obj_or_err) {
    std::string error_msg = llvm::toString(obj_or_err.takeError());
    error = Status::FromErrorStringWithFormatv(
        "failed to create script object: {0}", error_msg);
    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() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance);
}

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

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

  Status error = DoLaunch(nullptr, launch_info);
  // Process::LoadCore() doesn't go through DidLaunch().
  if (error.Success())
    DidLaunchOrAttach();
  return error;
}

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() { DidLaunchOrAttach(); }

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

  StructuredData::DictionarySP bits_sp = GetInterface().GetAddressableBits();
  if (!bits_sp)
    return;

  AddressableBits addressable_bits;
  uint64_t num_bits = 0;
  if (bits_sp->GetValueForKeyAsInteger("lowmem", num_bits))
    addressable_bits.SetLowmemAddressableBits(num_bits);
  if (bits_sp->GetValueForKeyAsInteger("highmem", num_bits))
    addressable_bits.SetHighmemAddressableBits(num_bits);
  SetAddressableBitMasks(addressable_bits);
}

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

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

  if (direction == RunDirection::eRunForward)
    return GetInterface().Resume();
  // FIXME: Pipe reverse continue through Scripted Processes
  return Status::FromErrorStringWithFormatv(
      "{0} does not support reverse execution of processes", GetPluginName());
}

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

  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();
  // Process::DidExec also comes through Process::CompleteAttach without
  // resetting the address masks, so they have to be reported again here.
  DidLaunchOrAttach();
}

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

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

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

  if (!data_extractor_sp || !data_extractor_sp->HasData() || error.Fail()) {
    if (error.Fail()) {
      error = Status::FromErrorStringWithFormatv(
          "Failed to read memory from scripted process at 0x{0:x-}: {1}", addr,
          error.AsCString());
    }
    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->HasData())
    return 0;

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

  if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET) {
    if (error.Fail()) {
      error = Status::FromErrorStringWithFormatv(
          "failed to write memory to scripted process at 0x{0:x-}: {1}",
          vm_addr, error.AsCString());
    }
    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 (IsBreakpointSitePhysicallyEnabled(*bp_site)) {
    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) {
      Debugger::ReportError(
          llvm::formatv("failed to create scripted thread ({0}): {1}", idx,
                        llvm::toString(thread_or_error.takeError()))
              .str(),
          GetTarget().GetDebugger().GetID());
      return false;
    }

    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(
    BinaryInformationLevel info_level) {
  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;

    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'");

    llvm::StringRef path = "";
    if (has_path) {
      dict->GetValueForKeyAsString("path", path);
      module_spec.GetFileSpec().SetPath(path);
    }

    llvm::StringRef uuid = "";
    if (has_uuid) {
      dict->GetValueForKeyAsString("uuid", uuid);
      module_spec.GetUUID().SetFromStringRef(uuid);
    }

    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;

    module_spec.GetArchitecture() = target.GetArchitecture();

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

    bool is_placeholder_module = false;

    if (!module_sp) {
      // Create a placeholder module
      LLDB_LOGF(
          GetLog(LLDBLog::Process),
          "ScriptedProcess::%s unable to locate the matching "
          "object file path %s, creating a placeholder module at 0x%" PRIx64,
          __FUNCTION__, path.str().c_str(), load_addr);

      module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>(
          module_spec, load_addr, module_spec.GetFileSpec().MemorySize());

      is_placeholder_module = true;
    }

    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.");

    FileSpec objfile(path);
    module_sp->SetFileSpecAndObjectName(objfile,
                                        ConstString(objfile.GetFilename()));

    if (is_placeholder_module) {
      target.GetImages().AppendIfNeeded(module_sp, true /*notify=*/);
      return true;
    }

    return module_list.AppendIfNeeded(module_sp);
  };

  size_t loaded_images_size = loaded_images_sp->GetSize();
  bool print_error = true;
  for (size_t idx = 0; idx < loaded_images_size; idx++) {
    const auto &loaded_image = loaded_images_sp->GetItemAtIndex(idx);
    if (!reload_image(loaded_image.get()) && print_error) {
      print_error = false;
      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;
}
