diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python')
10 files changed, 634 insertions, 107 deletions
| diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 7c49502f1b57..f51d9b3a796c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -24,7 +24,7 @@  #include "llvm/Support/ConvertUTF.h"  #include "llvm/Support/Errno.h" -#include <stdio.h> +#include <cstdio>  using namespace lldb_private;  using namespace lldb; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 22f6c67eb7a5..4577253227cd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -229,7 +229,7 @@ struct PythonFormat<  class PythonObject {  public: -  PythonObject() : m_py_obj(nullptr) {} +  PythonObject() = default;    PythonObject(PyRefType type, PyObject *py_obj) {      m_py_obj = py_obj; @@ -378,7 +378,7 @@ public:    }  protected: -  PyObject *m_py_obj; +  PyObject *m_py_obj = nullptr;  }; @@ -421,7 +421,7 @@ public:        Py_DECREF(py_obj);    } -  TypedPythonObject() {} +  TypedPythonObject() = default;  };  class PythonBytes : public TypedPythonObject<PythonBytes> { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp index 5f6429f5cd0e..95a3365ed983 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp @@ -2,7 +2,7 @@  #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE -#include <stdio.h> +#include <cstdio>  #include <editline/readline.h> diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp new file mode 100644 index 000000000000..7c7c5d73680a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp @@ -0,0 +1,48 @@ +//===-- SWIGPythonBridge.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "SWIGPythonBridge.h" + +using namespace lldb; + +namespace lldb_private { + +template <typename T> const char *GetPythonValueFormatString(T t); +template <> const char *GetPythonValueFormatString(char *) { return "s"; } +template <> const char *GetPythonValueFormatString(char) { return "b"; } +template <> const char *GetPythonValueFormatString(unsigned char) { +  return "B"; +} +template <> const char *GetPythonValueFormatString(short) { return "h"; } +template <> const char *GetPythonValueFormatString(unsigned short) { +  return "H"; +} +template <> const char *GetPythonValueFormatString(int) { return "i"; } +template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } +template <> const char *GetPythonValueFormatString(long) { return "l"; } +template <> const char *GetPythonValueFormatString(unsigned long) { +  return "k"; +} +template <> const char *GetPythonValueFormatString(long long) { return "L"; } +template <> const char *GetPythonValueFormatString(unsigned long long) { +  return "K"; +} +template <> const char *GetPythonValueFormatString(float) { return "f"; } +template <> const char *GetPythonValueFormatString(double) { return "d"; } + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h new file mode 100644 index 000000000000..1ef792bcf303 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -0,0 +1,56 @@ +//===-- ScriptInterpreterPython.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H + +#include <string> + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { + +// GetPythonValueFormatString provides a system independent type safe way to +// convert a variable's type into a python value format. Python value formats +// are defined in terms of builtin C types and could change from system to as +// the underlying typedef for uint* types, size_t, off_t and other values +// change. + +template <typename T> const char *GetPythonValueFormatString(T t); +template <> const char *GetPythonValueFormatString(char *); +template <> const char *GetPythonValueFormatString(char); +template <> const char *GetPythonValueFormatString(unsigned char); +template <> const char *GetPythonValueFormatString(short); +template <> const char *GetPythonValueFormatString(unsigned short); +template <> const char *GetPythonValueFormatString(int); +template <> const char *GetPythonValueFormatString(unsigned int); +template <> const char *GetPythonValueFormatString(long); +template <> const char *GetPythonValueFormatString(unsigned long); +template <> const char *GetPythonValueFormatString(long long); +template <> const char *GetPythonValueFormatString(unsigned long long); +template <> const char *GetPythonValueFormatString(float t); +template <> const char *GetPythonValueFormatString(double t); + +extern "C" void *LLDBSwigPythonCreateScriptedProcess( +    const char *python_class_name, const char *session_dictionary_name, +    const lldb::TargetSP &target_sp, StructuredDataImpl *args_impl, +    std::string &error_string); + +extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data); +extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data); +extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 6b53bd3a2edc..7ad63722c31c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -16,7 +16,11 @@  #include "PythonDataObjects.h"  #include "PythonReadline.h" +#include "SWIGPythonBridge.h"  #include "ScriptInterpreterPythonImpl.h" +#include "ScriptedProcessPythonInterface.h" + +#include "lldb/API/SBError.h"  #include "lldb/API/SBFrame.h"  #include "lldb/API/SBValue.h"  #include "lldb/Breakpoint/StoppointCallbackContext.h" @@ -41,10 +45,10 @@  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/FormatAdapters.h" +#include <cstdio> +#include <cstdlib>  #include <memory>  #include <mutex> -#include <stdio.h> -#include <stdlib.h>  #include <string>  using namespace lldb; @@ -148,8 +152,6 @@ extern "C" void *LLDBSwigPython_GetChildAtIndex(void *implementor,  extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor,                                                        const char *child_name); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); -  extern lldb::ValueObjectSP  LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); @@ -234,8 +236,7 @@ namespace {  // save off initial state at the beginning, and restore it at the end  struct InitializePythonRAII {  public: -  InitializePythonRAII() -      : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) { +  InitializePythonRAII() {      InitializePythonHome();  #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE @@ -355,8 +356,8 @@ private:    }    TerminalState m_stdin_tty_state; -  PyGILState_STATE m_gil_state; -  bool m_was_already_initialized; +  PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; +  bool m_was_already_initialized = false;  };  } // namespace @@ -410,6 +411,32 @@ FileSpec ScriptInterpreterPython::GetPythonDir() {    return g_spec;  } +void ScriptInterpreterPython::SharedLibraryDirectoryHelper( +    FileSpec &this_file) { +  // When we're loaded from python, this_file will point to the file inside the +  // python package directory. Replace it with the one in the lib directory. +#ifdef _WIN32 +  // On windows, we need to manually back out of the python tree, and go into +  // the bin directory. This is pretty much the inverse of what ComputePythonDir +  // does. +  if (this_file.GetFileNameExtension() == ConstString(".pyd")) { +    this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd +    this_file.RemoveLastPathComponent(); // lldb +    llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR; +    for (auto it = llvm::sys::path::begin(libdir), +              end = llvm::sys::path::end(libdir); +         it != end; ++it) +      this_file.RemoveLastPathComponent(); +    this_file.AppendPathComponent("bin"); +    this_file.AppendPathComponent("liblldb.dll"); +  } +#else +  // The python file is a symlink, so we can find the real library by resolving +  // it. We can do this unconditionally. +  FileSystem::Instance().ResolveSymbolicLink(this_file, this_file); +#endif +} +  lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() {    static ConstString g_name("script-python");    return g_name; @@ -506,6 +533,9 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)        m_command_thread_state(nullptr) {    InitializePrivate(); +  m_scripted_process_interface_up = +      std::make_unique<ScriptedProcessPythonInterface>(*this); +    m_dictionary_name.append("_dict");    StreamString run_string;    run_string.Printf("%s = dict()", m_dictionary_name.c_str()); @@ -605,11 +635,10 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,    case eIOHandlerNone:      break;    case eIOHandlerBreakpoint: { -    std::vector<BreakpointOptions *> *bp_options_vec = -        (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); -    for (auto bp_options : *bp_options_vec) { -      if (!bp_options) -        continue; +    std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec = +        (std::vector<std::reference_wrapper<BreakpointOptions>> *) +            io_handler.GetUserData(); +    for (BreakpointOptions &bp_options : *bp_options_vec) {        auto data_up = std::make_unique<CommandDataPython>();        if (!data_up) @@ -623,7 +652,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,                .Success()) {          auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(              std::move(data_up)); -        bp_options->SetCallback( +        bp_options.SetCallback(              ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);        } else if (!batch_mode) {          StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); @@ -1048,11 +1077,24 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(      llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,      void *ret_value, const ExecuteScriptOptions &options) { +  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> +      io_redirect_or_error = ScriptInterpreterIORedirect::Create( +          options.GetEnableIO(), m_debugger, /*result=*/nullptr); + +  if (!io_redirect_or_error) { +    llvm::consumeError(io_redirect_or_error.takeError()); +    return false; +  } + +  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; +    Locker locker(this,                  Locker::AcquireLock | Locker::InitSession |                      (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |                      Locker::NoSTDIN, -                Locker::FreeAcquiredLock | Locker::TearDownSession); +                Locker::FreeAcquiredLock | Locker::TearDownSession, +                io_redirect.GetInputFile(), io_redirect.GetOutputFile(), +                io_redirect.GetErrorFile());    PythonModule &main_module = GetMainModule();    PythonDictionary globals = main_module.GetDictionary(); @@ -1161,11 +1203,22 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(    if (in_string == nullptr)      return Status(); +  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> +      io_redirect_or_error = ScriptInterpreterIORedirect::Create( +          options.GetEnableIO(), m_debugger, /*result=*/nullptr); + +  if (!io_redirect_or_error) +    return Status(io_redirect_or_error.takeError()); + +  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; +    Locker locker(this,                  Locker::AcquireLock | Locker::InitSession |                      (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |                      Locker::NoSTDIN, -                Locker::FreeAcquiredLock | Locker::TearDownSession); +                Locker::FreeAcquiredLock | Locker::TearDownSession, +                io_redirect.GetInputFile(), io_redirect.GetOutputFile(), +                io_redirect.GetErrorFile());    PythonModule &main_module = GetMainModule();    PythonDictionary globals = main_module.GetDictionary(); @@ -1196,7 +1249,7 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(  }  void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( -    std::vector<BreakpointOptions *> &bp_options_vec, +    std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,      CommandReturnObject &result) {    m_active_io_handler = eIOHandlerBreakpoint;    m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler( @@ -1211,7 +1264,7 @@ void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(  }  Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( -    BreakpointOptions *bp_options, const char *function_name, +    BreakpointOptions &bp_options, const char *function_name,      StructuredData::ObjectSP extra_args_sp) {    Status error;    // For now just cons up a oneliner that calls the provided function. @@ -1253,7 +1306,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(  }  Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( -    BreakpointOptions *bp_options, +    BreakpointOptions &bp_options,      std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {    Status error;    error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source, @@ -1264,21 +1317,20 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(    }    auto baton_sp =        std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up)); -  bp_options->SetCallback( +  bp_options.SetCallback(        ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);    return error;  }  Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( -    BreakpointOptions *bp_options, const char *command_body_text) { +    BreakpointOptions &bp_options, const char *command_body_text) {    return SetBreakpointCommandCallback(bp_options, command_body_text, {},false);  }  // Set a Python one-liner as the callback for the breakpoint.  Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( -    BreakpointOptions *bp_options, const char *command_body_text, -    StructuredData::ObjectSP extra_args_sp, -    bool uses_extra_args) { +    BreakpointOptions &bp_options, const char *command_body_text, +    StructuredData::ObjectSP extra_args_sp, bool uses_extra_args) {    auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);    // Split the command_body_text into lines, and pass that to    // GenerateBreakpointCommandCallbackData.  That will wrap the body in an @@ -1292,7 +1344,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(    if (error.Success()) {      auto baton_sp =          std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up)); -    bp_options->SetCallback( +    bp_options.SetCallback(          ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);      return error;    } @@ -1330,7 +1382,7 @@ Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(    Status error = ExecuteMultipleLines(        function_def_string.c_str(), -      ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); +      ExecuteScriptOptions().SetEnableIO(false));    return error;  } @@ -1678,35 +1730,6 @@ StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo(    return StructuredData::ArraySP();  } -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to as -// the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *) { return "s"; } -template <> const char *GetPythonValueFormatString(char) { return "b"; } -template <> const char *GetPythonValueFormatString(unsigned char) { -  return "B"; -} -template <> const char *GetPythonValueFormatString(short) { return "h"; } -template <> const char *GetPythonValueFormatString(unsigned short) { -  return "H"; -} -template <> const char *GetPythonValueFormatString(int) { return "i"; } -template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString(long) { return "l"; } -template <> const char *GetPythonValueFormatString(unsigned long) { -  return "k"; -} -template <> const char *GetPythonValueFormatString(long long) { return "L"; } -template <> const char *GetPythonValueFormatString(unsigned long long) { -  return "K"; -} -template <> const char *GetPythonValueFormatString(float t) { return "f"; } -template <> const char *GetPythonValueFormatString(double t) { return "d"; } -  StructuredData::StringSP  ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData(      StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { @@ -2058,7 +2081,10 @@ ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,    StructuredData::ObjectSP module_sp; -  if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp)) +  LoadScriptOptions load_script_options = +      LoadScriptOptions().SetInitSession(true).SetSilent(false); +  if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options, +                          error, &module_sp))      return module_sp;    return StructuredData::ObjectSP(); @@ -2733,26 +2759,44 @@ uint64_t replace_all(std::string &str, const std::string &oldStr,  }  bool ScriptInterpreterPythonImpl::LoadScriptingModule( -    const char *pathname, bool init_session, lldb_private::Status &error, -    StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) { +    const char *pathname, const LoadScriptOptions &options, +    lldb_private::Status &error, StructuredData::ObjectSP *module_sp, +    FileSpec extra_search_dir) {    namespace fs = llvm::sys::fs;    namespace path = llvm::sys::path; +  ExecuteScriptOptions exc_options = ExecuteScriptOptions() +                                         .SetEnableIO(!options.GetSilent()) +                                         .SetSetLLDBGlobals(false); +    if (!pathname || !pathname[0]) {      error.SetErrorString("invalid pathname");      return false;    } +  llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> +      io_redirect_or_error = ScriptInterpreterIORedirect::Create( +          exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr); + +  if (!io_redirect_or_error) { +    error = io_redirect_or_error.takeError(); +    return false; +  } + +  ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;    lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();    // Before executing Python code, lock the GIL.    Locker py_lock(this,                   Locker::AcquireLock | -                     (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, +                     (options.GetInitSession() ? Locker::InitSession : 0) | +                     Locker::NoSTDIN,                   Locker::FreeAcquiredLock | -                     (init_session ? Locker::TearDownSession : 0)); +                     (options.GetInitSession() ? Locker::TearDownSession : 0), +                 io_redirect.GetInputFile(), io_redirect.GetOutputFile(), +                 io_redirect.GetErrorFile()); -  auto ExtendSysPath = [this](std::string directory) -> llvm::Error { +  auto ExtendSysPath = [&](std::string directory) -> llvm::Error {      if (directory.empty()) {        return llvm::make_error<llvm::StringError>(            "invalid directory name", llvm::inconvertibleErrorCode()); @@ -2767,11 +2811,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(                            "sys.path.insert(1,'%s');\n\n",                            directory.c_str(), directory.c_str());      bool syspath_retval = -        ExecuteMultipleLines(command_stream.GetData(), -                             ScriptInterpreter::ExecuteScriptOptions() -                                 .SetEnableIO(false) -                                 .SetSetLLDBGlobals(false)) -            .Success(); +        ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();      if (!syspath_retval) {        return llvm::make_error<llvm::StringError>(            "Python sys.path handling failed", llvm::inconvertibleErrorCode()); @@ -2781,6 +2821,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(    };    std::string module_name(pathname); +  bool possible_package = false;    if (extra_search_dir) {      if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) { @@ -2805,6 +2846,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(          return false;        }        // Not a filename, probably a package of some sort, let it go through. +      possible_package = true;      } else if (is_directory(st) || is_regular_file(st)) {        if (module_file.GetDirectory().IsEmpty()) {          error.SetErrorString("invalid directory name"); @@ -2831,35 +2873,39 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(        module_name.resize(module_name.length() - 4);    } -  // check if the module is already import-ed +  if (!possible_package && module_name.find('.') != llvm::StringRef::npos) { +    error.SetErrorStringWithFormat( +        "Python does not allow dots in module names: %s", module_name.c_str()); +    return false; +  } + +  if (module_name.find('-') != llvm::StringRef::npos) { +    error.SetErrorStringWithFormat( +        "Python discourages dashes in module names: %s", module_name.c_str()); +    return false; +  } + +  // Check if the module is already imported.    StreamString command_stream;    command_stream.Clear();    command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());    bool does_contain = false; -  // this call will succeed if the module was ever imported in any Debugger -  // in the lifetime of the process in which this LLDB framework is living -  bool was_imported_globally = -      (ExecuteOneLineWithReturn( -           command_stream.GetData(), -           ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, -           ScriptInterpreter::ExecuteScriptOptions() -               .SetEnableIO(false) -               .SetSetLLDBGlobals(false)) && -       does_contain); -  // this call will fail if the module was not imported in this Debugger -  // before -  command_stream.Clear(); -  command_stream.Printf("sys.getrefcount(%s)", module_name.c_str()); -  bool was_imported_locally = GetSessionDictionary() -                                  .GetItemForKey(PythonString(module_name)) -                                  .IsAllocated(); - -  bool was_imported = (was_imported_globally || was_imported_locally); +  // This call will succeed if the module was ever imported in any Debugger in +  // the lifetime of the process in which this LLDB framework is living. +  const bool does_contain_executed = ExecuteOneLineWithReturn( +      command_stream.GetData(), +      ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options); + +  const bool was_imported_globally = does_contain_executed && does_contain; +  const bool was_imported_locally = +      GetSessionDictionary() +          .GetItemForKey(PythonString(module_name)) +          .IsAllocated();    // now actually do the import    command_stream.Clear(); -  if (was_imported) { +  if (was_imported_globally || was_imported_locally) {      if (!was_imported_locally)        command_stream.Printf("import %s ; reload_module(%s)",                              module_name.c_str(), module_name.c_str()); @@ -2868,10 +2914,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(    } else      command_stream.Printf("import %s", module_name.c_str()); -  error = ExecuteMultipleLines(command_stream.GetData(), -                               ScriptInterpreter::ExecuteScriptOptions() -                                   .SetEnableIO(false) -                                   .SetSetLLDBGlobals(false)); +  error = ExecuteMultipleLines(command_stream.GetData(), exc_options);    if (error.Fail())      return false; @@ -2890,7 +2933,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(      void *module_pyobj = nullptr;      if (ExecuteOneLineWithReturn(              command_stream.GetData(), -            ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) && +            ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj, +            exc_options) &&          module_pyobj)        *module_sp = std::make_shared<StructuredPythonObject>(module_pyobj);    } @@ -3047,7 +3091,7 @@ bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,    if (ExecuteOneLineWithReturn(            command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,            &result_ptr, -          ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) { +          ExecuteScriptOptions().SetEnableIO(false))) {      if (result_ptr)        dest.assign(result_ptr);      return true; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index e59fedbd0971..b8b978118218 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -13,6 +13,8 @@  #if LLDB_ENABLE_PYTHON +#include "ScriptedProcessPythonInterface.h" +  #include "lldb/Breakpoint/BreakpointOptions.h"  #include "lldb/Core/IOHandler.h"  #include "lldb/Core/StructuredDataImpl.h" @@ -51,6 +53,7 @@ public:    static lldb_private::ConstString GetPluginNameStatic();    static const char *GetPluginDescriptionStatic();    static FileSpec GetPythonDir(); +  static void SharedLibraryDirectoryHelper(FileSpec &this_file);  protected:    static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 45dad4217005..d1b0b3fda1ef 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -6,6 +6,9 @@  //  //===----------------------------------------------------------------------===// +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H +  #include "lldb/Host/Config.h"  #if LLDB_ENABLE_PYTHON @@ -231,7 +234,8 @@ public:    bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,                                std::string &output, Status &error) override; -  bool LoadScriptingModule(const char *filename, bool init_session, +  bool LoadScriptingModule(const char *filename, +                           const LoadScriptOptions &options,                             lldb_private::Status &error,                             StructuredData::ObjectSP *module_sp = nullptr,                             FileSpec extra_search_dir = {}) override; @@ -241,7 +245,7 @@ public:    std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;    void CollectDataForBreakpointCommandCallback( -      std::vector<BreakpointOptions *> &bp_options_vec, +      std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,        CommandReturnObject &result) override;    void @@ -249,20 +253,19 @@ public:                                            CommandReturnObject &result) override;    /// Set the callback body text into the callback for the breakpoint. -  Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, +  Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,                                        const char *callback_body) override;    Status SetBreakpointCommandCallbackFunction( -      BreakpointOptions *bp_options, -      const char *function_name, +      BreakpointOptions &bp_options, const char *function_name,        StructuredData::ObjectSP extra_args_sp) override;    /// This one is for deserialization:    Status SetBreakpointCommandCallback( -      BreakpointOptions *bp_options, +      BreakpointOptions &bp_options,        std::unique_ptr<BreakpointOptions::CommandData> &data_up) override; -  Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, +  Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,                                        const char *command_body_text,                                        StructuredData::ObjectSP extra_args_sp,                                        bool uses_extra_args); @@ -416,7 +419,7 @@ public:        : IOHandler(debugger, IOHandler::Type::PythonInterpreter),          m_python(python) {} -  ~IOHandlerPythonInterpreter() override {} +  ~IOHandlerPythonInterpreter() override = default;    ConstString GetControlSequence(char ch) override {      if (ch == 'd') @@ -483,4 +486,5 @@ protected:  } // namespace lldb_private -#endif +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp new file mode 100644 index 000000000000..ce262c930f8b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -0,0 +1,306 @@ +//===-- ScriptedProcessPythonInterface.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "SWIGPythonBridge.h" +#include "ScriptInterpreterPythonImpl.h" +#include "ScriptedProcessPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( +    const llvm::StringRef class_name, lldb::TargetSP target_sp, +    StructuredData::DictionarySP args_sp) { +  if (class_name.empty()) +    return {}; + +  std::string error_string; +  StructuredDataImpl *args_impl = nullptr; +  if (args_sp) { +    args_impl = new StructuredDataImpl(); +    args_impl->SetObjectSP(args_sp); +  } + +  void *ret_val; + +  { + +    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, +                   Locker::FreeLock); + +    ret_val = LLDBSwigPythonCreateScriptedProcess( +        class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, +        args_impl, error_string); +  } + +  m_object_instance_sp = +      StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + +  return m_object_instance_sp; +} + +Status ScriptedProcessPythonInterface::Launch() { +  return GetStatusFromMethod("launch"); +} + +Status ScriptedProcessPythonInterface::Resume() { +  return GetStatusFromMethod("resume"); +} + +bool ScriptedProcessPythonInterface::ShouldStop() { +  llvm::Optional<unsigned long long> should_stop = +      GetGenericInteger("should_stop"); + +  if (!should_stop) +    return false; + +  return static_cast<bool>(*should_stop); +} + +Status ScriptedProcessPythonInterface::Stop() { +  return GetStatusFromMethod("stop"); +} + +Status ScriptedProcessPythonInterface::GetStatusFromMethod( +    llvm::StringRef method_name) { +  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, +                 Locker::FreeLock); + +  if (!m_object_instance_sp) +    return Status("Python object ill-formed."); + +  if (!m_object_instance_sp) +    return Status("Cannot convert Python object to StructuredData::Generic."); +  PythonObject implementor(PyRefType::Borrowed, +                           (PyObject *)m_object_instance_sp->GetValue()); + +  if (!implementor.IsAllocated()) +    return Status("Python implementor not allocated."); + +  PythonObject pmeth( +      PyRefType::Owned, +      PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  if (!pmeth.IsAllocated()) +    return Status("Python method not allocated."); + +  if (PyCallable_Check(pmeth.get()) == 0) { +    if (PyErr_Occurred()) +      PyErr_Clear(); +    return Status("Python method not callable."); +  } + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  PythonObject py_return(PyRefType::Owned, +                         PyObject_CallMethod(implementor.get(), +                                             method_name.str().c_str(), +                                             nullptr)); + +  if (PyErr_Occurred()) { +    PyErr_Print(); +    PyErr_Clear(); +    return Status("Python method could not be called."); +  } + +  if (PyObject *py_ret_ptr = py_return.get()) { +    lldb::SBError *sb_error = +        (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr); + +    if (!sb_error) +      return Status("Couldn't cast lldb::SBError to lldb::Status."); + +    Status status = m_interpreter.GetStatusFromSBError(*sb_error); + +    if (status.Fail()) +      return Status("error: %s", status.AsCString()); + +    return status; +  } + +  return Status("Returned object is null."); +} + +llvm::Optional<unsigned long long> +ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) { +  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, +                 Locker::FreeLock); + +  if (!m_object_instance_sp) +    return llvm::None; + +  if (!m_object_instance_sp) +    return llvm::None; +  PythonObject implementor(PyRefType::Borrowed, +                           (PyObject *)m_object_instance_sp->GetValue()); + +  if (!implementor.IsAllocated()) +    return llvm::None; + +  PythonObject pmeth( +      PyRefType::Owned, +      PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  if (!pmeth.IsAllocated()) +    return llvm::None; + +  if (PyCallable_Check(pmeth.get()) == 0) { +    if (PyErr_Occurred()) +      PyErr_Clear(); +    return llvm::None; +  } + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  PythonObject py_return(PyRefType::Owned, +                         PyObject_CallMethod(implementor.get(), +                                             method_name.str().c_str(), +                                             nullptr)); + +  if (PyErr_Occurred()) { +    PyErr_Print(); +    PyErr_Clear(); +  } + +  if (!py_return.get()) +    return llvm::None; + +  llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong(); +  // FIXME: Handle error. +  if (!size) +    return llvm::None; + +  return *size; +} + +lldb::MemoryRegionInfoSP +ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( +    lldb::addr_t address) { +  // TODO: Implement +  return nullptr; +} + +StructuredData::DictionarySP +ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { +  // TODO: Implement +  return nullptr; +} + +StructuredData::DictionarySP +ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { +  // TODO: Implement +  return nullptr; +} + +lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( +    lldb::addr_t address, size_t size, Status &error) { +  Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, +                 Locker::FreeLock); + +  auto error_with_message = [&error](llvm::StringRef message) { +    error.SetErrorString(message); +    return nullptr; +  }; + +  static char callee_name[] = "read_memory_at_address"; +  std::string param_format = GetPythonValueFormatString(address); +  param_format += GetPythonValueFormatString(size); + +  if (!m_object_instance_sp) +    return error_with_message("Python object ill-formed."); + +  if (!m_object_instance_sp) +    return error_with_message("Python method not callable."); + +  PythonObject implementor(PyRefType::Borrowed, +                           (PyObject *)m_object_instance_sp->GetValue()); + +  if (!implementor.IsAllocated()) +    return error_with_message("Python implementor not allocated."); + +  PythonObject pmeth(PyRefType::Owned, +                     PyObject_GetAttrString(implementor.get(), callee_name)); + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  if (!pmeth.IsAllocated()) +    return error_with_message("Python method not allocated."); + +  if (PyCallable_Check(pmeth.get()) == 0) { +    if (PyErr_Occurred()) +      PyErr_Clear(); +    return error_with_message("Python method not callable."); +  } + +  if (PyErr_Occurred()) +    PyErr_Clear(); + +  PythonObject py_return(PyRefType::Owned, +                         PyObject_CallMethod(implementor.get(), callee_name, +                                             param_format.c_str(), address, +                                             size)); + +  if (PyErr_Occurred()) { +    PyErr_Print(); +    PyErr_Clear(); +    return error_with_message("Python method could not be called."); +  } + +  if (PyObject *py_ret_ptr = py_return.get()) { +    lldb::SBData *sb_data = +        (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr); + +    if (!sb_data) +      return error_with_message( +          "Couldn't cast lldb::SBData to lldb::DataExtractor."); + +    return m_interpreter.GetDataExtractorFromSBData(*sb_data); +  } + +  return error_with_message("Returned object is null."); +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() { +  // TODO: Implement +  return nullptr; +} + +lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { +  llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id"); +  return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid; +} + +bool ScriptedProcessPythonInterface::IsAlive() { +  llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive"); + +  if (!is_alive) +    return false; + +  return static_cast<bool>(*is_alive); +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h new file mode 100644 index 000000000000..30cb5a882af2 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -0,0 +1,66 @@ +//===-- ScriptedProcessPythonInterface.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "lldb/Interpreter/ScriptedProcessInterface.h" + +namespace lldb_private { +class ScriptInterpreterPythonImpl; +class ScriptedProcessPythonInterface : public ScriptedProcessInterface { +public: +  ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter) +      : ScriptedProcessInterface(), m_interpreter(interpreter) {} + +  StructuredData::GenericSP +  CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp, +                     StructuredData::DictionarySP args_sp) override; + +  Status Launch() override; + +  Status Resume() override; + +  bool ShouldStop() override; + +  Status Stop() override; + +  lldb::MemoryRegionInfoSP +  GetMemoryRegionContainingAddress(lldb::addr_t address) override; + +  StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; + +  StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override; + +  lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, +                                            Status &error) override; + +  StructuredData::DictionarySP GetLoadedImages() override; + +  lldb::pid_t GetProcessID() override; + +  bool IsAlive() override; + +protected: +  llvm::Optional<unsigned long long> +  GetGenericInteger(llvm::StringRef method_name); +  Status GetStatusFromMethod(llvm::StringRef method_name); + +private: +  // The lifetime is managed by the ScriptInterpreter +  ScriptInterpreterPythonImpl &m_interpreter; +  StructuredData::GenericSP m_object_instance_sp; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H | 
