Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-106597: Add debugging struct with offsets for out-of-process tools #106598

Merged
merged 3 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
44 changes: 44 additions & 0 deletions Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,56 @@ typedef struct _Py_AuditHookEntry {
void *userData;
} _Py_AuditHookEntry;

typedef struct _Py_DebugOffsets {
pablogsal marked this conversation as resolved.
Show resolved Hide resolved
pablogsal marked this conversation as resolved.
Show resolved Hide resolved
// Runtime state offset;
off_t rs_finalizing;
off_t rs_interpreters_head;

// Interpreter state offset;
off_t is_next;
off_t is_threads_head;
off_t is_gc;
off_t is_imports_modules;
off_t is_sysdict;
off_t is_builtins;
off_t is_ceval_gil;

// Thread state offset;
off_t ts_prev;
off_t ts_next;
off_t ts_interp;
off_t ts_cframe;
off_t ts_thread_id;

// Frame object offset;
off_t fo_previous;
off_t fo_executable;
off_t fo_prev_instr;
off_t fo_localsplus;
off_t fo_owner;

// Code object offset;
off_t co_filename;
off_t co_name;
off_t co_linetable;
off_t co_firstlineno;
off_t co_argcount;
off_t co_localsplusnames;
off_t co_co_code_adaptive;
} _Py_DebugOffsets;

/* Full Python runtime state */

/* _PyRuntimeState holds the global state for the CPython runtime.
That data is exposed in the internal API as a static variable (_PyRuntime).
*/
typedef struct pyruntimestate {
/* This field must be first to facilitate locating it by out of process
* debuggers. Out of process debuggers will use the offsets contained in this
* field to be able to locate other fields in several interpreter structures
* in a way that doesn't require them to know the exact layout of those
* structures */
_Py_DebugOffsets debug_offsets;
/* Has been initialized to a safe state.

In order to be effective, this must be set to 0 during or right
Expand Down
33 changes: 32 additions & 1 deletion Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,40 @@ extern PyTypeObject _PyExc_MemoryError;
/* The static initializers defined here should only be used
in the runtime init code (in pystate.c and pylifecycle.c). */


#define _PyRuntimeState_INIT(runtime) \
{ \
.debug_offsets = { \
.rs_finalizing = offsetof(_PyRuntimeState, _finalizing), \
.rs_interpreters_head = offsetof(_PyRuntimeState, interpreters.head), \
\
.is_next = offsetof(PyInterpreterState, next), \
.is_threads_head = offsetof(PyInterpreterState, threads.head), \
.is_gc = offsetof(PyInterpreterState, gc), \
.is_imports_modules = offsetof(PyInterpreterState, imports.modules), \
.is_sysdict = offsetof(PyInterpreterState, sysdict), \
.is_builtins = offsetof(PyInterpreterState, builtins), \
.is_ceval_gil = offsetof(PyInterpreterState, ceval.gil), \
\
.ts_prev = offsetof(PyThreadState, prev), \
.ts_next = offsetof(PyThreadState, next), \
.ts_interp = offsetof(PyThreadState, interp), \
.ts_cframe = offsetof(PyThreadState, cframe), \
.ts_thread_id = offsetof(PyThreadState, thread_id), \
\
.fo_previous = offsetof(_PyInterpreterFrame, previous), \
.fo_executable = offsetof(_PyInterpreterFrame, f_executable), \
.fo_prev_instr = offsetof(_PyInterpreterFrame, prev_instr), \
.fo_localsplus = offsetof(_PyInterpreterFrame, localsplus), \
.fo_owner = offsetof(_PyInterpreterFrame, owner), \
\
.co_filename = offsetof(PyCodeObject, co_filename), \
.co_name = offsetof(PyCodeObject, co_name), \
.co_linetable = offsetof(PyCodeObject, co_linetable), \
.co_firstlineno = offsetof(PyCodeObject, co_firstlineno), \
.co_argcount = offsetof(PyCodeObject, co_argcount), \
.co_localsplusnames = offsetof(PyCodeObject, co_localsplusnames), \
.co_co_code_adaptive = offsetof(PyCodeObject, co_code_adaptive), \
}, \
.allocators = { \
.standard = _pymem_allocators_standard_INIT(runtime), \
.debug = _pymem_allocators_debug_INIT, \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
A new debug structure of offsets has been added to the ``_PyRuntimeState``
that will help out-of-process debuggers and profilers to obtain the offsets
to relevant interpreter structures in a way that is agnostic of how Python
was compiled and that doesn't require copying the headers. Patch by Pablo
Galindo
Loading