brintos

brintos / llvm-project-archived public Read only

0
0
Text · 104.9 KiB · 35a772c Raw
3101 lines · cpp
1//===-- ScriptInterpreterPython.cpp ---------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/Config.h"10 11#if LLDB_ENABLE_PYTHON12 13// LLDB Python header must be included first14#include "lldb-python.h"15 16#include "Interfaces/ScriptInterpreterPythonInterfaces.h"17#include "PythonDataObjects.h"18#include "PythonReadline.h"19#include "SWIGPythonBridge.h"20#include "ScriptInterpreterPythonImpl.h"21 22#include "lldb/API/SBError.h"23#include "lldb/API/SBExecutionContext.h"24#include "lldb/API/SBFrame.h"25#include "lldb/API/SBValue.h"26#include "lldb/Breakpoint/StoppointCallbackContext.h"27#include "lldb/Breakpoint/WatchpointOptions.h"28#include "lldb/Core/Debugger.h"29#include "lldb/Core/PluginManager.h"30#include "lldb/Core/ThreadedCommunication.h"31#include "lldb/DataFormatters/TypeSummary.h"32#include "lldb/Host/FileSystem.h"33#include "lldb/Host/HostInfo.h"34#include "lldb/Host/Pipe.h"35#include "lldb/Host/StreamFile.h"36#include "lldb/Interpreter/CommandInterpreter.h"37#include "lldb/Interpreter/CommandReturnObject.h"38#include "lldb/Target/Thread.h"39#include "lldb/Target/ThreadPlan.h"40#include "lldb/Utility/Instrumentation.h"41#include "lldb/Utility/LLDBLog.h"42#include "lldb/Utility/Timer.h"43#include "lldb/ValueObject/ValueObject.h"44#include "lldb/lldb-enumerations.h"45#include "lldb/lldb-forward.h"46#include "llvm/ADT/STLExtras.h"47#include "llvm/ADT/StringRef.h"48#include "llvm/Support/Error.h"49#include "llvm/Support/FileSystem.h"50#include "llvm/Support/FormatAdapters.h"51 52#include <cstdio>53#include <cstdlib>54#include <memory>55#include <mutex>56#include <optional>57#include <string>58 59using namespace lldb;60using namespace lldb_private;61using namespace lldb_private::python;62using llvm::Expected;63 64LLDB_PLUGIN_DEFINE(ScriptInterpreterPython)65 66// Defined in the SWIG source file67extern "C" PyObject *PyInit__lldb(void);68 69#define LLDBSwigPyInit PyInit__lldb70 71#if defined(_WIN32)72// Don't mess with the signal handlers on Windows.73#define LLDB_USE_PYTHON_SET_INTERRUPT 074#else75#define LLDB_USE_PYTHON_SET_INTERRUPT 176#endif77 78static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) {79  ScriptInterpreter *script_interpreter =80      debugger.GetScriptInterpreter(true, lldb::eScriptLanguagePython);81  return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);82}83 84namespace {85 86// Initializing Python is not a straightforward process.  We cannot control87// what external code may have done before getting to this point in LLDB,88// including potentially having already initialized Python, so we need to do a89// lot of work to ensure that the existing state of the system is maintained90// across our initialization.  We do this by using an RAII pattern where we91// save off initial state at the beginning, and restore it at the end92struct InitializePythonRAII {93public:94  InitializePythonRAII() {95    // The table of built-in modules can only be extended before Python is96    // initialized.97    if (!Py_IsInitialized()) {98#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE99      // Python's readline is incompatible with libedit being linked into lldb.100      // Provide a patched version local to the embedded interpreter.101      PyImport_AppendInittab("readline", initlldb_readline);102#endif103 104      // Register _lldb as a built-in module.105      PyImport_AppendInittab("_lldb", LLDBSwigPyInit);106    }107 108#if LLDB_EMBED_PYTHON_HOME109    PyConfig config;110    PyConfig_InitPythonConfig(&config);111 112    static std::string g_python_home = []() -> std::string {113      if (llvm::sys::path::is_absolute(LLDB_PYTHON_HOME))114        return LLDB_PYTHON_HOME;115 116      FileSpec spec = HostInfo::GetShlibDir();117      if (!spec)118        return {};119      spec.AppendPathComponent(LLDB_PYTHON_HOME);120      return spec.GetPath();121    }();122    if (!g_python_home.empty()) {123      PyConfig_SetBytesString(&config, &config.home, g_python_home.c_str());124    }125 126    config.install_signal_handlers = 0;127    Py_InitializeFromConfig(&config);128    PyConfig_Clear(&config);129#else130    Py_InitializeEx(/*install_sigs=*/0);131#endif132 133    // The only case we should go further and acquire the GIL: it is unlocked.134    PyGILState_STATE gil_state = PyGILState_Ensure();135    if (gil_state != PyGILState_UNLOCKED)136      return;137 138    m_was_already_initialized = true;139    m_gil_state = gil_state;140    LLDB_LOGV(GetLog(LLDBLog::Script),141              "Ensured PyGILState. Previous state = {0}",142              m_gil_state == PyGILState_UNLOCKED ? "unlocked" : "locked");143  }144 145  ~InitializePythonRAII() {146    if (m_was_already_initialized) {147      LLDB_LOGV(GetLog(LLDBLog::Script),148                "Releasing PyGILState. Returning to state = {0}",149                m_gil_state == PyGILState_UNLOCKED ? "unlocked" : "locked");150      PyGILState_Release(m_gil_state);151    } else {152      // We initialized the threads in this function, just unlock the GIL.153      PyEval_SaveThread();154    }155  }156 157private:158  PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;159  bool m_was_already_initialized = false;160};161 162#if LLDB_USE_PYTHON_SET_INTERRUPT163/// Saves the current signal handler for the specified signal and restores164/// it at the end of the current scope.165struct RestoreSignalHandlerScope {166  /// The signal handler.167  struct sigaction m_prev_handler;168  int m_signal_code;169  RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) {170    // Initialize sigaction to their default state.171    std::memset(&m_prev_handler, 0, sizeof(m_prev_handler));172    // Don't install a new handler, just read back the old one.173    struct sigaction *new_handler = nullptr;174    int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler);175    lldbassert(signal_err == 0 && "sigaction failed to read handler");176  }177  ~RestoreSignalHandlerScope() {178    int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr);179    lldbassert(signal_err == 0 && "sigaction failed to restore old handler");180  }181};182#endif183} // namespace184 185void ScriptInterpreterPython::ComputePythonDirForApple(186    llvm::SmallVectorImpl<char> &path) {187  auto style = llvm::sys::path::Style::posix;188 189  llvm::StringRef path_ref(path.begin(), path.size());190  auto rbegin = llvm::sys::path::rbegin(path_ref, style);191  auto rend = llvm::sys::path::rend(path_ref);192  auto framework = std::find(rbegin, rend, "LLDB.framework");193  if (framework == rend) {194    ComputePythonDir(path);195    return;196  }197  path.resize(framework - rend);198  llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");199}200 201void ScriptInterpreterPython::ComputePythonDir(202    llvm::SmallVectorImpl<char> &path) {203  // Build the path by backing out of the lib dir, then building with whatever204  // the real python interpreter uses.  (e.g. lib for most, lib64 on RHEL205  // x86_64, or bin on Windows).206  llvm::sys::path::remove_filename(path);207  llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR);208 209#if defined(_WIN32)210  // This will be injected directly through FileSpec.SetDirectory(),211  // so we need to normalize manually.212  std::replace(path.begin(), path.end(), '\\', '/');213#endif214}215 216FileSpec ScriptInterpreterPython::GetPythonDir() {217  static FileSpec g_spec = []() {218    FileSpec spec = HostInfo::GetShlibDir();219    if (!spec)220      return FileSpec();221    llvm::SmallString<64> path;222    spec.GetPath(path);223 224#if defined(__APPLE__)225    ComputePythonDirForApple(path);226#else227    ComputePythonDir(path);228#endif229    spec.SetDirectory(path);230    return spec;231  }();232  return g_spec;233}234 235static const char GetInterpreterInfoScript[] = R"(236import os237import sys238 239def main(lldb_python_dir, python_exe_relative_path):240  info = {241    "lldb-pythonpath": lldb_python_dir,242    "language": "python",243    "prefix": sys.prefix,244    "executable": os.path.join(sys.prefix, python_exe_relative_path)245  }246  return info247)";248 249static const char python_exe_relative_path[] = LLDB_PYTHON_EXE_RELATIVE_PATH;250 251StructuredData::DictionarySP ScriptInterpreterPython::GetInterpreterInfo() {252  GIL gil;253  FileSpec python_dir_spec = GetPythonDir();254  if (!python_dir_spec)255    return nullptr;256  PythonScript get_info(GetInterpreterInfoScript);257  auto info_json = unwrapIgnoringErrors(258      As<PythonDictionary>(get_info(PythonString(python_dir_spec.GetPath()),259                                    PythonString(python_exe_relative_path))));260  if (!info_json)261    return nullptr;262  return info_json.CreateStructuredDictionary();263}264 265void ScriptInterpreterPython::SharedLibraryDirectoryHelper(266    FileSpec &this_file) {267  // When we're loaded from python, this_file will point to the file inside the268  // python package directory. Replace it with the one in the lib directory.269#ifdef _WIN32270  // On windows, we need to manually back out of the python tree, and go into271  // the bin directory. This is pretty much the inverse of what ComputePythonDir272  // does.273  if (this_file.GetFileNameExtension() == ".pyd") {274    this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd275    this_file.RemoveLastPathComponent(); // native276    this_file.RemoveLastPathComponent(); // lldb277    llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;278    for (auto it = llvm::sys::path::begin(libdir),279              end = llvm::sys::path::end(libdir);280         it != end; ++it)281      this_file.RemoveLastPathComponent();282    this_file.AppendPathComponent("bin");283    this_file.AppendPathComponent("liblldb.dll");284  }285#else286  // The python file is a symlink, so we can find the real library by resolving287  // it. We can do this unconditionally.288  FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);289#endif290}291 292llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() {293  return "Embedded Python interpreter";294}295 296void ScriptInterpreterPython::Initialize() {297  static llvm::once_flag g_once_flag;298  llvm::call_once(g_once_flag, []() {299    PluginManager::RegisterPlugin(GetPluginNameStatic(),300                                  GetPluginDescriptionStatic(),301                                  lldb::eScriptLanguagePython,302                                  ScriptInterpreterPythonImpl::CreateInstance);303    ScriptInterpreterPythonImpl::Initialize();304  });305}306 307void ScriptInterpreterPython::Terminate() {}308 309ScriptInterpreterPythonImpl::Locker::Locker(310    ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,311    uint16_t on_leave, FileSP in, FileSP out, FileSP err)312    : ScriptInterpreterLocker(),313      m_teardown_session((on_leave & TearDownSession) == TearDownSession),314      m_python_interpreter(py_interpreter) {315  DoAcquireLock();316  if ((on_entry & InitSession) == InitSession) {317    if (!DoInitSession(on_entry, in, out, err)) {318      // Don't teardown the session if we didn't init it.319      m_teardown_session = false;320    }321  }322}323 324bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() {325  m_GILState = PyGILState_Ensure();326  LLDB_LOGV(GetLog(LLDBLog::Script), "Ensured PyGILState. Previous state = {0}",327            m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");328 329  // we need to save the thread state when we first start the command because330  // we might decide to interrupt it while some action is taking place outside331  // of Python (e.g. printing to screen, waiting for the network, ...) in that332  // case, _PyThreadState_Current will be NULL - and we would be unable to set333  // the asynchronous exception - not a desirable situation334  m_python_interpreter->SetThreadState(PyThreadState_Get());335  m_python_interpreter->IncrementLockCount();336  return true;337}338 339bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,340                                                        FileSP in, FileSP out,341                                                        FileSP err) {342  if (!m_python_interpreter)343    return false;344  return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);345}346 347bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {348  LLDB_LOGV(GetLog(LLDBLog::Script),349            "Releasing PyGILState. Returning to state = {0}",350            m_GILState == PyGILState_UNLOCKED ? "unlocked" : "locked");351  PyGILState_Release(m_GILState);352  m_python_interpreter->DecrementLockCount();353  return true;354}355 356bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {357  if (!m_python_interpreter)358    return false;359  m_python_interpreter->LeaveSession();360  return true;361}362 363ScriptInterpreterPythonImpl::Locker::~Locker() {364  if (m_teardown_session)365    DoTearDownSession();366  DoFreeLock();367}368 369ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)370    : ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(),371      m_saved_stderr(), m_main_module(),372      m_session_dict(PyInitialValue::Invalid),373      m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),374      m_run_one_line_str_global(),375      m_dictionary_name(m_debugger.GetInstanceName()),376      m_active_io_handler(eIOHandlerNone), m_session_is_active(false),377      m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),378      m_command_thread_state(nullptr) {379 380  m_dictionary_name.append("_dict");381  StreamString run_string;382  run_string.Printf("%s = dict()", m_dictionary_name.c_str());383 384  Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);385  RunSimpleString(run_string.GetData());386 387  run_string.Clear();388  run_string.Printf(389      "run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')",390      m_dictionary_name.c_str());391  RunSimpleString(run_string.GetData());392 393  // Reloading modules requires a different syntax in Python 2 and Python 3.394  // This provides a consistent syntax no matter what version of Python.395  run_string.Clear();396  run_string.Printf(397      "run_one_line (%s, 'from importlib import reload as reload_module')",398      m_dictionary_name.c_str());399  RunSimpleString(run_string.GetData());400 401  // WARNING: temporary code that loads Cocoa formatters - this should be done402  // on a per-platform basis rather than loading the whole set and letting the403  // individual formatter classes exploit APIs to check whether they can/cannot404  // do their task405  run_string.Clear();406  run_string.Printf(407      "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')",408      m_dictionary_name.c_str());409  RunSimpleString(run_string.GetData());410  run_string.Clear();411 412  run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from "413                    "lldb.embedded_interpreter import run_python_interpreter; "414                    "from lldb.embedded_interpreter import run_one_line')",415                    m_dictionary_name.c_str());416  RunSimpleString(run_string.GetData());417  run_string.Clear();418 419  run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64420                    "')",421                    m_dictionary_name.c_str(), m_debugger.GetID());422  RunSimpleString(run_string.GetData());423}424 425ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() {426  // the session dictionary may hold objects with complex state which means427  // that they may need to be torn down with some level of smarts and that, in428  // turn, requires a valid thread state force Python to procure itself such a429  // thread state, nuke the session dictionary and then release it for others430  // to use and proceed with the rest of the shutdown431  auto gil_state = PyGILState_Ensure();432  m_session_dict.Reset();433  PyGILState_Release(gil_state);434}435 436void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler,437                                                     bool interactive) {438  const char *instructions = nullptr;439 440  switch (m_active_io_handler) {441  case eIOHandlerNone:442    break;443  case eIOHandlerBreakpoint:444    instructions = R"(Enter your Python command(s). Type 'DONE' to end.445def function (frame, bp_loc, internal_dict):446    """frame: the lldb.SBFrame for the location at which you stopped447       bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information448       internal_dict: an LLDB support object not to be used"""449)";450    break;451  case eIOHandlerWatchpoint:452    instructions = "Enter your Python command(s). Type 'DONE' to end.\n";453    break;454  }455 456  if (instructions && interactive) {457    if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {458      LockedStreamFile locked_stream = stream_sp->Lock();459      locked_stream.PutCString(instructions);460      locked_stream.Flush();461    }462  }463}464 465void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,466                                                         std::string &data) {467  io_handler.SetIsDone(true);468  bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();469 470  switch (m_active_io_handler) {471  case eIOHandlerNone:472    break;473  case eIOHandlerBreakpoint: {474    std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =475        (std::vector<std::reference_wrapper<BreakpointOptions>> *)476            io_handler.GetUserData();477    for (BreakpointOptions &bp_options : *bp_options_vec) {478 479      auto data_up = std::make_unique<CommandDataPython>();480      if (!data_up)481        break;482      data_up->user_source.SplitIntoLines(data);483 484      if (GenerateBreakpointCommandCallbackData(data_up->user_source,485                                                data_up->script_source,486                                                /*has_extra_args=*/false,487                                                /*is_callback=*/false)488              .Success()) {489        auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(490            std::move(data_up));491        bp_options.SetCallback(492            ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);493      } else if (!batch_mode) {494        if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {495          LockedStreamFile locked_stream = error_sp->Lock();496          locked_stream.Printf("Warning: No command attached to breakpoint.\n");497        }498      }499    }500    m_active_io_handler = eIOHandlerNone;501  } break;502  case eIOHandlerWatchpoint: {503    WatchpointOptions *wp_options =504        (WatchpointOptions *)io_handler.GetUserData();505    auto data_up = std::make_unique<WatchpointOptions::CommandData>();506    data_up->user_source.SplitIntoLines(data);507 508    if (GenerateWatchpointCommandCallbackData(data_up->user_source,509                                              data_up->script_source,510                                              /*is_callback=*/false)) {511      auto baton_sp =512          std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));513      wp_options->SetCallback(514          ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);515    } else if (!batch_mode) {516      if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {517        LockedStreamFile locked_stream = error_sp->Lock();518        locked_stream.Printf("Warning: No command attached to breakpoint.\n");519      }520    }521    m_active_io_handler = eIOHandlerNone;522  } break;523  }524}525 526lldb::ScriptInterpreterSP527ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {528  return std::make_shared<ScriptInterpreterPythonImpl>(debugger);529}530 531void ScriptInterpreterPythonImpl::LeaveSession() {532  Log *log = GetLog(LLDBLog::Script);533  if (log)534    log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");535 536  // Unset the LLDB global variables.537  RunSimpleString("lldb.debugger = None; lldb.target = None; lldb.process "538                  "= None; lldb.thread = None; lldb.frame = None");539 540  // checking that we have a valid thread state - since we use our own541  // threading and locking in some (rare) cases during cleanup Python may end542  // up believing we have no thread state and PyImport_AddModule will crash if543  // that is the case - since that seems to only happen when destroying the544  // SBDebugger, we can make do without clearing up stdout and stderr545  if (PyThreadState_GetDict()) {546    PythonDictionary &sys_module_dict = GetSysModuleDictionary();547    if (sys_module_dict.IsValid()) {548      if (m_saved_stdin.IsValid()) {549        sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);550        m_saved_stdin.Reset();551      }552      if (m_saved_stdout.IsValid()) {553        sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);554        m_saved_stdout.Reset();555      }556      if (m_saved_stderr.IsValid()) {557        sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);558        m_saved_stderr.Reset();559      }560    }561  }562 563  m_session_is_active = false;564}565 566bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp,567                                               const char *py_name,568                                               PythonObject &save_file,569                                               const char *mode) {570  if (!file_sp || !*file_sp) {571    save_file.Reset();572    return false;573  }574  File &file = *file_sp;575 576  // Flush the file before giving it to python to avoid interleaved output.577  file.Flush();578 579  PythonDictionary &sys_module_dict = GetSysModuleDictionary();580 581  auto new_file = PythonFile::FromFile(file, mode);582  if (!new_file) {583    llvm::consumeError(new_file.takeError());584    return false;585  }586 587  save_file = sys_module_dict.GetItemForKey(PythonString(py_name));588 589  sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get());590  return true;591}592 593bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,594                                               FileSP in_sp, FileSP out_sp,595                                               FileSP err_sp) {596  // If we have already entered the session, without having officially 'left'597  // it, then there is no need to 'enter' it again.598  Log *log = GetLog(LLDBLog::Script);599  if (m_session_is_active) {600    LLDB_LOGF(601        log,602        "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16603        ") session is already active, returning without doing anything",604        on_entry_flags);605    return false;606  }607 608  LLDB_LOGF(609      log,610      "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")",611      on_entry_flags);612 613  m_session_is_active = true;614 615  StreamString run_string;616 617  if (on_entry_flags & Locker::InitGlobals) {618    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,619                      m_dictionary_name.c_str(), m_debugger.GetID());620    run_string.Printf(621        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",622        m_debugger.GetID());623    run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()");624    run_string.PutCString("; lldb.process = lldb.target.GetProcess()");625    run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()");626    run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");627    run_string.PutCString("')");628  } else {629    // If we aren't initing the globals, we should still always set the630    // debugger (since that is always unique.)631    run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,632                      m_dictionary_name.c_str(), m_debugger.GetID());633    run_string.Printf(634        "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",635        m_debugger.GetID());636    run_string.PutCString("')");637  }638 639  RunSimpleString(run_string.GetData());640  run_string.Clear();641 642  PythonDictionary &sys_module_dict = GetSysModuleDictionary();643  if (sys_module_dict.IsValid()) {644    lldb::FileSP top_in_sp;645    lldb::LockableStreamFileSP top_out_sp, top_err_sp;646    if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)647      m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,648                                                 top_err_sp);649 650    if (on_entry_flags & Locker::NoSTDIN) {651      m_saved_stdin.Reset();652    } else {653      if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) {654        if (top_in_sp)655          SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r");656      }657    }658 659    if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) {660      if (top_out_sp)661        SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,662                     "w");663    }664 665    if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) {666      if (top_err_sp)667        SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,668                     "w");669    }670  }671 672  if (PyErr_Occurred())673    PyErr_Clear();674 675  return true;676}677 678PythonModule &ScriptInterpreterPythonImpl::GetMainModule() {679  if (!m_main_module.IsValid())680    m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__"));681  return m_main_module;682}683 684PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {685  if (m_session_dict.IsValid())686    return m_session_dict;687 688  PythonObject &main_module = GetMainModule();689  if (!main_module.IsValid())690    return m_session_dict;691 692  PythonDictionary main_dict(PyRefType::Borrowed,693                             PyModule_GetDict(main_module.get()));694  if (!main_dict.IsValid())695    return m_session_dict;696 697  m_session_dict = unwrapIgnoringErrors(698      As<PythonDictionary>(main_dict.GetItem(m_dictionary_name)));699  return m_session_dict;700}701 702PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {703  if (m_sys_module_dict.IsValid())704    return m_sys_module_dict;705  PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys"));706  m_sys_module_dict = sys_module.GetDictionary();707  return m_sys_module_dict;708}709 710llvm::Expected<unsigned>711ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(712    const llvm::StringRef &callable_name) {713  if (callable_name.empty()) {714    return llvm::createStringError(llvm::inconvertibleErrorCode(),715                                   "called with empty callable name.");716  }717  Locker py_lock(this,718                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);719  auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(720      m_dictionary_name);721  auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(722      callable_name, dict);723  if (!pfunc.IsAllocated()) {724    return llvm::createStringError(llvm::inconvertibleErrorCode(),725                                   "can't find callable: %s",726                                   callable_name.str().c_str());727  }728  llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();729  if (!arg_info)730    return arg_info.takeError();731  return arg_info.get().max_positional_args;732}733 734static std::string GenerateUniqueName(const char *base_name_wanted,735                                      uint32_t &functions_counter,736                                      const void *name_token = nullptr) {737  StreamString sstr;738 739  if (!base_name_wanted)740    return std::string();741 742  if (!name_token)743    sstr.Printf("%s_%d", base_name_wanted, functions_counter++);744  else745    sstr.Printf("%s_%p", base_name_wanted, name_token);746 747  return std::string(sstr.GetString());748}749 750bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() {751  if (m_run_one_line_function.IsValid())752    return true;753 754  PythonObject module(PyRefType::Borrowed,755                      PyImport_AddModule("lldb.embedded_interpreter"));756  if (!module.IsValid())757    return false;758 759  PythonDictionary module_dict(PyRefType::Borrowed,760                               PyModule_GetDict(module.get()));761  if (!module_dict.IsValid())762    return false;763 764  m_run_one_line_function =765      module_dict.GetItemForKey(PythonString("run_one_line"));766  m_run_one_line_str_global =767      module_dict.GetItemForKey(PythonString("g_run_one_line_str"));768  return m_run_one_line_function.IsValid();769}770 771bool ScriptInterpreterPythonImpl::ExecuteOneLine(772    llvm::StringRef command, CommandReturnObject *result,773    const ExecuteScriptOptions &options) {774  std::string command_str = command.str();775 776  if (!m_valid_session)777    return false;778 779  if (!command.empty()) {780    // We want to call run_one_line, passing in the dictionary and the command781    // string.  We cannot do this through RunSimpleString here because the782    // command string may contain escaped characters, and putting it inside783    // another string to pass to RunSimpleString messes up the escaping.  So784    // we use the following more complicated method to pass the command string785    // directly down to Python.786    llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>787        io_redirect_or_error = ScriptInterpreterIORedirect::Create(788            options.GetEnableIO(), m_debugger, result);789    if (!io_redirect_or_error) {790      if (result)791        result->AppendErrorWithFormatv(792            "failed to redirect I/O: {0}\n",793            llvm::fmt_consume(io_redirect_or_error.takeError()));794      else795        llvm::consumeError(io_redirect_or_error.takeError());796      return false;797    }798 799    ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;800 801    bool success = false;802    {803      // WARNING!  It's imperative that this RAII scope be as tight as804      // possible. In particular, the scope must end *before* we try to join805      // the read thread.  The reason for this is that a pre-requisite for806      // joining the read thread is that we close the write handle (to break807      // the pipe and cause it to wake up and exit).  But acquiring the GIL as808      // below will redirect Python's stdio to use this same handle.  If we809      // close the handle while Python is still using it, bad things will810      // happen.811      Locker locker(812          this,813          Locker::AcquireLock | Locker::InitSession |814              (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |815              ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),816          Locker::FreeAcquiredLock | Locker::TearDownSession,817          io_redirect.GetInputFile(), io_redirect.GetOutputFile(),818          io_redirect.GetErrorFile());819 820      // Find the correct script interpreter dictionary in the main module.821      PythonDictionary &session_dict = GetSessionDictionary();822      if (session_dict.IsValid()) {823        if (GetEmbeddedInterpreterModuleObjects()) {824          if (PyCallable_Check(m_run_one_line_function.get())) {825            PythonObject pargs(826                PyRefType::Owned,827                Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));828            if (pargs.IsValid()) {829              PythonObject return_value(830                  PyRefType::Owned,831                  PyObject_CallObject(m_run_one_line_function.get(),832                                      pargs.get()));833              if (return_value.IsValid())834                success = true;835              else if (options.GetMaskoutErrors() && PyErr_Occurred()) {836                PyErr_Print();837                PyErr_Clear();838              }839            }840          }841        }842      }843 844      io_redirect.Flush();845    }846 847    if (success)848      return true;849 850    // The one-liner failed.  Append the error message.851    if (result) {852      result->AppendErrorWithFormat(853          "python failed attempting to evaluate '%s'\n", command_str.c_str());854    }855    return false;856  }857 858  if (result)859    result->AppendError("empty command passed to python\n");860  return false;861}862 863void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() {864  LLDB_SCOPED_TIMER();865 866  Debugger &debugger = m_debugger;867 868  // At the moment, the only time the debugger does not have an input file869  // handle is when this is called directly from Python, in which case it is870  // both dangerous and unnecessary (not to mention confusing) to try to embed871  // a running interpreter loop inside the already running Python interpreter872  // loop, so we won't do it.873 874  if (!debugger.GetInputFile().IsValid())875    return;876 877  IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));878  if (io_handler_sp) {879    debugger.RunIOHandlerAsync(io_handler_sp);880  }881}882 883bool ScriptInterpreterPythonImpl::Interrupt() {884#if LLDB_USE_PYTHON_SET_INTERRUPT885  // If the interpreter isn't evaluating any Python at the moment then return886  // false to signal that this function didn't handle the interrupt and the887  // next component should try handling it.888  if (!IsExecutingPython())889    return false;890 891  // Tell Python that it should pretend to have received a SIGINT.892  PyErr_SetInterrupt();893  // PyErr_SetInterrupt has no way to return an error so we can only pretend the894  // signal got successfully handled and return true.895  // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but896  // the error handling is limited to checking the arguments which would be897  // just our (hardcoded) input signal code SIGINT, so that's not useful at all.898  return true;899#else900  Log *log = GetLog(LLDBLog::Script);901 902  if (IsExecutingPython()) {903    PyThreadState *state = PyThreadState_Get();904    if (!state)905      state = GetThreadState();906    if (state) {907      long tid = PyThread_get_thread_ident();908      PyThreadState_Swap(state);909      int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);910      LLDB_LOGF(log,911                "ScriptInterpreterPythonImpl::Interrupt() sending "912                "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",913                tid, num_threads);914      return true;915    }916  }917  LLDB_LOGF(log,918            "ScriptInterpreterPythonImpl::Interrupt() python code not running, "919            "can't interrupt");920  return false;921#endif922}923 924bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(925    llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,926    void *ret_value, const ExecuteScriptOptions &options) {927 928  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>929      io_redirect_or_error = ScriptInterpreterIORedirect::Create(930          options.GetEnableIO(), m_debugger, /*result=*/nullptr);931 932  if (!io_redirect_or_error) {933    llvm::consumeError(io_redirect_or_error.takeError());934    return false;935  }936 937  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;938 939  Locker locker(this,940                Locker::AcquireLock | Locker::InitSession |941                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |942                    Locker::NoSTDIN,943                Locker::FreeAcquiredLock | Locker::TearDownSession,944                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),945                io_redirect.GetErrorFile());946 947  PythonModule &main_module = GetMainModule();948  PythonDictionary globals = main_module.GetDictionary();949 950  PythonDictionary locals = GetSessionDictionary();951  if (!locals.IsValid())952    locals = unwrapIgnoringErrors(953        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));954  if (!locals.IsValid())955    locals = globals;956 957  Expected<PythonObject> maybe_py_return =958      runStringOneLine(in_string, globals, locals);959 960  if (!maybe_py_return) {961    llvm::handleAllErrors(962        maybe_py_return.takeError(),963        [&](PythonException &E) {964          E.Restore();965          if (options.GetMaskoutErrors()) {966            if (E.Matches(PyExc_SyntaxError)) {967              PyErr_Print();968            }969            PyErr_Clear();970          }971        },972        [](const llvm::ErrorInfoBase &E) {});973    return false;974  }975 976  PythonObject py_return = std::move(maybe_py_return.get());977  assert(py_return.IsValid());978 979  switch (return_type) {980  case eScriptReturnTypeCharPtr: // "char *"981  {982    const char format[3] = "s#";983    return PyArg_Parse(py_return.get(), format, (char **)ret_value);984  }985  case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==986                                       // Py_None987  {988    const char format[3] = "z";989    return PyArg_Parse(py_return.get(), format, (char **)ret_value);990  }991  case eScriptReturnTypeBool: {992    const char format[2] = "b";993    return PyArg_Parse(py_return.get(), format, (bool *)ret_value);994  }995  case eScriptReturnTypeShortInt: {996    const char format[2] = "h";997    return PyArg_Parse(py_return.get(), format, (short *)ret_value);998  }999  case eScriptReturnTypeShortIntUnsigned: {1000    const char format[2] = "H";1001    return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);1002  }1003  case eScriptReturnTypeInt: {1004    const char format[2] = "i";1005    return PyArg_Parse(py_return.get(), format, (int *)ret_value);1006  }1007  case eScriptReturnTypeIntUnsigned: {1008    const char format[2] = "I";1009    return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);1010  }1011  case eScriptReturnTypeLongInt: {1012    const char format[2] = "l";1013    return PyArg_Parse(py_return.get(), format, (long *)ret_value);1014  }1015  case eScriptReturnTypeLongIntUnsigned: {1016    const char format[2] = "k";1017    return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);1018  }1019  case eScriptReturnTypeLongLong: {1020    const char format[2] = "L";1021    return PyArg_Parse(py_return.get(), format, (long long *)ret_value);1022  }1023  case eScriptReturnTypeLongLongUnsigned: {1024    const char format[2] = "K";1025    return PyArg_Parse(py_return.get(), format,1026                       (unsigned long long *)ret_value);1027  }1028  case eScriptReturnTypeFloat: {1029    const char format[2] = "f";1030    return PyArg_Parse(py_return.get(), format, (float *)ret_value);1031  }1032  case eScriptReturnTypeDouble: {1033    const char format[2] = "d";1034    return PyArg_Parse(py_return.get(), format, (double *)ret_value);1035  }1036  case eScriptReturnTypeChar: {1037    const char format[2] = "c";1038    return PyArg_Parse(py_return.get(), format, (char *)ret_value);1039  }1040  case eScriptReturnTypeOpaqueObject: {1041    *((PyObject **)ret_value) = py_return.release();1042    return true;1043  }1044  }1045  llvm_unreachable("Fully covered switch!");1046}1047 1048Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(1049    const char *in_string, const ExecuteScriptOptions &options) {1050 1051  if (in_string == nullptr)1052    return Status();1053 1054  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>1055      io_redirect_or_error = ScriptInterpreterIORedirect::Create(1056          options.GetEnableIO(), m_debugger, /*result=*/nullptr);1057 1058  if (!io_redirect_or_error)1059    return Status::FromError(io_redirect_or_error.takeError());1060 1061  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;1062 1063  Locker locker(this,1064                Locker::AcquireLock | Locker::InitSession |1065                    (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |1066                    Locker::NoSTDIN,1067                Locker::FreeAcquiredLock | Locker::TearDownSession,1068                io_redirect.GetInputFile(), io_redirect.GetOutputFile(),1069                io_redirect.GetErrorFile());1070 1071  PythonModule &main_module = GetMainModule();1072  PythonDictionary globals = main_module.GetDictionary();1073 1074  PythonDictionary locals = GetSessionDictionary();1075  if (!locals.IsValid())1076    locals = unwrapIgnoringErrors(1077        As<PythonDictionary>(globals.GetAttribute(m_dictionary_name)));1078  if (!locals.IsValid())1079    locals = globals;1080 1081  Expected<PythonObject> return_value =1082      runStringMultiLine(in_string, globals, locals);1083 1084  if (!return_value) {1085    llvm::Error error =1086        llvm::handleErrors(return_value.takeError(), [&](PythonException &E) {1087          llvm::Error error = llvm::createStringError(1088              llvm::inconvertibleErrorCode(), E.ReadBacktrace());1089          if (!options.GetMaskoutErrors())1090            E.Restore();1091          return error;1092        });1093    return Status::FromError(std::move(error));1094  }1095 1096  return Status();1097}1098 1099void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(1100    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,1101    CommandReturnObject &result) {1102  m_active_io_handler = eIOHandlerBreakpoint;1103  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(1104      "    ", *this, &bp_options_vec);1105}1106 1107void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(1108    WatchpointOptions *wp_options, CommandReturnObject &result) {1109  m_active_io_handler = eIOHandlerWatchpoint;1110  m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(1111      "    ", *this, wp_options);1112}1113 1114Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(1115    BreakpointOptions &bp_options, const char *function_name,1116    StructuredData::ObjectSP extra_args_sp) {1117  Status error;1118  // For now just cons up a oneliner that calls the provided function.1119  std::string function_signature = function_name;1120 1121  llvm::Expected<unsigned> maybe_args =1122      GetMaxPositionalArgumentsForCallable(function_name);1123  if (!maybe_args) {1124    error = Status::FromErrorStringWithFormat(1125        "could not get num args: %s",1126        llvm::toString(maybe_args.takeError()).c_str());1127    return error;1128  }1129  size_t max_args = *maybe_args;1130 1131  bool uses_extra_args = false;1132  if (max_args >= 4) {1133    uses_extra_args = true;1134    function_signature += "(frame, bp_loc, extra_args, internal_dict)";1135  } else if (max_args >= 3) {1136    if (extra_args_sp) {1137      error = Status::FromErrorStringWithFormat(1138          "cannot pass extra_args to a three argument callback");1139      return error;1140    }1141    uses_extra_args = false;1142    function_signature += "(frame, bp_loc, internal_dict)";1143  } else {1144    error = Status::FromErrorStringWithFormat("expected 3 or 4 argument "1145                                              "function, %s can only take %zu",1146                                              function_name, max_args);1147    return error;1148  }1149 1150  SetBreakpointCommandCallback(bp_options, function_signature.c_str(),1151                               extra_args_sp, uses_extra_args,1152                               /*is_callback=*/true);1153  return error;1154}1155 1156Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1157    BreakpointOptions &bp_options,1158    std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {1159  Status error;1160  error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,1161                                                cmd_data_up->script_source,1162                                                /*has_extra_args=*/false,1163                                                /*is_callback=*/false);1164  if (error.Fail()) {1165    return error;1166  }1167  auto baton_sp =1168      std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));1169  bp_options.SetCallback(1170      ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);1171  return error;1172}1173 1174Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1175    BreakpointOptions &bp_options, const char *command_body_text,1176    bool is_callback) {1177  return SetBreakpointCommandCallback(bp_options, command_body_text, {},1178                                      /*uses_extra_args=*/false, is_callback);1179}1180 1181// Set a Python one-liner as the callback for the breakpoint.1182Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(1183    BreakpointOptions &bp_options, const char *command_body_text,1184    StructuredData::ObjectSP extra_args_sp, bool uses_extra_args,1185    bool is_callback) {1186  auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);1187  // Split the command_body_text into lines, and pass that to1188  // GenerateBreakpointCommandCallbackData.  That will wrap the body in an1189  // auto-generated function, and return the function name in script_source.1190  // That is what the callback will actually invoke.1191 1192  data_up->user_source.SplitIntoLines(command_body_text);1193  Status error = GenerateBreakpointCommandCallbackData(1194      data_up->user_source, data_up->script_source, uses_extra_args,1195      is_callback);1196  if (error.Success()) {1197    auto baton_sp =1198        std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));1199    bp_options.SetCallback(1200        ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);1201    return error;1202  }1203  return error;1204}1205 1206// Set a Python one-liner as the callback for the watchpoint.1207void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback(1208    WatchpointOptions *wp_options, const char *user_input, bool is_callback) {1209  auto data_up = std::make_unique<WatchpointOptions::CommandData>();1210 1211  // It's necessary to set both user_source and script_source to the oneliner.1212  // The former is used to generate callback description (as in watchpoint1213  // command list) while the latter is used for Python to interpret during the1214  // actual callback.1215 1216  data_up->user_source.AppendString(user_input);1217  data_up->script_source.assign(user_input);1218 1219  if (GenerateWatchpointCommandCallbackData(1220          data_up->user_source, data_up->script_source, is_callback)) {1221    auto baton_sp =1222        std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));1223    wp_options->SetCallback(1224        ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);1225  }1226}1227 1228Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(1229    StringList &function_def) {1230  // Convert StringList to one long, newline delimited, const char *.1231  std::string function_def_string(function_def.CopyList());1232  LLDB_LOG(GetLog(LLDBLog::Script), "Added Function:\n%s\n",1233           function_def_string.c_str());1234 1235  Status error = ExecuteMultipleLines(1236      function_def_string.c_str(), ExecuteScriptOptions().SetEnableIO(false));1237  return error;1238}1239 1240Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,1241                                                     const StringList &input,1242                                                     bool is_callback) {1243  Status error;1244  int num_lines = input.GetSize();1245  if (num_lines == 0) {1246    error = Status::FromErrorString("No input data.");1247    return error;1248  }1249 1250  if (!signature || *signature == 0) {1251    error = Status::FromErrorString("No output function name.");1252    return error;1253  }1254 1255  StreamString sstr;1256  StringList auto_generated_function;1257  auto_generated_function.AppendString(signature);1258  auto_generated_function.AppendString(1259      "    global_dict = globals()"); // Grab the global dictionary1260  auto_generated_function.AppendString(1261      "    new_keys = internal_dict.keys()"); // Make a list of keys in the1262                                              // session dict1263  auto_generated_function.AppendString(1264      "    old_keys = global_dict.keys()"); // Save list of keys in global dict1265  auto_generated_function.AppendString(1266      "    global_dict.update(internal_dict)"); // Add the session dictionary1267                                                // to the global dictionary.1268 1269  if (is_callback) {1270    // If the user input is a callback to a python function, make sure the input1271    // is only 1 line, otherwise appending the user input would break the1272    // generated wrapped function1273    if (num_lines == 1) {1274      sstr.Clear();1275      sstr.Printf("    __return_val = %s", input.GetStringAtIndex(0));1276      auto_generated_function.AppendString(sstr.GetData());1277    } else {1278      return Status::FromErrorString(1279          "ScriptInterpreterPythonImpl::GenerateFunction(is_callback="1280          "true) = ERROR: python function is multiline.");1281    }1282  } else {1283    auto_generated_function.AppendString(1284        "    __return_val = None"); // Initialize user callback return value.1285    auto_generated_function.AppendString(1286        "    def __user_code():"); // Create a nested function that will wrap1287                                   // the user input. This is necessary to1288                                   // capture the return value of the user input1289                                   // and prevent early returns.1290    for (int i = 0; i < num_lines; ++i) {1291      sstr.Clear();1292      sstr.Printf("      %s", input.GetStringAtIndex(i));1293      auto_generated_function.AppendString(sstr.GetData());1294    }1295    auto_generated_function.AppendString(1296        "    __return_val = __user_code()"); //  Call user code and capture1297                                             //  return value1298  }1299  auto_generated_function.AppendString(1300      "    for key in new_keys:"); // Iterate over all the keys from session1301                                   // dict1302  auto_generated_function.AppendString(1303      "        if key in old_keys:"); // If key was originally in1304                                      // global dict1305  auto_generated_function.AppendString(1306      "            internal_dict[key] = global_dict[key]"); // Update it1307  auto_generated_function.AppendString(1308      "        elif key in global_dict:"); // Then if it is still in the1309                                           // global dict1310  auto_generated_function.AppendString(1311      "            del global_dict[key]"); //  remove key/value from the1312                                           //  global dict1313  auto_generated_function.AppendString(1314      "    return __return_val"); //  Return the user callback return value.1315 1316  // Verify that the results are valid Python.1317  error = ExportFunctionDefinitionToInterpreter(auto_generated_function);1318 1319  return error;1320}1321 1322bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(1323    StringList &user_input, std::string &output, const void *name_token) {1324  static uint32_t num_created_functions = 0;1325  user_input.RemoveBlankLines();1326  StreamString sstr;1327 1328  // Check to see if we have any data; if not, just return.1329  if (user_input.GetSize() == 0)1330    return false;1331 1332  // Take what the user wrote, wrap it all up inside one big auto-generated1333  // Python function, passing in the ValueObject as parameter to the function.1334 1335  std::string auto_generated_function_name(1336      GenerateUniqueName("lldb_autogen_python_type_print_func",1337                         num_created_functions, name_token));1338  sstr.Printf("def %s (valobj, internal_dict):",1339              auto_generated_function_name.c_str());1340 1341  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)1342           .Success())1343    return false;1344 1345  // Store the name of the auto-generated function to be called.1346  output.assign(auto_generated_function_name);1347  return true;1348}1349 1350bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(1351    StringList &user_input, std::string &output) {1352  static uint32_t num_created_functions = 0;1353  user_input.RemoveBlankLines();1354  StreamString sstr;1355 1356  // Check to see if we have any data; if not, just return.1357  if (user_input.GetSize() == 0)1358    return false;1359 1360  std::string auto_generated_function_name(GenerateUniqueName(1361      "lldb_autogen_python_cmd_alias_func", num_created_functions));1362 1363  sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",1364              auto_generated_function_name.c_str());1365 1366  if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)1367           .Success())1368    return false;1369 1370  // Store the name of the auto-generated function to be called.1371  output.assign(auto_generated_function_name);1372  return true;1373}1374 1375bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(1376    StringList &user_input, std::string &output, const void *name_token) {1377  static uint32_t num_created_classes = 0;1378  user_input.RemoveBlankLines();1379  int num_lines = user_input.GetSize();1380  StreamString sstr;1381 1382  // Check to see if we have any data; if not, just return.1383  if (user_input.GetSize() == 0)1384    return false;1385 1386  // Wrap all user input into a Python class1387 1388  std::string auto_generated_class_name(GenerateUniqueName(1389      "lldb_autogen_python_type_synth_class", num_created_classes, name_token));1390 1391  StringList auto_generated_class;1392 1393  // Create the function name & definition string.1394 1395  sstr.Printf("class %s:", auto_generated_class_name.c_str());1396  auto_generated_class.AppendString(sstr.GetString());1397 1398  // Wrap everything up inside the class, increasing the indentation. we don't1399  // need to play any fancy indentation tricks here because there is no1400  // surrounding code whose indentation we need to honor1401  for (int i = 0; i < num_lines; ++i) {1402    sstr.Clear();1403    sstr.Printf("     %s", user_input.GetStringAtIndex(i));1404    auto_generated_class.AppendString(sstr.GetString());1405  }1406 1407  // Verify that the results are valid Python. (even though the method is1408  // ExportFunctionDefinitionToInterpreter, a class will actually be exported)1409  // (TODO: rename that method to ExportDefinitionToInterpreter)1410  if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())1411    return false;1412 1413  // Store the name of the auto-generated class1414 1415  output.assign(auto_generated_class_name);1416  return true;1417}1418 1419StructuredData::GenericSP1420ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) {1421  if (class_name == nullptr || class_name[0] == '\0')1422    return StructuredData::GenericSP();1423 1424  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1425  PythonObject ret_val = SWIGBridge::LLDBSWIGPython_CreateFrameRecognizer(1426      class_name, m_dictionary_name.c_str());1427 1428  return StructuredData::GenericSP(1429      new StructuredPythonObject(std::move(ret_val)));1430}1431 1432lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments(1433    const StructuredData::ObjectSP &os_plugin_object_sp,1434    lldb::StackFrameSP frame_sp) {1435  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1436 1437  if (!os_plugin_object_sp)1438    return ValueObjectListSP();1439 1440  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();1441  if (!generic)1442    return nullptr;1443 1444  PythonObject implementor(PyRefType::Borrowed,1445                           (PyObject *)generic->GetValue());1446 1447  if (!implementor.IsAllocated())1448    return ValueObjectListSP();1449 1450  PythonObject py_return(PyRefType::Owned,1451                         SWIGBridge::LLDBSwigPython_GetRecognizedArguments(1452                             implementor.get(), frame_sp));1453 1454  // if it fails, print the error but otherwise go on1455  if (PyErr_Occurred()) {1456    PyErr_Print();1457    PyErr_Clear();1458  }1459  if (py_return.get()) {1460    PythonList result_list(PyRefType::Borrowed, py_return.get());1461    ValueObjectListSP result = std::make_shared<ValueObjectList>();1462    for (size_t i = 0; i < result_list.GetSize(); i++) {1463      PyObject *item = result_list.GetItemAtIndex(i).get();1464      lldb::SBValue *sb_value_ptr =1465          (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item);1466      auto valobj_sp =1467          SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr);1468      if (valobj_sp)1469        result->Append(valobj_sp);1470    }1471    return result;1472  }1473  return ValueObjectListSP();1474}1475 1476bool ScriptInterpreterPythonImpl::ShouldHide(1477    const StructuredData::ObjectSP &os_plugin_object_sp,1478    lldb::StackFrameSP frame_sp) {1479  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1480 1481  if (!os_plugin_object_sp)1482    return false;1483 1484  StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();1485  if (!generic)1486    return false;1487 1488  PythonObject implementor(PyRefType::Borrowed,1489                           (PyObject *)generic->GetValue());1490 1491  if (!implementor.IsAllocated())1492    return false;1493 1494  bool result =1495      SWIGBridge::LLDBSwigPython_ShouldHide(implementor.get(), frame_sp);1496 1497  // if it fails, print the error but otherwise go on1498  if (PyErr_Occurred()) {1499    PyErr_Print();1500    PyErr_Clear();1501  }1502  return result;1503}1504 1505ScriptedProcessInterfaceUP1506ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() {1507  return std::make_unique<ScriptedProcessPythonInterface>(*this);1508}1509 1510ScriptedStopHookInterfaceSP1511ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() {1512  return std::make_shared<ScriptedStopHookPythonInterface>(*this);1513}1514 1515ScriptedBreakpointInterfaceSP1516ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() {1517  return std::make_shared<ScriptedBreakpointPythonInterface>(*this);1518}1519 1520ScriptedThreadInterfaceSP1521ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {1522  return std::make_shared<ScriptedThreadPythonInterface>(*this);1523}1524 1525ScriptedFrameInterfaceSP1526ScriptInterpreterPythonImpl::CreateScriptedFrameInterface() {1527  return std::make_shared<ScriptedFramePythonInterface>(*this);1528}1529 1530ScriptedFrameProviderInterfaceSP1531ScriptInterpreterPythonImpl::CreateScriptedFrameProviderInterface() {1532  return std::make_shared<ScriptedFrameProviderPythonInterface>(*this);1533}1534 1535ScriptedThreadPlanInterfaceSP1536ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {1537  return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);1538}1539 1540OperatingSystemInterfaceSP1541ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {1542  return std::make_shared<OperatingSystemPythonInterface>(*this);1543}1544 1545StructuredData::ObjectSP1546ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(1547    ScriptObject obj) {1548  void *ptr = const_cast<void *>(obj.GetPointer());1549  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);1550  PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr));1551  if (!py_obj.IsValid() || py_obj.IsNone())1552    return {};1553  return py_obj.CreateStructuredObject();1554}1555 1556StructuredData::ObjectSP1557ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,1558                                              lldb_private::Status &error) {1559  if (!FileSystem::Instance().Exists(file_spec)) {1560    error = Status::FromErrorString("no such file");1561    return StructuredData::ObjectSP();1562  }1563 1564  StructuredData::ObjectSP module_sp;1565 1566  LoadScriptOptions load_script_options =1567      LoadScriptOptions().SetInitSession(true).SetSilent(false);1568  if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,1569                          error, &module_sp))1570    return module_sp;1571 1572  return StructuredData::ObjectSP();1573}1574 1575StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(1576    StructuredData::ObjectSP plugin_module_sp, Target *target,1577    const char *setting_name, lldb_private::Status &error) {1578  if (!plugin_module_sp || !target || !setting_name || !setting_name[0])1579    return StructuredData::DictionarySP();1580  StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();1581  if (!generic)1582    return StructuredData::DictionarySP();1583 1584  Locker py_lock(this,1585                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1586  TargetSP target_sp(target->shared_from_this());1587 1588  auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting(1589      generic->GetValue(), setting_name, target_sp);1590 1591  if (!setting)1592    return StructuredData::DictionarySP();1593 1594  PythonDictionary py_dict =1595      unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting)));1596 1597  if (!py_dict)1598    return StructuredData::DictionarySP();1599 1600  return py_dict.CreateStructuredDictionary();1601}1602 1603StructuredData::ObjectSP1604ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider(1605    const char *class_name, lldb::ValueObjectSP valobj) {1606  if (class_name == nullptr || class_name[0] == '\0')1607    return StructuredData::ObjectSP();1608 1609  if (!valobj.get())1610    return StructuredData::ObjectSP();1611 1612  ExecutionContext exe_ctx(valobj->GetExecutionContextRef());1613  Target *target = exe_ctx.GetTargetPtr();1614 1615  if (!target)1616    return StructuredData::ObjectSP();1617 1618  Debugger &debugger = target->GetDebugger();1619  ScriptInterpreterPythonImpl *python_interpreter =1620      GetPythonInterpreter(debugger);1621 1622  if (!python_interpreter)1623    return StructuredData::ObjectSP();1624 1625  Locker py_lock(this,1626                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1627  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateSyntheticProvider(1628      class_name, python_interpreter->m_dictionary_name.c_str(), valobj);1629 1630  return StructuredData::ObjectSP(1631      new StructuredPythonObject(std::move(ret_val)));1632}1633 1634StructuredData::GenericSP1635ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) {1636  DebuggerSP debugger_sp(m_debugger.shared_from_this());1637 1638  if (class_name == nullptr || class_name[0] == '\0')1639    return StructuredData::GenericSP();1640 1641  if (!debugger_sp.get())1642    return StructuredData::GenericSP();1643 1644  Locker py_lock(this,1645                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1646  PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateCommandObject(1647      class_name, m_dictionary_name.c_str(), debugger_sp);1648 1649  if (ret_val.IsValid())1650    return StructuredData::GenericSP(1651        new StructuredPythonObject(std::move(ret_val)));1652  else1653    return {};1654}1655 1656bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(1657    const char *oneliner, std::string &output, const void *name_token) {1658  StringList input;1659  input.SplitIntoLines(oneliner, strlen(oneliner));1660  return GenerateTypeScriptFunction(input, output, name_token);1661}1662 1663bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(1664    const char *oneliner, std::string &output, const void *name_token) {1665  StringList input;1666  input.SplitIntoLines(oneliner, strlen(oneliner));1667  return GenerateTypeSynthClass(input, output, name_token);1668}1669 1670Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(1671    StringList &user_input, std::string &output, bool has_extra_args,1672    bool is_callback) {1673  static uint32_t num_created_functions = 0;1674  user_input.RemoveBlankLines();1675  StreamString sstr;1676  Status error;1677  if (user_input.GetSize() == 0) {1678    error = Status::FromErrorString("No input data.");1679    return error;1680  }1681 1682  std::string auto_generated_function_name(GenerateUniqueName(1683      "lldb_autogen_python_bp_callback_func_", num_created_functions));1684  if (has_extra_args)1685    sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",1686                auto_generated_function_name.c_str());1687  else1688    sstr.Printf("def %s (frame, bp_loc, internal_dict):",1689                auto_generated_function_name.c_str());1690 1691  error = GenerateFunction(sstr.GetData(), user_input, is_callback);1692  if (!error.Success())1693    return error;1694 1695  // Store the name of the auto-generated function to be called.1696  output.assign(auto_generated_function_name);1697  return error;1698}1699 1700bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData(1701    StringList &user_input, std::string &output, bool is_callback) {1702  static uint32_t num_created_functions = 0;1703  user_input.RemoveBlankLines();1704  StreamString sstr;1705 1706  if (user_input.GetSize() == 0)1707    return false;1708 1709  std::string auto_generated_function_name(GenerateUniqueName(1710      "lldb_autogen_python_wp_callback_func_", num_created_functions));1711  sstr.Printf("def %s (frame, wp, internal_dict):",1712              auto_generated_function_name.c_str());1713 1714  if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success())1715    return false;1716 1717  // Store the name of the auto-generated function to be called.1718  output.assign(auto_generated_function_name);1719  return true;1720}1721 1722bool ScriptInterpreterPythonImpl::GetScriptedSummary(1723    const char *python_function_name, lldb::ValueObjectSP valobj,1724    StructuredData::ObjectSP &callee_wrapper_sp,1725    const TypeSummaryOptions &options, std::string &retval) {1726 1727  LLDB_SCOPED_TIMER();1728 1729  if (!valobj.get()) {1730    retval.assign("<no object>");1731    return false;1732  }1733 1734  void *old_callee = nullptr;1735  StructuredData::Generic *generic = nullptr;1736  if (callee_wrapper_sp) {1737    generic = callee_wrapper_sp->GetAsGeneric();1738    if (generic)1739      old_callee = generic->GetValue();1740  }1741  void *new_callee = old_callee;1742 1743  bool ret_val;1744  if (python_function_name && *python_function_name) {1745    {1746      Locker py_lock(this, Locker::AcquireLock | Locker::InitSession |1747                               Locker::NoSTDIN);1748      {1749        TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));1750 1751        static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");1752        Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");1753        ret_val = SWIGBridge::LLDBSwigPythonCallTypeScript(1754            python_function_name, GetSessionDictionary().get(), valobj,1755            &new_callee, options_sp, retval);1756      }1757    }1758  } else {1759    retval.assign("<no function name>");1760    return false;1761  }1762 1763  if (new_callee && old_callee != new_callee) {1764    Locker py_lock(this,1765                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1766    callee_wrapper_sp = std::make_shared<StructuredPythonObject>(1767        PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee)));1768  }1769 1770  return ret_val;1771}1772 1773bool ScriptInterpreterPythonImpl::FormatterCallbackFunction(1774    const char *python_function_name, TypeImplSP type_impl_sp) {1775  Locker py_lock(this,1776                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1777  return SWIGBridge::LLDBSwigPythonFormatterCallbackFunction(1778      python_function_name, m_dictionary_name.c_str(), type_impl_sp);1779}1780 1781bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(1782    void *baton, StoppointCallbackContext *context, user_id_t break_id,1783    user_id_t break_loc_id) {1784  CommandDataPython *bp_option_data = (CommandDataPython *)baton;1785  const char *python_function_name = bp_option_data->script_source.c_str();1786 1787  if (!context)1788    return true;1789 1790  ExecutionContext exe_ctx(context->exe_ctx_ref);1791  Target *target = exe_ctx.GetTargetPtr();1792 1793  if (!target)1794    return true;1795 1796  Debugger &debugger = target->GetDebugger();1797  ScriptInterpreterPythonImpl *python_interpreter =1798      GetPythonInterpreter(debugger);1799 1800  if (!python_interpreter)1801    return true;1802 1803  if (python_function_name && python_function_name[0]) {1804    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());1805    BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id);1806    if (breakpoint_sp) {1807      const BreakpointLocationSP bp_loc_sp(1808          breakpoint_sp->FindLocationByID(break_loc_id));1809 1810      if (stop_frame_sp && bp_loc_sp) {1811        bool ret_val = true;1812        {1813          Locker py_lock(python_interpreter, Locker::AcquireLock |1814                                                 Locker::InitSession |1815                                                 Locker::NoSTDIN);1816          Expected<bool> maybe_ret_val =1817              SWIGBridge::LLDBSwigPythonBreakpointCallbackFunction(1818                  python_function_name,1819                  python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,1820                  bp_loc_sp, bp_option_data->m_extra_args);1821 1822          if (!maybe_ret_val) {1823 1824            llvm::handleAllErrors(1825                maybe_ret_val.takeError(),1826                [&](PythonException &E) {1827                  *debugger.GetAsyncErrorStream() << E.ReadBacktrace();1828                },1829                [&](const llvm::ErrorInfoBase &E) {1830                  *debugger.GetAsyncErrorStream() << E.message();1831                });1832 1833          } else {1834            ret_val = maybe_ret_val.get();1835          }1836        }1837        return ret_val;1838      }1839    }1840  }1841  // We currently always true so we stop in case anything goes wrong when1842  // trying to call the script function1843  return true;1844}1845 1846bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction(1847    void *baton, StoppointCallbackContext *context, user_id_t watch_id) {1848  WatchpointOptions::CommandData *wp_option_data =1849      (WatchpointOptions::CommandData *)baton;1850  const char *python_function_name = wp_option_data->script_source.c_str();1851 1852  if (!context)1853    return true;1854 1855  ExecutionContext exe_ctx(context->exe_ctx_ref);1856  Target *target = exe_ctx.GetTargetPtr();1857 1858  if (!target)1859    return true;1860 1861  Debugger &debugger = target->GetDebugger();1862  ScriptInterpreterPythonImpl *python_interpreter =1863      GetPythonInterpreter(debugger);1864 1865  if (!python_interpreter)1866    return true;1867 1868  if (python_function_name && python_function_name[0]) {1869    const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());1870    WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);1871    if (wp_sp) {1872      if (stop_frame_sp && wp_sp) {1873        bool ret_val = true;1874        {1875          Locker py_lock(python_interpreter, Locker::AcquireLock |1876                                                 Locker::InitSession |1877                                                 Locker::NoSTDIN);1878          ret_val = SWIGBridge::LLDBSwigPythonWatchpointCallbackFunction(1879              python_function_name,1880              python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,1881              wp_sp);1882        }1883        return ret_val;1884      }1885    }1886  }1887  // We currently always true so we stop in case anything goes wrong when1888  // trying to call the script function1889  return true;1890}1891 1892size_t ScriptInterpreterPythonImpl::CalculateNumChildren(1893    const StructuredData::ObjectSP &implementor_sp, uint32_t max) {1894  if (!implementor_sp)1895    return 0;1896  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();1897  if (!generic)1898    return 0;1899  auto *implementor = static_cast<PyObject *>(generic->GetValue());1900  if (!implementor)1901    return 0;1902 1903  size_t ret_val = 0;1904 1905  {1906    Locker py_lock(this,1907                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1908    ret_val = SWIGBridge::LLDBSwigPython_CalculateNumChildren(implementor, max);1909  }1910 1911  return ret_val;1912}1913 1914lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex(1915    const StructuredData::ObjectSP &implementor_sp, uint32_t idx) {1916  if (!implementor_sp)1917    return lldb::ValueObjectSP();1918 1919  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();1920  if (!generic)1921    return lldb::ValueObjectSP();1922  auto *implementor = static_cast<PyObject *>(generic->GetValue());1923  if (!implementor)1924    return lldb::ValueObjectSP();1925 1926  lldb::ValueObjectSP ret_val;1927  {1928    Locker py_lock(this,1929                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1930    PyObject *child_ptr =1931        SWIGBridge::LLDBSwigPython_GetChildAtIndex(implementor, idx);1932    if (child_ptr != nullptr && child_ptr != Py_None) {1933      lldb::SBValue *sb_value_ptr =1934          (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);1935      if (sb_value_ptr == nullptr)1936        Py_XDECREF(child_ptr);1937      else1938        ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(1939            sb_value_ptr);1940    } else {1941      Py_XDECREF(child_ptr);1942    }1943  }1944 1945  return ret_val;1946}1947 1948llvm::Expected<uint32_t> ScriptInterpreterPythonImpl::GetIndexOfChildWithName(1949    const StructuredData::ObjectSP &implementor_sp, const char *child_name) {1950  if (!implementor_sp)1951    return llvm::createStringError("Type has no child named '%s'", child_name);1952 1953  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();1954  if (!generic)1955    return llvm::createStringError("Type has no child named '%s'", child_name);1956  auto *implementor = static_cast<PyObject *>(generic->GetValue());1957  if (!implementor)1958    return llvm::createStringError("Type has no child named '%s'", child_name);1959 1960  uint32_t ret_val = UINT32_MAX;1961 1962  {1963    Locker py_lock(this,1964                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1965    ret_val = SWIGBridge::LLDBSwigPython_GetIndexOfChildWithName(implementor,1966                                                                 child_name);1967  }1968 1969  if (ret_val == UINT32_MAX)1970    return llvm::createStringError("Type has no child named '%s'", child_name);1971  return ret_val;1972}1973 1974bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance(1975    const StructuredData::ObjectSP &implementor_sp) {1976  bool ret_val = false;1977 1978  if (!implementor_sp)1979    return ret_val;1980 1981  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();1982  if (!generic)1983    return ret_val;1984  auto *implementor = static_cast<PyObject *>(generic->GetValue());1985  if (!implementor)1986    return ret_val;1987 1988  {1989    Locker py_lock(this,1990                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);1991    ret_val =1992        SWIGBridge::LLDBSwigPython_UpdateSynthProviderInstance(implementor);1993  }1994 1995  return ret_val;1996}1997 1998bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance(1999    const StructuredData::ObjectSP &implementor_sp) {2000  bool ret_val = false;2001 2002  if (!implementor_sp)2003    return ret_val;2004 2005  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2006  if (!generic)2007    return ret_val;2008  auto *implementor = static_cast<PyObject *>(generic->GetValue());2009  if (!implementor)2010    return ret_val;2011 2012  {2013    Locker py_lock(this,2014                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2015    ret_val = SWIGBridge::LLDBSwigPython_MightHaveChildrenSynthProviderInstance(2016        implementor);2017  }2018 2019  return ret_val;2020}2021 2022lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue(2023    const StructuredData::ObjectSP &implementor_sp) {2024  lldb::ValueObjectSP ret_val(nullptr);2025 2026  if (!implementor_sp)2027    return ret_val;2028 2029  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2030  if (!generic)2031    return ret_val;2032  auto *implementor = static_cast<PyObject *>(generic->GetValue());2033  if (!implementor)2034    return ret_val;2035 2036  {2037    Locker py_lock(this,2038                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2039    PyObject *child_ptr =2040        SWIGBridge::LLDBSwigPython_GetValueSynthProviderInstance(implementor);2041    if (child_ptr != nullptr && child_ptr != Py_None) {2042      lldb::SBValue *sb_value_ptr =2043          (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);2044      if (sb_value_ptr == nullptr)2045        Py_XDECREF(child_ptr);2046      else2047        ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(2048            sb_value_ptr);2049    } else {2050      Py_XDECREF(child_ptr);2051    }2052  }2053 2054  return ret_val;2055}2056 2057ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName(2058    const StructuredData::ObjectSP &implementor_sp) {2059  Locker py_lock(this,2060                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2061 2062  if (!implementor_sp)2063    return {};2064 2065  StructuredData::Generic *generic = implementor_sp->GetAsGeneric();2066  if (!generic)2067    return {};2068 2069  PythonObject implementor(PyRefType::Borrowed,2070                           (PyObject *)generic->GetValue());2071  if (!implementor.IsAllocated())2072    return {};2073 2074  llvm::Expected<PythonObject> expected_py_return =2075      implementor.CallMethod("get_type_name");2076 2077  if (!expected_py_return) {2078    llvm::consumeError(expected_py_return.takeError());2079    return {};2080  }2081 2082  PythonObject py_return = std::move(expected_py_return.get());2083  if (!py_return.IsAllocated() || !PythonString::Check(py_return.get()))2084    return {};2085 2086  PythonString type_name(PyRefType::Borrowed, py_return.get());2087  return ConstString(type_name.GetString());2088}2089 2090bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2091    const char *impl_function, Process *process, std::string &output,2092    Status &error) {2093  bool ret_val;2094  if (!process) {2095    error = Status::FromErrorString("no process");2096    return false;2097  }2098  if (!impl_function || !impl_function[0]) {2099    error = Status::FromErrorString("no function to execute");2100    return false;2101  }2102 2103  {2104    Locker py_lock(this,2105                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2106    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordProcess(2107        impl_function, m_dictionary_name.c_str(), process->shared_from_this(),2108        output);2109    if (!ret_val)2110      error = Status::FromErrorString("python script evaluation failed");2111  }2112  return ret_val;2113}2114 2115bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2116    const char *impl_function, Thread *thread, std::string &output,2117    Status &error) {2118  if (!thread) {2119    error = Status::FromErrorString("no thread");2120    return false;2121  }2122  if (!impl_function || !impl_function[0]) {2123    error = Status::FromErrorString("no function to execute");2124    return false;2125  }2126 2127  Locker py_lock(this,2128                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2129  if (std::optional<std::string> result =2130          SWIGBridge::LLDBSWIGPythonRunScriptKeywordThread(2131              impl_function, m_dictionary_name.c_str(),2132              thread->shared_from_this())) {2133    output = std::move(*result);2134    return true;2135  }2136  error = Status::FromErrorString("python script evaluation failed");2137  return false;2138}2139 2140bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2141    const char *impl_function, Target *target, std::string &output,2142    Status &error) {2143  bool ret_val;2144  if (!target) {2145    error = Status::FromErrorString("no thread");2146    return false;2147  }2148  if (!impl_function || !impl_function[0]) {2149    error = Status::FromErrorString("no function to execute");2150    return false;2151  }2152 2153  {2154    TargetSP target_sp(target->shared_from_this());2155    Locker py_lock(this,2156                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2157    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordTarget(2158        impl_function, m_dictionary_name.c_str(), target_sp, output);2159    if (!ret_val)2160      error = Status::FromErrorString("python script evaluation failed");2161  }2162  return ret_val;2163}2164 2165bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2166    const char *impl_function, StackFrame *frame, std::string &output,2167    Status &error) {2168  if (!frame) {2169    error = Status::FromErrorString("no frame");2170    return false;2171  }2172  if (!impl_function || !impl_function[0]) {2173    error = Status::FromErrorString("no function to execute");2174    return false;2175  }2176 2177  Locker py_lock(this,2178                 Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2179  if (std::optional<std::string> result =2180          SWIGBridge::LLDBSWIGPythonRunScriptKeywordFrame(2181              impl_function, m_dictionary_name.c_str(),2182              frame->shared_from_this())) {2183    output = std::move(*result);2184    return true;2185  }2186  error = Status::FromErrorString("python script evaluation failed");2187  return false;2188}2189 2190bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(2191    const char *impl_function, ValueObject *value, std::string &output,2192    Status &error) {2193  bool ret_val;2194  if (!value) {2195    error = Status::FromErrorString("no value");2196    return false;2197  }2198  if (!impl_function || !impl_function[0]) {2199    error = Status::FromErrorString("no function to execute");2200    return false;2201  }2202 2203  {2204    Locker py_lock(this,2205                   Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);2206    ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue(2207        impl_function, m_dictionary_name.c_str(), value->GetSP(), output);2208    if (!ret_val)2209      error = Status::FromErrorString("python script evaluation failed");2210  }2211  return ret_val;2212}2213 2214uint64_t replace_all(std::string &str, const std::string &oldStr,2215                     const std::string &newStr) {2216  size_t pos = 0;2217  uint64_t matches = 0;2218  while ((pos = str.find(oldStr, pos)) != std::string::npos) {2219    matches++;2220    str.replace(pos, oldStr.length(), newStr);2221    pos += newStr.length();2222  }2223  return matches;2224}2225 2226bool ScriptInterpreterPythonImpl::LoadScriptingModule(2227    const char *pathname, const LoadScriptOptions &options,2228    lldb_private::Status &error, StructuredData::ObjectSP *module_sp,2229    FileSpec extra_search_dir, lldb::TargetSP target_sp) {2230  namespace fs = llvm::sys::fs;2231  namespace path = llvm::sys::path;2232 2233  ExecuteScriptOptions exc_options = ExecuteScriptOptions()2234                                         .SetEnableIO(!options.GetSilent())2235                                         .SetSetLLDBGlobals(false);2236 2237  if (!pathname || !pathname[0]) {2238    error = Status::FromErrorString("empty path");2239    return false;2240  }2241 2242  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>2243      io_redirect_or_error = ScriptInterpreterIORedirect::Create(2244          exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);2245 2246  if (!io_redirect_or_error) {2247    error = Status::FromError(io_redirect_or_error.takeError());2248    return false;2249  }2250 2251  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;2252 2253  // Before executing Python code, lock the GIL.2254  Locker py_lock(this,2255                 Locker::AcquireLock |2256                     (options.GetInitSession() ? Locker::InitSession : 0) |2257                     Locker::NoSTDIN,2258                 Locker::FreeAcquiredLock |2259                     (options.GetInitSession() ? Locker::TearDownSession : 0),2260                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(),2261                 io_redirect.GetErrorFile());2262 2263  auto ExtendSysPath = [&](std::string directory) -> llvm::Error {2264    if (directory.empty()) {2265      return llvm::createStringError("invalid directory name");2266    }2267 2268    replace_all(directory, "\\", "\\\\");2269    replace_all(directory, "'", "\\'");2270 2271    // Make sure that Python has "directory" in the search path.2272    StreamString command_stream;2273    command_stream.Printf("if not (sys.path.__contains__('%s')):\n    "2274                          "sys.path.insert(1,'%s');\n\n",2275                          directory.c_str(), directory.c_str());2276    bool syspath_retval =2277        ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();2278    if (!syspath_retval)2279      return llvm::createStringError("Python sys.path handling failed");2280 2281    return llvm::Error::success();2282  };2283 2284  std::string module_name(pathname);2285  bool possible_package = false;2286 2287  if (extra_search_dir) {2288    if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {2289      error = Status::FromError(std::move(e));2290      return false;2291    }2292  } else {2293    FileSpec module_file(pathname);2294    FileSystem::Instance().Resolve(module_file);2295 2296    fs::file_status st;2297    std::error_code ec = status(module_file.GetPath(), st);2298 2299    if (ec || st.type() == fs::file_type::status_error ||2300        st.type() == fs::file_type::type_unknown ||2301        st.type() == fs::file_type::file_not_found) {2302      // if not a valid file of any sort, check if it might be a filename still2303      // dot can't be used but / and \ can, and if either is found, reject2304      if (strchr(pathname, '\\') || strchr(pathname, '/')) {2305        error = Status::FromErrorStringWithFormatv("invalid pathname '{0}'",2306                                                   pathname);2307        return false;2308      }2309      // Not a filename, probably a package of some sort, let it go through.2310      possible_package = true;2311    } else if (is_directory(st) || is_regular_file(st)) {2312      if (module_file.GetDirectory().IsEmpty()) {2313        error = Status::FromErrorStringWithFormatv(2314            "invalid directory name '{0}'", pathname);2315        return false;2316      }2317      if (llvm::Error e =2318              ExtendSysPath(module_file.GetDirectory().GetCString())) {2319        error = Status::FromError(std::move(e));2320        return false;2321      }2322      module_name = module_file.GetFilename().GetCString();2323    } else {2324      error = Status::FromErrorString(2325          "no known way to import this module specification");2326      return false;2327    }2328  }2329 2330  // Strip .py or .pyc extension2331  llvm::StringRef extension = llvm::sys::path::extension(module_name);2332  if (!extension.empty()) {2333    if (extension == ".py")2334      module_name.resize(module_name.length() - 3);2335    else if (extension == ".pyc")2336      module_name.resize(module_name.length() - 4);2337  }2338 2339  if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {2340    error = Status::FromErrorStringWithFormat(2341        "Python does not allow dots in module names: %s", module_name.c_str());2342    return false;2343  }2344 2345  if (module_name.find('-') != llvm::StringRef::npos) {2346    error = Status::FromErrorStringWithFormat(2347        "Python discourages dashes in module names: %s", module_name.c_str());2348    return false;2349  }2350 2351  // Check if the module is already imported.2352  StreamString command_stream;2353  command_stream.Clear();2354  command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());2355  bool does_contain = false;2356  // This call will succeed if the module was ever imported in any Debugger in2357  // the lifetime of the process in which this LLDB framework is living.2358  const bool does_contain_executed = ExecuteOneLineWithReturn(2359      command_stream.GetData(),2360      ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,2361      exc_options);2362 2363  const bool was_imported_globally = does_contain_executed && does_contain;2364  const bool was_imported_locally =2365      GetSessionDictionary()2366          .GetItemForKey(PythonString(module_name))2367          .IsAllocated();2368 2369  // now actually do the import2370  command_stream.Clear();2371 2372  if (was_imported_globally || was_imported_locally) {2373    if (!was_imported_locally)2374      command_stream.Printf("import %s ; reload_module(%s)",2375                            module_name.c_str(), module_name.c_str());2376    else2377      command_stream.Printf("reload_module(%s)", module_name.c_str());2378  } else2379    command_stream.Printf("import %s", module_name.c_str());2380 2381  error = ExecuteMultipleLines(command_stream.GetData(), exc_options);2382  if (error.Fail())2383    return false;2384 2385  // if we are here, everything worked2386  // call __lldb_init_module(debugger,dict)2387  if (!SWIGBridge::LLDBSwigPythonCallModuleInit(2388          module_name.c_str(), m_dictionary_name.c_str(),2389          m_debugger.shared_from_this())) {2390    error = Status::FromErrorString("calling __lldb_init_module failed");2391    return false;2392  }2393 2394  if (module_sp) {2395    // everything went just great, now set the module object2396    command_stream.Clear();2397    command_stream.Printf("%s", module_name.c_str());2398    void *module_pyobj = nullptr;2399    if (ExecuteOneLineWithReturn(2400            command_stream.GetData(),2401            ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,2402            exc_options) &&2403        module_pyobj)2404      *module_sp = std::make_shared<StructuredPythonObject>(PythonObject(2405          PyRefType::Owned, static_cast<PyObject *>(module_pyobj)));2406  }2407 2408  // Finally, if we got a target passed in, then we should tell the new module2409  // about this target:2410  if (target_sp)2411    return SWIGBridge::LLDBSwigPythonCallModuleNewTarget(2412        module_name.c_str(), m_dictionary_name.c_str(), target_sp);2413 2414  return true;2415}2416 2417bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {2418  if (!word || !word[0])2419    return false;2420 2421  llvm::StringRef word_sr(word);2422 2423  // filter out a few characters that would just confuse us and that are2424  // clearly not keyword material anyway2425  if (word_sr.find('"') != llvm::StringRef::npos ||2426      word_sr.find('\'') != llvm::StringRef::npos)2427    return false;2428 2429  StreamString command_stream;2430  command_stream.Printf("keyword.iskeyword('%s')", word);2431  bool result;2432  ExecuteScriptOptions options;2433  options.SetEnableIO(false);2434  options.SetMaskoutErrors(true);2435  options.SetSetLLDBGlobals(false);2436  if (ExecuteOneLineWithReturn(command_stream.GetData(),2437                               ScriptInterpreter::eScriptReturnTypeBool,2438                               &result, options))2439    return result;2440  return false;2441}2442 2443ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler(2444    lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro)2445    : m_debugger_sp(debugger_sp), m_synch_wanted(synchro),2446      m_old_asynch(debugger_sp->GetAsyncExecution()) {2447  if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)2448    m_debugger_sp->SetAsyncExecution(false);2449  else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)2450    m_debugger_sp->SetAsyncExecution(true);2451}2452 2453ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() {2454  if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)2455    m_debugger_sp->SetAsyncExecution(m_old_asynch);2456}2457 2458bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(2459    const char *impl_function, llvm::StringRef args,2460    ScriptedCommandSynchronicity synchronicity,2461    lldb_private::CommandReturnObject &cmd_retobj, Status &error,2462    const lldb_private::ExecutionContext &exe_ctx) {2463  if (!impl_function) {2464    error = Status::FromErrorString("no function to execute");2465    return false;2466  }2467 2468  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2469  lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));2470 2471  if (!debugger_sp.get()) {2472    error = Status::FromErrorString("invalid Debugger pointer");2473    return false;2474  }2475 2476  bool ret_val = false;2477 2478  {2479    Locker py_lock(this,2480                   Locker::AcquireLock | Locker::InitSession |2481                       (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2482                   Locker::FreeLock | Locker::TearDownSession);2483 2484    SynchronicityHandler synch_handler(debugger_sp, synchronicity);2485 2486    std::string args_str = args.str();2487    ret_val = SWIGBridge::LLDBSwigPythonCallCommand(2488        impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),2489        cmd_retobj, exe_ctx_ref_sp);2490  }2491 2492  if (!ret_val)2493    error = Status::FromErrorString("unable to execute script function");2494  else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2495    return false;2496 2497  error.Clear();2498  return ret_val;2499}2500 2501bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(2502    StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,2503    ScriptedCommandSynchronicity synchronicity,2504    lldb_private::CommandReturnObject &cmd_retobj, Status &error,2505    const lldb_private::ExecutionContext &exe_ctx) {2506  if (!impl_obj_sp || !impl_obj_sp->IsValid()) {2507    error = Status::FromErrorString("no function to execute");2508    return false;2509  }2510 2511  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2512  lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));2513 2514  if (!debugger_sp.get()) {2515    error = Status::FromErrorString("invalid Debugger pointer");2516    return false;2517  }2518 2519  bool ret_val = false;2520 2521  {2522    Locker py_lock(this,2523                   Locker::AcquireLock | Locker::InitSession |2524                       (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2525                   Locker::FreeLock | Locker::TearDownSession);2526 2527    SynchronicityHandler synch_handler(debugger_sp, synchronicity);2528 2529    std::string args_str = args.str();2530    ret_val = SWIGBridge::LLDBSwigPythonCallCommandObject(2531        static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp,2532        args_str.c_str(), cmd_retobj, exe_ctx_ref_sp);2533  }2534 2535  if (!ret_val)2536    error = Status::FromErrorString("unable to execute script function");2537  else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2538    return false;2539 2540  error.Clear();2541  return ret_val;2542}2543 2544bool ScriptInterpreterPythonImpl::RunScriptBasedParsedCommand(2545    StructuredData::GenericSP impl_obj_sp, Args &args,2546    ScriptedCommandSynchronicity synchronicity,2547    lldb_private::CommandReturnObject &cmd_retobj, Status &error,2548    const lldb_private::ExecutionContext &exe_ctx) {2549  if (!impl_obj_sp || !impl_obj_sp->IsValid()) {2550    error = Status::FromErrorString("no function to execute");2551    return false;2552  }2553 2554  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2555  lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));2556 2557  if (!debugger_sp.get()) {2558    error = Status::FromErrorString("invalid Debugger pointer");2559    return false;2560  }2561 2562  bool ret_val = false;2563 2564  {2565    Locker py_lock(this,2566                   Locker::AcquireLock | Locker::InitSession |2567                       (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),2568                   Locker::FreeLock | Locker::TearDownSession);2569 2570    SynchronicityHandler synch_handler(debugger_sp, synchronicity);2571 2572    StructuredData::ArraySP args_arr_sp(new StructuredData::Array());2573 2574    for (const Args::ArgEntry &entry : args) {2575      args_arr_sp->AddStringItem(entry.ref());2576    }2577    StructuredDataImpl args_impl(args_arr_sp);2578 2579    ret_val = SWIGBridge::LLDBSwigPythonCallParsedCommandObject(2580        static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp,2581        args_impl, cmd_retobj, exe_ctx_ref_sp);2582  }2583 2584  if (!ret_val)2585    error = Status::FromErrorString("unable to execute script function");2586  else if (cmd_retobj.GetStatus() == eReturnStatusFailed)2587    return false;2588 2589  error.Clear();2590  return ret_val;2591}2592 2593std::optional<std::string>2594ScriptInterpreterPythonImpl::GetRepeatCommandForScriptedCommand(2595    StructuredData::GenericSP impl_obj_sp, Args &args) {2596  if (!impl_obj_sp || !impl_obj_sp->IsValid())2597    return std::nullopt;2598 2599  lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();2600 2601  if (!debugger_sp.get())2602    return std::nullopt;2603 2604  std::optional<std::string> ret_val;2605 2606  {2607    Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,2608                   Locker::FreeLock);2609 2610    StructuredData::ArraySP args_arr_sp(new StructuredData::Array());2611 2612    // For scripting commands, we send the command string:2613    std::string command;2614    args.GetQuotedCommandString(command);2615    ret_val = SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand(2616        static_cast<PyObject *>(impl_obj_sp->GetValue()), command);2617  }2618  return ret_val;2619}2620 2621StructuredData::DictionarySP2622ScriptInterpreterPythonImpl::HandleArgumentCompletionForScriptedCommand(2623    StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args,2624    size_t args_pos, size_t char_in_arg) {2625  StructuredData::DictionarySP completion_dict_sp;2626  if (!impl_obj_sp || !impl_obj_sp->IsValid())2627    return completion_dict_sp;2628 2629  {2630    Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,2631                   Locker::FreeLock);2632 2633    completion_dict_sp =2634        SWIGBridge::LLDBSwigPythonHandleArgumentCompletionForScriptedCommand(2635            static_cast<PyObject *>(impl_obj_sp->GetValue()), args, args_pos,2636            char_in_arg);2637  }2638  return completion_dict_sp;2639}2640 2641StructuredData::DictionarySP2642ScriptInterpreterPythonImpl::HandleOptionArgumentCompletionForScriptedCommand(2643    StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_option,2644    size_t char_in_arg) {2645  StructuredData::DictionarySP completion_dict_sp;2646  if (!impl_obj_sp || !impl_obj_sp->IsValid())2647    return completion_dict_sp;2648 2649  {2650    Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,2651                   Locker::FreeLock);2652 2653    completion_dict_sp = SWIGBridge::2654        LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand(2655            static_cast<PyObject *>(impl_obj_sp->GetValue()), long_option,2656            char_in_arg);2657  }2658  return completion_dict_sp;2659}2660 2661/// In Python, a special attribute __doc__ contains the docstring for an object2662/// (function, method, class, ...) if any is defined Otherwise, the attribute's2663/// value is None.2664bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,2665                                                          std::string &dest) {2666  dest.clear();2667 2668  if (!item || !*item)2669    return false;2670 2671  std::string command(item);2672  command += ".__doc__";2673 2674  // Python is going to point this to valid data if ExecuteOneLineWithReturn2675  // returns successfully.2676  char *result_ptr = nullptr;2677 2678  if (ExecuteOneLineWithReturn(2679          command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,2680          &result_ptr, ExecuteScriptOptions().SetEnableIO(false))) {2681    if (result_ptr)2682      dest.assign(result_ptr);2683    return true;2684  }2685 2686  StreamString str_stream;2687  str_stream << "Function " << item2688             << " was not found. Containing module might be missing.";2689  dest = std::string(str_stream.GetString());2690 2691  return false;2692}2693 2694bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject(2695    StructuredData::GenericSP cmd_obj_sp, std::string &dest) {2696  dest.clear();2697 2698  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2699 2700  if (!cmd_obj_sp)2701    return false;2702 2703  PythonObject implementor(PyRefType::Borrowed,2704                           (PyObject *)cmd_obj_sp->GetValue());2705 2706  if (!implementor.IsAllocated())2707    return false;2708 2709  llvm::Expected<PythonObject> expected_py_return =2710      implementor.CallMethod("get_short_help");2711 2712  if (!expected_py_return) {2713    llvm::consumeError(expected_py_return.takeError());2714    return false;2715  }2716 2717  PythonObject py_return = std::move(expected_py_return.get());2718 2719  if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {2720    PythonString py_string(PyRefType::Borrowed, py_return.get());2721    llvm::StringRef return_data(py_string.GetString());2722    dest.assign(return_data.data(), return_data.size());2723    return true;2724  }2725 2726  return false;2727}2728 2729uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject(2730    StructuredData::GenericSP cmd_obj_sp) {2731  uint32_t result = 0;2732 2733  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2734 2735  static char callee_name[] = "get_flags";2736 2737  if (!cmd_obj_sp)2738    return result;2739 2740  PythonObject implementor(PyRefType::Borrowed,2741                           (PyObject *)cmd_obj_sp->GetValue());2742 2743  if (!implementor.IsAllocated())2744    return result;2745 2746  PythonObject pmeth(PyRefType::Owned,2747                     PyObject_GetAttrString(implementor.get(), callee_name));2748 2749  if (PyErr_Occurred())2750    PyErr_Clear();2751 2752  if (!pmeth.IsAllocated())2753    return result;2754 2755  if (PyCallable_Check(pmeth.get()) == 0) {2756    if (PyErr_Occurred())2757      PyErr_Clear();2758    return result;2759  }2760 2761  if (PyErr_Occurred())2762    PyErr_Clear();2763 2764  long long py_return = unwrapOrSetPythonException(2765      As<long long>(implementor.CallMethod(callee_name)));2766 2767  // if it fails, print the error but otherwise go on2768  if (PyErr_Occurred()) {2769    PyErr_Print();2770    PyErr_Clear();2771  } else {2772    result = py_return;2773  }2774 2775  return result;2776}2777 2778StructuredData::ObjectSP2779ScriptInterpreterPythonImpl::GetOptionsForCommandObject(2780    StructuredData::GenericSP cmd_obj_sp) {2781  StructuredData::ObjectSP result = {};2782 2783  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2784 2785  static char callee_name[] = "get_options_definition";2786 2787  if (!cmd_obj_sp)2788    return result;2789 2790  PythonObject implementor(PyRefType::Borrowed,2791                           (PyObject *)cmd_obj_sp->GetValue());2792 2793  if (!implementor.IsAllocated())2794    return result;2795 2796  PythonObject pmeth(PyRefType::Owned,2797                     PyObject_GetAttrString(implementor.get(), callee_name));2798 2799  if (PyErr_Occurred())2800    PyErr_Clear();2801 2802  if (!pmeth.IsAllocated())2803    return result;2804 2805  if (PyCallable_Check(pmeth.get()) == 0) {2806    if (PyErr_Occurred())2807      PyErr_Clear();2808    return result;2809  }2810 2811  if (PyErr_Occurred())2812    PyErr_Clear();2813 2814  PythonDictionary py_return = unwrapOrSetPythonException(2815      As<PythonDictionary>(implementor.CallMethod(callee_name)));2816 2817  // if it fails, print the error but otherwise go on2818  if (PyErr_Occurred()) {2819    PyErr_Print();2820    PyErr_Clear();2821    return {};2822  }2823  return py_return.CreateStructuredObject();2824}2825 2826StructuredData::ObjectSP2827ScriptInterpreterPythonImpl::GetArgumentsForCommandObject(2828    StructuredData::GenericSP cmd_obj_sp) {2829  StructuredData::ObjectSP result = {};2830 2831  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2832 2833  static char callee_name[] = "get_args_definition";2834 2835  if (!cmd_obj_sp)2836    return result;2837 2838  PythonObject implementor(PyRefType::Borrowed,2839                           (PyObject *)cmd_obj_sp->GetValue());2840 2841  if (!implementor.IsAllocated())2842    return result;2843 2844  PythonObject pmeth(PyRefType::Owned,2845                     PyObject_GetAttrString(implementor.get(), callee_name));2846 2847  if (PyErr_Occurred())2848    PyErr_Clear();2849 2850  if (!pmeth.IsAllocated())2851    return result;2852 2853  if (PyCallable_Check(pmeth.get()) == 0) {2854    if (PyErr_Occurred())2855      PyErr_Clear();2856    return result;2857  }2858 2859  if (PyErr_Occurred())2860    PyErr_Clear();2861 2862  PythonList py_return = unwrapOrSetPythonException(2863      As<PythonList>(implementor.CallMethod(callee_name)));2864 2865  // if it fails, print the error but otherwise go on2866  if (PyErr_Occurred()) {2867    PyErr_Print();2868    PyErr_Clear();2869    return {};2870  }2871  return py_return.CreateStructuredObject();2872}2873 2874void ScriptInterpreterPythonImpl::OptionParsingStartedForCommandObject(2875    StructuredData::GenericSP cmd_obj_sp) {2876 2877  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2878 2879  static char callee_name[] = "option_parsing_started";2880 2881  if (!cmd_obj_sp)2882    return;2883 2884  PythonObject implementor(PyRefType::Borrowed,2885                           (PyObject *)cmd_obj_sp->GetValue());2886 2887  if (!implementor.IsAllocated())2888    return;2889 2890  PythonObject pmeth(PyRefType::Owned,2891                     PyObject_GetAttrString(implementor.get(), callee_name));2892 2893  if (PyErr_Occurred())2894    PyErr_Clear();2895 2896  if (!pmeth.IsAllocated())2897    return;2898 2899  if (PyCallable_Check(pmeth.get()) == 0) {2900    if (PyErr_Occurred())2901      PyErr_Clear();2902    return;2903  }2904 2905  if (PyErr_Occurred())2906    PyErr_Clear();2907 2908  // option_parsing_starting doesn't return anything, ignore anything but2909  // python errors.2910  unwrapOrSetPythonException(As<bool>(implementor.CallMethod(callee_name)));2911 2912  // if it fails, print the error but otherwise go on2913  if (PyErr_Occurred()) {2914    PyErr_Print();2915    PyErr_Clear();2916    return;2917  }2918}2919 2920bool ScriptInterpreterPythonImpl::SetOptionValueForCommandObject(2921    StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx,2922    llvm::StringRef long_option, llvm::StringRef value) {2923  StructuredData::ObjectSP result = {};2924 2925  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2926 2927  static char callee_name[] = "set_option_value";2928 2929  if (!cmd_obj_sp)2930    return false;2931 2932  PythonObject implementor(PyRefType::Borrowed,2933                           (PyObject *)cmd_obj_sp->GetValue());2934 2935  if (!implementor.IsAllocated())2936    return false;2937 2938  PythonObject pmeth(PyRefType::Owned,2939                     PyObject_GetAttrString(implementor.get(), callee_name));2940 2941  if (PyErr_Occurred())2942    PyErr_Clear();2943 2944  if (!pmeth.IsAllocated())2945    return false;2946 2947  if (PyCallable_Check(pmeth.get()) == 0) {2948    if (PyErr_Occurred())2949      PyErr_Clear();2950    return false;2951  }2952 2953  if (PyErr_Occurred())2954    PyErr_Clear();2955 2956  lldb::ExecutionContextRefSP exe_ctx_ref_sp;2957  if (exe_ctx)2958    exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);2959  PythonObject ctx_ref_obj = SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp);2960 2961  bool py_return = unwrapOrSetPythonException(As<bool>(2962      implementor.CallMethod(callee_name, ctx_ref_obj,2963                             long_option.str().c_str(), value.str().c_str())));2964 2965  // if it fails, print the error but otherwise go on2966  if (PyErr_Occurred()) {2967    PyErr_Print();2968    PyErr_Clear();2969    return false;2970  }2971  return py_return;2972}2973 2974bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject(2975    StructuredData::GenericSP cmd_obj_sp, std::string &dest) {2976  dest.clear();2977 2978  Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);2979 2980  if (!cmd_obj_sp)2981    return false;2982 2983  PythonObject implementor(PyRefType::Borrowed,2984                           (PyObject *)cmd_obj_sp->GetValue());2985 2986  if (!implementor.IsAllocated())2987    return false;2988 2989  llvm::Expected<PythonObject> expected_py_return =2990      implementor.CallMethod("get_long_help");2991 2992  if (!expected_py_return) {2993    llvm::consumeError(expected_py_return.takeError());2994    return false;2995  }2996 2997  PythonObject py_return = std::move(expected_py_return.get());2998 2999  bool got_string = false;3000  if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {3001    PythonString str(PyRefType::Borrowed, py_return.get());3002    llvm::StringRef str_data(str.GetString());3003    dest.assign(str_data.data(), str_data.size());3004    got_string = true;3005  }3006 3007  return got_string;3008}3009 3010std::unique_ptr<ScriptInterpreterLocker>3011ScriptInterpreterPythonImpl::AcquireInterpreterLock() {3012  std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(3013      this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,3014      Locker::FreeLock | Locker::TearDownSession));3015  return py_lock;3016}3017 3018void ScriptInterpreterPythonImpl::Initialize() {3019  LLDB_SCOPED_TIMER();3020 3021  // RAII-based initialization which correctly handles multiple-initialization,3022  // version- specific differences among Python 2 and Python 3, and saving and3023  // restoring various other pieces of state that can get mucked with during3024  // initialization.3025  InitializePythonRAII initialize_guard;3026 3027  LLDBSwigPyInit();3028 3029  // Update the path python uses to search for modules to include the current3030  // directory.3031 3032  RunSimpleString("import sys");3033  AddToSysPath(AddLocation::End, ".");3034 3035  // Don't denormalize paths when calling file_spec.GetPath().  On platforms3036  // that use a backslash as the path separator, this will result in executing3037  // python code containing paths with unescaped backslashes.  But Python also3038  // accepts forward slashes, so to make life easier we just use that.3039  if (FileSpec file_spec = GetPythonDir())3040    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));3041  if (FileSpec file_spec = HostInfo::GetShlibDir())3042    AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));3043 3044  RunSimpleString("sys.dont_write_bytecode = 1; import "3045                  "lldb.embedded_interpreter; from "3046                  "lldb.embedded_interpreter import run_python_interpreter; "3047                  "from lldb.embedded_interpreter import run_one_line");3048 3049#if LLDB_USE_PYTHON_SET_INTERRUPT3050  // Python will not just overwrite its internal SIGINT handler but also the3051  // one from the process. Backup the current SIGINT handler to prevent that3052  // Python deletes it.3053  RestoreSignalHandlerScope save_sigint(SIGINT);3054 3055  // Setup a default SIGINT signal handler that works the same way as the3056  // normal Python REPL signal handler which raises a KeyboardInterrupt.3057  // Also make sure to not pollute the user's REPL with the signal module nor3058  // our utility function.3059  RunSimpleString("def lldb_setup_sigint_handler():\n"3060                  "  import signal;\n"3061                  "  def signal_handler(sig, frame):\n"3062                  "    raise KeyboardInterrupt()\n"3063                  "  signal.signal(signal.SIGINT, signal_handler);\n"3064                  "lldb_setup_sigint_handler();\n"3065                  "del lldb_setup_sigint_handler\n");3066#endif3067}3068 3069void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,3070                                               std::string path) {3071  std::string statement;3072  if (location == AddLocation::Beginning) {3073    statement.assign("sys.path.insert(0,\"");3074    statement.append(path);3075    statement.append("\")");3076  } else {3077    statement.assign("sys.path.append(\"");3078    statement.append(path);3079    statement.append("\")");3080  }3081  RunSimpleString(statement.c_str());3082}3083 3084// We are intentionally NOT calling Py_Finalize here (this would be the logical3085// place to call it).  Calling Py_Finalize here causes test suite runs to seg3086// fault:  The test suite runs in Python.  It registers SBDebugger::Terminate to3087// be called 'at_exit'.  When the test suite Python harness finishes up, it3088// calls Py_Finalize, which calls all the 'at_exit' registered functions.3089// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,3090// which calls ScriptInterpreter::Terminate, which calls3091// ScriptInterpreterPythonImpl::Terminate.  So if we call Py_Finalize here, we3092// end up with Py_Finalize being called from within Py_Finalize, which results3093// in a seg fault. Since this function only gets called when lldb is shutting3094// down and going away anyway, the fact that we don't actually call Py_Finalize3095// should not cause any problems (everything should shut down/go away anyway3096// when the process exits).3097//3098// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }3099 3100#endif3101