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

#include "Interfaces/ScriptInterpreterPythonInterfaces.h"
#include "PythonDataObjects.h"
#include "PythonReadline.h"
#include "SWIGPythonBridge.h"
#include "ScriptInterpreterPythonImpl.h"

#include "lldb/API/SBError.h"
#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ThreadedCommunication.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/ScriptInterpreterRuntimeLoader.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/Timer.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"

#if defined(_WIN32)
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif

#include <cstdio>
#include <cstdlib>
#include <memory>
#include <optional>
#include <stdlib.h>
#include <string>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
using llvm::Expected;

LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)

// Defined in the SWIG source file
extern "C" PyObject *PyInit__lldb(void);

#define LLDBSwigPyInit PyInit__lldb

#if defined(_WIN32)
// Don't mess with the signal handlers on Windows.
#define LLDB_USE_PYTHON_SET_INTERRUPT 0
#else
#define LLDB_USE_PYTHON_SET_INTERRUPT 1
#endif

static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) {
  ScriptInterpreter *script_interpreter =
      debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython);
  return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
}

namespace {

// Initializing Python is not a straightforward process.  We cannot control
// what external code may have done before getting to this point in LLDB,
// including potentially having already initialized Python, so we need to do a
// lot of work to ensure that the existing state of the system is maintained
// across our initialization.  We do this by using an RAII pattern where we
// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
  llvm::Error DoInitialize() {
    const bool was_initialized = Py_IsInitialized();

    // The table of built-in modules can only be extended before Python is
    // initialized.
    if (!was_initialized) {
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
      // Python's readline is incompatible with libedit being linked into lldb.
      // Provide a patched version local to the embedded interpreter.
      PyImport_AppendInittab("readline", initlldb_readline);
#endif

      // Register _lldb as a built-in module.
      PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
    }

#if LLDB_EMBED_PYTHON_HOME
    if (!was_initialized) {
      PyConfig config;
      PyConfig_InitPythonConfig(&config);

      static std::string g_python_home = []() -> std::string {
        if (llvm::sys::path::is_absolute(LLDB_PYTHON_HOME))
          return LLDB_PYTHON_HOME;

        FileSpec spec = HostInfo::GetShlibDir();
        if (!spec)
          return {};
        spec.AppendPathComponent(LLDB_PYTHON_HOME);
        return spec.GetPath();
      }();
      if (!g_python_home.empty()) {
        PyStatus status = PyConfig_SetBytesString(&config, &config.home,
                                                  g_python_home.c_str());
        if (PyStatus_Exception(status)) {
          PyConfig_Clear(&config);
          return llvm::createStringError(
              "failed to set the Python config: '%s'", status.err_msg);
        }
      }

      config.install_signal_handlers = 0;
      PyStatus status = Py_InitializeFromConfig(&config);
      PyConfig_Clear(&config);
      if (PyStatus_Exception(status))
        return llvm::createStringError("Python failed to initialize: '%s'",
                                       status.err_msg);
    }
#else
    if (!was_initialized)
      Py_InitializeEx(/*install_sigs=*/0);
    if (!Py_IsInitialized())
      return llvm::createStringError("Python failed to initialize");
#endif

    m_python_initialized = true;

    // The only case we should go further and acquire the GIL: it is unlocked.
    PyGILState_STATE gil_state = PyGILState_Ensure();
    if (gil_state != PyGILState_UNLOCKED)
      return llvm::Error::success();

    m_was_already_initialized = true;
    m_gil_state = gil_state;
    LLDB_LOG_VERBOSE(
        GetLog(LLDBLog::Script), "Ensured PyGILState. Previous state = {0}",
        m_gil_state == PyGILState_UNLOCKED ? "unlocked" : "locked");
    return llvm::Error::success();
  }

  ~InitializePythonRAII() {
    if (!m_python_initialized)
      return;

    if (m_was_already_initialized) {
      LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                       "Releasing PyGILState. Returning to state = {0}",
                       m_gil_state == PyGILState_UNLOCKED ? "unlocked"
                                                          : "locked");
      PyGILState_Release(m_gil_state);
    } else {
      // We initialized the threads in this function, just unlock the GIL.
      PyEval_SaveThread();
    }
  }

private:
  PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
  bool m_was_already_initialized = false;
  bool m_python_initialized = false;
};

#if LLDB_USE_PYTHON_SET_INTERRUPT
/// Saves the current signal handler for the specified signal and restores
/// it at the end of the current scope.
struct RestoreSignalHandlerScope {
  /// The signal handler.
  struct sigaction m_prev_handler;
  int m_signal_code;
  RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) {
    // Initialize sigaction to their default state.
    std::memset(&m_prev_handler, 0, sizeof(m_prev_handler));
    // Don't install a new handler, just read back the old one.
    struct sigaction *new_handler = nullptr;
    int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler);
    lldbassert(signal_err == 0 && "sigaction failed to read handler");
  }
  ~RestoreSignalHandlerScope() {
    int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr);
    lldbassert(signal_err == 0 && "sigaction failed to restore old handler");
  }
};
#endif
} // namespace

void ScriptInterpreterPython::ComputePythonDirForApple(
    llvm::SmallVectorImpl<char> &path) {
  auto style = llvm::sys::path::Style::posix;

  llvm::StringRef path_ref(path.begin(), path.size());
  auto rbegin = llvm::sys::path::rbegin(path_ref, style);
  auto rend = llvm::sys::path::rend(path_ref);
  auto framework = std::find(rbegin, rend, "LLDB.framework");
  if (framework == rend) {
    ComputePythonDir(path);
    return;
  }
  path.resize(framework - rend);
  llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
}

void ScriptInterpreterPython::ComputePythonDir(
    llvm::SmallVectorImpl<char> &path) {
  // Build the path by backing out of the lib dir, then building with whatever
  // the real python interpreter uses.  (e.g. lib for most, lib64 on RHEL
  // x86_64, or bin on Windows).
  llvm::sys::path::remove_filename(path);
  llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);

#if defined(_WIN32)
  // This will be injected directly through FileSpec.SetDirectory(),
  // so we need to normalize manually.
  std::replace(path.begin(), path.end(), '\\', '/');
#endif
}

FileSpec ScriptInterpreterPython::GetPythonDir() {
  static FileSpec g_spec = []() {
    FileSpec spec = HostInfo::GetShlibDir();
    if (!spec)
      return FileSpec();
    llvm::SmallString<64> path;
    spec.GetPath(path);

#if defined(__APPLE__)
    ComputePythonDirForApple(path);
#else
    ComputePythonDir(path);
#endif
    spec.SetDirectory(path);
    return spec;
  }();
  return g_spec;
}

static const char GetInterpreterInfoScript[] = R"(
import os
import sys

def main(lldb_python_dir, python_exe_relative_path):
  info = {
    "lldb-pythonpath": lldb_python_dir,
    "language": "python",
    "prefix": sys.prefix,
    "executable": os.path.join(sys.prefix, python_exe_relative_path)
  }
  return info
)";

static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;

StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {
  GIL gil;
  FileSpec python_dir_spec = GetPythonDir();
  if (!python_dir_spec)
    return nullptr;
  PythonScript get_info(GetInterpreterInfoScript);
  auto info_json = unwrapIgnoringErrors(
      As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),
                                    PythonString(python_exe_relative_path))));
  if (!info_json)
    return nullptr;
  return info_json.CreateStructuredDictionary();
}

llvm::Expected<std::string> ScriptInterpreterPython::ExtensionToImportPath(
    lldb::ScriptedExtension extension) {
  switch (extension) {
  case eScriptedExtensionOperatingSystem:
    return "lldb.plugins.operating_system";
  case eScriptedExtensionScriptedPlatform:
    return "lldb.plugins.scripted_platform";
  case eScriptedExtensionScriptedProcess:
    return "lldb.plugins.scripted_process";
  case eScriptedExtensionScriptedHook:
    return "lldb.plugins.scripted_hook";
  case eScriptedExtensionScriptedBreakpointResolver:
    return "lldb.plugins.scripted_breakpoint";
  case eScriptedExtensionScriptedThreadPlan:
    return "lldb.plugins.scripted_thread_plan";
  case eScriptedExtensionScriptedFrameProvider:
    return "lldb.plugins.scripted_frame_provider";
  case eScriptedExtensionScriptedThread:
  case eScriptedExtensionScriptedFrame:
    return "lldb.plugins.scripted_process";
  case eScriptedExtensionScriptedStackFrameRecognizer:
    return "lldb.plugins.scripted_stackframe_recognizer";
  case eScriptedExtensionScriptedCommand:
  case eScriptedExtensionParsedCommand:
    return "lldb.plugins.scripted_command";
  case eScriptedExtensionScriptedStringSummary:
    return "lldb.plugins.scripted_string_summary";
  case eScriptedExtensionScriptedSyntheticChildren:
    return "lldb.plugins.scripted_synthetic_children";
  case eScriptedExtensionInvalid:
    return llvm::createStringError("invalid extension name");
  }
  return llvm::createStringError("invalid extension name");
}

llvm::Expected<StructuredData::ObjectSP>
ScriptInterpreterPython::GetExtensionSchema(
    const llvm::SmallVector<llvm::StringRef> &extension_path) {
  lldb::ScriptedExtension extension =
      ScriptInterpreter::StringToExtension(extension_path.back());
  auto import_path_or_err = ExtensionToImportPath(extension);
  if (!import_path_or_err)
    return import_path_or_err.takeError();

  StreamString command_stream;
  // __import__(path, fromlist=['']) imports the submodule and returns it
  // directly (rather than the top-level package), as a single expression --
  // this keeps the whole call eval-able in one line while guaranteeing the
  // module is imported first; referencing "<import_path>.<ClassName>"
  // directly would only work if something else had already imported
  // <import_path> as a side effect.
  command_stream.Printf("lldb.embedded_interpreter.generate_extension_schema("
                        "__import__('%s', fromlist=['']).%s)",
                        import_path_or_err->c_str(),
                        ScriptInterpreter::ExtensionToString(extension).data());

  // Use eScriptReturnTypeOpaqueObject: it transfers a real owned reference
  // we can safely extract the string from. eScriptReturnTypeCharStrOrNone
  // instead hands back a pointer to a temporary Python object's buffer
  // that gets destroyed (and, for a freshly created string like this one,
  // deallocated) as soon as ExecuteOneLineWithReturn returns -- reading
  // it afterwards is a use-after-free.
  void *result_obj = nullptr;
  if (!ExecuteOneLineWithReturn(
          command_stream.GetData(),
          ScriptInterpreter::eScriptReturnTypeOpaqueObject, &result_obj,
          ExecuteScriptOptions().SetEnableIO(false)))
    return llvm::createStringError("invalid extension schema format");

  // ExecuteOneLineWithReturn releases the GIL before returning, so touching
  // the returned object (Str() below can execute arbitrary Python code) must
  // re-acquire it first. py_result is scoped so its destructor (a DECREF)
  // also runs before the GIL is released below, not after.
  std::string schema_str;
  {
    PyGILState_STATE gil_state = PyGILState_Ensure();
    {
      PythonObject py_result(PyRefType::Owned,
                             static_cast<PyObject *>(result_obj));
      if (py_result.IsAllocated() && py_result.get() != Py_None)
        schema_str = py_result.Str().GetString().str();
    }
    PyGILState_Release(gil_state);
  }

  if (schema_str.empty())
    return llvm::createStringError("empty extension schema");
  return StructuredData::ParseJSON(schema_str);
}

