diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index 480430fede928..f3c1c8cd2dff6 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -62,7 +62,7 @@ CMake configuration error. +-------------------+--------------------------------------------------------------+--------------------------+ | Libxml2 | XML | ``LLDB_ENABLE_LIBXML2`` | +-------------------+--------------------------------------------------------------+--------------------------+ -| Python | Python scripting. >= 3.8 is required. | ``LLDB_ENABLE_PYTHON`` | +| Python | Python scripting. >= 3.0 is required, >= 3.8 is recommended. | ``LLDB_ENABLE_PYTHON`` | +-------------------+--------------------------------------------------------------+--------------------------+ | Lua | Lua scripting. Lua 5.3 and 5.4 are supported. | ``LLDB_ENABLE_LUA`` | +-------------------+--------------------------------------------------------------+--------------------------+ diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 1340425aade43..a0f8cf954f804 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -73,8 +73,10 @@ Expected python::As(Expected &&obj) { static bool python_is_finalizing() { #if PY_VERSION_HEX >= 0x030d0000 return Py_IsFinalizing(); -#else +#elif PY_VERSION_HEX >= 0x03070000 return _Py_IsFinalizing(); +#else + return _Py_Finalizing != nullptr; #endif } @@ -808,6 +810,7 @@ bool PythonCallable::Check(PyObject *py_obj) { return PyCallable_Check(py_obj); } +#if PY_VERSION_HEX >= 0x03030000 static const char get_arg_info_script[] = R"( from inspect import signature, Parameter, ismethod from collections import namedtuple @@ -829,12 +832,15 @@ def main(f): raise Exception(f'unknown parameter kind: {kind}') return ArgInfo(count, varargs) )"; +#endif Expected PythonCallable::GetArgInfo() const { ArgInfo result = {}; if (!IsValid()) return nullDeref(); +#if PY_VERSION_HEX >= 0x03030000 + // no need to synchronize access to this global, we already have the GIL static PythonScript get_arg_info(get_arg_info_script); Expected pyarginfo = get_arg_info(*this); @@ -846,6 +852,57 @@ Expected PythonCallable::GetArgInfo() const { cantFail(As(pyarginfo.get().GetAttribute("has_varargs"))); result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count; +#else + PyObject *py_func_obj; + bool is_bound_method = false; + bool is_class = false; + + if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { + auto init = GetAttribute("__init__"); + if (!init) + return init.takeError(); + py_func_obj = init.get().get(); + is_class = true; + } else { + py_func_obj = m_py_obj; + } + + if (PyMethod_Check(py_func_obj)) { + py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); + PythonObject im_self = GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + is_bound_method = true; + } else { + // see if this is a callable object with an __call__ method + if (!PyFunction_Check(py_func_obj)) { + PythonObject __call__ = GetAttributeValue("__call__"); + if (__call__.IsValid()) { + auto __callable__ = __call__.AsType(); + if (__callable__.IsValid()) { + py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); + PythonObject im_self = __callable__.GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + is_bound_method = true; + } + } + } + } + + if (!py_func_obj) + return result; + + PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(py_func_obj); + if (!code) + return result; + + auto count = code->co_argcount; + bool has_varargs = !!(code->co_flags & CO_VARARGS); + result.max_positional_args = + has_varargs ? ArgInfo::UNBOUNDED + : (count - (int)is_bound_method) - (int)is_class; + +#endif + return result; } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 0c864dc85ce71..d9b93b888816b 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -72,7 +72,8 @@ extern "C" PyObject *PyInit__lldb(void); // Don't mess with the signal handlers on Windows. #define LLDB_USE_PYTHON_SET_INTERRUPT 0 #else -#define LLDB_USE_PYTHON_SET_INTERRUPT 1 +// PyErr_SetInterrupt was introduced in 3.2. +#define LLDB_USE_PYTHON_SET_INTERRUPT PY_VERSION_HEX >= 0x03020000 #endif static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { @@ -92,8 +93,10 @@ namespace { struct InitializePythonRAII { public: InitializePythonRAII() { +#if PY_VERSION_HEX >= 0x03080000 PyConfig config; PyConfig_InitPythonConfig(&config); +#endif #if LLDB_EMBED_PYTHON_HOME static std::string g_python_home = []() -> std::string { @@ -107,7 +110,14 @@ struct InitializePythonRAII { return spec.GetPath(); }(); if (!g_python_home.empty()) { +#if PY_VERSION_HEX >= 0x03080000 PyConfig_SetBytesString(&config, &config.home, g_python_home.c_str()); +#else + size_t size = 0; + wchar_t *python_home_w = Py_DecodeLocale(g_python_home.c_str(), &size); + Py_SetPythonHome(python_home_w); + PyMem_RawFree(python_home_w); +#endif } #endif @@ -134,10 +144,23 @@ struct InitializePythonRAII { PyImport_AppendInittab("_lldb", LLDBSwigPyInit); } +#if PY_VERSION_HEX >= 0x03080000 config.install_signal_handlers = 0; Py_InitializeFromConfig(&config); PyConfig_Clear(&config); InitializeThreadsPrivate(); +#else +// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for +// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you +// call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last. +#if PY_VERSION_HEX >= 0x03020000 + Py_InitializeEx(0); + InitializeThreadsPrivate(); +#else + InitializeThreadsPrivate(); + Py_InitializeEx(0); +#endif +#endif } ~InitializePythonRAII() { @@ -161,10 +184,11 @@ struct InitializePythonRAII { // `PyGILState_Ensure/Release` flow would be executed instead of unlocking // GIL with `PyEval_SaveThread`. When an another thread calls // `PyGILState_Ensure` it would get stuck in deadlock. - +#if PY_VERSION_HEX >= 0x03070000 // The only case we should go further and acquire the GIL: it is unlocked. if (PyGILState_Check()) return; +#endif // `PyEval_ThreadsInitialized` was deprecated in Python 3.9 and removed in // Python 3.13. It has been returning `true` always since Python 3.7. diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h index 4a6c11dba02e8..b68598b9d59d9 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h @@ -50,8 +50,8 @@ static llvm::Expected *g_fcxx_modules_workaround [[maybe_unused]]; // Provide a meaningful diagnostic error if someone tries to compile this file // with a version of Python we don't support. -static_assert(PY_VERSION_HEX >= 0x03080000, - "LLDB requires at least Python 3.8"); +static_assert(PY_VERSION_HEX >= 0x03000000, + "LLDB requires at least Python 3.0"); #endif #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp index 2dd92fc00fea1..365ebc8e52c24 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp @@ -760,6 +760,10 @@ class NewStyle(object): EXPECT_EQ(arginfo.get().max_positional_args, 3u); } +#if PY_VERSION_HEX >= 0x03030000 + + // the old implementation of GetArgInfo just doesn't work on builtins. + { auto builtins = PythonModule::BuiltinsModule(); auto hex = As(builtins.GetAttribute("hex")); @@ -768,6 +772,8 @@ class NewStyle(object): ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); EXPECT_EQ(arginfo.get().max_positional_args, 1u); } + +#endif } TEST_F(PythonDataObjectsTest, TestScript) { diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index a126d7ae1ab4a..64712d8534ddc 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -288,8 +288,6 @@ Changes to the LLVM tools Changes to LLDB --------------------------------- -* When building LLDB with Python support, the minimum version of Python is now - 3.8. * LLDB now supports hardware watchpoints for AArch64 Windows targets. Windows does not provide API to query the number of supported hardware watchpoints. Therefore current implementation allows only 1 watchpoint, as tested with