Add debug offsets for free threaded builds (#123041)

This commit is contained in:
Pablo Galindo Salgado 2024-08-15 19:42:41 +01:00 committed by GitHub
parent b15b81ed4f
commit d7a3df9150
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 86 additions and 5 deletions

View File

@ -44,6 +44,15 @@ struct _gilstate_runtime_state {
/* Runtime audit hook state */ /* Runtime audit hook state */
#define _Py_Debug_Cookie "xdebugpy"
#ifdef Py_GIL_DISABLED
# define _Py_Debug_gilruntimestate_enabled offsetof(struct _gil_runtime_state, enabled)
# define _Py_Debug_Free_Threaded 1
#else
# define _Py_Debug_gilruntimestate_enabled 0
# define _Py_Debug_Free_Threaded 0
#endif
typedef struct _Py_AuditHookEntry { typedef struct _Py_AuditHookEntry {
struct _Py_AuditHookEntry *next; struct _Py_AuditHookEntry *next;
Py_AuditHookFunction hookCFunction; Py_AuditHookFunction hookCFunction;
@ -53,6 +62,7 @@ typedef struct _Py_AuditHookEntry {
typedef struct _Py_DebugOffsets { typedef struct _Py_DebugOffsets {
char cookie[8]; char cookie[8];
uint64_t version; uint64_t version;
uint64_t free_threaded;
// Runtime state offset; // Runtime state offset;
struct _runtime_state { struct _runtime_state {
uint64_t size; uint64_t size;
@ -71,6 +81,8 @@ typedef struct _Py_DebugOffsets {
uint64_t sysdict; uint64_t sysdict;
uint64_t builtins; uint64_t builtins;
uint64_t ceval_gil; uint64_t ceval_gil;
uint64_t gil_runtime_state;
uint64_t gil_runtime_state_enabled;
uint64_t gil_runtime_state_locked; uint64_t gil_runtime_state_locked;
uint64_t gil_runtime_state_holder; uint64_t gil_runtime_state_holder;
} interpreter_state; } interpreter_state;
@ -122,20 +134,57 @@ typedef struct _Py_DebugOffsets {
struct _type_object { struct _type_object {
uint64_t size; uint64_t size;
uint64_t tp_name; uint64_t tp_name;
uint64_t tp_repr;
uint64_t tp_flags;
} type_object; } type_object;
// PyTuple object offset; // PyTuple object offset;
struct _tuple_object { struct _tuple_object {
uint64_t size; uint64_t size;
uint64_t ob_item; uint64_t ob_item;
uint64_t ob_size;
} tuple_object; } tuple_object;
// PyList object offset;
struct _list_object {
uint64_t size;
uint64_t ob_item;
uint64_t ob_size;
} list_object;
// PyDict object offset;
struct _dict_object {
uint64_t size;
uint64_t ma_keys;
uint64_t ma_values;
} dict_object;
// PyFloat object offset;
struct _float_object {
uint64_t size;
uint64_t ob_fval;
} float_object;
// PyLong object offset;
struct _long_object {
uint64_t size;
uint64_t lv_tag;
uint64_t ob_digit;
} long_object;
// PyBytes object offset;
struct _bytes_object {
uint64_t size;
uint64_t ob_size;
uint64_t ob_sval;
} bytes_object;
// Unicode object offset; // Unicode object offset;
struct _unicode_object { struct _unicode_object {
uint64_t size; uint64_t size;
uint64_t state; uint64_t state;
uint64_t length; uint64_t length;
size_t asciiobject_size; uint64_t asciiobject_size;
} unicode_object; } unicode_object;
// GC runtime state offset; // GC runtime state offset;

View File

@ -29,11 +29,12 @@ extern PyTypeObject _PyExc_MemoryError;
/* The static initializers defined here should only be used /* The static initializers defined here should only be used
in the runtime init code (in pystate.c and pylifecycle.c). */ in the runtime init code (in pystate.c and pylifecycle.c). */
#define _PyRuntimeState_INIT(runtime) \ #define _PyRuntimeState_INIT(runtime, debug_cookie) \
{ \ { \
.debug_offsets = { \ .debug_offsets = { \
.cookie = "xdebugpy", \ .cookie = debug_cookie, \
.version = PY_VERSION_HEX, \ .version = PY_VERSION_HEX, \
.free_threaded = _Py_Debug_Free_Threaded, \
.runtime_state = { \ .runtime_state = { \
.size = sizeof(_PyRuntimeState), \ .size = sizeof(_PyRuntimeState), \
.finalizing = offsetof(_PyRuntimeState, _finalizing), \ .finalizing = offsetof(_PyRuntimeState, _finalizing), \
@ -49,6 +50,8 @@ extern PyTypeObject _PyExc_MemoryError;
.sysdict = offsetof(PyInterpreterState, sysdict), \ .sysdict = offsetof(PyInterpreterState, sysdict), \
.builtins = offsetof(PyInterpreterState, builtins), \ .builtins = offsetof(PyInterpreterState, builtins), \
.ceval_gil = offsetof(PyInterpreterState, ceval.gil), \ .ceval_gil = offsetof(PyInterpreterState, ceval.gil), \
.gil_runtime_state = offsetof(PyInterpreterState, _gil), \
.gil_runtime_state_enabled = _Py_Debug_gilruntimestate_enabled, \
.gil_runtime_state_locked = offsetof(PyInterpreterState, _gil.locked), \ .gil_runtime_state_locked = offsetof(PyInterpreterState, _gil.locked), \
.gil_runtime_state_holder = offsetof(PyInterpreterState, _gil.last_holder), \ .gil_runtime_state_holder = offsetof(PyInterpreterState, _gil.last_holder), \
}, \ }, \
@ -90,10 +93,37 @@ extern PyTypeObject _PyExc_MemoryError;
.type_object = { \ .type_object = { \
.size = sizeof(PyTypeObject), \ .size = sizeof(PyTypeObject), \
.tp_name = offsetof(PyTypeObject, tp_name), \ .tp_name = offsetof(PyTypeObject, tp_name), \
.tp_repr = offsetof(PyTypeObject, tp_repr), \
.tp_flags = offsetof(PyTypeObject, tp_flags), \
}, \ }, \
.tuple_object = { \ .tuple_object = { \
.size = sizeof(PyTupleObject), \ .size = sizeof(PyTupleObject), \
.ob_item = offsetof(PyTupleObject, ob_item), \ .ob_item = offsetof(PyTupleObject, ob_item), \
.ob_size = offsetof(PyTupleObject, ob_base.ob_size), \
}, \
.list_object = { \
.size = sizeof(PyListObject), \
.ob_item = offsetof(PyListObject, ob_item), \
.ob_size = offsetof(PyListObject, ob_base.ob_size), \
}, \
.dict_object = { \
.size = sizeof(PyDictObject), \
.ma_keys = offsetof(PyDictObject, ma_keys), \
.ma_values = offsetof(PyDictObject, ma_values), \
}, \
.float_object = { \
.size = sizeof(PyFloatObject), \
.ob_fval = offsetof(PyFloatObject, ob_fval), \
}, \
.long_object = { \
.size = sizeof(PyLongObject), \
.lv_tag = offsetof(_PyLongValue, lv_tag), \
.ob_digit = offsetof(_PyLongValue, ob_digit), \
}, \
.bytes_object = { \
.size = sizeof(PyBytesObject), \
.ob_size = offsetof(PyBytesObject, ob_base.ob_size), \
.ob_sval = offsetof(PyBytesObject, ob_sval), \
}, \ }, \
.unicode_object = { \ .unicode_object = { \
.size = sizeof(PyUnicodeObject), \ .size = sizeof(PyUnicodeObject), \

View File

@ -104,7 +104,7 @@ _PyRuntimeState _PyRuntime
#if defined(__linux__) && (defined(__GNUC__) || defined(__clang__)) #if defined(__linux__) && (defined(__GNUC__) || defined(__clang__))
__attribute__ ((section (".PyRuntime"))) __attribute__ ((section (".PyRuntime")))
#endif #endif
= _PyRuntimeState_INIT(_PyRuntime); = _PyRuntimeState_INIT(_PyRuntime, _Py_Debug_Cookie);
_Py_COMP_DIAG_POP _Py_COMP_DIAG_POP
static int runtime_initialized = 0; static int runtime_initialized = 0;

View File

@ -390,7 +390,7 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
Note that we initialize "initial" relative to _PyRuntime, Note that we initialize "initial" relative to _PyRuntime,
to ensure pre-initialized pointers point to the active to ensure pre-initialized pointers point to the active
runtime state (and not "initial"). */ runtime state (and not "initial"). */
static const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime); static const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime, "");
_Py_COMP_DIAG_POP _Py_COMP_DIAG_POP
#define LOCKS_INIT(runtime) \ #define LOCKS_INIT(runtime) \
@ -455,6 +455,8 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
// Py_Initialize() must be running again. // Py_Initialize() must be running again.
// Reset to _PyRuntimeState_INIT. // Reset to _PyRuntimeState_INIT.
memcpy(runtime, &initial, sizeof(*runtime)); memcpy(runtime, &initial, sizeof(*runtime));
// Preserve the cookie from the original runtime.
memcpy(runtime->debug_offsets.cookie, _Py_Debug_Cookie, 8);
assert(!runtime->_initialized); assert(!runtime->_initialized);
} }