llvm::Error ScriptInterpreterPython::ParseExtensionSchema(
    Stream &s, llvm::StringRef output_script_prefix,
    const llvm::SmallVector<llvm::StringRef> &extension_path,
    bool generate_non_abstract_methods, std::set<std::string> &typing_imports) {
  auto schema_or_err = GetExtensionSchema(extension_path);
  if (!schema_or_err)
    return schema_or_err.takeError();

  StructuredData::ObjectSP schema = *schema_or_err;
  if (!schema)
    return llvm::createStringError("empty extension schema");
  StructuredData::Dictionary *dict = schema->GetAsDictionary();
  if (!dict)
    return llvm::createStringError("extension schema is not a JSON object");

  // Merge each class' typing imports into the caller-owned set so the
  // final `from typing import ...` line covers every class we emit.
  StructuredData::Array *schema_typing;
  if (dict->GetValueForKeyAsArray("typing_imports", schema_typing))
    schema_typing->ForEach([&](StructuredData::Object *entry) {
      if (auto *str = entry->GetAsString())
        typing_imports.insert(str->GetValue().str());
      return true;
    });

  llvm::StringRef base_class, import_path;
  if (!dict->GetValueForKeyAsString("class", base_class))
    return llvm::createStringError(
        llvm::formatv("extension schema dictionary is missing 'class' key")
            .str());
  if (!dict->GetValueForKeyAsString("module", import_path))
    return llvm::createStringError(
        llvm::formatv("extension schema dictionary is missing 'module' key")
            .str());

  // imports
  s.Printf("from %s import %s\n", import_path.data(), base_class.data());
  s.EOL();

  // class definition
  s.Printf("class %s%s(%s):\n", output_script_prefix.data(), base_class.data(),
           base_class.data());
  s.IndentMore();

  // Class docstring: list the non-callable members the base class exposes
  // so the user sees what's available without having to hop back to the
  // base class definition.
  bool has_body = false;
  StructuredData::Array *attributes;
  if (dict->GetValueForKeyAsArray("attributes", attributes) &&
      attributes->GetSize()) {
    s.Indent();
    s.PutCString("\"\"\"\n");
    s.Indent();
    s.Printf("Attributes inherited from %s:\n", base_class.data());
    for (size_t i = 0; i < attributes->GetSize(); i++) {
      auto maybe_dict = attributes->GetItemAtIndexAsDictionary(i);
      if (!maybe_dict)
        continue;
      StructuredData::Dictionary *attr_dict = *maybe_dict;
      llvm::StringRef attr_name;
      if (!attr_dict->GetValueForKeyAsString("name", attr_name))
        continue;
      llvm::StringRef attr_type;
      bool has_type = attr_dict->GetValueForKeyAsString("type", attr_type);
      s.Indent();
      s.Printf("- %s", attr_name.data());
      if (has_type)
        s.Printf(": %s", attr_type.data());
      s.EOL();
    }
    s.Indent();
    s.PutCString("\"\"\"\n\n");
    has_body = true;
  }

  // members
  StructuredData::Array *members;
  if (!dict->GetValueForKeyAsArray("members", members))
    return llvm::createStringError("missing 'members' key in extension schema");

  // If the base class doesn't mark anything `@abstractmethod`, the filter
  // "only stub abstract methods" would leave the derived class empty --
  // which isn't a useful starting point. Fall back to emitting every
  // method in that case so the user has actual code to edit.
  bool any_abstract = false;
  for (size_t i = 0; i < members->GetSize(); i++) {
    auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
    if (!maybe_dict)
      continue;
    bool is_abstract = false;
    if ((*maybe_dict)->GetValueForKeyAsBoolean("is_abstract", is_abstract) &&
        is_abstract) {
      any_abstract = true;
      break;
    }
  }
  bool emit_all_methods = generate_non_abstract_methods || !any_abstract;

  for (size_t i = 0; i < members->GetSize(); i++) {
    auto maybe_dict = members->GetItemAtIndexAsDictionary(i);
    if (!maybe_dict)
      return llvm::createStringError(
          llvm::formatv(
              "member at index {0} in extension schema isn't a dictionary")
              .str());

    StructuredData::Dictionary *member_dict = *maybe_dict;
    llvm::StringRef symbol, args;
    if (!member_dict->GetValueForKeyAsString("name", symbol))
      return llvm::createStringError(
          llvm::formatv(
              "member at index {0} in extension schema is missing 'name' key")
              .str());
    if (!member_dict->GetValueForKeyAsString("signature", args))
      return llvm::createStringError(
          llvm::formatv("member at index {0} in extension schema is missing "
                        "'signature' key")
              .str());

    bool is_abstract = false;
    bool has_is_abstract =
        member_dict->GetValueForKeyAsBoolean("is_abstract", is_abstract);
    if (!emit_all_methods)
      if (!has_is_abstract || !is_abstract)
        continue;

    s.Indent();
    s.Printf("def %s%s:\n", symbol.data(), args.data());

    s.IndentMore();
    llvm::StringRef documentation;
    if (member_dict->GetValueForKeyAsString("doc", documentation)) {
      s.Indent();
      s.PutCString("\"\"\"\n");

      llvm::SmallVector<llvm::StringRef> lines;
      documentation.split(lines, "\n");

      for (llvm::StringRef line : lines) {
        s.Indent();
        s.PutCString(line);
        s.EOL();
      }

      s.Indent();
      s.PutCString("\"\"\"");
      s.EOL();
    }

    if (symbol == "__init__") {
      // The base class' constructor sets up attributes (e.g. self.target,
      // self.process) that the inherited, non-overridden methods rely on.
      // Forward the same arguments so that state is still initialized.
      // Splitting the param list on `,` requires bracket-depth awareness
      // because annotations like `Union[X, Y]` also contain commas.
      llvm::StringRef params = args.trim("()");
      std::vector<std::string> forwarded_args;
      int depth = 0;
      size_t start = 0;
      auto flush = [&](size_t end) {
        llvm::StringRef param = params.slice(start, end);
        param = param.split(':').first.split('=').first.trim();
        if (!param.empty() && param != "self")
          forwarded_args.push_back(param.str());
      };
      for (size_t i = 0; i < params.size(); ++i) {
        char c = params[i];
        if (c == '[' || c == '(' || c == '{')
          ++depth;
        else if (c == ']' || c == ')' || c == '}')
          --depth;
        else if (c == ',' && depth == 0) {
          flush(i);
          start = i + 1;
        }
      }
      flush(params.size());
      s.Indent();
      s.Printf("super().__init__(%s)\n",
               llvm::join(forwarded_args, ", ").c_str());
    }

    s.Indent();
    s.PutCString("# TODO: Implement\n");
    s.Indent();
    s.PutCString("pass\n\n");
    s.IndentLess();
    has_body = true;
  }

  // A class with no body is a Python syntax error, so emit `pass` when the
  // base class has nothing to stub out (no methods and no attributes to
  // document).
  if (!has_body) {
    s.Indent();
    s.PutCString("pass\n");
  }

  return llvm::Error::success();
}

llvm::Expected<FileSpec> ScriptInterpreterPython::GenerateExtensionTemplate(
    const std::string &name, std::vector<ExtensionTemplateRequest> &extensions,
    bool generate_non_abstract_methods, std::string output_file) {
  // `ParseExtensionSchema` accumulates every `typing` generic it sees
  // (`Optional`, `Union`, `List`, ...) into this set so we can emit a
  // targeted `from typing import ...` line only for what's actually
  // referenced. The Python schema does the detection so we don't have
  // to re-scan strings here.
  std::set<std::string> typing_imports;
  StreamString bodies;
  for (const ExtensionTemplateRequest &extension : extensions) {
    if (llvm::Error err =
            ParseExtensionSchema(bodies, name, extension.path,
                                 generate_non_abstract_methods, typing_imports))
      return std::move(err);
    bodies.PutCString("\n\n");
  }

  StreamString generated_file_stream;
  generated_file_stream.PutCString("import lldb\n");
  if (!typing_imports.empty()) {
    std::vector<std::string> sorted_imports(typing_imports.begin(),
                                            typing_imports.end());
    generated_file_stream.Format("from typing import {0}\n",
                                 llvm::join(sorted_imports, ", "));
  }
  generated_file_stream.PutCString("\n");
  generated_file_stream.PutCString(bodies.GetString());

  FileSpec save_location;
  if (output_file.empty()) {
    // Sanitize the caller-supplied class prefix so it can't escape the
    // temp directory (`../`, path separators, ...). Only keep ASCII
    // alphanumerics; everything else collapses to `_`, and an all-junk
    // name falls back to a fixed default.
    std::string sanitized;
    sanitized.reserve(name.size());
    for (char c : name)
      sanitized.push_back(llvm::isAlnum(c) ? static_cast<char>(llvm::toLower(c))
                                           : '_');
    if (sanitized.find_first_not_of('_') == std::string::npos)
      sanitized = "extension";
    const std::string file_name = "lldb_" + sanitized + "_extension.py";
    save_location = HostInfo::GetGlobalTempDir();
    FileSystem::Instance().Resolve(save_location);
    save_location.AppendPathComponent(file_name);
  } else {
    save_location = FileSpec(output_file);
    FileSystem::Instance().Resolve(save_location);
  }

  File::OpenOptions flags = File::eOpenOptionWriteOnly |
                            File::eOpenOptionCanCreate |
                            File::eOpenOptionTruncate;

  auto opened_file = FileSystem::Instance().Open(save_location, flags);

  if (!opened_file)
    return opened_file.takeError();

  FileUP file = std::move(opened_file.get());

  size_t byte_size = generated_file_stream.GetSize();

  Status error = file->Write(generated_file_stream.GetData(), byte_size);

  if (error.Fail() || byte_size != generated_file_stream.GetSize())
    return llvm::createStringError("Unable to write to destination file. Bytes "
                                   "written do not match generated file size.");
  return save_location;
}

void ScriptInterpreterPython::SharedLibraryDirectoryHelper(
    FileSpec &this_file) {
  // When we're loaded from python, this_file will point to the file inside the
  // python package directory. Replace it with the one in the lib directory.
#ifdef _WIN32
  // On windows, we need to manually back out of the python tree, and go into
  // the bin directory. This is pretty much the inverse of what ComputePythonDir
  // does.
  if (this_file.GetFileNameExtension() == ".pyd") {
    this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd
    this_file.RemoveLastPathComponent(); // native
    this_file.RemoveLastPathComponent(); // lldb
    llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;
    for (auto it = llvm::sys::path::begin(libdir),
              end = llvm::sys::path::end(libdir);
         it != end; ++it)
      this_file.RemoveLastPathComponent();
    this_file.AppendPathComponent("bin");
    this_file.AppendPathComponent("liblldb.dll");
  }
#else
  // The python file is a symlink, so we can find the real library by resolving
  // it. We can do this unconditionally.
  FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);
#endif
}

llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() {
  return "Embedded Python interpreter";
}

void ScriptInterpreterPython::Initialize() {
  llvm::Expected<ScriptInterpreterRuntimeLoader &> loader =
      ScriptInterpreterRuntimeLoader::Get(lldb::eScriptLanguagePython);
  if (!loader) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), loader.takeError(), "{0}");
    return;
  }
  if (llvm::Error error = loader->Load()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
    return;
  }

#if LLDB_ENABLE_MTE
  // Python's allocator (pymalloc) is not aware of Memory Tagging Extension
  // (MTE) and crashes.
  // https://bugs.python.org/issue43593
  setenv("PYTHONMALLOC", "malloc", /*overwrite=*/true);
#endif

  // When the plugin is a separate shared library, the SWIG wrapper lives in
  // the plugin library, so the path helper that redirects lookups back to
  // liblldb is unnecessary.
#if !LLDB_ENABLE_DYNAMIC_SCRIPTINTERPRETERS
  HostInfo::SetSharedLibraryDirectoryHelper(
      ScriptInterpreterPython::SharedLibraryDirectoryHelper);
#endif

  // Bring the interpreter up before registering, so a Python that refuses to
  // initialize leaves no plugin claiming eScriptLanguagePython behind.
  // GetScriptInterpreterForLanguage then hands out ScriptInterpreterNone and
  // the rest of lldb keeps working without scripting.
  if (llvm::Error error = ScriptInterpreterPythonImpl::Initialize()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), std::move(error), "{0}");
    return;
  }

  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), GetPluginDescriptionStatic(),
      lldb::eScriptLanguagePython, ScriptInterpreterPythonImpl::CreateInstance,
      ScriptInterpreterPythonImpl::GetPythonDir);
  ScriptInterpreterPythonInterfaces::Initialize();
}

void ScriptInterpreterPython::Terminate() {
  ScriptInterpreterPythonInterfaces::Terminate();
  PluginManager::UnregisterPlugin(ScriptInterpreterPythonImpl::CreateInstance);
}

ScriptInterpreterPythonImpl::Locker::Locker(
    ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
    uint16_t on_leave, FileSP in, FileSP out, FileSP err)
    : ScriptInterpreterLocker(),
      m_teardown_session((on_leave & TearDownSession) == TearDownSession),
      m_python_interpreter(py_interpreter) {
  DoAcquireLock();
  if ((on_entry & InitSession) == InitSession) {
    if (!DoInitSession(on_entry, in, out, err)) {
      // Don't teardown the session if we didn't init it.
      m_teardown_session = false;
    }
  }
}

bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() {
  m_GILState = PyGILState_Ensure();
  LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                   "Ensured PyGILState. Previous state = {0}",
                   m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");

  // we need to save the thread state when we first start the command because
  // we might decide to interrupt it while some action is taking place outside
  // of Python (e.g. printing to screen, waiting for the network, ...) in that
  // case, _PyThreadState_Current will be NULL - and we would be unable to set
  // the asynchronous exception - not a desirable situation
  m_python_interpreter->SetThreadState(PyThreadState_Get());
  m_python_interpreter->IncrementLockCount();
  return true;
}

bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,
                                                        FileSP in, FileSP out,
                                                        FileSP err) {
  if (!m_python_interpreter)
    return false;
  return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
}

bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {
  LLDB_LOG_VERBOSE(GetLog(LLDBLog::Script),
                   "Releasing PyGILState. Returning to state = {0}",
                   m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");
  PyGILState_Release(m_GILState);
  m_python_interpreter->DecrementLockCount();
  return true;
}

bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {
  if (!m_python_interpreter)
    return false;
  m_python_interpreter->LeaveSession();
  return true;
}

ScriptInterpreterPythonImpl::Locker::~Locker() {
  if (m_teardown_session)
    DoTearDownSession();
  DoFreeLock();
}

ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
    : ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(),
      m_saved_stderr(), m_main_module(),
      m_session_dict(PyInitialValue::Invalid),
      m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),
      m_run_one_line_str_global(),
      m_dictionary_name(m_debugger.GetInstanceName()),
      m_active_io_handler(eIOHandlerNone), m_session_is_active(false),
      m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),
      m_command_thread_state(nullptr) {

  m_dictionary_name.append("_dict");
  StreamString run_string;
  run_string.Printf("%s = dict()", m_dictionary_name.c_str());

  Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);
  RunSimpleString(run_string.GetData());

  run_string.Clear();
  run_string.Printf("run_one_line (%s, 'import copy, keyword, os, re, sys, "
                    "uuid, lldb, importlib')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());

  // WARNING: temporary code that loads Cocoa formatters - this should be done
  // on a per-platform basis rather than loading the whole set and letting the
  // individual formatter classes exploit APIs to check whether they can/cannot
  // do their task
  run_string.Clear();
  run_string.Printf(
      "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",
      m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "
                    "lldb.embedded_interpreter import run_python_interpreter; "
                    "from lldb.embedded_interpreter import run_one_line')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  // Configure pydoc (built-in module) to use the "plain" pager. The default one
  // doesn't play nice with the statusline.
  run_string.Printf("run_one_line (%s, 'import pydoc; pydoc.pager = "
                    "pydoc.plainpager')",
                    m_dictionary_name.c_str());
  RunSimpleString(run_string.GetData());
  run_string.Clear();

  run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64
                    "')",
                    m_dictionary_name.c_str(), m_debugger.GetID());
  RunSimpleString(run_string.GetData());
}

/// A Python sys.stdout/stderr file backed by a pipe whose read end is drained
/// by a reader thread that writes to the debugger's terminal under the output
/// lock (Debugger::PrintAsync). Handing Python the raw terminal descriptor
/// instead lets a script's print() race the statusline, which redraws on the
/// event thread under that lock. Its cursor save/restore then rewinds over and
/// eats the script's output.
class ScriptInterpreterPythonImpl::SessionIORedirect {
public:
  static std::unique_ptr<SessionIORedirect> Create(lldb::user_id_t debugger_id,
                                                   bool is_stdout) {
    Pipe pipe;
    if (pipe.CreateNew().Fail())
      return nullptr;

    std::unique_ptr<SessionIORedirect> redirect(
        new SessionIORedirect(debugger_id, is_stdout));

#if defined(_WIN32)
    lldb::file_t read_handle = pipe.GetReadNativeHandle();
    pipe.ReleaseReadFileDescriptor();
    std::unique_ptr<Connection> conn =
        std::make_unique<ConnectionGenericFile>(read_handle, true);
#else
    std::unique_ptr<Connection> conn =
        std::make_unique<ConnectionFileDescriptor>(
            pipe.ReleaseReadFileDescriptor(), /*owns_fd=*/true);
#endif
    if (!conn->IsConnected())
      return nullptr;

    redirect->m_communication.SetConnection(std::move(conn));
    redirect->m_communication.SetReadThreadBytesReceivedCallback(
        ReadThreadBytesReceived, redirect.get());
    if (!redirect->m_communication.StartReadThread())
      return nullptr;
    redirect->m_connected = true;

    // The write end is owned here. Python only borrows its descriptor.
    redirect->m_write_file_sp = std::make_shared<NativeFile>(
        pipe.ReleaseWriteFileDescriptor(), File::eOpenOptionWriteOnly,
        NativeFile::Owned);
    return redirect;
  }

  ~SessionIORedirect() {
    if (!m_connected)
      return;
    // Close the write end so the reader sees EOF and exits, then join it.
    if (m_write_file_sp)
      m_write_file_sp->Close();
    m_communication.JoinReadThread();
    m_communication.Disconnect();
  }

  int GetWriteDescriptor() const {
    return m_write_file_sp ? m_write_file_sp->GetDescriptor()
                           : File::kInvalidDescriptor;
  }

private:
  SessionIORedirect(lldb::user_id_t debugger_id, bool is_stdout)
      : m_debugger_id(debugger_id), m_is_stdout(is_stdout),
        m_communication("lldb.ScriptInterpreterPython.io-redirect") {}

  static void ReadThreadBytesReceived(void *baton, const void *src,
                                      size_t src_len) {
    if (!src || !src_len)
      return;
    auto *self = static_cast<SessionIORedirect *>(baton);
    if (lldb::DebuggerSP debugger_sp =
            Debugger::FindDebuggerWithID(self->m_debugger_id))
      debugger_sp->PrintAsync(static_cast<const char *>(src), src_len,
                              self->m_is_stdout);
  }

  lldb::user_id_t m_debugger_id;
  bool m_is_stdout;
  lldb::FileSP m_write_file_sp;
  ThreadedCommunication m_communication;
  bool m_connected = false;
};

ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() {
  // the session dictionary may hold objects with complex state which means
  // that they may need to be torn down with some level of smarts and that, in
  // turn, requires a valid thread state force Python to procure itself such a
  // thread state, nuke the session dictionary and then release it for others
  // to use and proceed with the rest of the shutdown
  auto gil_state = PyGILState_Ensure();
  m_session_dict.Reset();
  PyGILState_Release(gil_state);
}

void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler,
                                                     bool interactive) {
  const char *instructions = nullptr;

  switch (m_active_io_handler) {
  case eIOHandlerNone:
    break;
  case eIOHandlerBreakpoint:
    instructions = R"(Enter your Python command(s). Type 'DONE' to end.
def function (frame, bp_loc, internal_dict):
    """frame: the lldb.SBFrame for the location at which you stopped
       bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
       internal_dict: an LLDB support object not to be used"""
)";
    break;
  case eIOHandlerWatchpoint:
    instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
    break;
  }

  if (instructions && interactive) {
    if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {
      LockedStreamFile locked_stream = stream_sp->Lock();
      locked_stream.PutCString(instructions);
      locked_stream.Flush();
    }
  }
}

