mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
499 lines
15 KiB
C
499 lines
15 KiB
C
|
|
/******************************************************************************
|
||
|
|
* Python Remote Debugging Module - Shared Header
|
||
|
|
*
|
||
|
|
* This header provides common declarations, types, and utilities shared
|
||
|
|
* across the remote debugging module implementation files.
|
||
|
|
******************************************************************************/
|
||
|
|
|
||
|
|
#ifndef Py_REMOTE_DEBUGGING_H
|
||
|
|
#define Py_REMOTE_DEBUGGING_H
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
extern "C" {
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define _GNU_SOURCE
|
||
|
|
|
||
|
|
#ifndef Py_BUILD_CORE_BUILTIN
|
||
|
|
# define Py_BUILD_CORE_MODULE 1
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "Python.h"
|
||
|
|
#include <internal/pycore_debug_offsets.h> // _Py_DebugOffsets
|
||
|
|
#include <internal/pycore_frame.h> // FRAME_SUSPENDED_YIELD_FROM
|
||
|
|
#include <internal/pycore_interpframe.h> // FRAME_OWNED_BY_INTERPRETER
|
||
|
|
#include <internal/pycore_llist.h> // struct llist_node
|
||
|
|
#include <internal/pycore_long.h> // _PyLong_GetZero
|
||
|
|
#include <internal/pycore_stackref.h> // Py_TAG_BITS
|
||
|
|
#include "../../Python/remote_debug.h"
|
||
|
|
|
||
|
|
#include <assert.h>
|
||
|
|
#include <errno.h>
|
||
|
|
#include <fcntl.h>
|
||
|
|
#include <stddef.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#ifndef HAVE_PROCESS_VM_READV
|
||
|
|
# define HAVE_PROCESS_VM_READV 0
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(__APPLE__) && TARGET_OS_OSX
|
||
|
|
#include <libproc.h>
|
||
|
|
#include <sys/types.h>
|
||
|
|
#define MAX_NATIVE_THREADS 4096
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MS_WINDOWS
|
||
|
|
#include <windows.h>
|
||
|
|
#include <winternl.h>
|
||
|
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
||
|
|
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
|
||
|
|
typedef enum _WIN32_THREADSTATE {
|
||
|
|
WIN32_THREADSTATE_INITIALIZED = 0,
|
||
|
|
WIN32_THREADSTATE_READY = 1,
|
||
|
|
WIN32_THREADSTATE_RUNNING = 2,
|
||
|
|
WIN32_THREADSTATE_STANDBY = 3,
|
||
|
|
WIN32_THREADSTATE_TERMINATED = 4,
|
||
|
|
WIN32_THREADSTATE_WAITING = 5,
|
||
|
|
WIN32_THREADSTATE_TRANSITION = 6,
|
||
|
|
WIN32_THREADSTATE_UNKNOWN = 7
|
||
|
|
} WIN32_THREADSTATE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* MACROS AND CONSTANTS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset)))
|
||
|
|
#define CLEAR_PTR_TAG(ptr) (((uintptr_t)(ptr) & ~Py_TAG_BITS))
|
||
|
|
#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset))))
|
||
|
|
|
||
|
|
/* Size macros for opaque buffers */
|
||
|
|
#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
|
||
|
|
#define SIZEOF_CODE_OBJ sizeof(PyCodeObject)
|
||
|
|
#define SIZEOF_GEN_OBJ sizeof(PyGenObject)
|
||
|
|
#define SIZEOF_INTERP_FRAME sizeof(_PyInterpreterFrame)
|
||
|
|
#define SIZEOF_LLIST_NODE sizeof(struct llist_node)
|
||
|
|
#define SIZEOF_PAGE_CACHE_ENTRY sizeof(page_cache_entry_t)
|
||
|
|
#define SIZEOF_PYOBJECT sizeof(PyObject)
|
||
|
|
#define SIZEOF_SET_OBJ sizeof(PySetObject)
|
||
|
|
#define SIZEOF_TASK_OBJ 4096
|
||
|
|
#define SIZEOF_THREAD_STATE sizeof(PyThreadState)
|
||
|
|
#define SIZEOF_TYPE_OBJ sizeof(PyTypeObject)
|
||
|
|
#define SIZEOF_UNICODE_OBJ sizeof(PyUnicodeObject)
|
||
|
|
#define SIZEOF_LONG_OBJ sizeof(PyLongObject)
|
||
|
|
#define SIZEOF_GC_RUNTIME_STATE sizeof(struct _gc_runtime_state)
|
||
|
|
#define SIZEOF_INTERPRETER_STATE sizeof(PyInterpreterState)
|
||
|
|
|
||
|
|
#ifndef MAX
|
||
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef Py_GIL_DISABLED
|
||
|
|
#define INTERP_STATE_MIN_SIZE MAX(MAX(MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
|
||
|
|
offsetof(PyInterpreterState, tlbc_indices.tlbc_generation) + sizeof(uint32_t)), \
|
||
|
|
offsetof(PyInterpreterState, threads.head) + sizeof(void*)), \
|
||
|
|
offsetof(PyInterpreterState, _gil.last_holder) + sizeof(PyThreadState*)), \
|
||
|
|
offsetof(PyInterpreterState, gc.frame) + sizeof(_PyInterpreterFrame *))
|
||
|
|
#else
|
||
|
|
#define INTERP_STATE_MIN_SIZE MAX(MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
|
||
|
|
offsetof(PyInterpreterState, threads.head) + sizeof(void*)), \
|
||
|
|
offsetof(PyInterpreterState, _gil.last_holder) + sizeof(PyThreadState*)), \
|
||
|
|
offsetof(PyInterpreterState, gc.frame) + sizeof(_PyInterpreterFrame *))
|
||
|
|
#endif
|
||
|
|
#define INTERP_STATE_BUFFER_SIZE MAX(INTERP_STATE_MIN_SIZE, 256)
|
||
|
|
|
||
|
|
#define MAX_TLBC_SIZE 2048
|
||
|
|
|
||
|
|
/* Thread status flags */
|
||
|
|
#define THREAD_STATUS_HAS_GIL (1 << 0)
|
||
|
|
#define THREAD_STATUS_ON_CPU (1 << 1)
|
||
|
|
#define THREAD_STATUS_UNKNOWN (1 << 2)
|
||
|
|
#define THREAD_STATUS_GIL_REQUESTED (1 << 3)
|
||
|
|
|
||
|
|
/* Exception cause macro */
|
||
|
|
#define set_exception_cause(unwinder, exc_type, message) \
|
||
|
|
if (unwinder->debug) { \
|
||
|
|
_set_debug_exception_cause(exc_type, message); \
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* TYPE DEFINITIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
struct _Py_AsyncioModuleDebugOffsets {
|
||
|
|
struct _asyncio_task_object {
|
||
|
|
uint64_t size;
|
||
|
|
uint64_t task_name;
|
||
|
|
uint64_t task_awaited_by;
|
||
|
|
uint64_t task_is_task;
|
||
|
|
uint64_t task_awaited_by_is_set;
|
||
|
|
uint64_t task_coro;
|
||
|
|
uint64_t task_node;
|
||
|
|
} asyncio_task_object;
|
||
|
|
struct _asyncio_interpreter_state {
|
||
|
|
uint64_t size;
|
||
|
|
uint64_t asyncio_tasks_head;
|
||
|
|
} asyncio_interpreter_state;
|
||
|
|
struct _asyncio_thread_state {
|
||
|
|
uint64_t size;
|
||
|
|
uint64_t asyncio_running_loop;
|
||
|
|
uint64_t asyncio_running_task;
|
||
|
|
uint64_t asyncio_tasks_head;
|
||
|
|
} asyncio_thread_state;
|
||
|
|
};
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
PyObject *func_name;
|
||
|
|
PyObject *file_name;
|
||
|
|
int first_lineno;
|
||
|
|
PyObject *linetable; // bytes
|
||
|
|
uintptr_t addr_code_adaptive;
|
||
|
|
} CachedCodeMetadata;
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
PyTypeObject *RemoteDebugging_Type;
|
||
|
|
PyTypeObject *TaskInfo_Type;
|
||
|
|
PyTypeObject *FrameInfo_Type;
|
||
|
|
PyTypeObject *CoroInfo_Type;
|
||
|
|
PyTypeObject *ThreadInfo_Type;
|
||
|
|
PyTypeObject *InterpreterInfo_Type;
|
||
|
|
PyTypeObject *AwaitedInfo_Type;
|
||
|
|
} RemoteDebuggingState;
|
||
|
|
|
||
|
|
enum _ThreadState {
|
||
|
|
THREAD_STATE_RUNNING,
|
||
|
|
THREAD_STATE_IDLE,
|
||
|
|
THREAD_STATE_GIL_WAIT,
|
||
|
|
THREAD_STATE_UNKNOWN
|
||
|
|
};
|
||
|
|
|
||
|
|
enum _ProfilingMode {
|
||
|
|
PROFILING_MODE_WALL = 0,
|
||
|
|
PROFILING_MODE_CPU = 1,
|
||
|
|
PROFILING_MODE_GIL = 2,
|
||
|
|
PROFILING_MODE_ALL = 3
|
||
|
|
};
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
PyObject_HEAD
|
||
|
|
proc_handle_t handle;
|
||
|
|
uintptr_t runtime_start_address;
|
||
|
|
struct _Py_DebugOffsets debug_offsets;
|
||
|
|
int async_debug_offsets_available;
|
||
|
|
struct _Py_AsyncioModuleDebugOffsets async_debug_offsets;
|
||
|
|
uintptr_t interpreter_addr;
|
||
|
|
uintptr_t tstate_addr;
|
||
|
|
uint64_t code_object_generation;
|
||
|
|
_Py_hashtable_t *code_object_cache;
|
||
|
|
int debug;
|
||
|
|
int only_active_thread;
|
||
|
|
int mode;
|
||
|
|
int skip_non_matching_threads;
|
||
|
|
int native;
|
||
|
|
int gc;
|
||
|
|
RemoteDebuggingState *cached_state;
|
||
|
|
#ifdef Py_GIL_DISABLED
|
||
|
|
uint32_t tlbc_generation;
|
||
|
|
_Py_hashtable_t *tlbc_cache;
|
||
|
|
#endif
|
||
|
|
#ifdef __APPLE__
|
||
|
|
uint64_t thread_id_offset;
|
||
|
|
#endif
|
||
|
|
#ifdef MS_WINDOWS
|
||
|
|
PVOID win_process_buffer;
|
||
|
|
ULONG win_process_buffer_size;
|
||
|
|
#endif
|
||
|
|
} RemoteUnwinderObject;
|
||
|
|
|
||
|
|
#define RemoteUnwinder_CAST(op) ((RemoteUnwinderObject *)(op))
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
int lineno;
|
||
|
|
int end_lineno;
|
||
|
|
int column;
|
||
|
|
int end_column;
|
||
|
|
} LocationInfo;
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
uintptr_t remote_addr;
|
||
|
|
size_t size;
|
||
|
|
void *local_copy;
|
||
|
|
} StackChunkInfo;
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
StackChunkInfo *chunks;
|
||
|
|
size_t count;
|
||
|
|
} StackChunkList;
|
||
|
|
|
||
|
|
/* Function pointer types for iteration callbacks */
|
||
|
|
typedef int (*thread_processor_func)(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t thread_state_addr,
|
||
|
|
unsigned long tid,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
typedef int (*set_entry_processor_func)(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t key_addr,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* STRUCTSEQ DESCRIPTORS (extern declarations)
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern PyStructSequence_Desc TaskInfo_desc;
|
||
|
|
extern PyStructSequence_Desc FrameInfo_desc;
|
||
|
|
extern PyStructSequence_Desc CoroInfo_desc;
|
||
|
|
extern PyStructSequence_Desc ThreadInfo_desc;
|
||
|
|
extern PyStructSequence_Desc InterpreterInfo_desc;
|
||
|
|
extern PyStructSequence_Desc AwaitedInfo_desc;
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* UTILITY FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
/* State access functions */
|
||
|
|
extern RemoteDebuggingState *RemoteDebugging_GetState(PyObject *module);
|
||
|
|
extern RemoteDebuggingState *RemoteDebugging_GetStateFromType(PyTypeObject *type);
|
||
|
|
extern RemoteDebuggingState *RemoteDebugging_GetStateFromObject(PyObject *obj);
|
||
|
|
extern int RemoteDebugging_InitState(RemoteDebuggingState *st);
|
||
|
|
|
||
|
|
/* Cache management */
|
||
|
|
extern void cached_code_metadata_destroy(void *ptr);
|
||
|
|
|
||
|
|
/* Validation */
|
||
|
|
extern int is_prerelease_version(uint64_t version);
|
||
|
|
extern int validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets);
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* MEMORY READING FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern int read_ptr(RemoteUnwinderObject *unwinder, uintptr_t address, uintptr_t *result);
|
||
|
|
extern int read_Py_ssize_t(RemoteUnwinderObject *unwinder, uintptr_t address, Py_ssize_t *result);
|
||
|
|
extern int read_char(RemoteUnwinderObject *unwinder, uintptr_t address, char *result);
|
||
|
|
extern int read_py_ptr(RemoteUnwinderObject *unwinder, uintptr_t address, uintptr_t *ptr_addr);
|
||
|
|
|
||
|
|
/* Python object reading */
|
||
|
|
extern PyObject *read_py_str(RemoteUnwinderObject *unwinder, uintptr_t address, Py_ssize_t max_len);
|
||
|
|
extern PyObject *read_py_bytes(RemoteUnwinderObject *unwinder, uintptr_t address, Py_ssize_t max_len);
|
||
|
|
extern long read_py_long(RemoteUnwinderObject *unwinder, uintptr_t address);
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* CODE OBJECT FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern int parse_code_object(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
PyObject **result,
|
||
|
|
uintptr_t address,
|
||
|
|
uintptr_t instruction_pointer,
|
||
|
|
uintptr_t *previous_frame,
|
||
|
|
int32_t tlbc_index
|
||
|
|
);
|
||
|
|
|
||
|
|
extern PyObject *make_frame_info(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
PyObject *file,
|
||
|
|
PyObject *line,
|
||
|
|
PyObject *func
|
||
|
|
);
|
||
|
|
|
||
|
|
/* Line table parsing */
|
||
|
|
extern bool parse_linetable(
|
||
|
|
const uintptr_t addrq,
|
||
|
|
const char* linetable,
|
||
|
|
int firstlineno,
|
||
|
|
LocationInfo* info
|
||
|
|
);
|
||
|
|
|
||
|
|
/* TLBC cache (only for Py_GIL_DISABLED) */
|
||
|
|
#ifdef Py_GIL_DISABLED
|
||
|
|
typedef struct {
|
||
|
|
void *tlbc_array;
|
||
|
|
Py_ssize_t tlbc_array_size;
|
||
|
|
uint32_t generation;
|
||
|
|
} TLBCCacheEntry;
|
||
|
|
|
||
|
|
extern void tlbc_cache_entry_destroy(void *ptr);
|
||
|
|
extern TLBCCacheEntry *get_tlbc_cache_entry(RemoteUnwinderObject *self, uintptr_t code_addr, uint32_t current_generation);
|
||
|
|
extern int cache_tlbc_array(RemoteUnwinderObject *unwinder, uintptr_t code_addr, uintptr_t tlbc_array_addr, uint32_t generation);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* FRAME FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern int is_frame_valid(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t frame_addr,
|
||
|
|
uintptr_t code_object_addr
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int parse_frame_object(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
PyObject** result,
|
||
|
|
uintptr_t address,
|
||
|
|
uintptr_t* address_of_code_object,
|
||
|
|
uintptr_t* previous_frame
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int parse_frame_from_chunks(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
PyObject **result,
|
||
|
|
uintptr_t address,
|
||
|
|
uintptr_t *previous_frame,
|
||
|
|
uintptr_t *stackpointer,
|
||
|
|
StackChunkList *chunks
|
||
|
|
);
|
||
|
|
|
||
|
|
/* Stack chunk management */
|
||
|
|
extern void cleanup_stack_chunks(StackChunkList *chunks);
|
||
|
|
extern int copy_stack_chunks(RemoteUnwinderObject *unwinder, uintptr_t tstate_addr, StackChunkList *out_chunks);
|
||
|
|
extern void *find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr);
|
||
|
|
|
||
|
|
extern int process_frame_chain(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t initial_frame_addr,
|
||
|
|
StackChunkList *chunks,
|
||
|
|
PyObject *frame_info,
|
||
|
|
uintptr_t gc_frame
|
||
|
|
);
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* THREAD FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern int iterate_threads(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
thread_processor_func processor,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int populate_initial_state_data(
|
||
|
|
int all_threads,
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t runtime_start_address,
|
||
|
|
uintptr_t *interpreter_state,
|
||
|
|
uintptr_t *tstate
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int find_running_frame(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t address_of_thread,
|
||
|
|
uintptr_t *frame
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int get_thread_status(RemoteUnwinderObject *unwinder, uint64_t tid, uint64_t pthread_id);
|
||
|
|
|
||
|
|
extern PyObject* unwind_stack_for_thread(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t *current_tstate,
|
||
|
|
uintptr_t gil_holder_tstate,
|
||
|
|
uintptr_t gc_frame
|
||
|
|
);
|
||
|
|
|
||
|
|
/* ============================================================================
|
||
|
|
* ASYNCIO FUNCTION DECLARATIONS
|
||
|
|
* ============================================================================ */
|
||
|
|
|
||
|
|
extern uintptr_t _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle);
|
||
|
|
extern int read_async_debug(RemoteUnwinderObject *unwinder);
|
||
|
|
|
||
|
|
/* Task parsing */
|
||
|
|
extern PyObject *parse_task_name(RemoteUnwinderObject *unwinder, uintptr_t task_address);
|
||
|
|
|
||
|
|
extern int parse_task(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t task_address,
|
||
|
|
PyObject *render_to
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int parse_coro_chain(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t coro_address,
|
||
|
|
PyObject *render_to
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int parse_async_frame_chain(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
PyObject *calls,
|
||
|
|
uintptr_t address_of_thread,
|
||
|
|
uintptr_t running_task_code_obj
|
||
|
|
);
|
||
|
|
|
||
|
|
/* Set iteration */
|
||
|
|
extern int iterate_set_entries(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t set_addr,
|
||
|
|
set_entry_processor_func processor,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
/* Task awaited_by processing */
|
||
|
|
extern int process_task_awaited_by(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t task_address,
|
||
|
|
set_entry_processor_func processor,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int process_single_task_node(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t task_addr,
|
||
|
|
PyObject **task_info,
|
||
|
|
PyObject *result
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int process_task_and_waiters(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t task_addr,
|
||
|
|
PyObject *result
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int find_running_task_in_thread(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t thread_state_addr,
|
||
|
|
uintptr_t *running_task_addr
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int get_task_code_object(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t task_addr,
|
||
|
|
uintptr_t *code_obj_addr
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int append_awaited_by(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
unsigned long tid,
|
||
|
|
uintptr_t head_addr,
|
||
|
|
PyObject *result
|
||
|
|
);
|
||
|
|
|
||
|
|
/* Thread processors for asyncio */
|
||
|
|
extern int process_thread_for_awaited_by(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t thread_state_addr,
|
||
|
|
unsigned long tid,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
extern int process_thread_for_async_stack_trace(
|
||
|
|
RemoteUnwinderObject *unwinder,
|
||
|
|
uintptr_t thread_state_addr,
|
||
|
|
unsigned long tid,
|
||
|
|
void *context
|
||
|
|
);
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#endif /* Py_REMOTE_DEBUGGING_H */
|