#define PYUW_SCOPED_DEBUG_ENTER_EXIT \
scoped_debug_enter_exit (pyuw_debug, "py-unwind")
+/* Require a valid pending frame. */
+#define PENDING_FRAMEPY_REQUIRE_VALID(pending_frame) \
+ do { \
+ if ((pending_frame)->frame_info == nullptr) \
+ { \
+ PyErr_SetString (PyExc_ValueError, \
+ _("gdb.PendingFrame is invalid.")); \
+ return nullptr; \
+ } \
+ } while (0)
+
struct pending_frame_object
{
PyObject_HEAD
}
/* Create UnwindInfo instance for given PendingFrame and frame ID.
- Sets Python error and returns NULL on error. */
+ Sets Python error and returns NULL on error.
+
+ The PYO_PENDING_FRAME object must be valid. */
static PyObject *
pyuw_create_unwind_info (PyObject *pyo_pending_frame,
struct frame_id frame_id)
{
+ gdb_assert (((pending_frame_object *) pyo_pending_frame)->frame_info
+ != nullptr);
+
unwind_info_object *unwind_info
- = PyObject_New (unwind_info_object, &unwind_info_object_type);
+ = PyObject_New (unwind_info_object, &unwind_info_object_type);
- if (((pending_frame_object *) pyo_pending_frame)->frame_info == NULL)
- {
- PyErr_SetString (PyExc_ValueError,
- "Attempting to use stale PendingFrame");
- return NULL;
- }
unwind_info->frame_id = frame_id;
Py_INCREF (pyo_pending_frame);
unwind_info->pending_frame = pyo_pending_frame;
pending_framepy_read_register (PyObject *self, PyObject *args)
{
pending_frame_object *pending_frame = (pending_frame_object *) self;
+ PENDING_FRAMEPY_REQUIRE_VALID (pending_frame);
+
int regnum;
PyObject *pyo_reg_id;
- if (pending_frame->frame_info == NULL)
- {
- PyErr_SetString (PyExc_ValueError,
- "Attempting to read register from stale PendingFrame");
- return NULL;
- }
if (!PyArg_UnpackTuple (args, "read_register", 1, 1, &pyo_reg_id))
return NULL;
if (!gdbpy_parse_register_id (pending_frame->gdbarch, pyo_reg_id, ®num))
CORE_ADDR pc;
CORE_ADDR special;
+ PENDING_FRAMEPY_REQUIRE_VALID ((pending_frame_object *) self);
+
if (!PyArg_ParseTuple (args, "O:create_unwind_info", &pyo_frame_id))
return NULL;
if (!pyuw_object_attribute_to_pointer (pyo_frame_id, "sp", &sp))
{
pending_frame_object *pending_frame = (pending_frame_object *) self;
- if (pending_frame->frame_info == NULL)
- {
- PyErr_SetString (PyExc_ValueError,
- "Attempting to read register from stale PendingFrame");
- return NULL;
- }
+ PENDING_FRAMEPY_REQUIRE_VALID (pending_frame);
+
return gdbarch_to_arch_object (pending_frame->gdbarch);
}
{
pending_frame_object *pending_frame = (pending_frame_object *) self;
- if (pending_frame->frame_info == NULL)
- {
- PyErr_SetString (PyExc_ValueError,
- "Attempting to read stack level from stale PendingFrame");
- return NULL;
- }
+ PENDING_FRAMEPY_REQUIRE_VALID (pending_frame);
+
int level = frame_relative_level (pending_frame->frame_info);
return gdb_py_object_from_longest (level).release ();
}
return 0;
}
pfo->gdbarch = gdbarch;
+ pfo->frame_info = nullptr;
scoped_restore invalidate_frame = make_scoped_restore (&pfo->frame_info,
this_frame);
[multi_line \
"TypeError: incorrect type for name: <class 'bool'>" \
"Error while executing Python code\\."]
+
+# Now register the simple_unwinder with a valid name, and use the
+# unwinder to capture a PendingFrame object.
+gdb_test_no_output "python obj = simple_unwinder(\"simple\")"
+gdb_test_no_output "python gdb.unwinder.register_unwinder(None, obj)"
+check_for_broken_backtrace "backtrace to capture a PendingFrame object"
+
+# Call methods on the captured gdb.PendingFrame and check we see the
+# expected error.
+gdb_test_no_output "python pf = captured_pending_frame"
+foreach cmd {"pf.read_register(\"pc\")" \
+ "pf.create_unwind_info(None)" \
+ "pf.architecture()" \
+ "pf.level()"} {
+ gdb_test "python $cmd" \
+ [multi_line \
+ "ValueError: gdb\\.PendingFrame is invalid\\." \
+ "Error while executing Python code\\."]
+}