mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-135371: Clean tags from pointers in all cases in remote debugging module (#135534)
This commit is contained in:
parent
81237fbcf6
commit
b9a1b04982
1 changed files with 60 additions and 46 deletions
|
@ -39,6 +39,8 @@
|
|||
* ============================================================================ */
|
||||
|
||||
#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)
|
||||
|
@ -243,6 +245,13 @@ module _remote_debugging
|
|||
* FORWARD DECLARATIONS
|
||||
* ============================================================================ */
|
||||
|
||||
static inline int
|
||||
is_frame_valid(
|
||||
RemoteUnwinderObject *unwinder,
|
||||
uintptr_t frame_addr,
|
||||
uintptr_t code_object_addr
|
||||
);
|
||||
|
||||
static int
|
||||
parse_tasks_in_set(
|
||||
RemoteUnwinderObject *unwinder,
|
||||
|
@ -734,8 +743,7 @@ parse_task_name(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uintptr_t task_name_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_name);
|
||||
task_name_addr &= ~Py_TAG_BITS;
|
||||
uintptr_t task_name_addr = GET_MEMBER_NO_TAG(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_name);
|
||||
|
||||
// The task name can be a long or a string so we need to check the type
|
||||
char task_name_obj[SIZEOF_PYOBJECT];
|
||||
|
@ -798,8 +806,7 @@ static int parse_task_awaited_by(
|
|||
return -1;
|
||||
}
|
||||
|
||||
uintptr_t task_ab_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_awaited_by);
|
||||
task_ab_addr &= ~Py_TAG_BITS;
|
||||
uintptr_t task_ab_addr = GET_MEMBER_NO_TAG(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_awaited_by);
|
||||
|
||||
if ((void*)task_ab_addr == NULL) {
|
||||
return 0;
|
||||
|
@ -849,8 +856,7 @@ handle_yield_from_frame(
|
|||
return -1;
|
||||
}
|
||||
|
||||
uintptr_t stackpointer_addr = GET_MEMBER(uintptr_t, iframe, unwinder->debug_offsets.interpreter_frame.stackpointer);
|
||||
stackpointer_addr &= ~Py_TAG_BITS;
|
||||
uintptr_t stackpointer_addr = GET_MEMBER_NO_TAG(uintptr_t, iframe, unwinder->debug_offsets.interpreter_frame.stackpointer);
|
||||
|
||||
if ((void*)stackpointer_addr != NULL) {
|
||||
uintptr_t gi_await_addr;
|
||||
|
@ -917,6 +923,11 @@ parse_coro_chain(
|
|||
return -1;
|
||||
}
|
||||
|
||||
int8_t frame_state = GET_MEMBER(int8_t, gen_object, unwinder->debug_offsets.gen_object.gi_frame_state);
|
||||
if (frame_state == FRAME_CLEARED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t gen_type_addr = GET_MEMBER(uintptr_t, gen_object, unwinder->debug_offsets.pyobject.ob_type);
|
||||
|
||||
PyObject* name = NULL;
|
||||
|
@ -936,7 +947,7 @@ parse_coro_chain(
|
|||
}
|
||||
Py_DECREF(name);
|
||||
|
||||
if (GET_MEMBER(int8_t, gen_object, unwinder->debug_offsets.gen_object.gi_frame_state) == FRAME_SUSPENDED_YIELD_FROM) {
|
||||
if (frame_state == FRAME_SUSPENDED_YIELD_FROM) {
|
||||
return handle_yield_from_frame(unwinder, gi_iframe_addr, gen_type_addr, render_to);
|
||||
}
|
||||
|
||||
|
@ -981,8 +992,7 @@ create_task_result(
|
|||
goto error;
|
||||
}
|
||||
|
||||
coro_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_coro);
|
||||
coro_addr &= ~Py_TAG_BITS;
|
||||
coro_addr = GET_MEMBER_NO_TAG(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_coro);
|
||||
|
||||
if ((void*)coro_addr != NULL) {
|
||||
if (parse_coro_chain(unwinder, coro_addr, call_stack) < 0) {
|
||||
|
@ -1816,10 +1826,10 @@ parse_frame_from_chunks(
|
|||
|
||||
char *frame = (char *)frame_ptr;
|
||||
*previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) >= FRAME_OWNED_BY_INTERPRETER ||
|
||||
!GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable)) {
|
||||
return 0;
|
||||
uintptr_t code_object = GET_MEMBER_NO_TAG(uintptr_t, frame_ptr, unwinder->debug_offsets.interpreter_frame.executable);
|
||||
int frame_valid = is_frame_valid(unwinder, (uintptr_t)frame, code_object);
|
||||
if (frame_valid != 1) {
|
||||
return frame_valid;
|
||||
}
|
||||
|
||||
uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
|
||||
|
@ -1832,9 +1842,7 @@ parse_frame_from_chunks(
|
|||
}
|
||||
#endif
|
||||
|
||||
return parse_code_object(
|
||||
unwinder, result, GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable),
|
||||
instruction_pointer, previous_frame, tlbc_index);
|
||||
return parse_code_object(unwinder, result, code_object, instruction_pointer, previous_frame, tlbc_index);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
|
@ -2077,6 +2085,33 @@ find_running_task_and_coro(
|
|||
* FRAME PARSING FUNCTIONS
|
||||
* ============================================================================ */
|
||||
|
||||
static inline int
|
||||
is_frame_valid(
|
||||
RemoteUnwinderObject *unwinder,
|
||||
uintptr_t frame_addr,
|
||||
uintptr_t code_object_addr
|
||||
) {
|
||||
if ((void*)code_object_addr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* frame = (void*)frame_addr;
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_CSTACK ||
|
||||
GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_INTERPRETER) {
|
||||
return 0; // C frame
|
||||
}
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_GENERATOR
|
||||
&& GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_THREAD) {
|
||||
PyErr_Format(PyExc_RuntimeError, "Unhandled frame owner %d.\n",
|
||||
GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner));
|
||||
set_exception_cause(unwinder, PyExc_RuntimeError, "Unhandled frame owner type in async frame");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_frame_object(
|
||||
RemoteUnwinderObject *unwinder,
|
||||
|
@ -2098,13 +2133,10 @@ parse_frame_object(
|
|||
}
|
||||
|
||||
*previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) >= FRAME_OWNED_BY_INTERPRETER) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((void*)GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable) == NULL) {
|
||||
return 0;
|
||||
uintptr_t code_object = GET_MEMBER_NO_TAG(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable);
|
||||
int frame_valid = is_frame_valid(unwinder, (uintptr_t)frame, code_object);
|
||||
if (frame_valid != 1) {
|
||||
return frame_valid;
|
||||
}
|
||||
|
||||
uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
|
||||
|
@ -2117,9 +2149,7 @@ parse_frame_object(
|
|||
}
|
||||
#endif
|
||||
|
||||
return parse_code_object(
|
||||
unwinder, result, GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable),
|
||||
instruction_pointer, previous_frame, tlbc_index);
|
||||
return parse_code_object(unwinder, result, code_object,instruction_pointer, previous_frame, tlbc_index);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2144,26 +2174,10 @@ parse_async_frame_object(
|
|||
}
|
||||
|
||||
*previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
|
||||
|
||||
*code_object = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable);
|
||||
// Strip tag bits for consistent comparison
|
||||
*code_object &= ~Py_TAG_BITS;
|
||||
assert(code_object != NULL);
|
||||
if ((void*)*code_object == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_CSTACK ||
|
||||
GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_INTERPRETER) {
|
||||
return 0; // C frame
|
||||
}
|
||||
|
||||
if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_GENERATOR
|
||||
&& GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_THREAD) {
|
||||
PyErr_Format(PyExc_RuntimeError, "Unhandled frame owner %d.\n",
|
||||
GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner));
|
||||
set_exception_cause(unwinder, PyExc_RuntimeError, "Unhandled frame owner type in async frame");
|
||||
return -1;
|
||||
*code_object = GET_MEMBER_NO_TAG(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable);
|
||||
int frame_valid = is_frame_valid(unwinder, (uintptr_t)frame, *code_object);
|
||||
if (frame_valid != 1) {
|
||||
return frame_valid;
|
||||
}
|
||||
|
||||
uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue