GH-100987: Allow objects other than code objects as the "executable" of an internal frame. (GH-105727)

* Add table describing possible executable classes for out-of-process debuggers.

* Remove shim code object creation code as it is no longer needed.

* Make lltrace a bit more robust w.r.t. non-standard frames.
This commit is contained in:
Mark Shannon 2023-06-14 13:46:37 +01:00 committed by GitHub
parent ad56340b66
commit 7199584ac8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 541 additions and 606 deletions

View file

@ -14,7 +14,7 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
Py_VISIT(frame->frame_obj);
Py_VISIT(frame->f_locals);
Py_VISIT(frame->f_funcobj);
Py_VISIT(frame->f_code);
Py_VISIT(_PyFrame_GetCode(frame));
/* locals */
PyObject **locals = _PyFrame_GetLocalsArray(frame);
int i = 0;
@ -31,7 +31,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
assert(frame->frame_obj == NULL);
PyObject *exc = PyErr_GetRaisedException();
PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame));
if (f == NULL) {
Py_XDECREF(exc);
return NULL;
@ -65,7 +65,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
void
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
{
assert(src->stacktop >= src->f_code->co_nlocalsplus);
assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
memcpy(dest, src, size);
// Don't leave a dangling pointer to the old frame when creating generators
@ -81,7 +81,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
assert(frame->owner != FRAME_CLEARED);
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
Py_INCREF(frame->f_code);
Py_INCREF(_PyFrame_GetCode(frame));
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
frame = (_PyInterpreterFrame *)f->_f_frame_data;
f->f_frame = frame;
@ -89,7 +89,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
if (_PyFrame_IsIncomplete(frame)) {
// This may be a newly-created generator or coroutine frame. Since it's
// dead anyways, just pretend that the first RESUME ran:
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
}
assert(!_PyFrame_IsIncomplete(frame));
@ -149,7 +149,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
PyObject *
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
{
PyObject *code = (PyObject *)frame->f_code;
PyObject *code = frame->f_executable;
Py_INCREF(code);
return code;
}
@ -164,5 +164,13 @@ int
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
{
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
return PyCode_Addr2Line(frame->f_code, addr);
return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
}
const PyTypeObject *const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1] = {
[PY_EXECUTABLE_KIND_SKIP] = &_PyNone_Type,
[PY_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type,
[PY_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type,
[PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
[PY_EXECUTABLE_KINDS] = NULL,
};