//===-- OperatingSystemPython.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 "lldb/Host/Config.h"

#if LLDB_ENABLE_PYTHON

#include "OperatingSystemPython.h"

#include "Plugins/Process/Utility/RegisterContextDummy.h"
#include "Plugins/Process/Utility/RegisterContextMemory.h"
#include "Plugins/Process/Utility/ThreadMemory.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(OperatingSystemPython)

void OperatingSystemPython::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                nullptr);
}

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

OperatingSystem *OperatingSystemPython::CreateInstance(Process *process,
                                                       bool force) {
  // Python OperatingSystem plug-ins must be requested by name, so force must
  // be true
  FileSpec python_os_plugin_spec(process->GetPythonOSPluginPath());
  if (python_os_plugin_spec &&
      FileSystem::Instance().Exists(python_os_plugin_spec)) {
    std::unique_ptr<OperatingSystemPython> os_up(
        new OperatingSystemPython(process, python_os_plugin_spec));
    if (os_up.get() && os_up->IsValid())
      return os_up.release();
  }
  return nullptr;
}

llvm::StringRef OperatingSystemPython::GetPluginDescriptionStatic() {
  return "Operating system plug-in that gathers OS information from a python "
         "class that implements the necessary OperatingSystem functionality.";
}

OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
                                             const FileSpec &python_module_path)
    : OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_up(),
      m_interpreter(nullptr), m_python_object_sp() {
  if (!process)
    return;
  TargetSP target_sp = process->CalculateTarget();
  if (!target_sp)
    return;
  m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
  if (m_interpreter) {

    std::string os_plugin_class_name(
        python_module_path.GetFilename().AsCString(""));
    if (!os_plugin_class_name.empty()) {
      LoadScriptOptions options;
      char python_module_path_cstr[PATH_MAX];
      python_module_path.GetPath(python_module_path_cstr,
                                 sizeof(python_module_path_cstr));
      Status error;
      if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
                                             error)) {
        // Strip the ".py" extension if there is one
        size_t py_extension_pos = os_plugin_class_name.rfind(".py");
        if (py_extension_pos != std::string::npos)
          os_plugin_class_name.erase(py_extension_pos);
        // Add ".OperatingSystemPlugIn" to the module name to get a string like
        // "modulename.OperatingSystemPlugIn"
        os_plugin_class_name += ".OperatingSystemPlugIn";
        StructuredData::ObjectSP object_sp =
            m_interpreter->OSPlugin_CreatePluginObject(
                os_plugin_class_name.c_str(), process->CalculateProcess());
        if (object_sp && object_sp->IsValid())
          m_python_object_sp = object_sp;
      }
    }
  }
}

OperatingSystemPython::~OperatingSystemPython() = default;

DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
  if (m_register_info_up == nullptr) {
    if (!m_interpreter || !m_python_object_sp)
      return nullptr;
    Log *log = GetLog(LLDBLog::OS);

    LLDB_LOGF(log,
              "OperatingSystemPython::GetDynamicRegisterInfo() fetching "
              "thread register definitions from python for pid %" PRIu64,
              m_process->GetID());

    StructuredData::DictionarySP dictionary =
        m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp);
    if (!dictionary)
      return nullptr;

    m_register_info_up = std::make_unique<DynamicRegisterInfo>(
        *dictionary, m_process->GetTarget().GetArchitecture());
    assert(m_register_info_up->GetNumRegisters() > 0);
    assert(m_register_info_up->GetNumRegisterSets() > 0);
  }
  return m_register_info_up.get();
}

bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
                                             ThreadList &core_thread_list,
                                             ThreadList &new_thread_list) {
  if (!m_interpreter || !m_python_object_sp)
    return false;

  Log *log = GetLog(LLDBLog::OS);

  // First thing we have to do is to try to get the API lock, and the
  // interpreter lock. We're going to change the thread content of the process,
  // and we're going to use python, which requires the API lock to do it. We
  // need the interpreter lock to make sure thread_info_dict stays alive.
  //
  // If someone already has the API lock, that is ok, we just want to avoid
  // external code from making new API calls while this call is happening.
  //
  // This is a recursive lock so we can grant it to any Python code called on
  // the stack below us.
  Target &target = m_process->GetTarget();
  std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
                                                  std::defer_lock);
  (void)api_lock.try_lock(); // See above.
  auto interpreter_lock = m_interpreter->AcquireInterpreterLock();

  LLDB_LOGF(log,
            "OperatingSystemPython::UpdateThreadList() fetching thread "
            "data from python for pid %" PRIu64,
            m_process->GetID());

  // The threads that are in "core_thread_list" upon entry are the threads from
  // the lldb_private::Process subclass, no memory threads will be in this
  // list.
  StructuredData::ArraySP threads_list =
      m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);

  const uint32_t num_cores = core_thread_list.GetSize(false);

  // Make a map so we can keep track of which cores were used from the
  // core_thread list. Any real threads/cores that weren't used should later be
  // put back into the "new_thread_list".
  std::vector<bool> core_used_map(num_cores, false);
  if (threads_list) {
    if (log) {
      StreamString strm;
      threads_list->Dump(strm);
      LLDB_LOGF(log, "threads_list = %s", strm.GetData());
    }

    const uint32_t num_threads = threads_list->GetSize();
    for (uint32_t i = 0; i < num_threads; ++i) {
      StructuredData::ObjectSP thread_dict_obj =
          threads_list->GetItemAtIndex(i);
      if (auto thread_dict = thread_dict_obj->GetAsDictionary()) {
        ThreadSP thread_sp(CreateThreadFromThreadInfo(
            *thread_dict, core_thread_list, old_thread_list, core_used_map,
            nullptr));
        if (thread_sp)
          new_thread_list.AddThread(thread_sp);
      }
    }
  }

  // Any real core threads that didn't end up backing a memory thread should
  // still be in the main thread list, and they should be inserted at the
  // beginning of the list
  uint32_t insert_idx = 0;
  for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx) {
    if (!core_used_map[core_idx]) {
      new_thread_list.InsertThread(
          core_thread_list.GetThreadAtIndex(core_idx, false), insert_idx);
      ++insert_idx;
    }
  }

  return new_thread_list.GetSize(false) > 0;
}

ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo(
    StructuredData::Dictionary &thread_dict, ThreadList &core_thread_list,
    ThreadList &old_thread_list, std::vector<bool> &core_used_map,
    bool *did_create_ptr) {
  ThreadSP thread_sp;
  tid_t tid = LLDB_INVALID_THREAD_ID;
  if (!thread_dict.GetValueForKeyAsInteger("tid", tid))
    return ThreadSP();

  uint32_t core_number;
  addr_t reg_data_addr;
  llvm::StringRef name;
  llvm::StringRef queue;

  thread_dict.GetValueForKeyAsInteger("core", core_number, UINT32_MAX);
  thread_dict.GetValueForKeyAsInteger("register_data_addr", reg_data_addr,
                                      LLDB_INVALID_ADDRESS);
  thread_dict.GetValueForKeyAsString("name", name);
  thread_dict.GetValueForKeyAsString("queue", queue);

  // See if a thread already exists for "tid"
  thread_sp = old_thread_list.FindThreadByID(tid, false);
  if (thread_sp) {
    // A thread already does exist for "tid", make sure it was an operating
    // system
    // plug-in generated thread.
    if (!IsOperatingSystemPluginThread(thread_sp)) {
      // We have thread ID overlap between the protocol threads and the
      // operating system threads, clear the thread so we create an operating
      // system thread for this.
      thread_sp.reset();
    }
  }

  if (!thread_sp) {
    if (did_create_ptr)
      *did_create_ptr = true;
    thread_sp = std::make_shared<ThreadMemory>(*m_process, tid, name, queue,
                                               reg_data_addr);
  }

  if (core_number < core_thread_list.GetSize(false)) {
    ThreadSP core_thread_sp(
        core_thread_list.GetThreadAtIndex(core_number, false));
    if (core_thread_sp) {
      // Keep track of which cores were set as the backing thread for memory
      // threads...
      if (core_number < core_used_map.size())
        core_used_map[core_number] = true;

      ThreadSP backing_core_thread_sp(core_thread_sp->GetBackingThread());
      if (backing_core_thread_sp) {
        thread_sp->SetBackingThread(backing_core_thread_sp);
      } else {
        thread_sp->SetBackingThread(core_thread_sp);
      }
    }
  }
  return thread_sp;
}

void OperatingSystemPython::ThreadWasSelected(Thread *thread) {}

