//===-- 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/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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_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