void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
                                                         std::string &data) {
  io_handler.SetIsDone(true);
  bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();

  switch (m_active_io_handler) {
  case eIOHandlerNone:
    break;
  case eIOHandlerBreakpoint: {
    std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
        (std::vector<std::reference_wrapper<BreakpointOptions>> *)
            io_handler.GetUserData();
    for (BreakpointOptions &bp_options : *bp_options_vec) {

      auto data_up = std::make_unique<CommandDataPython>();
      if (!data_up)
        break;
      data_up->user_source.SplitIntoLines(data);

      if (GenerateBreakpointCommandCallbackData(data_up->user_source,
                                                data_up->script_source,
                                                /*has_extra_args=*/false,
                                                /*is_callback=*/false)
              .Success()) {
        auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
            std::move(data_up));
        bp_options.SetCallback(
            ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
      } else if (!batch_mode) {
        if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
          LockedStreamFile locked_stream = error_sp->Lock();
          locked_stream.Printf("Warning: No command attached to breakpoint.\n");
        }
      }
    }
    m_active_io_handler = eIOHandlerNone;
  } break;
  case eIOHandlerWatchpoint: {
    WatchpointOptions *wp_options =
        (WatchpointOptions *)io_handler.GetUserData();
    auto data_up = std::make_unique<WatchpointOptions::CommandData>();
    data_up->user_source.SplitIntoLines(data);

    if (GenerateWatchpointCommandCallbackData(data_up->user_source,
                                              data_up->script_source,
                                              /*is_callback=*/false)) {
      auto baton_sp =
          std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
      wp_options->SetCallback(
          ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
    } else if (!batch_mode) {
      if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
        LockedStreamFile locked_stream = error_sp->Lock();
        locked_stream.Printf("Warning: No command attached to breakpoint.\n");
      }
    }
    m_active_io_handler = eIOHandlerNone;
  } break;
  }
}

lldb::ScriptInterpreterSP
ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {
  return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
}

void ScriptInterpreterPythonImpl::LeaveSession() {
  Log *log = GetLog(LLDBLog::Script);
  if (log)
    log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");

  // Unset the LLDB global variables.
  RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
                  "= None; lldb.thread = None; lldb.frame = None");

  // checking that we have a valid thread state - since we use our own
  // threading and locking in some (rare) cases during cleanup Python may end
  // up believing we have no thread state and PyImport_AddModule will crash if
  // that is the case - since that seems to only happen when destroying the
  // SBDebugger, we can make do without clearing up stdout and stderr
  if (PyThreadState_GetDict()) {
    PythonDictionary &sys_module_dict = GetSysModuleDictionary();
    if (sys_module_dict.IsValid()) {
      // Flush the pipe-backed wrappers while they are still sys.stdout/stderr.
      // Line buffering already flushes on each newline, but a trailing
      // unterminated line would otherwise be stranded (and later flushed into
      // a closed descriptor) once we close the pipe write end below.
      auto flush_redirect = [&](const char *py_name,
                                std::unique_ptr<SessionIORedirect> &redirect) {
        if (!redirect)
          return;
        PythonObject file =
            sys_module_dict.GetItemForKey(PythonString(py_name));
        if (!file.IsValid())
          return;
        if (llvm::Expected<PythonObject> result = file.CallMethod("flush"))
          (void)result;
        else
          llvm::consumeError(result.takeError());
      };
      flush_redirect("stdout", m_stdout_redirect);
      flush_redirect("stderr", m_stderr_redirect);

      if (m_saved_stdin.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
        m_saved_stdin.Reset();
      }
      if (m_saved_stdout.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
        m_saved_stdout.Reset();
      }
      if (m_saved_stderr.IsValid()) {
        sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
        m_saved_stderr.Reset();
      }
    }
  }

  // Tear down the pipe redirects (closes each write end and joins its reader).
  // The wrappers were flushed above, so nothing buffered is lost.
  m_stdout_redirect.reset();
  m_stderr_redirect.reset();

  m_session_is_active = false;
}

bool ScriptInterpreterPythonImpl::RedirectTerminalHandleThroughLock(
    const char *py_name, PythonObject &save_file, const char *mode,
    File &file) {
  const bool is_stdout = ::strcmp(py_name, "stdout") == 0;
  if (!is_stdout && ::strcmp(py_name, "stderr") != 0)
    return false;

  // The statusline is the only writer that races Python's terminal output.
  // When it isn't drawing there is nothing to serialize against, so keep the
  // normal wrapping and skip the reader thread and pipe.
  if (!m_debugger.StatuslineSupported())
    return false;

  // Only the debugger's own terminal races the statusline. A redirect to a
  // pipe or user file (a different descriptor) is wrapped normally.
  lldb::FileSP debugger_file =
      is_stdout ? m_debugger.GetOutputFileSP() : m_debugger.GetErrorFileSP();
  int fd = file.GetDescriptor();
  if (!debugger_file || fd == File::kInvalidDescriptor ||
      fd != debugger_file->GetDescriptor())
    return false;

  std::unique_ptr<SessionIORedirect> &redirect =
      is_stdout ? m_stdout_redirect : m_stderr_redirect;
  redirect = SessionIORedirect::Create(m_debugger.GetID(), is_stdout);
  if (!redirect)
    return false;

  // Line-buffer the wrapper so each print() reaches the reader (and the
  // terminal) promptly: the pipe descriptor is not a tty, so the default
  // buffering would hold output back until the buffer filled.
  PyObject *pipe_file = PyFile_FromFd(
      PythonFile::TranslateFdToPython(redirect->GetWriteDescriptor()), nullptr,
      mode, /*buffering=*/1,
      /*encoding=*/nullptr, /*errors=*/"ignore",
      /*newline=*/nullptr,
      /*closefd=*/0);
  if (!pipe_file) {
    // Fall back to the raw descriptor. That reopens the statusline race, so
    // leave a breadcrumb rather than failing silently.
    LLDB_LOG(GetLog(LLDBLog::Script),
             "failed to wrap sys.{0} on a synchronized pipe; falling back to "
             "the unsynchronized terminal descriptor",
             py_name);
    PyErr_Clear();
    redirect.reset();
    return false;
  }

  PythonObject new_file(PyRefType::Owned, pipe_file);
  PythonDictionary &sys_module_dict = GetSysModuleDictionary();
  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));
  sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
  return true;
}

bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp,
                                               const char *py_name,
                                               PythonObject &save_file,
                                               const char *mode,
                                               bool serialize_terminal_output) {
  if (!file_sp || !*file_sp) {
    save_file.Reset();
    return false;
  }
  File &file = *file_sp;

  // When stdout/stderr point at the debugger's own terminal, route Python's
  // output through a pipe drained under the output lock so a script's print()
  // cannot race the statusline. Any other target keeps the normal wrapping.
  if (serialize_terminal_output &&
      RedirectTerminalHandleThroughLock(py_name, save_file, mode, file))
    return true;

  // Flush the file before giving it to python to avoid interleaved output.
  file.Flush();

  PythonDictionary &sys_module_dict = GetSysModuleDictionary();

  auto new_file = PythonFile::FromFile(file, mode);
  if (!new_file) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), new_file.takeError(),
                   "ScriptInterpreterPythonImpl::SetStdHandle failed to wrap "
                   "sys.{1}: {0}",
                   py_name);
    return false;
  }

  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));

  sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());
  return true;
}

bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
                                               FileSP in_sp, FileSP out_sp,
                                               FileSP err_sp) {
  // If we have already entered the session, without having officially 'left'
  // it, then there is no need to 'enter' it again.
  Log *log = GetLog(LLDBLog::Script);
  if (m_session_is_active) {
    LLDB_LOGF(
        log,
        "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
        ") session is already active, returning without doing anything",
        on_entry_flags);
    return false;
  }

  LLDB_LOGF(
      log,
      "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",
      on_entry_flags);

  m_session_is_active = true;

  StreamString run_string;

  if (on_entry_flags & Locker::InitGlobals) {
    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
                      m_dictionary_name.c_str(), m_debugger.GetID());
    run_string.Printf(
        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
        m_debugger.GetID());
    run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");
    run_string.PutCString("; lldb.process = lldb.target.GetProcess()");
    run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");
    run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
    run_string.PutCString("')");
  } else {
    // If we aren't initing the globals, we should still always set the
    // debugger (since that is always unique.)
    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
                      m_dictionary_name.c_str(), m_debugger.GetID());
    run_string.Printf(
        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
        m_debugger.GetID());
    run_string.PutCString("')");
  }

  RunSimpleString(run_string.GetData());
  run_string.Clear();

  PythonDictionary &sys_module_dict = GetSysModuleDictionary();
  if (sys_module_dict.IsValid()) {
    lldb::FileSP top_in_sp;
    lldb::LockableStreamFileSP top_out_sp, top_err_sp;
    if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
      m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
                                                 top_err_sp);

    if (on_entry_flags & Locker::NoSTDIN) {
      m_saved_stdin.Reset();
    } else {
      if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r",
                        /*serialize_terminal_output=*/false)) {
        if (top_in_sp)
          SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r",
                       /*serialize_terminal_output=*/false);
      }
    }

    // Serialize terminal output for every session except those that opt out
    // with NoOutputRedirect (see the flag for why).
    const bool serialize_terminal_output =
        !(on_entry_flags & Locker::NoOutputRedirect);

    if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w",
                      serialize_terminal_output)) {
      if (top_out_sp)
        SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,
                     "w", serialize_terminal_output);
    }

    if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w",
                      serialize_terminal_output)) {
      if (top_err_sp)
        SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,
                     "w", serialize_terminal_output);
    }
  }

  if (PyErr_Occurred())
    PyErr_Clear();

  return true;
}

PythonModule &ScriptInterpreterPythonImpl::GetMainModule() {
  if (!m_main_module.IsValid())
    m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__"));
  return m_main_module;
}

PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {
  if (m_session_dict.IsValid())
    return m_session_dict;

  PythonObject &main_module = GetMainModule();
  if (!main_module.IsValid())
    return m_session_dict;

  PythonDictionary main_dict(PyRefType::Borrowed,
                             PyModule_GetDict(main_module.get()));
  if (!main_dict.IsValid())
    return m_session_dict;

  m_session_dict = unwrapIgnoringErrors(
      As<PythonDictionary>(main_dict.GetItem(m_dictionary_name)));
  return m_session_dict;
}

PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
  if (m_sys_module_dict.IsValid())
    return m_sys_module_dict;
  PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));
  m_sys_module_dict = sys_module.GetDictionary();
  return m_sys_module_dict;
}

