Index: lldb/trunk/source/API/SBHostOS.cpp =================================================================== --- lldb/trunk/source/API/SBHostOS.cpp +++ lldb/trunk/source/API/SBHostOS.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_DISABLE_PYTHON -#include "Plugins/ScriptInterpreter/Python/lldb-python.h" -#endif - #include "SBReproducerPrivate.h" #include "lldb/API/SBError.h" #include "lldb/API/SBHostOS.h" Index: lldb/trunk/source/API/SystemInitializerFull.cpp =================================================================== --- lldb/trunk/source/API/SystemInitializerFull.cpp +++ lldb/trunk/source/API/SystemInitializerFull.cpp @@ -6,10 +6,6 @@ // //===----------------------------------------------------------------------===// -#if !defined(LLDB_DISABLE_PYTHON) -#include "Plugins/ScriptInterpreter/Python/lldb-python.h" -#endif - #include "SystemInitializerFull.h" #include "lldb/API/SBCommandInterpreter.h" Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h =================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -15,21 +15,17 @@ #else -#include -#include -#include - -#include "PythonDataObjects.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/IOHandler.h" -#include "lldb/Host/Terminal.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/lldb-private.h" -class IOHandlerPythonInterpreter; +#include +#include +#include namespace lldb_private { - +/// Abstract interface for the Python script interpreter. class ScriptInterpreterPython : public ScriptInterpreter, public IOHandlerDelegateMultiline { public: @@ -40,408 +36,22 @@ } }; - friend class ::IOHandlerPythonInterpreter; - - ScriptInterpreterPython(CommandInterpreter &interpreter); - - ~ScriptInterpreterPython() override; - - bool Interrupt() override; - - bool ExecuteOneLine( - llvm::StringRef command, CommandReturnObject *result, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - void ExecuteInterpreterLoop() override; - - bool ExecuteOneLineWithReturn( - llvm::StringRef in_string, - ScriptInterpreter::ScriptReturnType return_type, void *ret_value, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - lldb_private::Status ExecuteMultipleLines( - const char *in_string, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - Status - ExportFunctionDefinitionToInterpreter(StringList &function_def) override; - - bool GenerateTypeScriptFunction(StringList &input, std::string &output, - const void *name_token = nullptr) override; - - bool GenerateTypeSynthClass(StringList &input, std::string &output, - const void *name_token = nullptr) override; - - bool GenerateTypeSynthClass(const char *oneliner, std::string &output, - const void *name_token = nullptr) override; - - // use this if the function code is just a one-liner script - bool GenerateTypeScriptFunction(const char *oneliner, std::string &output, - const void *name_token = nullptr) override; - - bool GenerateScriptAliasFunction(StringList &input, - std::string &output) override; - - StructuredData::ObjectSP - CreateSyntheticScriptedProvider(const char *class_name, - lldb::ValueObjectSP valobj) override; - - StructuredData::GenericSP - CreateScriptCommandObject(const char *class_name) override; - - StructuredData::ObjectSP - CreateScriptedThreadPlan(const char *class_name, - lldb::ThreadPlanSP thread_plan) override; - - bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, - Event *event, - bool &script_error) override; - - bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, - Event *event, bool &script_error) override; - - bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, - bool &script_error) override; - - lldb::StateType - ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, - bool &script_error) override; - - StructuredData::GenericSP - CreateScriptedBreakpointResolver(const char *class_name, - StructuredDataImpl *args_data, - lldb::BreakpointSP &bkpt_sp) override; - bool - ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP - implementor_sp, - SymbolContext *sym_ctx) override; - - lldb::SearchDepth - ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP - implementor_sp) override; - - StructuredData::GenericSP - CreateFrameRecognizer(const char *class_name) override; - - lldb::ValueObjectListSP - GetRecognizedArguments(const StructuredData::ObjectSP &implementor, - lldb::StackFrameSP frame_sp) override; - - StructuredData::GenericSP - OSPlugin_CreatePluginObject(const char *class_name, - lldb::ProcessSP process_sp) override; - - StructuredData::DictionarySP - OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::ArraySP - OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::StringSP - OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t thread_id) override; - - StructuredData::DictionarySP - OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, - lldb::tid_t tid, lldb::addr_t context) override; - - StructuredData::ObjectSP - LoadPluginModule(const FileSpec &file_spec, - lldb_private::Status &error) override; - - StructuredData::DictionarySP - GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, - const char *setting_name, - lldb_private::Status &error) override; - - size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, - uint32_t max) override; - - lldb::ValueObjectSP - GetChildAtIndex(const StructuredData::ObjectSP &implementor, - uint32_t idx) override; - - int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, - const char *child_name) override; - - bool UpdateSynthProviderInstance( - const StructuredData::ObjectSP &implementor) override; - - bool MightHaveChildrenSynthProviderInstance( - const StructuredData::ObjectSP &implementor) override; - - lldb::ValueObjectSP - GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; - - ConstString - GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override; - - bool - RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, - Status &error, - const lldb_private::ExecutionContext &exe_ctx) override; - - bool RunScriptBasedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, Status &error, - const lldb_private::ExecutionContext &exe_ctx) override; - - Status GenerateFunction(const char *signature, - const StringList &input) override; - - Status GenerateBreakpointCommandCallbackData(StringList &input, - std::string &output) override; - - bool GenerateWatchpointCommandCallbackData(StringList &input, - std::string &output) override; - - static bool BreakpointCallbackFunction(void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - static bool WatchpointCallbackFunction(void *baton, - StoppointCallbackContext *context, - lldb::user_id_t watch_id); - - bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, - StructuredData::ObjectSP &callee_wrapper_sp, - const TypeSummaryOptions &options, - std::string &retval) override; - - void Clear() override; - - bool GetDocumentationForItem(const char *item, std::string &dest) override; - - bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) override; - - uint32_t - GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; + ScriptInterpreterPython(CommandInterpreter &interpreter) + : ScriptInterpreter(interpreter, lldb::eScriptLanguagePython), + IOHandlerDelegateMultiline("DONE") {} - bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) override; - - bool CheckObjectExists(const char *name) override { - if (!name || !name[0]) - return false; - std::string temp; - return GetDocumentationForItem(name, temp); - } - - bool RunScriptFormatKeyword(const char *impl_function, Process *process, - std::string &output, Status &error) override; - - bool RunScriptFormatKeyword(const char *impl_function, Thread *thread, - std::string &output, Status &error) override; - - bool RunScriptFormatKeyword(const char *impl_function, Target *target, - std::string &output, Status &error) override; - - bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame, - std::string &output, Status &error) override; - - bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value, - std::string &output, Status &error) override; - - bool - LoadScriptingModule(const char *filename, bool can_reload, bool init_session, - lldb_private::Status &error, - StructuredData::ObjectSP *module_sp = nullptr) override; - - bool IsReservedWord(const char *word) override; - - std::unique_ptr AcquireInterpreterLock() override; - - void CollectDataForBreakpointCommandCallback( - std::vector &bp_options_vec, - CommandReturnObject &result) override; - - void - CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, - CommandReturnObject &result) override; - - /// Set the callback body text into the callback for the breakpoint. - Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, - const char *callback_body) override; - - void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options, - const char *function_name) override; - - /// This one is for deserialization: - Status SetBreakpointCommandCallback( - BreakpointOptions *bp_options, - std::unique_ptr &data_up) override; - - /// Set a one-liner as the callback for the watchpoint. - void SetWatchpointCommandCallback(WatchpointOptions *wp_options, - const char *oneliner) override; - - StringList ReadCommandInputFromUser(FILE *in_file); - - void ResetOutputFileHandle(FILE *new_fh) override; - - const char *GetDictionaryName() { return m_dictionary_name.c_str(); } - - PyThreadState *GetThreadState() { return m_command_thread_state; } - - void SetThreadState(PyThreadState *s) { - if (s) - m_command_thread_state = s; - } - - //---------------------------------------------------------------------- - // IOHandlerDelegate - //---------------------------------------------------------------------- - void IOHandlerActivated(IOHandler &io_handler, bool interactive) override; - - void IOHandlerInputComplete(IOHandler &io_handler, - std::string &data) override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ static void Initialize(); - static void Terminate(); - - static lldb::ScriptInterpreterSP - CreateInstance(CommandInterpreter &interpreter); - static lldb_private::ConstString GetPluginNameStatic(); - static const char *GetPluginDescriptionStatic(); - static FileSpec GetPythonDir(); - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - - class Locker : public ScriptInterpreterLocker { - public: - enum OnEntry { - AcquireLock = 0x0001, - InitSession = 0x0002, - InitGlobals = 0x0004, - NoSTDIN = 0x0008 - }; - - enum OnLeave { - FreeLock = 0x0001, - FreeAcquiredLock = 0x0002, // do not free the lock if we already held it - // when calling constructor - TearDownSession = 0x0004 - }; - - Locker(ScriptInterpreterPython *py_interpreter = nullptr, - uint16_t on_entry = AcquireLock | InitSession, - uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr, - FILE *out = nullptr, FILE *err = nullptr); - - ~Locker() override; - - private: - bool DoAcquireLock(); - - bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); - - bool DoFreeLock(); - - bool DoTearDownSession(); - - static void ReleasePythonLock(); - - bool m_teardown_session; - ScriptInterpreterPython *m_python_interpreter; - // FILE* m_tmp_fh; - PyGILState_STATE m_GILState; - }; - protected: - static void InitializePrivate(); - - class SynchronicityHandler { - private: - lldb::DebuggerSP m_debugger_sp; - ScriptedCommandSynchronicity m_synch_wanted; - bool m_old_asynch; - - public: - SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity); - - ~SynchronicityHandler(); - }; - - enum class AddLocation { Beginning, End }; - - static void AddToSysPath(AddLocation location, std::string path); - static void ComputePythonDirForApple(llvm::SmallVectorImpl &path); static void ComputePythonDirForPosix(llvm::SmallVectorImpl &path); static void ComputePythonDirForWindows(llvm::SmallVectorImpl &path); - - bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); - - void LeaveSession(); - - void SaveTerminalState(int fd); - - void RestoreTerminalState(); - - uint32_t IsExecutingPython() const { return m_lock_count > 0; } - - uint32_t IncrementLockCount() { return ++m_lock_count; } - - uint32_t DecrementLockCount() { - if (m_lock_count > 0) - --m_lock_count; - return m_lock_count; - } - - enum ActiveIOHandler { - eIOHandlerNone, - eIOHandlerBreakpoint, - eIOHandlerWatchpoint - }; - - PythonObject &GetMainModule(); - - PythonDictionary &GetSessionDictionary(); - - PythonDictionary &GetSysModuleDictionary(); - - bool GetEmbeddedInterpreterModuleObjects(); - - bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file, - const char *mode); - - PythonFile m_saved_stdin; - PythonFile m_saved_stdout; - PythonFile m_saved_stderr; - PythonObject m_main_module; - PythonDictionary m_session_dict; - PythonDictionary m_sys_module_dict; - PythonObject m_run_one_line_function; - PythonObject m_run_one_line_str_global; - std::string m_dictionary_name; - TerminalState m_terminal_state; - ActiveIOHandler m_active_io_handler; - bool m_session_is_active; - bool m_pty_slave_is_open; - bool m_valid_session; - uint32_t m_lock_count; - PyThreadState *m_command_thread_state; }; - } // namespace lldb_private #endif // LLDB_DISABLE_PYTHON - #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp =================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -17,10 +17,10 @@ #include "PythonDataObjects.h" #include "PythonExceptionState.h" -#include "ScriptInterpreterPython.h" +#include "ScriptInterpreterPythonImpl.h" -#include "lldb/API/SBValue.h" #include "lldb/API/SBFrame.h" +#include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/Communication.h" @@ -55,8 +55,6 @@ using namespace lldb; using namespace lldb_private; -#ifndef LLDB_DISABLE_PYTHON - // Defined in the SWIG source file #if PY_MAJOR_VERSION >= 3 extern "C" PyObject *PyInit__lldb(void); @@ -189,8 +187,6 @@ LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, const lldb::TargetSP &target_sp); -#endif - static bool g_initialized = false; namespace { @@ -252,12 +248,13 @@ Py_SetPythonHome(g_python_home); #else #if defined(__APPLE__) && PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7 - // For Darwin, the only Python version supported is the one shipped in the OS - // OS and linked with lldb. Other installation of Python may have higher + // For Darwin, the only Python version supported is the one shipped in the + // OS OS and linked with lldb. Other installation of Python may have higher // priorities in the path, overriding PYTHONHOME and causing // problems/incompatibilities. In order to avoid confusion, always hardcode // the PythonHome to be right, as it's not going to change. - static char path[] = "/System/Library/Frameworks/Python.framework/Versions/2.7"; + static char path[] = + "/System/Library/Frameworks/Python.framework/Versions/2.7"; Py_SetPythonHome(path); #endif #endif @@ -271,7 +268,7 @@ // executed instead of unlocking GIL with `PyEval_SaveThread`. When // an another thread calls `PyGILState_Ensure` it would get stuck in deadlock. #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION > 3) -// The only case we should go further and acquire the GIL: it is unlocked. + // The only case we should go further and acquire the GIL: it is unlocked. if (PyGILState_Check()) return; #endif @@ -294,11 +291,98 @@ PyGILState_STATE m_gil_state; bool m_was_already_initialized; }; +} // namespace + +void ScriptInterpreterPython::ComputePythonDirForApple( + llvm::SmallVectorImpl &path) { + auto style = llvm::sys::path::Style::posix; + + llvm::StringRef path_ref(path.begin(), path.size()); + auto rbegin = llvm::sys::path::rbegin(path_ref, style); + auto rend = llvm::sys::path::rend(path_ref); + auto framework = std::find(rbegin, rend, "LLDB.framework"); + if (framework == rend) { + ComputePythonDirForPosix(path); + return; + } + path.resize(framework - rend); + llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python"); +} + +void ScriptInterpreterPython::ComputePythonDirForPosix( + llvm::SmallVectorImpl &path) { + auto style = llvm::sys::path::Style::posix; +#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) + // Build the path by backing out of the lib dir, then building with whatever + // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL + // x86_64). + llvm::sys::path::remove_filename(path, style); + llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR); +#else + llvm::sys::path::append(path, style, + "python" + llvm::Twine(PY_MAJOR_VERSION) + "." + + llvm::Twine(PY_MINOR_VERSION), + "site-packages"); +#endif +} + +void ScriptInterpreterPython::ComputePythonDirForWindows( + llvm::SmallVectorImpl &path) { + auto style = llvm::sys::path::Style::windows; + llvm::sys::path::remove_filename(path, style); + llvm::sys::path::append(path, style, "lib", "site-packages"); + + // This will be injected directly through FileSpec.GetDirectory().SetString(), + // so we need to normalize manually. + std::replace(path.begin(), path.end(), '\\', '/'); } -ScriptInterpreterPython::Locker::Locker(ScriptInterpreterPython *py_interpreter, - uint16_t on_entry, uint16_t on_leave, - FILE *in, FILE *out, FILE *err) +FileSpec ScriptInterpreterPython::GetPythonDir() { + static FileSpec g_spec = []() { + FileSpec spec = HostInfo::GetShlibDir(); + if (!spec) + return FileSpec(); + llvm::SmallString<64> path; + spec.GetPath(path); + +#if defined(__APPLE__) + ComputePythonDirForApple(path); +#elif defined(_WIN32) + ComputePythonDirForWindows(path); +#else + ComputePythonDirForPosix(path); +#endif + spec.GetDirectory().SetString(path); + return spec; + }(); + return g_spec; +} + +lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() { + static ConstString g_name("script-python"); + return g_name; +} + +const char *ScriptInterpreterPython::GetPluginDescriptionStatic() { + return "Embedded Python interpreter"; +} + +void ScriptInterpreterPython::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + lldb::eScriptLanguagePython, + ScriptInterpreterPythonImpl::CreateInstance); + }); +} + +void ScriptInterpreterPython::Terminate() {} + +ScriptInterpreterPythonImpl::Locker::Locker( + ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry, + uint16_t on_leave, FILE *in, FILE *out, FILE *err) : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { @@ -311,7 +395,7 @@ } } -bool ScriptInterpreterPython::Locker::DoAcquireLock() { +bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); m_GILState = PyGILState_Ensure(); LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked", @@ -327,15 +411,15 @@ return true; } -bool ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, - FILE *in, FILE *out, - FILE *err) { +bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags, + FILE *in, FILE *out, + FILE *err) { if (!m_python_interpreter) return false; return m_python_interpreter->EnterSession(on_entry_flags, in, out, err); } -bool ScriptInterpreterPython::Locker::DoFreeLock() { +bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked", m_GILState == PyGILState_UNLOCKED ? "un" : ""); @@ -344,23 +428,22 @@ return true; } -bool ScriptInterpreterPython::Locker::DoTearDownSession() { +bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() { if (!m_python_interpreter) return false; m_python_interpreter->LeaveSession(); return true; } -ScriptInterpreterPython::Locker::~Locker() { +ScriptInterpreterPythonImpl::Locker::~Locker() { if (m_teardown_session) DoTearDownSession(); DoFreeLock(); } -ScriptInterpreterPython::ScriptInterpreterPython( +ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl( CommandInterpreter &interpreter) - : ScriptInterpreter(interpreter, eScriptLanguagePython), - IOHandlerDelegateMultiline("DONE"), m_saved_stdin(), m_saved_stdout(), + : ScriptInterpreterPython(interpreter), m_saved_stdin(), m_saved_stdout(), m_saved_stderr(), m_main_module(), m_session_dict(PyInitialValue::Invalid), m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), @@ -376,8 +459,7 @@ StreamString run_string; run_string.Printf("%s = dict()", m_dictionary_name.c_str()); - Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); + Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock); PyRun_SimpleString(run_string.GetData()); run_string.Clear(); @@ -418,7 +500,7 @@ PyRun_SimpleString(run_string.GetData()); } -ScriptInterpreterPython::~ScriptInterpreterPython() { +ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() { // the session dictionary may hold objects with complex state which means // that they may need to be torn down with some level of smarts and that, in // turn, requires a valid thread state force Python to procure itself such a @@ -429,104 +511,14 @@ PyGILState_Release(gil_state); } -void ScriptInterpreterPython::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - lldb::eScriptLanguagePython, CreateInstance); - }); -} - -void ScriptInterpreterPython::Terminate() {} - -lldb::ScriptInterpreterSP -ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter) { - return std::make_shared(interpreter); -} - -lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() { - static ConstString g_name("script-python"); - return g_name; -} - -const char *ScriptInterpreterPython::GetPluginDescriptionStatic() { - return "Embedded Python interpreter"; -} - -void ScriptInterpreterPython::ComputePythonDirForApple( - llvm::SmallVectorImpl &path) { - auto style = llvm::sys::path::Style::posix; - - llvm::StringRef path_ref(path.begin(), path.size()); - auto rbegin = llvm::sys::path::rbegin(path_ref, style); - auto rend = llvm::sys::path::rend(path_ref); - auto framework = std::find(rbegin, rend, "LLDB.framework"); - if (framework == rend) { - ComputePythonDirForPosix(path); - return; - } - path.resize(framework - rend); - llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python"); -} - -void ScriptInterpreterPython::ComputePythonDirForPosix( - llvm::SmallVectorImpl &path) { - auto style = llvm::sys::path::Style::posix; -#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) - // Build the path by backing out of the lib dir, then building with whatever - // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL - // x86_64). - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR); -#else - llvm::sys::path::append(path, style, - "python" + llvm::Twine(PY_MAJOR_VERSION) + "." + - llvm::Twine(PY_MINOR_VERSION), - "site-packages"); -#endif -} - -void ScriptInterpreterPython::ComputePythonDirForWindows( - llvm::SmallVectorImpl &path) { - auto style = llvm::sys::path::Style::windows; - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, "lib", "site-packages"); - - // This will be injected directly through FileSpec.GetDirectory().SetString(), - // so we need to normalize manually. - std::replace(path.begin(), path.end(), '\\', '/'); -} - -FileSpec ScriptInterpreterPython::GetPythonDir() { - static FileSpec g_spec = []() { - FileSpec spec = HostInfo::GetShlibDir(); - if (!spec) - return FileSpec(); - llvm::SmallString<64> path; - spec.GetPath(path); - -#if defined(__APPLE__) - ComputePythonDirForApple(path); -#elif defined(_WIN32) - ComputePythonDirForWindows(path); -#else - ComputePythonDirForPosix(path); -#endif - spec.GetDirectory().SetString(path); - return spec; - }(); - return g_spec; -} - -lldb_private::ConstString ScriptInterpreterPython::GetPluginName() { +lldb_private::ConstString ScriptInterpreterPythonImpl::GetPluginName() { return GetPluginNameStatic(); } -uint32_t ScriptInterpreterPython::GetPluginVersion() { return 1; } +uint32_t ScriptInterpreterPythonImpl::GetPluginVersion() { return 1; } -void ScriptInterpreterPython::IOHandlerActivated(IOHandler &io_handler, bool interactive) { +void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler, + bool interactive) { const char *instructions = nullptr; switch (m_active_io_handler) { @@ -554,8 +546,8 @@ } } -void ScriptInterpreterPython::IOHandlerInputComplete(IOHandler &io_handler, - std::string &data) { +void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) { io_handler.SetIsDone(true); bool batch_mode = m_interpreter.GetBatchCommandMode(); @@ -580,7 +572,7 @@ auto baton_sp = std::make_shared( std::move(data_up)); bp_options->SetCallback( - ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); + ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); if (error_sp) { @@ -602,7 +594,7 @@ auto baton_sp = std::make_shared(std::move(data_up)); wp_options->SetCallback( - ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); + ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } else if (!batch_mode) { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); if (error_sp) { @@ -615,9 +607,14 @@ } } -void ScriptInterpreterPython::ResetOutputFileHandle(FILE *fh) {} +lldb::ScriptInterpreterSP +ScriptInterpreterPythonImpl::CreateInstance(CommandInterpreter &interpreter) { + return std::make_shared(interpreter); +} + +void ScriptInterpreterPythonImpl::ResetOutputFileHandle(FILE *fh) {} -void ScriptInterpreterPython::SaveTerminalState(int fd) { +void ScriptInterpreterPythonImpl::SaveTerminalState(int fd) { // Python mucks with the terminal state of STDIN. If we can possibly avoid // this by setting the file handles up correctly prior to entering the // interpreter we should. For now we save and restore the terminal state on @@ -625,7 +622,7 @@ m_terminal_state.Save(fd, false); } -void ScriptInterpreterPython::RestoreTerminalState() { +void ScriptInterpreterPythonImpl::RestoreTerminalState() { // Python mucks with the terminal state of STDIN. If we can possibly avoid // this by setting the file handles up correctly prior to entering the // interpreter we should. For now we save and restore the terminal state on @@ -633,10 +630,10 @@ m_terminal_state.Restore(); } -void ScriptInterpreterPython::LeaveSession() { +void ScriptInterpreterPythonImpl::LeaveSession() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (log) - log->PutCString("ScriptInterpreterPython::LeaveSession()"); + log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()"); // checking that we have a valid thread state - since we use our own // threading and locking in some (rare) cases during cleanup Python may end @@ -668,9 +665,9 @@ m_session_is_active = false; } -bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name, - PythonFile &save_file, - const char *mode) { +bool ScriptInterpreterPythonImpl::SetStdHandle(File &file, const char *py_name, + PythonFile &save_file, + const char *mode) { if (file.IsValid()) { // Flush the file before giving it to python to avoid interleaved output. file.Flush(); @@ -688,15 +685,15 @@ return false; } -bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in, - FILE *out, FILE *err) { +bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, + FILE *in, FILE *out, FILE *err) { // If we have already entered the session, without having officially 'left' // it, then there is no need to 'enter' it again. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (m_session_is_active) { if (log) log->Printf( - "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags); return false; @@ -704,7 +701,8 @@ if (log) log->Printf( - "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 + ")", on_entry_flags); m_session_is_active = true; @@ -777,13 +775,13 @@ return true; } -PythonObject &ScriptInterpreterPython::GetMainModule() { +PythonObject &ScriptInterpreterPythonImpl::GetMainModule() { if (!m_main_module.IsValid()) m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); return m_main_module; } -PythonDictionary &ScriptInterpreterPython::GetSessionDictionary() { +PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() { if (m_session_dict.IsValid()) return m_session_dict; @@ -801,7 +799,7 @@ return m_session_dict; } -PythonDictionary &ScriptInterpreterPython::GetSysModuleDictionary() { +PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() { if (m_sys_module_dict.IsValid()) return m_sys_module_dict; @@ -828,7 +826,7 @@ return sstr.GetString(); } -bool ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects() { +bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() { if (m_run_one_line_function.IsValid()) return true; @@ -858,7 +856,7 @@ } } -bool ScriptInterpreterPython::ExecuteOneLine( +bool ScriptInterpreterPythonImpl::ExecuteOneLine( llvm::StringRef command, CommandReturnObject *result, const ExecuteScriptOptions &options) { std::string command_str = command.str(); @@ -879,7 +877,7 @@ StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm( - "lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); + "lldb.ScriptInterpreterPythonImpl.ExecuteOneLine.comm"); bool join_read_thread = false; if (options.GetEnableIO()) { if (result) { @@ -952,15 +950,11 @@ // happen. Locker locker( this, - ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() - ? ScriptInterpreterPython::Locker::InitGlobals - : 0) | + Locker::AcquireLock | Locker::InitSession | + (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession, - in_file, out_file, err_file); + Locker::FreeAcquiredLock | Locker::TearDownSession, in_file, out_file, + err_file); // Find the correct script interpreter dictionary in the main module. PythonDictionary &session_dict = GetSessionDictionary(); @@ -1020,78 +1014,7 @@ return false; } -class IOHandlerPythonInterpreter : public IOHandler { -public: - IOHandlerPythonInterpreter(Debugger &debugger, - ScriptInterpreterPython *python) - : IOHandler(debugger, IOHandler::Type::PythonInterpreter), - m_python(python) {} - - ~IOHandlerPythonInterpreter() override {} - - ConstString GetControlSequence(char ch) override { - if (ch == 'd') - return ConstString("quit()\n"); - return ConstString(); - } - - void Run() override { - if (m_python) { - int stdin_fd = GetInputFD(); - if (stdin_fd >= 0) { - Terminal terminal(stdin_fd); - TerminalState terminal_state; - const bool is_a_tty = terminal.IsATerminal(); - - if (is_a_tty) { - terminal_state.Save(stdin_fd, false); - terminal.SetCanonical(false); - terminal.SetEcho(true); - } - - ScriptInterpreterPython::Locker locker( - m_python, ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - ScriptInterpreterPython::Locker::InitGlobals, - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession); - - // The following call drops into the embedded interpreter loop and - // stays there until the user chooses to exit from the Python - // interpreter. This embedded interpreter will, as any Python code that - // performs I/O, unlock the GIL before a system call that can hang, and - // lock it when the syscall has returned. - - // We need to surround the call to the embedded interpreter with calls - // to PyGILState_Ensure and PyGILState_Release (using the Locker - // above). This is because Python has a global lock which must be held - // whenever we want to touch any Python objects. Otherwise, if the user - // calls Python code, the interpreter state will be off, and things - // could hang (it's happened before). - - StreamString run_string; - run_string.Printf("run_python_interpreter (%s)", - m_python->GetDictionaryName()); - PyRun_SimpleString(run_string.GetData()); - - if (is_a_tty) - terminal_state.Restore(); - } - } - SetIsDone(true); - } - - void Cancel() override {} - - bool Interrupt() override { return m_python->Interrupt(); } - - void GotEOF() override {} - -protected: - ScriptInterpreterPython *m_python; -}; - -void ScriptInterpreterPython::ExecuteInterpreterLoop() { +void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); @@ -1112,7 +1035,7 @@ } } -bool ScriptInterpreterPython::Interrupt() { +bool ScriptInterpreterPythonImpl::Interrupt() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (IsExecutingPython()) { @@ -1124,29 +1047,27 @@ PyThreadState_Swap(state); int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); if (log) - log->Printf("ScriptInterpreterPython::Interrupt() sending " + log->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); return true; } } if (log) - log->Printf("ScriptInterpreterPython::Interrupt() python code not running, " - "can't interrupt"); + log->Printf( + "ScriptInterpreterPythonImpl::Interrupt() python code not running, " + "can't interrupt"); return false; } -bool ScriptInterpreterPython::ExecuteOneLineWithReturn( +bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { - Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() - ? ScriptInterpreterPython::Locker::InitGlobals - : 0) | - Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession); + Locker locker(this, + Locker::AcquireLock | Locker::InitSession | + (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | + Locker::NoSTDIN, + Locker::FreeAcquiredLock | Locker::TearDownSession); PythonObject py_return; PythonObject &main_module = GetMainModule(); @@ -1291,18 +1212,15 @@ return ret_success; } -Status ScriptInterpreterPython::ExecuteMultipleLines( +Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( const char *in_string, const ExecuteScriptOptions &options) { Status error; - Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() - ? ScriptInterpreterPython::Locker::InitGlobals - : 0) | - Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession); + Locker locker(this, + Locker::AcquireLock | Locker::InitSession | + (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | + Locker::NoSTDIN, + Locker::FreeAcquiredLock | Locker::TearDownSession); PythonObject return_value; PythonObject &main_module = GetMainModule(); @@ -1352,7 +1270,7 @@ return error; } -void ScriptInterpreterPython::CollectDataForBreakpointCommandCallback( +void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( std::vector &bp_options_vec, CommandReturnObject &result) { m_active_io_handler = eIOHandlerBreakpoint; @@ -1360,13 +1278,13 @@ &bp_options_vec); } -void ScriptInterpreterPython::CollectDataForWatchpointCommandCallback( +void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback( WatchpointOptions *wp_options, CommandReturnObject &result) { m_active_io_handler = eIOHandlerWatchpoint; m_interpreter.GetPythonCommandsFromIOHandler(" ", *this, true, wp_options); } -void ScriptInterpreterPython::SetBreakpointCommandCallbackFunction( +void ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( BreakpointOptions *bp_options, const char *function_name) { // For now just cons up a oneliner that calls the provided function. std::string oneliner("return "); @@ -1376,7 +1294,7 @@ bp_options, oneliner.c_str()); } -Status ScriptInterpreterPython::SetBreakpointCommandCallback( +Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( BreakpointOptions *bp_options, std::unique_ptr &cmd_data_up) { Status error; @@ -1387,13 +1305,13 @@ } auto baton_sp = std::make_shared(std::move(cmd_data_up)); - bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction, - baton_sp); + bp_options->SetCallback( + ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); return error; } // Set a Python one-liner as the callback for the breakpoint. -Status ScriptInterpreterPython::SetBreakpointCommandCallback( +Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { auto data_up = llvm::make_unique(); @@ -1408,15 +1326,15 @@ if (error.Success()) { auto baton_sp = std::make_shared(std::move(data_up)); - bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction, - baton_sp); + bp_options->SetCallback( + ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); return error; } else return error; } // Set a Python one-liner as the callback for the watchpoint. -void ScriptInterpreterPython::SetWatchpointCommandCallback( +void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( WatchpointOptions *wp_options, const char *oneliner) { auto data_up = llvm::make_unique(); @@ -1432,14 +1350,14 @@ data_up->script_source)) { auto baton_sp = std::make_shared(std::move(data_up)); - wp_options->SetCallback(ScriptInterpreterPython::WatchpointCallbackFunction, - baton_sp); + wp_options->SetCallback( + ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } return; } -Status ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter( +Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( StringList &function_def) { // Convert StringList to one long, newline delimited, const char *. std::string function_def_string(function_def.CopyList()); @@ -1450,8 +1368,8 @@ return error; } -Status ScriptInterpreterPython::GenerateFunction(const char *signature, - const StringList &input) { +Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature, + const StringList &input) { Status error; int num_lines = input.GetSize(); if (num_lines == 0) { @@ -1507,7 +1425,7 @@ return error; } -bool ScriptInterpreterPython::GenerateTypeScriptFunction( +bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( StringList &user_input, std::string &output, const void *name_token) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); @@ -1534,7 +1452,7 @@ return true; } -bool ScriptInterpreterPython::GenerateScriptAliasFunction( +bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); @@ -1558,9 +1476,8 @@ return true; } -bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input, - std::string &output, - const void *name_token) { +bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass( + StringList &user_input, std::string &output, const void *name_token) { static uint32_t num_created_classes = 0; user_input.RemoveBlankLines(); int num_lines = user_input.GetSize(); @@ -1603,8 +1520,8 @@ return true; } -StructuredData::GenericSP ScriptInterpreterPython::CreateFrameRecognizer( - const char *class_name) { +StructuredData::GenericSP +ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); @@ -1620,20 +1537,23 @@ return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } -lldb::ValueObjectListSP ScriptInterpreterPython::GetRecognizedArguments( +lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( const StructuredData::ObjectSP &os_plugin_object_sp, lldb::StackFrameSP frame_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - if (!os_plugin_object_sp) return ValueObjectListSP(); + if (!os_plugin_object_sp) + return ValueObjectListSP(); StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) return nullptr; + if (!generic) + return nullptr; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); - if (!implementor.IsAllocated()) return ValueObjectListSP(); + if (!implementor.IsAllocated()) + return ValueObjectListSP(); PythonObject py_return(PyRefType::Owned, (PyObject *)LLDBSwigPython_GetRecognizedArguments( @@ -1652,14 +1572,16 @@ lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item); auto valobj_sp = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); - if (valobj_sp) result->Append(valobj_sp); + if (valobj_sp) + result->Append(valobj_sp); } return result; } return ValueObjectListSP(); } -StructuredData::GenericSP ScriptInterpreterPython::OSPlugin_CreatePluginObject( +StructuredData::GenericSP +ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( const char *class_name, lldb::ProcessSP process_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); @@ -1679,7 +1601,7 @@ return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } -StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_RegisterInfo( +StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); @@ -1734,7 +1656,7 @@ return StructuredData::DictionarySP(); } -StructuredData::ArraySP ScriptInterpreterPython::OSPlugin_ThreadsInfo( +StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); @@ -1819,7 +1741,8 @@ template <> const char *GetPythonValueFormatString(float t) { return "f"; } template <> const char *GetPythonValueFormatString(double t) { return "d"; } -StructuredData::StringSP ScriptInterpreterPython::OSPlugin_RegisterContextData( +StructuredData::StringSP +ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); @@ -1875,7 +1798,7 @@ return StructuredData::StringSP(); } -StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_CreateThread( +StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); @@ -1934,7 +1857,7 @@ return StructuredData::DictionarySP(); } -StructuredData::ObjectSP ScriptInterpreterPython::CreateScriptedThreadPlan( +StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( const char *class_name, lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); @@ -1945,8 +1868,8 @@ Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = - static_cast(script_interpreter); + ScriptInterpreterPythonImpl *python_interpreter = + static_cast(script_interpreter); if (!script_interpreter) return StructuredData::ObjectSP(); @@ -1965,7 +1888,7 @@ return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); } -bool ScriptInterpreterPython::ScriptedThreadPlanExplainsStop( +bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop( StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool explains_stop = true; StructuredData::Generic *generic = nullptr; @@ -1982,7 +1905,7 @@ return explains_stop; } -bool ScriptInterpreterPython::ScriptedThreadPlanShouldStop( +bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop( StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool should_stop = true; StructuredData::Generic *generic = nullptr; @@ -1999,7 +1922,7 @@ return should_stop; } -bool ScriptInterpreterPython::ScriptedThreadPlanIsStale( +bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale( StructuredData::ObjectSP implementor_sp, bool &script_error) { bool is_stale = true; StructuredData::Generic *generic = nullptr; @@ -2016,7 +1939,7 @@ return is_stale; } -lldb::StateType ScriptInterpreterPython::ScriptedThreadPlanGetRunState( +lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( StructuredData::ObjectSP implementor_sp, bool &script_error) { bool should_step = false; StructuredData::Generic *generic = nullptr; @@ -2037,9 +1960,8 @@ } StructuredData::GenericSP -ScriptInterpreterPython::CreateScriptedBreakpointResolver( - const char *class_name, - StructuredDataImpl *args_data, +ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( + const char *class_name, StructuredDataImpl *args_data, lldb::BreakpointSP &bkpt_sp) { if (class_name == nullptr || class_name[0] == '\0') @@ -2051,8 +1973,8 @@ Debugger &debugger = bkpt_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = - static_cast(script_interpreter); + ScriptInterpreterPythonImpl *python_interpreter = + static_cast(script_interpreter); if (!script_interpreter) return StructuredData::GenericSP(); @@ -2071,10 +1993,8 @@ return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } -bool -ScriptInterpreterPython::ScriptedBreakpointResolverSearchCallback( - StructuredData::GenericSP implementor_sp, - SymbolContext *sym_ctx) { +bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( + StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) { bool should_continue = false; if (implementor_sp) { @@ -2091,7 +2011,7 @@ } lldb::SearchDepth -ScriptInterpreterPython::ScriptedBreakpointResolverSearchDepth( +ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( StructuredData::GenericSP implementor_sp) { int depth_as_int = lldb::eSearchDepthModule; if (implementor_sp) { @@ -2108,14 +2028,14 @@ return lldb::eSearchDepthModule; if (depth_as_int <= lldb::kLastSearchDepthKind) - return (lldb::SearchDepth) depth_as_int; + return (lldb::SearchDepth)depth_as_int; else return lldb::eSearchDepthModule; } StructuredData::ObjectSP -ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, - lldb_private::Status &error) { +ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, + lldb_private::Status &error) { if (!FileSystem::Instance().Exists(file_spec)) { error.SetErrorString("no such file"); return StructuredData::ObjectSP(); @@ -2130,7 +2050,7 @@ return StructuredData::ObjectSP(); } -StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings( +StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings( StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Status &error) { if (!plugin_module_sp || !target || !setting_name || !setting_name[0]) @@ -2152,7 +2072,7 @@ } StructuredData::ObjectSP -ScriptInterpreterPython::CreateSyntheticScriptedProvider( +ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( const char *class_name, lldb::ValueObjectSP valobj) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); @@ -2169,8 +2089,8 @@ Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = - (ScriptInterpreterPython *)script_interpreter; + ScriptInterpreterPythonImpl *python_interpreter = + (ScriptInterpreterPythonImpl *)script_interpreter; if (!script_interpreter) return StructuredData::ObjectSP(); @@ -2188,7 +2108,7 @@ } StructuredData::GenericSP -ScriptInterpreterPython::CreateScriptCommandObject(const char *class_name) { +ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { DebuggerSP debugger_sp( GetCommandInterpreter().GetDebugger().shared_from_this()); @@ -2210,22 +2130,21 @@ return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } -bool ScriptInterpreterPython::GenerateTypeScriptFunction( +bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( const char *oneliner, std::string &output, const void *name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); return GenerateTypeScriptFunction(input, output, name_token); } -bool ScriptInterpreterPython::GenerateTypeSynthClass(const char *oneliner, - std::string &output, - const void *name_token) { +bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass( + const char *oneliner, std::string &output, const void *name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); return GenerateTypeSynthClass(input, output, name_token); } -Status ScriptInterpreterPython::GenerateBreakpointCommandCallbackData( +Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); @@ -2250,7 +2169,7 @@ return error; } -bool ScriptInterpreterPython::GenerateWatchpointCommandCallbackData( +bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); @@ -2272,7 +2191,7 @@ return true; } -bool ScriptInterpreterPython::GetScriptedSummary( +bool ScriptInterpreterPythonImpl::GetScriptedSummary( const char *python_function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) { @@ -2320,11 +2239,10 @@ return ret_val; } -void ScriptInterpreterPython::Clear() { +void ScriptInterpreterPythonImpl::Clear() { // Release any global variables that might have strong references to // LLDB objects when clearing the python script interpreter. - Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); + Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock); // This may be called as part of Py_Finalize. In that case the modules are // destroyed in random order and we can't guarantee that we can access these. @@ -2333,7 +2251,7 @@ "= None; lldb.thread = None; lldb.frame = None"); } -bool ScriptInterpreterPython::BreakpointCallbackFunction( +bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { CommandDataPython *bp_option_data = (CommandDataPython *)baton; @@ -2351,8 +2269,8 @@ Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = - (ScriptInterpreterPython *)script_interpreter; + ScriptInterpreterPythonImpl *python_interpreter = + (ScriptInterpreterPythonImpl *)script_interpreter; if (!script_interpreter) return true; @@ -2384,7 +2302,7 @@ return true; } -bool ScriptInterpreterPython::WatchpointCallbackFunction( +bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t watch_id) { WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *)baton; @@ -2402,8 +2320,8 @@ Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = - (ScriptInterpreterPython *)script_interpreter; + ScriptInterpreterPythonImpl *python_interpreter = + (ScriptInterpreterPythonImpl *)script_interpreter; if (!script_interpreter) return true; @@ -2432,7 +2350,7 @@ return true; } -size_t ScriptInterpreterPython::CalculateNumChildren( +size_t ScriptInterpreterPythonImpl::CalculateNumChildren( const StructuredData::ObjectSP &implementor_sp, uint32_t max) { if (!implementor_sp) return 0; @@ -2454,7 +2372,7 @@ return ret_val; } -lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex( +lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex( const StructuredData::ObjectSP &implementor_sp, uint32_t idx) { if (!implementor_sp) return lldb::ValueObjectSP(); @@ -2466,7 +2384,6 @@ if (!implementor) return lldb::ValueObjectSP(); - lldb::ValueObjectSP ret_val; { Locker py_lock(this, @@ -2487,7 +2404,7 @@ return ret_val; } -int ScriptInterpreterPython::GetIndexOfChildWithName( +int ScriptInterpreterPythonImpl::GetIndexOfChildWithName( const StructuredData::ObjectSP &implementor_sp, const char *child_name) { if (!implementor_sp) return UINT32_MAX; @@ -2510,7 +2427,7 @@ return ret_val; } -bool ScriptInterpreterPython::UpdateSynthProviderInstance( +bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance( const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; @@ -2533,7 +2450,7 @@ return ret_val; } -bool ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance( +bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance( const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; @@ -2547,7 +2464,6 @@ if (!implementor) return ret_val; - { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); @@ -2558,7 +2474,7 @@ return ret_val; } -lldb::ValueObjectSP ScriptInterpreterPython::GetSyntheticValue( +lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue( const StructuredData::ObjectSP &implementor_sp) { lldb::ValueObjectSP ret_val(nullptr); @@ -2591,7 +2507,7 @@ return ret_val; } -ConstString ScriptInterpreterPython::GetSyntheticTypeName( +ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( const StructuredData::ObjectSP &implementor_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); @@ -2657,10 +2573,9 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, - Process *process, - std::string &output, - Status &error) { +bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( + const char *impl_function, Process *process, std::string &output, + Status &error) { bool ret_val; if (!process) { error.SetErrorString("no process"); @@ -2683,10 +2598,9 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, - Thread *thread, - std::string &output, - Status &error) { +bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( + const char *impl_function, Thread *thread, std::string &output, + Status &error) { bool ret_val; if (!thread) { error.SetErrorString("no thread"); @@ -2709,10 +2623,9 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, - Target *target, - std::string &output, - Status &error) { +bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( + const char *impl_function, Target *target, std::string &output, + Status &error) { bool ret_val; if (!target) { error.SetErrorString("no thread"); @@ -2735,10 +2648,9 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, - StackFrame *frame, - std::string &output, - Status &error) { +bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( + const char *impl_function, StackFrame *frame, std::string &output, + Status &error) { bool ret_val; if (!frame) { error.SetErrorString("no frame"); @@ -2761,10 +2673,9 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, - ValueObject *value, - std::string &output, - Status &error) { +bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( + const char *impl_function, ValueObject *value, std::string &output, + Status &error) { bool ret_val; if (!value) { error.SetErrorString("no value"); @@ -2799,7 +2710,7 @@ return matches; } -bool ScriptInterpreterPython::LoadScriptingModule( +bool ScriptInterpreterPythonImpl::LoadScriptingModule( const char *pathname, bool can_reload, bool init_session, lldb_private::Status &error, StructuredData::ObjectSP *module_sp) { if (!pathname || !pathname[0]) { @@ -2817,9 +2728,10 @@ StreamString command_stream; // Before executing Python code, lock the GIL. - Locker py_lock(this, Locker::AcquireLock | - (init_session ? Locker::InitSession : 0) | - Locker::NoSTDIN, + Locker py_lock(this, + Locker::AcquireLock | + (init_session ? Locker::InitSession : 0) | + Locker::NoSTDIN, Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); namespace fs = llvm::sys::fs; @@ -2885,7 +2797,7 @@ bool was_imported_globally = (ExecuteOneLineWithReturn( command_stream.GetData(), - ScriptInterpreterPython::eScriptReturnTypeBool, &does_contain, + ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, ScriptInterpreter::ExecuteScriptOptions() .SetEnableIO(false) .SetSetLLDBGlobals(false)) && @@ -2949,7 +2861,7 @@ } } -bool ScriptInterpreterPython::IsReservedWord(const char *word) { +bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) { if (!word || !word[0]) return false; @@ -2974,7 +2886,7 @@ return false; } -ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler( +ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler( lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro) : m_debugger_sp(debugger_sp), m_synch_wanted(synchro), m_old_asynch(debugger_sp->GetAsyncExecution()) { @@ -2984,12 +2896,12 @@ m_debugger_sp->SetAsyncExecution(true); } -ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() { +ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() { if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) m_debugger_sp->SetAsyncExecution(m_old_asynch); } -bool ScriptInterpreterPython::RunScriptBasedCommand( +bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( const char *impl_function, llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, @@ -3033,7 +2945,7 @@ return ret_val; } -bool ScriptInterpreterPython::RunScriptBasedCommand( +bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, @@ -3080,8 +2992,8 @@ // in Python, a special attribute __doc__ contains the docstring for an object // (function, method, class, ...) if any is defined Otherwise, the attribute's // value is None -bool ScriptInterpreterPython::GetDocumentationForItem(const char *item, - std::string &dest) { +bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item, + std::string &dest) { dest.clear(); if (!item || !*item) return false; @@ -3107,7 +3019,7 @@ } } -bool ScriptInterpreterPython::GetShortHelpForCommandObject( +bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { bool got_string = false; dest.clear(); @@ -3163,7 +3075,7 @@ return got_string; } -uint32_t ScriptInterpreterPython::GetFlagsForCommandObject( +uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject( StructuredData::GenericSP cmd_obj_sp) { uint32_t result = 0; @@ -3217,7 +3129,7 @@ return result; } -bool ScriptInterpreterPython::GetLongHelpForCommandObject( +bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { bool got_string = false; dest.clear(); @@ -3276,14 +3188,14 @@ } std::unique_ptr -ScriptInterpreterPython::AcquireInterpreterLock() { +ScriptInterpreterPythonImpl::AcquireInterpreterLock() { std::unique_ptr py_lock(new Locker( this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, Locker::FreeLock | Locker::TearDownSession)); return py_lock; } -void ScriptInterpreterPython::InitializePrivate() { +void ScriptInterpreterPythonImpl::InitializePrivate() { if (g_initialized) return; @@ -3321,8 +3233,8 @@ "from lldb.embedded_interpreter import run_one_line"); } -void ScriptInterpreterPython::AddToSysPath(AddLocation location, - std::string path) { +void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location, + std::string path) { std::string path_copy; std::string statement; @@ -3345,13 +3257,13 @@ // calls Py_Finalize, which calls all the 'at_exit' registered functions. // SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate, // which calls ScriptInterpreter::Terminate, which calls -// ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end -// up with Py_Finalize being called from within Py_Finalize, which results in a -// seg fault. Since this function only gets called when lldb is shutting down -// and going away anyway, the fact that we don't actually call Py_Finalize +// ScriptInterpreterPythonImpl::Terminate. So if we call Py_Finalize here, we +// end up with Py_Finalize being called from within Py_Finalize, which results +// in a seg fault. Since this function only gets called when lldb is shutting +// down and going away anyway, the fact that we don't actually call Py_Finalize // should not cause any problems (everything should shut down/go away anyway // when the process exits). // -// void ScriptInterpreterPython::Terminate() { Py_Finalize (); } +// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); } #endif // LLDB_DISABLE_PYTHON Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h =================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -0,0 +1,478 @@ +//===-- ScriptInterpreterPythonImpl.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 +// +//===----------------------------------------------------------------------===// + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +#include "lldb-python.h" + +#include "PythonDataObjects.h" +#include "ScriptInterpreterPython.h" + +#include "lldb/Host/Terminal.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_private { +class IOHandlerPythonInterpreter; +class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { +public: + friend class IOHandlerPythonInterpreter; + + ScriptInterpreterPythonImpl(CommandInterpreter &interpreter); + + ~ScriptInterpreterPythonImpl() override; + + bool Interrupt() override; + + bool ExecuteOneLine( + llvm::StringRef command, CommandReturnObject *result, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + + void ExecuteInterpreterLoop() override; + + bool ExecuteOneLineWithReturn( + llvm::StringRef in_string, + ScriptInterpreter::ScriptReturnType return_type, void *ret_value, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + + lldb_private::Status ExecuteMultipleLines( + const char *in_string, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + + Status + ExportFunctionDefinitionToInterpreter(StringList &function_def) override; + + bool GenerateTypeScriptFunction(StringList &input, std::string &output, + const void *name_token = nullptr) override; + + bool GenerateTypeSynthClass(StringList &input, std::string &output, + const void *name_token = nullptr) override; + + bool GenerateTypeSynthClass(const char *oneliner, std::string &output, + const void *name_token = nullptr) override; + + // use this if the function code is just a one-liner script + bool GenerateTypeScriptFunction(const char *oneliner, std::string &output, + const void *name_token = nullptr) override; + + bool GenerateScriptAliasFunction(StringList &input, + std::string &output) override; + + StructuredData::ObjectSP + CreateSyntheticScriptedProvider(const char *class_name, + lldb::ValueObjectSP valobj) override; + + StructuredData::GenericSP + CreateScriptCommandObject(const char *class_name) override; + + StructuredData::ObjectSP + CreateScriptedThreadPlan(const char *class_name, + lldb::ThreadPlanSP thread_plan) override; + + bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, + Event *event, + bool &script_error) override; + + bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, + Event *event, bool &script_error) override; + + bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp, + bool &script_error) override; + + lldb::StateType + ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, + bool &script_error) override; + + StructuredData::GenericSP + CreateScriptedBreakpointResolver(const char *class_name, + StructuredDataImpl *args_data, + lldb::BreakpointSP &bkpt_sp) override; + bool ScriptedBreakpointResolverSearchCallback( + StructuredData::GenericSP implementor_sp, + SymbolContext *sym_ctx) override; + + lldb::SearchDepth ScriptedBreakpointResolverSearchDepth( + StructuredData::GenericSP implementor_sp) override; + + StructuredData::GenericSP + CreateFrameRecognizer(const char *class_name) override; + + lldb::ValueObjectListSP + GetRecognizedArguments(const StructuredData::ObjectSP &implementor, + lldb::StackFrameSP frame_sp) override; + + StructuredData::GenericSP + OSPlugin_CreatePluginObject(const char *class_name, + lldb::ProcessSP process_sp) override; + + StructuredData::DictionarySP + OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + + StructuredData::ArraySP + OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + + StructuredData::StringSP + OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, + lldb::tid_t thread_id) override; + + StructuredData::DictionarySP + OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, + lldb::tid_t tid, lldb::addr_t context) override; + + StructuredData::ObjectSP + LoadPluginModule(const FileSpec &file_spec, + lldb_private::Status &error) override; + + StructuredData::DictionarySP + GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, + const char *setting_name, + lldb_private::Status &error) override; + + size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, + uint32_t max) override; + + lldb::ValueObjectSP + GetChildAtIndex(const StructuredData::ObjectSP &implementor, + uint32_t idx) override; + + int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, + const char *child_name) override; + + bool UpdateSynthProviderInstance( + const StructuredData::ObjectSP &implementor) override; + + bool MightHaveChildrenSynthProviderInstance( + const StructuredData::ObjectSP &implementor) override; + + lldb::ValueObjectSP + GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; + + ConstString + GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override; + + bool + RunScriptBasedCommand(const char *impl_function, llvm::StringRef args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject &cmd_retobj, + Status &error, + const lldb_private::ExecutionContext &exe_ctx) override; + + bool RunScriptBasedCommand( + StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject &cmd_retobj, Status &error, + const lldb_private::ExecutionContext &exe_ctx) override; + + Status GenerateFunction(const char *signature, + const StringList &input) override; + + Status GenerateBreakpointCommandCallbackData(StringList &input, + std::string &output) override; + + bool GenerateWatchpointCommandCallbackData(StringList &input, + std::string &output) override; + + bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, + StructuredData::ObjectSP &callee_wrapper_sp, + const TypeSummaryOptions &options, + std::string &retval) override; + + void Clear() override; + + bool GetDocumentationForItem(const char *item, std::string &dest) override; + + bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, + std::string &dest) override; + + uint32_t + GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; + + bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, + std::string &dest) override; + + bool CheckObjectExists(const char *name) override { + if (!name || !name[0]) + return false; + std::string temp; + return GetDocumentationForItem(name, temp); + } + + bool RunScriptFormatKeyword(const char *impl_function, Process *process, + std::string &output, Status &error) override; + + bool RunScriptFormatKeyword(const char *impl_function, Thread *thread, + std::string &output, Status &error) override; + + bool RunScriptFormatKeyword(const char *impl_function, Target *target, + std::string &output, Status &error) override; + + bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame, + std::string &output, Status &error) override; + + bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value, + std::string &output, Status &error) override; + + bool + LoadScriptingModule(const char *filename, bool can_reload, bool init_session, + lldb_private::Status &error, + StructuredData::ObjectSP *module_sp = nullptr) override; + + bool IsReservedWord(const char *word) override; + + std::unique_ptr AcquireInterpreterLock() override; + + void CollectDataForBreakpointCommandCallback( + std::vector &bp_options_vec, + CommandReturnObject &result) override; + + void + CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, + CommandReturnObject &result) override; + + /// Set the callback body text into the callback for the breakpoint. + Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, + const char *callback_body) override; + + void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options, + const char *function_name) override; + + /// This one is for deserialization: + Status SetBreakpointCommandCallback( + BreakpointOptions *bp_options, + std::unique_ptr &data_up) override; + + /// Set a one-liner as the callback for the watchpoint. + void SetWatchpointCommandCallback(WatchpointOptions *wp_options, + const char *oneliner) override; + + void ResetOutputFileHandle(FILE *new_fh) override; + + const char *GetDictionaryName() { return m_dictionary_name.c_str(); } + + PyThreadState *GetThreadState() { return m_command_thread_state; } + + void SetThreadState(PyThreadState *s) { + if (s) + m_command_thread_state = s; + } + + //---------------------------------------------------------------------- + // IOHandlerDelegate + //---------------------------------------------------------------------- + void IOHandlerActivated(IOHandler &io_handler, bool interactive) override; + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override; + + static lldb::ScriptInterpreterSP + CreateInstance(CommandInterpreter &interpreter); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + + class Locker : public ScriptInterpreterLocker { + public: + enum OnEntry { + AcquireLock = 0x0001, + InitSession = 0x0002, + InitGlobals = 0x0004, + NoSTDIN = 0x0008 + }; + + enum OnLeave { + FreeLock = 0x0001, + FreeAcquiredLock = 0x0002, // do not free the lock if we already held it + // when calling constructor + TearDownSession = 0x0004 + }; + + Locker(ScriptInterpreterPythonImpl *py_interpreter = nullptr, + uint16_t on_entry = AcquireLock | InitSession, + uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr, + FILE *out = nullptr, FILE *err = nullptr); + + ~Locker() override; + + private: + bool DoAcquireLock(); + + bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + + bool DoFreeLock(); + + bool DoTearDownSession(); + + bool m_teardown_session; + ScriptInterpreterPythonImpl *m_python_interpreter; + // FILE* m_tmp_fh; + PyGILState_STATE m_GILState; + }; + + static bool BreakpointCallbackFunction(void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + static bool WatchpointCallbackFunction(void *baton, + StoppointCallbackContext *context, + lldb::user_id_t watch_id); + static void InitializePrivate(); + + class SynchronicityHandler { + private: + lldb::DebuggerSP m_debugger_sp; + ScriptedCommandSynchronicity m_synch_wanted; + bool m_old_asynch; + + public: + SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity); + + ~SynchronicityHandler(); + }; + + enum class AddLocation { Beginning, End }; + + static void AddToSysPath(AddLocation location, std::string path); + + bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + + void LeaveSession(); + + void SaveTerminalState(int fd); + + void RestoreTerminalState(); + + uint32_t IsExecutingPython() const { return m_lock_count > 0; } + + uint32_t IncrementLockCount() { return ++m_lock_count; } + + uint32_t DecrementLockCount() { + if (m_lock_count > 0) + --m_lock_count; + return m_lock_count; + } + + enum ActiveIOHandler { + eIOHandlerNone, + eIOHandlerBreakpoint, + eIOHandlerWatchpoint + }; + + PythonObject &GetMainModule(); + + PythonDictionary &GetSessionDictionary(); + + PythonDictionary &GetSysModuleDictionary(); + + bool GetEmbeddedInterpreterModuleObjects(); + + bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file, + const char *mode); + + PythonFile m_saved_stdin; + PythonFile m_saved_stdout; + PythonFile m_saved_stderr; + PythonObject m_main_module; + PythonDictionary m_session_dict; + PythonDictionary m_sys_module_dict; + PythonObject m_run_one_line_function; + PythonObject m_run_one_line_str_global; + std::string m_dictionary_name; + TerminalState m_terminal_state; + ActiveIOHandler m_active_io_handler; + bool m_session_is_active; + bool m_pty_slave_is_open; + bool m_valid_session; + uint32_t m_lock_count; + PyThreadState *m_command_thread_state; +}; + +class IOHandlerPythonInterpreter : public IOHandler { +public: + IOHandlerPythonInterpreter(Debugger &debugger, + ScriptInterpreterPythonImpl *python) + : IOHandler(debugger, IOHandler::Type::PythonInterpreter), + m_python(python) {} + + ~IOHandlerPythonInterpreter() override {} + + ConstString GetControlSequence(char ch) override { + if (ch == 'd') + return ConstString("quit()\n"); + return ConstString(); + } + + void Run() override { + if (m_python) { + int stdin_fd = GetInputFD(); + if (stdin_fd >= 0) { + Terminal terminal(stdin_fd); + TerminalState terminal_state; + const bool is_a_tty = terminal.IsATerminal(); + + if (is_a_tty) { + terminal_state.Save(stdin_fd, false); + terminal.SetCanonical(false); + terminal.SetEcho(true); + } + + ScriptInterpreterPythonImpl::Locker locker( + m_python, + ScriptInterpreterPythonImpl::Locker::AcquireLock | + ScriptInterpreterPythonImpl::Locker::InitSession | + ScriptInterpreterPythonImpl::Locker::InitGlobals, + ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock | + ScriptInterpreterPythonImpl::Locker::TearDownSession); + + // The following call drops into the embedded interpreter loop and + // stays there until the user chooses to exit from the Python + // interpreter. This embedded interpreter will, as any Python code that + // performs I/O, unlock the GIL before a system call that can hang, and + // lock it when the syscall has returned. + + // We need to surround the call to the embedded interpreter with calls + // to PyGILState_Ensure and PyGILState_Release (using the Locker + // above). This is because Python has a global lock which must be held + // whenever we want to touch any Python objects. Otherwise, if the user + // calls Python code, the interpreter state will be off, and things + // could hang (it's happened before). + + StreamString run_string; + run_string.Printf("run_python_interpreter (%s)", + m_python->GetDictionaryName()); + PyRun_SimpleString(run_string.GetData()); + + if (is_a_tty) + terminal_state.Restore(); + } + } + SetIsDone(true); + } + + void Cancel() override {} + + bool Interrupt() override { return m_python->Interrupt(); } + + void GotEOF() override {} + +protected: + ScriptInterpreterPythonImpl *m_python; +}; + +} // namespace lldb_private + +#endif Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h =================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/lldb-python.h @@ -32,6 +32,12 @@ #undef _XOPEN_SOURCE #endif +// Include locale before Python so _PY_PORT_CTYPE_UTF8_ISSUE doesn't cause +// macro redefinitions. +#if defined(__APPLE__) +#include +#endif + // Include python for non windows machines #include #endif // LLDB_DISABLE_PYTHON