Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions lldb/bindings/python/python-typemaps.swig
Original file line number Diff line number Diff line change
Expand Up @@ -220,19 +220,19 @@ AND call SWIG_fail at the same time, because it will result in a double free.
}

// Disable default type checking for this method to avoid SWIG dispatch issues.
//
//
// Problem: SBThread::GetStopDescription has two overloads:
// 1. GetStopDescription(char* dst_or_null, size_t dst_len)
// 1. GetStopDescription(char* dst_or_null, size_t dst_len)
// 2. GetStopDescription(lldb::SBStream& stream)
//
// SWIG generates a dispatch function to select the correct overload based on argument types.
// see https://www.swig.org/Doc4.0/SWIGDocumentation.html#Typemaps_overloading.
// However, this dispatcher doesn't consider typemaps that transform function signatures.
//
// In Python, our typemap converts GetStopDescription(char*, size_t) to GetStopDescription(int).
// The dispatcher still checks against the original (char*, size_t) signature instead of
// The dispatcher still checks against the original (char*, size_t) signature instead of
// the transformed (int) signature, causing type matching to fail.
// This only affects SBThread::GetStopDescription since the type check also matches
// This only affects SBThread::GetStopDescription since the type check also matches
// the argument name, which is unique to this function.
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (char *dst_or_null, size_t dst_len) ""

Expand Down Expand Up @@ -628,12 +628,11 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
}
}

// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i,
// and fixed so they will not crash if PyObject_GetBuffer fails.
// https://github.com/swig/swig/issues/1640
//
// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper,
// doing it right away is not legal according to the python buffer protocol.
// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i.
// - Avoids crash if PyObject_GetBuffer fails and delays calling
// PyBuffer_Release (https://github.com/swig/swig/issues/1640)
// - Avoids using deprecated "old buffer protocol" APIs when targeting the
// Stable C API.
%inline %{
struct Py_buffer_RAII {
Py_buffer buffer = {};
Expand Down
7 changes: 5 additions & 2 deletions lldb/bindings/python/python-wrapper.swig
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,11 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallTypeScript(

PyObject *pfunc_impl = nullptr;

if (pyfunct_wrapper && *pyfunct_wrapper &&
PyFunction_Check(*pyfunct_wrapper)) {
if (pyfunct_wrapper && *pyfunct_wrapper
#ifndef Py_LIMITED_API
&& PyFunction_Check(*pyfunct_wrapper)
#endif
) {
pfunc_impl = (PyObject *)(*pyfunct_wrapper);
if (pfunc_impl->ob_refcnt == 1) {
Py_XDECREF(pfunc_impl);
Expand Down
5 changes: 5 additions & 0 deletions lldb/bindings/python/python.swig
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ except ImportError:
// Parameter types will be used in the autodoc string.
%feature("autodoc", "1");

// Include lldb-python first as it sets Py_LIMITED_API.
%begin %{
#include "../source/Plugins/ScriptInterpreter/Python/lldb-python.h"
%}

%pythoncode%{
import uuid
import re
Expand Down
6 changes: 4 additions & 2 deletions lldb/cmake/modules/LLDBConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,14 @@ if (LLDB_ENABLE_PYTHON)
"Path to use as PYTHONHOME in lldb. If a relative path is specified, it will be resolved at runtime relative to liblldb directory.")
endif()

if (SWIG_VERSION VERSION_GREATER_EQUAL "4.2" AND NOT LLDB_EMBED_PYTHON_HOME)
if (SWIG_VERSION VERSION_GREATER_EQUAL "4.2"
AND Python3_VERSION VERSION_GREATER_EQUAL "3.11"
AND NOT LLDB_EMBED_PYTHON_HOME)
set(default_enable_python_limited_api ON)
else()
set(default_enable_python_limited_api OFF)
endif()
option(LLDB_ENABLE_PYTHON_LIMITED_API "Force LLDB to only use the Python Limited API (requires SWIG 4.2 or later)"
option(LLDB_ENABLE_PYTHON_LIMITED_API "Only use the Python Limited API (requires at least Python 3.11 and SWIG 4.2)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to print a diagnostic if someone uses -DLLDB_ENABLE_PYTHON_LIMITED_API=On with old python/SWIG?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an older Python will get caught by the static_assert in lldb-python.h. An older version of SWIG wouldn't, but I also don't necessarily want to prevent it when someone explicitly provided the override.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. (My thinking is that there are two ways someone would want to use the option: one, to force it off because the new API usage causes some issue, or two, force it on to enforce a particular build config. In the latter case, you really want to catch the mistake as soon as possible, instead of giving some weird build error later.)

Copy link
Member

@bulbazord bulbazord Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a good middle ground may be to emit a warning? Something like "Hey you did this unsupported thing and now you're on your own"

Copy link
Member Author

@JDevlieghere JDevlieghere Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the PR to diagnose the issues at configuration time. I used SEND_ERROR so that if there's multiple issues, you don't need to keep reconfiguring. I think the target audience that would want to work around this and try different versions is most likely just me and maybe a handful of other LLDB devs who can easily turn the error into a warning while working on it.

${default_enable_python_limited_api})
else()
# Even if Python scripting is disabled, we still need a Python interpreter to
Expand Down
7 changes: 4 additions & 3 deletions lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ static llvm::Expected<bool> *g_fcxx_modules_workaround [[maybe_unused]];
#include <locale>
#endif

#define LLDB_MINIMUM_PYTHON_VERSION 0x03080000

#if LLDB_ENABLE_PYTHON_LIMITED_API
// If defined, LLDB will be ABI-compatible with all Python 3 releases from the
// specified one onward, and can use Limited API introduced up to that version.
#if LLDB_ENABLE_PYTHON_LIMITED_API
#define LLDB_MINIMUM_PYTHON_VERSION 0x030b0000
#define Py_LIMITED_API LLDB_MINIMUM_PYTHON_VERSION
#else
#define LLDB_MINIMUM_PYTHON_VERSION 0x03080000
#endif

// Include python for non windows machines
Expand Down
Loading