llvm::Expected<unsigned>
ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(
    const llvm::StringRef &callable_name) {
  if (callable_name.empty()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "called with empty callable name.");
  }
  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
      m_dictionary_name);
  auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
      callable_name, dict);
  if (!pfunc.IsAllocated()) {
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "can't find callable: %s",
                                   callable_name.str().c_str());
  }
  llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
  if (!arg_info) {
    // `-f` may point at a builtin, unlike other GetArgInfo() callers.
    LLDB_LOG_ERROR(GetLog(LLDBLog::Script), arg_info.takeError(),
                   "GetArgInfo failed for callable {1}, falling back to "
                   "inspect.signature: {0}",
                   callable_name);
    arg_info = PythonCallable::GetArgInfoFromInspectSignature(pfunc);
  }
  if (!arg_info)
    return arg_info.takeError();
  return arg_info.get().max_positional_args;
}

static std::string GenerateUniqueName(const char *base_name_wanted,
                                      uint32_t &functions_counter,
                                      const void *name_token = nullptr) {
  StreamString sstr;

  if (!base_name_wanted)
    return std::string();

  if (!name_token)
    sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
  else
    sstr.Printf("%s_%p", base_name_wanted, name_token);

  return std::string(sstr.GetString());
}

bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() {
  if (m_run_one_line_function.IsValid())
    return true;

  PythonObject module(PyRefType::Borrowed,
                      PyImport_AddModule("lldb.embedded_interpreter"));
  if (!module.IsValid())
    return false;

  PythonDictionary module_dict(PyRefType::Borrowed,
                               PyModule_GetDict(module.get()));
  if (!module_dict.IsValid())
    return false;

  m_run_one_line_function =
      module_dict.GetItemForKey(PythonString("run_one_line"));
  m_run_one_line_str_global =
      module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
  return m_run_one_line_function.IsValid();
}

bool ScriptInterpreterPythonImpl::ExecuteOneLine(
    llvm::StringRef command, CommandReturnObject *result,
    const ExecuteScriptOptions &options) {
  std::string command_str = command.str();

  if (!m_valid_session)
    return false;

  if (!command.empty()) {
    // We want to call run_one_line, passing in the dictionary and the command
    // string.  We cannot do this through RunSimpleString here because the
    // command string may contain escaped characters, and putting it inside
    // another string to pass to RunSimpleString messes up the escaping.  So
    // we use the following more complicated method to pass the command string
    // directly down to Python.
    llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
        io_redirect_or_error = ScriptInterpreterIORedirect::Create(
            options.GetEnableIO(), m_debugger, result);
    if (!io_redirect_or_error) {
      if (result)
        result->AppendErrorWithFormatv(
            "failed to redirect I/O: {0}\n",
            llvm::fmt_consume(io_redirect_or_error.takeError()));
      else
        llvm::consumeError(io_redirect_or_error.takeError());
      return false;
    }

    ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

    bool success = false;
    {
      // WARNING!  It's imperative that this RAII scope be as tight as
      // possible. In particular, the scope must end *before* we try to join
      // the read thread.  The reason for this is that a pre-requisite for
      // joining the read thread is that we close the write handle (to break
      // the pipe and cause it to wake up and exit).  But acquiring the GIL as
      // below will redirect Python's stdio to use this same handle.  If we
      // close the handle while Python is still using it, bad things will
      // happen.
      Locker locker(
          this,
          Locker::AcquireLock | Locker::InitSession |
              (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
              ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
          Locker::FreeAcquiredLock | Locker::TearDownSession,
          io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
          io_redirect.GetErrorFile());

      // Find the correct script interpreter dictionary in the main module.
      PythonDictionary &session_dict = GetSessionDictionary();
      if (session_dict.IsValid()) {
        if (GetEmbeddedInterpreterModuleObjects()) {
          if (PyCallable_Check(m_run_one_line_function.get())) {
            PythonObject pargs(
                PyRefType::Owned,
                Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
            if (pargs.IsValid()) {
              PythonObject return_value(
                  PyRefType::Owned,
                  PyObject_CallObject(m_run_one_line_function.get(),
                                      pargs.get()));
              if (return_value.IsValid())
                success = true;
              else if (options.GetMaskoutErrors() && PyErr_Occurred()) {
                PyErr_Print();
                PyErr_Clear();
              }
            }
          }
        }
      }

      io_redirect.Flush();
    }

    if (success)
      return true;

    // The one-liner failed.  Append the error message.
    if (result) {
      result->AppendErrorWithFormat("python failed attempting to evaluate '%s'",
                                    command_str.c_str());
    }
    return false;
  }

  if (result)
    result->AppendError("empty command passed to python\n");
  return false;
}

void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() {
  LLDB_SCOPED_TIMER();

  Debugger &debugger = m_debugger;

  // At the moment, the only time the debugger does not have an input file
  // handle is when this is called directly from Python, in which case it is
  // both dangerous and unnecessary (not to mention confusing) to try to embed
  // a running interpreter loop inside the already running Python interpreter
  // loop, so we won't do it.

  if (!debugger.GetInputFile().IsValid())
    return;

  IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
  if (io_handler_sp) {
    debugger.RunIOHandlerAsync(io_handler_sp);
  }
}

bool ScriptInterpreterPythonImpl::Interrupt() {
#if LLDB_USE_PYTHON_SET_INTERRUPT
  // If the interpreter isn't evaluating any Python at the moment then return
  // false to signal that this function didn't handle the interrupt and the
  // next component should try handling it.
  if (!IsExecutingPython())
    return false;

  // Tell Python that it should pretend to have received a SIGINT.
  PyErr_SetInterrupt();
  // PyErr_SetInterrupt has no way to return an error so we can only pretend the
  // signal got successfully handled and return true.
  // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but
  // the error handling is limited to checking the arguments which would be
  // just our (hardcoded) input signal code SIGINT, so that's not useful at all.
  return true;
#else
  Log *log = GetLog(LLDBLog::Script);

  if (IsExecutingPython()) {
    PyThreadState *state = PyThreadState_Get();
    if (!state)
      state = GetThreadState();
    if (state) {
      long tid = PyThread_get_thread_ident();
      PyThreadState_Swap(state);
      int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
      LLDB_LOGF(log,
                "ScriptInterpreterPythonImpl::Interrupt() sending "
                "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
                tid, num_threads);
      return true;
    }
  }
  LLDB_LOGF(log,
            "ScriptInterpreterPythonImpl::Interrupt() python code not running, "
            "can't interrupt");
  return false;
#endif
}

bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
    llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
    void *ret_value, const ExecuteScriptOptions &options) {

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error) {
    llvm::consumeError(io_redirect_or_error.takeError());
    return false;
  }

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  Locker locker(this,
                Locker::AcquireLock | Locker::InitSession |
                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
                    Locker::NoSTDIN,
                Locker::FreeAcquiredLock | Locker::TearDownSession,
                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                io_redirect.GetErrorFile());

  PythonModule &main_module = GetMainModule();
  PythonDictionary globals = main_module.GetDictionary();

  PythonDictionary locals = GetSessionDictionary();
  if (!locals.IsValid())
    locals = unwrapIgnoringErrors(
        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
  if (!locals.IsValid())
    locals = globals;

  Expected<PythonObject> maybe_py_return =
      runStringOneLine(in_string, globals, locals);

  if (!maybe_py_return) {
    llvm::handleAllErrors(
        maybe_py_return.takeError(),
        [&](PythonException &E) {
          E.Restore();
          if (options.GetMaskoutErrors()) {
            if (E.Matches(PyExc_SyntaxError)) {
              PyErr_Print();
            }
            PyErr_Clear();
          }
        },
        [](const llvm::ErrorInfoBase &E) {});
    return false;
  }

  PythonObject py_return = std::move(maybe_py_return.get());
  assert(py_return.IsValid());

  switch (return_type) {
  case eScriptReturnTypeCharPtr: // "char *"
  {
    const char format[3] = "s#";
    return PyArg_Parse(py_return.get(), format, (char **)ret_value);
  }
  case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
                                       // Py_None
  {
    const char format[3] = "z";
    return PyArg_Parse(py_return.get(), format, (char **)ret_value);
  }
  case eScriptReturnTypeBool: {
    const char format[2] = "b";
    return PyArg_Parse(py_return.get(), format, (bool *)ret_value);
  }
  case eScriptReturnTypeShortInt: {
    const char format[2] = "h";
    return PyArg_Parse(py_return.get(), format, (short *)ret_value);
  }
  case eScriptReturnTypeShortIntUnsigned: {
    const char format[2] = "H";
    return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
  }
  case eScriptReturnTypeInt: {
    const char format[2] = "i";
    return PyArg_Parse(py_return.get(), format, (int *)ret_value);
  }
  case eScriptReturnTypeIntUnsigned: {
    const char format[2] = "I";
    return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
  }
  case eScriptReturnTypeLongInt: {
    const char format[2] = "l";
    return PyArg_Parse(py_return.get(), format, (long *)ret_value);
  }
  case eScriptReturnTypeLongIntUnsigned: {
    const char format[2] = "k";
    return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
  }
  case eScriptReturnTypeLongLong: {
    const char format[2] = "L";
    return PyArg_Parse(py_return.get(), format, (long long *)ret_value);
  }
  case eScriptReturnTypeLongLongUnsigned: {
    const char format[2] = "K";
    return PyArg_Parse(py_return.get(), format,
                       (unsigned long long *)ret_value);
  }
  case eScriptReturnTypeFloat: {
    const char format[2] = "f";
    return PyArg_Parse(py_return.get(), format, (float *)ret_value);
  }
  case eScriptReturnTypeDouble: {
    const char format[2] = "d";
    return PyArg_Parse(py_return.get(), format, (double *)ret_value);
  }
  case eScriptReturnTypeChar: {
    const char format[2] = "c";
    return PyArg_Parse(py_return.get(), format, (char *)ret_value);
  }
  case eScriptReturnTypeOpaqueObject: {
    *((PyObject **)ret_value) = py_return.release();
    return true;
  }
  }
  llvm_unreachable("Fully covered switch!");
}

Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
    const char *in_string, const ExecuteScriptOptions &options) {

  if (in_string == nullptr)
    return Status();

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error)
    return Status::FromError(io_redirect_or_error.takeError());

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  Locker locker(this,
                Locker::AcquireLock | Locker::InitSession |
                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
                    Locker::NoSTDIN,
                Locker::FreeAcquiredLock | Locker::TearDownSession,
                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                io_redirect.GetErrorFile());

  PythonModule &main_module = GetMainModule();
  PythonDictionary globals = main_module.GetDictionary();

  PythonDictionary locals = GetSessionDictionary();
  if (!locals.IsValid())
    locals = unwrapIgnoringErrors(
        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));
  if (!locals.IsValid())
    locals = globals;

  Expected<PythonObject> return_value =
      runStringMultiLine(in_string, globals, locals);

  if (!return_value) {
    llvm::Error error =
        llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {
          llvm::Error error = llvm::createStringError(
              llvm::inconvertibleErrorCode(), E.ReadBacktrace());
          if (!options.GetMaskoutErrors())
            E.Restore();
          return error;
        });
    return Status::FromError(std::move(error));
  }

  return Status();
}