RegisterContextSP
OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
                                                      addr_t reg_data_addr) {
  RegisterContextSP reg_ctx_sp;
  if (!m_interpreter || !m_python_object_sp || !thread)
    return reg_ctx_sp;

  if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
    return reg_ctx_sp;

  // First thing we have to do is to try to get the API lock, and the
  // interpreter lock. We're going to change the thread content of the process,
  // and we're going to use python, which requires the API lock to do it. We
  // need the interpreter lock to make sure thread_info_dict stays alive.
  //
  // If someone already has the API lock, that is ok, we just want to avoid
  // external code from making new API calls while this call is happening.
  //
  // This is a recursive lock so we can grant it to any Python code called on
  // the stack below us.
  Target &target = m_process->GetTarget();
  std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
                                                  std::defer_lock);
  (void)api_lock.try_lock(); // See above.
  auto interpreter_lock = m_interpreter->AcquireInterpreterLock();

  Log *log = GetLog(LLDBLog::Thread);

  if (reg_data_addr != LLDB_INVALID_ADDRESS) {
    // The registers data is in contiguous memory, just create the register
    // context using the address provided
    LLDB_LOGF(log,
              "OperatingSystemPython::CreateRegisterContextForThread (tid "
              "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64
              ") creating memory register context",
              thread->GetID(), thread->GetProtocolID(), reg_data_addr);
    reg_ctx_sp = std::make_shared<RegisterContextMemory>(
        *thread, 0, *GetDynamicRegisterInfo(), reg_data_addr);
  } else {
    // No register data address is provided, query the python plug-in to let it
    // make up the data as it sees fit
    LLDB_LOGF(log,
              "OperatingSystemPython::CreateRegisterContextForThread (tid "
              "= 0x%" PRIx64 ", 0x%" PRIx64
              ") fetching register data from python",
              thread->GetID(), thread->GetProtocolID());

    StructuredData::StringSP reg_context_data =
        m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp,
                                                    thread->GetID());
    if (reg_context_data) {
      std::string value = std::string(reg_context_data->GetValue());
      DataBufferSP data_sp(new DataBufferHeap(value.c_str(), value.length()));
      if (data_sp->GetByteSize()) {
        RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory(
            *thread, 0, *GetDynamicRegisterInfo(), LLDB_INVALID_ADDRESS);
        if (reg_ctx_memory) {
          reg_ctx_sp.reset(reg_ctx_memory);
          reg_ctx_memory->SetAllRegisterData(data_sp);
        }
      }
    }
  }
  // if we still have no register data, fallback on a dummy context to avoid
  // crashing
  if (!reg_ctx_sp) {
    LLDB_LOGF(log,
              "OperatingSystemPython::CreateRegisterContextForThread (tid "
              "= 0x%" PRIx64 ") forcing a dummy register context",
              thread->GetID());
    reg_ctx_sp = std::make_shared<RegisterContextDummy>(
        *thread, 0, target.GetArchitecture().GetAddressByteSize());
  }
  return reg_ctx_sp;
}

StopInfoSP
OperatingSystemPython::CreateThreadStopReason(lldb_private::Thread *thread) {
  // We should have gotten the thread stop info from the dictionary of data for
  // the thread in the initial call to get_thread_info(), this should have been
  // cached so we can return it here
  StopInfoSP
      stop_info_sp; //(StopInfo::CreateStopReasonWithSignal (*thread, SIGSTOP));
  return stop_info_sp;
}

lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
                                                   addr_t context) {
  Log *log = GetLog(LLDBLog::Thread);

  LLDB_LOGF(log,
            "OperatingSystemPython::CreateThread (tid = 0x%" PRIx64
            ", context = 0x%" PRIx64 ") fetching register data from python",
            tid, context);

  if (m_interpreter && m_python_object_sp) {
    // First thing we have to do is to try to get the API lock, and the
    // interpreter lock. We're going to change the thread content of the
    // process, and we're going to use python, which requires the API lock to
    // do it. We need the interpreter lock to make sure thread_info_dict stays
    // alive.
    //
    // If someone already has the API lock, that is ok, we just want to avoid
    // external code from making new API calls while this call is happening.
    //
    // This is a recursive lock so we can grant it to any Python code called on
    // the stack below us.
    Target &target = m_process->GetTarget();
    std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
                                                    std::defer_lock);
    (void)api_lock.try_lock(); // See above.
    auto interpreter_lock = m_interpreter->AcquireInterpreterLock();

    StructuredData::DictionarySP thread_info_dict =
        m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
    std::vector<bool> core_used_map;
    if (thread_info_dict) {
      ThreadList core_threads(m_process);
      ThreadList &thread_list = m_process->GetThreadList();
      bool did_create = false;
      ThreadSP thread_sp(
          CreateThreadFromThreadInfo(*thread_info_dict, core_threads,
                                     thread_list, core_used_map, &did_create));
      if (did_create)
        thread_list.AddThread(thread_sp);
      return thread_sp;
    }
  }
  return ThreadSP();
}

#endif // #if LLDB_ENABLE_PYTHON
