Skip to content

Commit

Permalink
Add support for Python 3.13
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Galindo <[email protected]>
  • Loading branch information
pablogsal committed Jun 5, 2024
1 parent f6d8a97 commit 2da7127
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 8 deletions.
1 change: 1 addition & 0 deletions news/186.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for Python 3.13
18 changes: 18 additions & 0 deletions src/pystack/_pystack/cpython/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ typedef struct
PyObject** ma_values;
} PyDictObject;

typedef struct _dictvalues
{
PyObject* values[1];
} PyDictValuesObject;

} // namespace Python3
namespace Python3_3 {
typedef struct _dictkeysobject
Expand Down Expand Up @@ -81,4 +86,17 @@ typedef struct _dictkeysobject
} PyDictKeysObject;
} // namespace Python3_11

namespace Python3_13 {

typedef struct _dictvalues
{
uint8_t capacity;
uint8_t size;
uint8_t embedded;
uint8_t valid;
PyObject* values[1];
} PyDictValuesObject;

} // namespace Python3_13

} // namespace pystack
93 changes: 93 additions & 0 deletions src/pystack/_pystack/cpython/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,98 @@ typedef struct _is
} PyInterpreterState;
} // namespace Python3_12

namespace Python3_13 {

struct _pythreadstate; /* Forward */
struct PyMutex
{
uint8_t v;
};
typedef int (*_Py_pending_call_func)(void*);
struct _pending_call
{
_Py_pending_call_func func;
void* arg;
int flags;
};
struct _pending_calls
{
void* handling_thread;
PyMutex mutex;
int32_t npending;
int32_t max;
int32_t maxloop;
struct _pending_call calls[300];
int first;
int next;
};

struct _ceval_state
{
uintptr_t instrumentation_version;
int recursion_limit;
struct _gil_runtime_state* gil;
int own_gil;
struct _pending_calls pending;
};

struct _import_state
{
PyObject* modules;
PyObject* modules_by_index;
PyObject* importlib;
int override_frozen_modules;
int override_multi_interp_extensions_check;
int dlopenflags;
PyObject* import_func;
struct
{
PyThread_type_lock mutex;
unsigned long thread;
int level;
} lock;
struct
{
int import_level;
int64_t accumulated;
int header;
} find_and_load;
};

typedef struct _is
{
struct _ceval_state ceval;
struct _is* next;

int64_t id;
int64_t id_refcount;
int requires_idref;
PyThread_type_lock id_mutex;
long _whence;
int _initialized;
int _ready;
int finalizing;
uint64_t last_restart_version;
struct pythreads
{
uint64_t next_unique_id;
_pythreadstate* head;
_pythreadstate* main;
long count;
size_t stacksize;
} threads;
struct pyruntimestate* runtime;
void* _finalizing;
unsigned long _finalizing_id;
struct Python3_8::_gc_runtime_state gc;
// Dictionary of the sys module
PyObject* sysdict;
// Dictionary of the builtins module
PyObject* builtins;
struct _import_state imports;
} PyInterpreterState;
} // namespace Python3_13

typedef union {
Python2::PyInterpreterState v2;
Python3_5::PyInterpreterState v3_5;
Expand All @@ -255,5 +347,6 @@ typedef union {
Python3_9::PyInterpreterState v3_9;
Python3_11::PyInterpreterState v3_11;
Python3_12::PyInterpreterState v3_12;
Python3_13::PyInterpreterState v3_13;
} PyInterpreterState;
} // namespace pystack
117 changes: 117 additions & 0 deletions src/pystack/_pystack/cpython/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,129 @@ typedef struct pyruntimestate
} PyRuntimeState;
} // namespace Python3_12

namespace Python3_13 {

typedef struct _Py_DebugOffsets
{
char cookie[8];
uint64_t version;
// Runtime state offset;
struct _runtime_state
{
uint64_t finalizing;
uint64_t interpreters_head;
} runtime_state;

// Interpreter state offset;
struct _interpreter_state
{
uint64_t next;
uint64_t threads_head;
uint64_t gc;
uint64_t imports_modules;
uint64_t sysdict;
uint64_t builtins;
uint64_t ceval_gil;
uint64_t gil_runtime_state_locked;
uint64_t gil_runtime_state_holder;
} interpreter_state;

// Thread state offset;
struct _thread_state
{
uint64_t prev;
uint64_t next;
uint64_t interp;
uint64_t current_frame;
uint64_t thread_id;
uint64_t native_thread_id;
} thread_state;

// InterpreterFrame offset;
struct _interpreter_frame
{
uint64_t previous;
uint64_t executable;
uint64_t instr_ptr;
uint64_t localsplus;
uint64_t owner;
} interpreter_frame;

// CFrame offset;
struct _cframe
{
uint64_t current_frame;
uint64_t previous;
} cframe;

// Code object offset;
struct _code_object
{
uint64_t filename;
uint64_t name;
uint64_t linetable;
uint64_t firstlineno;
uint64_t argcount;
uint64_t localsplusnames;
uint64_t localspluskinds;
uint64_t co_code_adaptive;
} code_object;

// PyObject offset;
struct _pyobject
{
uint64_t ob_type;
} pyobject;

// PyTypeObject object offset;
struct _type_object
{
uint64_t tp_name;
} type_object;

// PyTuple object offset;
struct _tuple_object
{
uint64_t ob_item;
} tuple_object;

// Unicode object offset;
struct _unicode_object
{
uint64_t state;
uint64_t length;
size_t asciiobject_size;
} unicode_object;
} _Py_DebugOffsets;

typedef struct pyruntimestate
{
_Py_DebugOffsets debug_offsets;
int _initialized;
int preinitializing;
int preinitialized;
int core_initialized;
int initialized;
PyThreadState* finalizing;
unsigned long _finalizing_id;

struct pyinterpreters
{
PyThread_type_lock mutex;
PyInterpreterState* head;
PyInterpreterState* main;
int64_t next_id;
} interpreters;
} PyRuntimeState;

} // namespace Python3_13
typedef union {
Python3_7::PyRuntimeState v3_7;
Python3_8::PyRuntimeState v3_8;
Python3_9::PyRuntimeState v3_9;
Python3_11::PyRuntimeState v3_11;
Python3_12::PyRuntimeState v3_12;
Python3_13::PyRuntimeState v3_13;
} PyRuntimeState;

} // namespace pystack
63 changes: 63 additions & 0 deletions src/pystack/_pystack/cpython/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,75 @@ typedef struct _pythreadstate
} PyThreadState;
} // namespace Python3_12

namespace Python3_13 {
typedef struct _err_stackitem
{
PyObject* exc_value;
struct _err_stackitem* previous_item;
} _PyErr_StackItem;
typedef struct _pythreadstate
{
struct _pythreadstate* prev;
struct _pythreadstate* next;
struct _is* interp;
uintptr_t eval_breaker;
struct
{
unsigned int initialized : 1;
unsigned int bound : 1;
unsigned int unbound : 1;
unsigned int bound_gilstate : 1;
unsigned int active : 1;
unsigned int finalizing : 1;
unsigned int cleared : 1;
unsigned int finalized : 1;
unsigned int : 24;
} _status;
int _whence;
int state;
int py_recursion_remaining;
int py_recursion_limit;
int c_recursion_remaining;
int recursion_headroom;
int tracing;
int what_event;
void* frame;
Py_tracefunc c_profilefunc;
Py_tracefunc c_tracefunc;
PyObject* c_profileobj;
PyObject* c_traceobj;
PyObject* current_exception;
_PyErr_StackItem* exc_info;
PyObject* dict;
int gilstate_counter;
PyObject* async_exc;
unsigned long thread_id;
unsigned long native_thread_id;

PyObject* delete_later;
uintptr_t critical_section;
int coroutine_origin_tracking_depth;
PyObject* async_gen_firstiter;
PyObject* async_gen_finalizer;
PyObject* context;
uint64_t context_ver;
uint64_t id;
void* datastack_chunk;
PyObject** datastack_top;
PyObject** datastack_limit;
_PyErr_StackItem exc_state;
PyObject* previous_executor;
uint64_t dict_global_version;
} PyThreadState;
} // namespace Python3_13

typedef union {
Python2::PyThreadState v2;
Python3_4::PyThreadState v3_4;
Python3_7::PyThreadState v3_7;
Python3_11::PyThreadState v3_11;
Python3_12::PyThreadState v3_12;
Python3_13::PyThreadState v3_13;
} PyThreadState;

union CFrame {
Expand Down
14 changes: 14 additions & 0 deletions src/pystack/_pystack/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,20 @@ AbstractProcessManager::Pid() const
{
return d_pid;
}

remote_addr_t
AbstractProcessManager::getAddressFromCache(const std::string& symbol) const
{
return d_symbol_cache[symbol];
}

void
AbstractProcessManager::registerAddressInCache(const std::string& symbol, remote_addr_t address) const
{
d_symbol_cache[symbol] = address;
return;
}

std::string
AbstractProcessManager::getCStringFromAddress(remote_addr_t addr) const
{
Expand Down
3 changes: 3 additions & 0 deletions src/pystack/_pystack/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class AbstractProcessManager : public std::enable_shared_from_this<AbstractProce
// Getters
pid_t Pid() const;
virtual const std::vector<int>& Tids() const = 0;
remote_addr_t getAddressFromCache(const std::string& symbol) const;
void registerAddressInCache(const std::string& symbol, remote_addr_t address) const;

// Methods
std::vector<NativeFrame> unwindThread(pid_t tid) const;
Expand Down Expand Up @@ -119,6 +121,7 @@ class AbstractProcessManager : public std::enable_shared_from_this<AbstractProce
int d_major{};
int d_minor{};
const python_v* d_py_v{};
mutable std::unordered_map<std::string, remote_addr_t> d_type_cache;

// Methods
bool isValidInterpreterState(remote_addr_t addr) const;
Expand Down
Loading

0 comments on commit 2da7127

Please sign in to comment.