void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
    CommandReturnObject &result) {
  m_active_io_handler = eIOHandlerBreakpoint;
  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
      "    ", *this, &bp_options_vec);
}

void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
    WatchpointOptions *wp_options, CommandReturnObject &result) {
  m_active_io_handler = eIOHandlerWatchpoint;
  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
      "    ", *this, wp_options);
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
    BreakpointOptions &bp_options, const char *function_name,
    StructuredData::ObjectSP extra_args_sp) {
  Status error;
  // For now just cons up a oneliner that calls the provided function.
  std::string function_signature = function_name;

  llvm::Expected<unsigned> maybe_args =
      GetMaxPositionalArgumentsForCallable(function_name);
  if (!maybe_args) {
    error = Status::FromErrorStringWithFormat(
        "could not get num args: %s",
        llvm::toString(maybe_args.takeError()).c_str());
    return error;
  }
  size_t max_args = *maybe_args;

  bool uses_extra_args = false;
  if (max_args >= 4) {
    uses_extra_args = true;
    function_signature += "(frame, bp_loc, extra_args, internal_dict)";
  } else if (max_args >= 3) {
    if (extra_args_sp) {
      error = Status::FromErrorStringWithFormat(
          "cannot pass extra_args to a three argument callback");
      return error;
    }
    uses_extra_args = false;
    function_signature += "(frame, bp_loc, internal_dict)";
  } else {
    error = Status::FromErrorStringWithFormat("expected 3 or 4 argument "
                                              "function, %s can only take %zu",
                                              function_name, max_args);
    return error;
  }

  SetBreakpointCommandCallback(bp_options, function_signature.c_str(),
                               extra_args_sp, uses_extra_args,
                               /*is_callback=*/true);
  return error;
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options,
    std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
  Status error;
  error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
                                                cmd_data_up->script_source,
                                                /*has_extra_args=*/false,
                                                /*is_callback=*/false);
  if (error.Fail()) {
    return error;
  }
  auto baton_sp =
      std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
  bp_options.SetCallback(
      ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
  return error;
}

Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    bool is_callback) {
  return SetBreakpointCommandCallback(bp_options, command_body_text, {},
                                      /*uses_extra_args=*/false, is_callback);
}

// Set a Python one-liner as the callback for the breakpoint.
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
    BreakpointOptions &bp_options, const char *command_body_text,
    StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,
    bool is_callback) {
  auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
  // Split the command_body_text into lines, and pass that to
  // GenerateBreakpointCommandCallbackData.  That will wrap the body in an
  // auto-generated function, and return the function name in script_source.
  // That is what the callback will actually invoke.

  data_up->user_source.SplitIntoLines(command_body_text);
  Status error = GenerateBreakpointCommandCallbackData(
      data_up->user_source, data_up->script_source, uses_extra_args,
      is_callback);
  if (error.Success()) {
    auto baton_sp =
        std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
    bp_options.SetCallback(
        ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
    return error;
  }
  return error;
}

// Set a Python one-liner as the callback for the watchpoint.
void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback(
    WatchpointOptions *wp_options, const char *user_input, bool is_callback) {
  auto data_up = std::make_unique<WatchpointOptions::CommandData>();

  // It's necessary to set both user_source and script_source to the oneliner.
  // The former is used to generate callback description (as in watchpoint
  // command list) while the latter is used for Python to interpret during the
  // actual callback.

  data_up->user_source.AppendString(user_input);
  data_up->script_source.assign(user_input);

  if (GenerateWatchpointCommandCallbackData(
          data_up->user_source, data_up->script_source, is_callback)) {
    auto baton_sp =
        std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
    wp_options->SetCallback(
        ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
  }
}

Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(
    StringList &function_def) {
  // Convert StringList to one long, newline delimited, const char *.
  std::string function_def_string(function_def.CopyList());
  LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n{0}\n",
           function_def_string.c_str());

  Status error = ExecuteMultipleLines(
      function_def_string.c_str(), ExecuteScriptOptions().SetEnableIO(false));
  return error;
}

Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,
                                                     const StringList &input,
                                                     bool is_callback) {
  Status error;
  int num_lines = input.GetSize();
  if (num_lines == 0) {
    error = Status::FromErrorString("No input data.");
    return error;
  }

  if (!signature || *signature == 0) {
    error = Status::FromErrorString("No output function name.");
    return error;
  }

  StreamString sstr;
  StringList auto_generated_function;
  auto_generated_function.AppendString(signature);
  auto_generated_function.AppendString(
      "    global_dict = globals()"); // Grab the global dictionary
  auto_generated_function.AppendString(
      "    new_keys = internal_dict.keys()"); // Make a list of keys in the
                                              // session dict
  auto_generated_function.AppendString(
      "    old_keys = global_dict.keys()"); // Save list of keys in global dict
  auto_generated_function.AppendString(
      "    global_dict.update(internal_dict)"); // Add the session dictionary
                                                // to the global dictionary.

  if (is_callback) {
    // If the user input is a callback to a python function, make sure the input
    // is only 1 line, otherwise appending the user input would break the
    // generated wrapped function
    if (num_lines == 1) {
      sstr.Clear();
      sstr.Printf("    __return_val = %s", input.GetStringAtIndex(0));
      auto_generated_function.AppendString(sstr.GetData());
    } else {
      return Status::FromErrorString(
          "ScriptInterpreterPythonImpl::GenerateFunction(is_callback="
          "true) = ERROR: python function is multiline.");
    }
  } else {
    auto_generated_function.AppendString(
        "    __return_val = None"); // Initialize user callback return value.
    auto_generated_function.AppendString(
        "    def __user_code():"); // Create a nested function that will wrap
                                   // the user input. This is necessary to
                                   // capture the return value of the user input
                                   // and prevent early returns.
    for (int i = 0; i < num_lines; ++i) {
      sstr.Clear();
      sstr.Printf("      %s", input.GetStringAtIndex(i));
      auto_generated_function.AppendString(sstr.GetData());
    }
    auto_generated_function.AppendString(
        "    __return_val = __user_code()"); //  Call user code and capture
                                             //  return value
  }
  auto_generated_function.AppendString(
      "    for key in new_keys:"); // Iterate over all the keys from session
                                   // dict
  auto_generated_function.AppendString(
      "        if key in old_keys:"); // If key was originally in
                                      // global dict
  auto_generated_function.AppendString(
      "            internal_dict[key] = global_dict[key]"); // Update it
  auto_generated_function.AppendString(
      "        elif key in global_dict:"); // Then if it is still in the
                                           // global dict
  auto_generated_function.AppendString(
      "            del global_dict[key]"); //  remove key/value from the
                                           //  global dict
  auto_generated_function.AppendString(
      "    return __return_val"); //  Return the user callback return value.

  // Verify that the results are valid Python.
  error = ExportFunctionDefinitionToInterpreter(auto_generated_function);

  return error;
}

bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
    StringList &user_input, std::string &output, const void *name_token) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  // Take what the user wrote, wrap it all up inside one big auto-generated
  // Python function, passing in the ValueObject as parameter to the function.

  std::string auto_generated_function_name(
      GenerateUniqueName("lldb_autogen_python_type_print_func",
                         num_created_functions, name_token));
  sstr.Printf("def %s (valobj, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
           .Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(
    StringList &user_input, std::string &output) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_cmd_alias_func", num_created_functions));

  sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
           .Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
    StringList &user_input, std::string &output, const void *name_token) {
  static uint32_t num_created_classes = 0;
  user_input.RemoveBlankLines();
  int num_lines = user_input.GetSize();
  StreamString sstr;

  // Check to see if we have any data; if not, just return.
  if (user_input.GetSize() == 0)
    return false;

  // Wrap all user input into a Python class

  std::string auto_generated_class_name(GenerateUniqueName(
      "lldb_autogen_python_type_synth_class", num_created_classes, name_token));

  StringList auto_generated_class;

  // Create the function name & definition string.

  sstr.Printf("class %s:", auto_generated_class_name.c_str());
  auto_generated_class.AppendString(sstr.GetString());

  // Wrap everything up inside the class, increasing the indentation. we don't
  // need to play any fancy indentation tricks here because there is no
  // surrounding code whose indentation we need to honor
  for (int i = 0; i < num_lines; ++i) {
    sstr.Clear();
    sstr.Printf("     %s", user_input.GetStringAtIndex(i));
    auto_generated_class.AppendString(sstr.GetString());
  }

  // Verify that the results are valid Python. (even though the method is
  // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
  // (TODO: rename that method to ExportDefinitionToInterpreter)
  if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
    return false;

  // Store the name of the auto-generated class

  output.assign(auto_generated_class_name);
  return true;
}

ScriptedProcessInterfaceUP
ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {
  return std::make_unique<ScriptedProcessPythonInterface>(*this);
}

ScriptedHookInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedHookInterface() {
  return std::make_shared<ScriptedHookPythonInterface>(*this);
}

ScriptedBreakpointInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() {
  return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
}

ScriptedStackFrameRecognizerInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedStackFrameRecognizerInterface() {
  return std::make_shared<ScriptedStackFrameRecognizerPythonInterface>(*this);
}

ScriptedCommandInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedCommandInterface() {
  return std::make_shared<ScriptedCommandPythonInterface>(*this);
}

ScriptedStringSummaryInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedStringSummaryInterface() {
  return std::make_shared<ScriptedStringSummaryPythonInterface>(*this);
}

ScriptedSyntheticChildrenInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedSyntheticChildrenInterface() {
  return std::make_shared<ScriptedSyntheticChildrenPythonInterface>(*this);
}

ScriptedThreadInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
  return std::make_shared<ScriptedThreadPythonInterface>(*this);
}

ScriptedFrameInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedFrameInterface() {
  return std::make_shared<ScriptedFramePythonInterface>(*this);
}

ScriptedFrameProviderInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedFrameProviderInterface() {
  return std::make_shared<ScriptedFrameProviderPythonInterface>(*this);
}

ScriptedThreadPlanInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {
  return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
}

OperatingSystemInterfaceSP
ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {
  return std::make_shared<OperatingSystemPythonInterface>(*this);
}

StructuredData::ObjectSP
ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
    ScriptObject obj) {
  void *ptr = const_cast<void *>(obj.GetPointer());
  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
  PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));
  if (!py_obj.IsValid() || py_obj.IsNone())
    return {};
  return py_obj.CreateStructuredObject();
}

StructuredData::ObjectSP
ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
                                              lldb_private::Status &error) {
  if (!FileSystem::Instance().Exists(file_spec)) {
    error = Status::FromErrorString("no such file");
    return StructuredData::ObjectSP();
  }

  StructuredData::ObjectSP module_sp;

  LoadScriptOptions load_script_options =
      LoadScriptOptions().SetInitSession(true).SetSilent(false);
  if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
                          error, &module_sp))
    return module_sp;

  return StructuredData::ObjectSP();
}

StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(
    StructuredData::ObjectSP plugin_module_sp, Target *target,
    const char *setting_name, lldb_private::Status &error) {
  if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
    return StructuredData::DictionarySP();
  StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
  if (!generic)
    return StructuredData::DictionarySP();

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  TargetSP target_sp(target->shared_from_this());

  auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(
      generic->GetValue(), setting_name, target_sp);

  if (!setting)
    return StructuredData::DictionarySP();

  PythonDictionary py_dict =
      unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting)));

  if (!py_dict)
    return StructuredData::DictionarySP();

  return py_dict.CreateStructuredDictionary();
}

bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
    const char *oneliner, std::string &output, const void *name_token) {
  StringList input;
  input.SplitIntoLines(oneliner, strlen(oneliner));
  return GenerateTypeScriptFunction(input, output, name_token);
}

bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
    const char *oneliner, std::string &output, const void *name_token) {
  StringList input;
  input.SplitIntoLines(oneliner, strlen(oneliner));
  return GenerateTypeSynthClass(input, output, name_token);
}

Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
    StringList &user_input, std::string &output, bool has_extra_args,
    bool is_callback) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;
  Status error;
  if (user_input.GetSize() == 0) {
    error = Status::FromErrorString("No input data.");
    return error;
  }

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_bp_callback_func_", num_created_functions));
  if (has_extra_args)
    sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
                auto_generated_function_name.c_str());
  else
    sstr.Printf("def %s (frame, bp_loc, internal_dict):",
                auto_generated_function_name.c_str());

  error = GenerateFunction(sstr.GetData(), user_input, is_callback);
  if (!error.Success())
    return error;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return error;
}

bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData(
    StringList &user_input, std::string &output, bool is_callback) {
  static uint32_t num_created_functions = 0;
  user_input.RemoveBlankLines();
  StreamString sstr;

  if (user_input.GetSize() == 0)
    return false;

  std::string auto_generated_function_name(GenerateUniqueName(
      "lldb_autogen_python_wp_callback_func_", num_created_functions));
  sstr.Printf("def %s (frame, wp, internal_dict):",
              auto_generated_function_name.c_str());

  if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())
    return false;

  // Store the name of the auto-generated function to be called.
  output.assign(auto_generated_function_name);
  return true;
}

bool ScriptInterpreterPythonImpl::GetScriptedSummary(
    const char *python_function_name, lldb::ValueObjectSP valobj,
    StructuredData::ObjectSP &callee_wrapper_sp,
    const TypeSummaryOptions &options, std::string &retval) {

  LLDB_SCOPED_TIMER();

  if (!valobj.get()) {
    retval.assign("<no object>");
    return false;
  }

  void *old_callee = nullptr;
  StructuredData::Generic *generic = nullptr;
  if (callee_wrapper_sp) {
    generic = callee_wrapper_sp->GetAsGeneric();
    if (generic)
      old_callee = generic->GetValue();
  }
  void *new_callee = old_callee;

  bool ret_val;
  if (python_function_name && *python_function_name) {
    {
      Locker py_lock(this, Locker::AcquireLock | Locker::InitSession |
                               Locker::NoSTDIN);
      {
        TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));

        static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");
        Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");
        ret_val = SWIGBridge::LLDBSwigPythonCallTypeScript(
            python_function_name, GetSessionDictionary().get(), valobj,
            &new_callee, options_sp, retval);
      }
    }
  } else {
    retval.assign("<no function name>");
    return false;
  }

  if (new_callee && old_callee != new_callee) {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    callee_wrapper_sp = std::make_shared<StructuredPythonObject>(
        PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));
  }

  return ret_val;
}

bool ScriptInterpreterPythonImpl::FormatterCallbackFunction(
    const char *python_function_name, TypeImplSP type_impl_sp) {
  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  return SWIGBridge::LLDBSwigPythonFormatterCallbackFunction(
      python_function_name, m_dictionary_name.c_str(), type_impl_sp);
}

bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t break_id,
    user_id_t break_loc_id) {
  CommandDataPython *bp_option_data = (CommandDataPython *)baton;
  const char *python_function_name = bp_option_data->script_source.c_str();

  if (!context)
    return true;

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();

  if (!target)
    return true;

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterPythonImpl *python_interpreter =
      GetPythonInterpreter(debugger);

  if (!python_interpreter)
    return true;

  if (python_function_name && python_function_name[0]) {
    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
    BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);
    if (breakpoint_sp) {
      const BreakpointLocationSP bp_loc_sp(
          breakpoint_sp->FindLocationByID(break_loc_id));

      if (stop_frame_sp && bp_loc_sp) {
        bool ret_val = true;
        {
          Locker py_lock(python_interpreter, Locker::AcquireLock |
                                                 Locker::InitSession |
                                                 Locker::NoSTDIN);
          Expected<bool> maybe_ret_val =
              SWIGBridge::LLDBSwigPythonBreakpointCallbackFunction(
                  python_function_name,
                  python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
                  bp_loc_sp, bp_option_data->m_extra_args);

          if (!maybe_ret_val) {

            llvm::handleAllErrors(
                maybe_ret_val.takeError(),
                [&](PythonException &E) {
                  *debugger.GetAsyncErrorStream() << E.ReadBacktrace();
                },
                [&](const llvm::ErrorInfoBase &E) {
                  *debugger.GetAsyncErrorStream() << E.message();
                });

          } else {
            ret_val = maybe_ret_val.get();
          }
        }
        return ret_val;
      }
    }
  }
  // We currently always true so we stop in case anything goes wrong when
  // trying to call the script function
  return true;
}

bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction(
    void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
  WatchpointOptions::CommandData *wp_option_data =
      (WatchpointOptions::CommandData *)baton;
  const char *python_function_name = wp_option_data->script_source.c_str();

  if (!context)
    return true;

  ExecutionContext exe_ctx(context->exe_ctx_ref);
  Target *target = exe_ctx.GetTargetPtr();

  if (!target)
    return true;

  Debugger &debugger = target->GetDebugger();
  ScriptInterpreterPythonImpl *python_interpreter =
      GetPythonInterpreter(debugger);

  if (!python_interpreter)
    return true;

  if (python_function_name && python_function_name[0]) {
    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
    WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
    if (wp_sp) {
      if (stop_frame_sp && wp_sp) {
        bool ret_val = true;
        {
          Locker py_lock(python_interpreter, Locker::AcquireLock |
                                                 Locker::InitSession |
                                                 Locker::NoSTDIN);
          ret_val = SWIGBridge::LLDBSwigPythonWatchpointCallbackFunction(
              python_function_name,
              python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
              wp_sp);
        }
        return ret_val;
      }
    }
  }
  // We currently always true so we stop in case anything goes wrong when
  // trying to call the script function
  return true;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Process *process, std::string &output,
    Status &error) {
  bool ret_val;
  if (!process) {
    error = Status::FromErrorString("no process");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordProcess(
        impl_function, m_dictionary_name.c_str(), process->shared_from_this(),
        output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Thread *thread, std::string &output,
    Status &error) {
  if (!thread) {
    error = Status::FromErrorString("no thread");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  if (std::optional<std::string> result =
          SWIGBridge::LLDBSWIGPythonRunScriptKeywordThread(
              impl_function, m_dictionary_name.c_str(),
              thread->shared_from_this())) {
    output = std::move(*result);
    return true;
  }
  error = Status::FromErrorString("python script evaluation failed");
  return false;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, Target *target, std::string &output,
    Status &error) {
  bool ret_val;
  if (!target) {
    error = Status::FromErrorString("no thread");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    TargetSP target_sp(target->shared_from_this());
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordTarget(
        impl_function, m_dictionary_name.c_str(), target_sp, output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, StackFrame *frame, std::string &output,
    Status &error) {
  if (!frame) {
    error = Status::FromErrorString("no frame");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  Locker py_lock(this,
                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
  if (std::optional<std::string> result =
          SWIGBridge::LLDBSWIGPythonRunScriptKeywordFrame(
              impl_function, m_dictionary_name.c_str(),
              frame->shared_from_this())) {
    output = std::move(*result);
    return true;
  }
  error = Status::FromErrorString("python script evaluation failed");
  return false;
}

bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
    const char *impl_function, ValueObject *value, std::string &output,
    Status &error) {
  bool ret_val;
  if (!value) {
    error = Status::FromErrorString("no value");
    return false;
  }
  if (!impl_function || !impl_function[0]) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(
        impl_function, m_dictionary_name.c_str(), value->GetSP(), output);
    if (!ret_val)
      error = Status::FromErrorString("python script evaluation failed");
  }
  return ret_val;
}

uint64_t replace_all(std::string &str, const std::string &oldStr,
                     const std::string &newStr) {
  size_t pos = 0;
  uint64_t matches = 0;
  while ((pos = str.find(oldStr, pos)) != std::string::npos) {
    matches++;
    str.replace(pos, oldStr.length(), newStr);
    pos += newStr.length();
  }
  return matches;
}

bool ScriptInterpreterPythonImpl::LoadScriptingModule(
    const char *pathname, const LoadScriptOptions &options,
    lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
    FileSpec extra_search_dir, lldb::TargetSP target_sp) {
  namespace fs = llvm::sys::fs;
  namespace path = llvm::sys::path;

  ExecuteScriptOptions exc_options = ExecuteScriptOptions()
                                         .SetEnableIO(!options.GetSilent())
                                         .SetSetLLDBGlobals(false);

  if (!pathname || !pathname[0]) {
    error = Status::FromErrorString("empty path");
    return false;
  }

  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
      io_redirect_or_error = ScriptInterpreterIORedirect::Create(
          exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);

  if (!io_redirect_or_error) {
    error = Status::FromError(io_redirect_or_error.takeError());
    return false;
  }

  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;

  // Before executing Python code, lock the GIL.
  Locker py_lock(this,
                 Locker::AcquireLock |
                     (options.GetInitSession() ? Locker::InitSession : 0) |
                     Locker::NoSTDIN,
                 Locker::FreeAcquiredLock |
                     (options.GetInitSession() ? Locker::TearDownSession : 0),
                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
                 io_redirect.GetErrorFile());

  auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
    if (directory.empty()) {
      return llvm::createStringError("invalid directory name");
    }

    replace_all(directory, "\\", "\\\\");
    replace_all(directory, "'", "\\'");

    // Make sure that Python has "directory" in the search path.
    StreamString command_stream;
    command_stream.Printf("if not (sys.path.__contains__('%s')):\n    "
                          "sys.path.insert(1,'%s');\n\n",
                          directory.c_str(), directory.c_str());
    bool syspath_retval =
        ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
    if (!syspath_retval)
      return llvm::createStringError("Python sys.path handling failed");

    return llvm::Error::success();
  };

  std::string module_name(pathname);
  bool possible_package = false;

  if (extra_search_dir) {
    if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
      error = Status::FromError(std::move(e));
      return false;
    }
  } else {
    FileSpec module_file(pathname);
    FileSystem::Instance().Resolve(module_file);

    fs::file_status st;
    std::error_code ec = status(module_file.GetPath(), st);

    if (ec || st.type() == fs::file_type::status_error ||
        st.type() == fs::file_type::type_unknown ||
        st.type() == fs::file_type::file_not_found) {
      // if not a valid file of any sort, check if it might be a filename still
      // dot can't be used but / and \ can, and if either is found, reject
      if (strchr(pathname, '\\') || strchr(pathname, '/')) {
        error = Status::FromErrorStringWithFormatv("invalid pathname '{0}'",
                                                   pathname);
        return false;
      }
      // Not a filename, probably a package of some sort, let it go through.
      possible_package = true;
    } else if (is_directory(st) || is_regular_file(st)) {
      if (module_file.GetDirectory().empty()) {
        error = Status::FromErrorStringWithFormatv(
            "invalid directory name '{0}'", pathname);
        return false;
      }
      if (llvm::Error e = ExtendSysPath(module_file.GetDirectory().str())) {
        error = Status::FromError(std::move(e));
        return false;
      }
      module_name = module_file.GetFilename().str();
    } else {
      error = Status::FromErrorString(
          "no known way to import this module specification");
      return false;
    }
  }

  // Strip .py or .pyc extension
  llvm::StringRef extension = llvm::sys::path::extension(module_name);
  if (!extension.empty()) {
    if (extension == ".py")
      module_name.resize(module_name.length() - 3);
    else if (extension == ".pyc")
      module_name.resize(module_name.length() - 4);
  }

  if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
    error = Status::FromErrorStringWithFormat(
        "Python does not allow dots in module names: %s", module_name.c_str());
    return false;
  }

  if (module_name.find('-') != llvm::StringRef::npos) {
    error = Status::FromErrorStringWithFormat(
        "Python discourages dashes in module names: %s", module_name.c_str());
    return false;
  }

  // Check if the module is already imported.
  StreamString command_stream;
  command_stream.Clear();
  command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
  bool does_contain = false;
  // This call will succeed if the module was ever imported in any Debugger in
  // the lifetime of the process in which this LLDB framework is living.
  const bool does_contain_executed = ExecuteOneLineWithReturn(
      command_stream.GetData(),
      ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,
      exc_options);

  const bool was_imported_globally = does_contain_executed && does_contain;
  const bool was_imported_locally =
      GetSessionDictionary()
          .GetItemForKey(PythonString(module_name))
          .IsAllocated();

  // now actually do the import
  command_stream.Clear();

  if (was_imported_globally || was_imported_locally) {
    if (!was_imported_locally)
      command_stream.Printf("import %s ; importlib.reload(%s)",
                            module_name.c_str(), module_name.c_str());
    else
      command_stream.Printf("importlib.reload(%s)", module_name.c_str());
  } else
    command_stream.Printf("import %s", module_name.c_str());

  error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
  if (error.Fail())
    return false;

  // if we are here, everything worked
  // call __lldb_init_module(debugger,dict)
  if (!SWIGBridge::LLDBSwigPythonCallModuleInit(
          module_name.c_str(), m_dictionary_name.c_str(),
          m_debugger.shared_from_this())) {
    error = Status::FromErrorString("calling __lldb_init_module failed");
    return false;
  }

  if (module_sp) {
    // everything went just great, now set the module object
    command_stream.Clear();
    command_stream.Printf("%s", module_name.c_str());
    void *module_pyobj = nullptr;
    if (ExecuteOneLineWithReturn(
            command_stream.GetData(),
            ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,
            exc_options) &&
        module_pyobj)
      *module_sp = std::make_shared<StructuredPythonObject>(PythonObject(
          PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));
  }

  // Finally, if we got a target passed in, then we should tell the new module
  // about this target:
  if (target_sp)
    return SWIGBridge::LLDBSwigPythonCallModuleNewTarget(
        module_name.c_str(), m_dictionary_name.c_str(), target_sp);

  return true;
}

bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {
  if (!word || !word[0])
    return false;

  llvm::StringRef word_sr(word);

  // filter out a few characters that would just confuse us and that are
  // clearly not keyword material anyway
  if (word_sr.find('"') != llvm::StringRef::npos ||
      word_sr.find('\'') != llvm::StringRef::npos)
    return false;

  StreamString command_stream;
  command_stream.Printf("keyword.iskeyword('%s')", word);
  bool result;
  ExecuteScriptOptions options;
  options.SetEnableIO(false);
  options.SetMaskoutErrors(true);
  options.SetSetLLDBGlobals(false);
  if (ExecuteOneLineWithReturn(command_stream.GetData(),
                               ScriptInterpreter::eScriptReturnTypeBool,
                               &result, options))
    return result;
  return false;
}

ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler(
    lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro)
    : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),
      m_old_asynch(debugger_sp->GetAsyncExecution()) {
  if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
    m_debugger_sp->SetAsyncExecution(false);
  else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
    m_debugger_sp->SetAsyncExecution(true);
}

ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() {
  if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
    m_debugger_sp->SetAsyncExecution(m_old_asynch);
}

bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(
    const char *impl_function, llvm::StringRef args,
    ScriptedCommandSynchronicity synchronicity,
    lldb_private::CommandReturnObject &cmd_retobj, Status &error,
    const lldb_private::ExecutionContext &exe_ctx) {
  if (!impl_function) {
    error = Status::FromErrorString("no function to execute");
    return false;
  }

  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
  lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));

  if (!debugger_sp.get()) {
    error = Status::FromErrorString("invalid Debugger pointer");
    return false;
  }

  bool ret_val = false;

  {
    Locker py_lock(this,
                   Locker::AcquireLock | Locker::InitSession |
                       (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
                   Locker::FreeLock | Locker::TearDownSession);

    SynchronicityHandler synch_handler(debugger_sp, synchronicity);

    std::string args_str = args.str();
    ret_val = SWIGBridge::LLDBSwigPythonCallCommand(
        impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),
        cmd_retobj, exe_ctx_ref_sp);
  }

  if (!ret_val) {
    error = Status::FromErrorString("unable to execute script function");
    return false;
  }
  if (cmd_retobj.GetStatus() == eReturnStatusFailed)
    return false;

  error.Clear();
  return ret_val;
}

/// In Python, a special attribute __doc__ contains the docstring for an object
/// (function, method, class, ...) if any is defined Otherwise, the attribute's
/// value is None.
bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,
                                                          std::string &dest) {
  dest.clear();

  if (!item || !*item)
    return false;

  std::string command(item);
  command += ".__doc__";

  // Python is going to point this to valid data if ExecuteOneLineWithReturn
  // returns successfully.
  char *result_ptr = nullptr;

  if (ExecuteOneLineWithReturn(
          command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
          &result_ptr, ExecuteScriptOptions().SetEnableIO(false))) {
    if (result_ptr)
      dest.assign(result_ptr);
    return true;
  }

  StreamString str_stream;
  str_stream << "Function " << item
             << " was not found. Containing module might be missing.";
  dest = std::string(str_stream.GetString());

  return false;
}

std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreterPythonImpl::AcquireInterpreterLock() {
  std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
      this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
      Locker::FreeLock | Locker::TearDownSession));
  return py_lock;
}

llvm::Error ScriptInterpreterPythonImpl::Initialize() {
  LLDB_SCOPED_TIMER();

  // RAII-based initialization which correctly handles multiple-initialization,
  // version- specific differences among Python 2 and Python 3, and saving and
  // restoring various other pieces of state that can get mucked with during
  // initialization.
  InitializePythonRAII initialize_guard;
  if (llvm::Error error = initialize_guard.DoInitialize())
    return error;

  LLDBSwigPyInit();

  // Update the path python uses to search for modules to include the current
  // directory.

  RunSimpleString("import sys");
  AddToSysPath(AddLocation::End, ".");

  // Don't denormalize paths when calling file_spec.GetPath().  On platforms
  // that use a backslash as the path separator, this will result in executing
  // python code containing paths with unescaped backslashes.  But Python also
  // accepts forward slashes, so to make life easier we just use that.
  if (FileSpec file_spec = GetPythonDir())
    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
  if (FileSpec file_spec = HostInfo::GetShlibDir())
    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));

  RunSimpleString("sys.dont_write_bytecode = 1; import "
                  "lldb.embedded_interpreter; from "
                  "lldb.embedded_interpreter import run_python_interpreter; "
                  "from lldb.embedded_interpreter import run_one_line");

#if LLDB_USE_PYTHON_SET_INTERRUPT
  // Python will not just overwrite its internal SIGINT handler but also the
  // one from the process. Backup the current SIGINT handler to prevent that
  // Python deletes it.
  RestoreSignalHandlerScope save_sigint(SIGINT);

  // Setup a default SIGINT signal handler that works the same way as the
  // normal Python REPL signal handler which raises a KeyboardInterrupt.
  // Also make sure to not pollute the user's REPL with the signal module nor
  // our utility function.
  RunSimpleString("def lldb_setup_sigint_handler():\n"
                  "  import signal;\n"
                  "  def signal_handler(sig, frame):\n"
                  "    raise KeyboardInterrupt()\n"
                  "  signal.signal(signal.SIGINT, signal_handler);\n"
                  "lldb_setup_sigint_handler();\n"
                  "del lldb_setup_sigint_handler\n");
#endif
  return llvm::Error::success();
}

void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,
                                               std::string path) {
  std::string statement;
  if (location == AddLocation::Beginning) {
    statement.assign("sys.path.insert(0,\"");
    statement.append(path);
    statement.append("\")");
  } else {
    statement.assign("sys.path.append(\"");
    statement.append(path);
    statement.append("\")");
  }
  RunSimpleString(statement.c_str());
}

// We are intentionally NOT calling Py_Finalize here (this would be the logical
// place to call it).  Calling Py_Finalize here causes test suite runs to seg
// fault:  The test suite runs in Python.  It registers SBDebugger::Terminate to
// be called 'at_exit'.  When the test suite Python harness finishes up, it
// calls Py_Finalize, which calls all the 'at_exit' registered functions.
// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
// which calls ScriptInterpreter::Terminate, which calls
// ScriptInterpreterPythonImpl::Terminate.  So if we call Py_Finalize here, we
// end up with Py_Finalize being called from within Py_Finalize, which results
// in a seg fault. Since this function only gets called when lldb is shutting
// down and going away anyway, the fact that we don't actually call Py_Finalize
// should not cause any problems (everything should shut down/go away anyway
// when the process exits).
//
// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
