gdb/python/py-finishbreakpoint.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
- #include "defs.h"
- #include "python-internal.h"
- #include "breakpoint.h"
- #include "frame.h"
- #include "gdbthread.h"
- #include "arch-utils.h"
- #include "language.h"
- #include "observer.h"
- #include "inferior.h"
- #include "block.h"
- static char * const outofscope_func = "out_of_scope";
- struct finish_breakpoint_object
- {
-
- gdbpy_breakpoint_object py_bp;
-
- PyObject *return_type;
-
- PyObject *function_value;
-
- PyObject *return_value;
- };
- static PyTypeObject finish_breakpoint_object_type
- CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("finish_breakpoint_object");
- static PyObject *
- bpfinishpy_get_returnvalue (PyObject *self, void *closure)
- {
- struct finish_breakpoint_object *self_finishbp =
- (struct finish_breakpoint_object *) self;
- if (!self_finishbp->return_value)
- Py_RETURN_NONE;
- Py_INCREF (self_finishbp->return_value);
- return self_finishbp->return_value;
- }
- static void
- bpfinishpy_dealloc (PyObject *self)
- {
- struct finish_breakpoint_object *self_bpfinish =
- (struct finish_breakpoint_object *) self;
- Py_XDECREF (self_bpfinish->function_value);
- Py_XDECREF (self_bpfinish->return_type);
- Py_XDECREF (self_bpfinish->return_value);
- }
- void
- bpfinishpy_pre_stop_hook (struct gdbpy_breakpoint_object *bp_obj)
- {
- struct finish_breakpoint_object *self_finishbp =
- (struct finish_breakpoint_object *) bp_obj;
- volatile struct gdb_exception except;
-
- gdb_assert (!self_finishbp->return_value);
- if (!self_finishbp->return_type)
- return;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- struct value *function =
- value_object_to_value (self_finishbp->function_value);
- struct type *value_type =
- type_object_to_type (self_finishbp->return_type);
- struct value *ret = get_return_value (function, value_type);
- if (ret)
- {
- self_finishbp->return_value = value_to_value_object (ret);
- if (!self_finishbp->return_value)
- gdbpy_print_stack ();
- }
- else
- {
- Py_INCREF (Py_None);
- self_finishbp->return_value = Py_None;
- }
- }
- if (except.reason < 0)
- {
- gdbpy_convert_exception (except);
- gdbpy_print_stack ();
- }
- }
- void
- bpfinishpy_post_stop_hook (struct gdbpy_breakpoint_object *bp_obj)
- {
- volatile struct gdb_exception except;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
-
- disable_breakpoint (bp_obj->bp);
- gdb_assert (bp_obj->bp->disposition == disp_del);
- }
- if (except.reason < 0)
- {
- gdbpy_convert_exception (except);
- gdbpy_print_stack ();
- }
- }
- static int
- bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
- {
- static char *keywords[] = { "frame", "internal", NULL };
- struct finish_breakpoint_object *self_bpfinish =
- (struct finish_breakpoint_object *) self;
- int type = bp_breakpoint;
- PyObject *frame_obj = NULL;
- int thread;
- struct frame_info *frame = NULL;
- struct frame_info *prev_frame = NULL;
- struct frame_id frame_id;
- PyObject *internal = NULL;
- int internal_bp = 0;
- CORE_ADDR finish_pc, pc;
- volatile struct gdb_exception except;
- char *addr_str, small_buf[100];
- struct symbol *function;
- if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
- &frame_obj, &internal))
- return -1;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
-
- if (frame_obj == NULL)
- frame = get_current_frame ();
- else
- frame = frame_object_to_frame_info (frame_obj);
- if (frame == NULL)
- {
- PyErr_SetString (PyExc_ValueError,
- _("Invalid ID for the `frame' object."));
- }
- else
- {
- prev_frame = get_prev_frame (frame);
- if (prev_frame == 0)
- {
- PyErr_SetString (PyExc_ValueError,
- _("\"FinishBreakpoint\" not "
- "meaningful in the outermost "
- "frame."));
- }
- else if (get_frame_type (prev_frame) == DUMMY_FRAME)
- {
- PyErr_SetString (PyExc_ValueError,
- _("\"FinishBreakpoint\" cannot "
- "be set on a dummy frame."));
- }
- else
- {
- frame_id = get_frame_id (prev_frame);
- if (frame_id_eq (frame_id, null_frame_id))
- PyErr_SetString (PyExc_ValueError,
- _("Invalid ID for the `frame' object."));
- }
- }
- }
- if (except.reason < 0)
- {
- gdbpy_convert_exception (except);
- return -1;
- }
- else if (PyErr_Occurred ())
- return -1;
- thread = pid_to_thread_id (inferior_ptid);
- if (thread == 0)
- {
- PyErr_SetString (PyExc_ValueError,
- _("No thread currently selected."));
- return -1;
- }
- if (internal)
- {
- internal_bp = PyObject_IsTrue (internal);
- if (internal_bp == -1)
- {
- PyErr_SetString (PyExc_ValueError,
- _("The value of `internal' must be a boolean."));
- return -1;
- }
- }
-
- self_bpfinish->return_type = NULL;
- self_bpfinish->function_value = NULL;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- if (get_frame_pc_if_available (frame, &pc))
- {
- function = find_pc_function (pc);
- if (function != NULL)
- {
- struct type *ret_type =
- TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
-
- if (TYPE_CODE (ret_type) != TYPE_CODE_VOID)
- {
- struct value *func_value;
-
- self_bpfinish->return_type = type_to_type_object (ret_type);
- PyErr_Clear ();
- func_value = read_var_value (function, frame);
- self_bpfinish->function_value =
- value_to_value_object (func_value);
- PyErr_Clear ();
- }
- }
- }
- }
- if (except.reason < 0
- || !self_bpfinish->return_type || !self_bpfinish->function_value)
- {
-
- Py_XDECREF (self_bpfinish->return_type);
- Py_XDECREF (self_bpfinish->function_value);
- self_bpfinish->return_type = NULL;
- self_bpfinish->function_value = NULL;
- }
- bppy_pending_object = &self_bpfinish->py_bp;
- bppy_pending_object->number = -1;
- bppy_pending_object->bp = NULL;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
-
- finish_pc = get_frame_pc (prev_frame);
- xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc));
- addr_str = small_buf;
- create_breakpoint (python_gdbarch,
- addr_str, NULL, thread, NULL,
- 0,
- 1 ,
- bp_breakpoint,
- 0,
- AUTO_BOOLEAN_TRUE,
- &bkpt_breakpoint_ops,
- 0, 1, internal_bp, 0);
- }
- GDB_PY_SET_HANDLE_EXCEPTION (except);
- self_bpfinish->py_bp.bp->frame_id = frame_id;
- self_bpfinish->py_bp.is_finish_bp = 1;
-
- self_bpfinish->py_bp.bp->pspace = current_program_space;
- return 0;
- }
- static void
- bpfinishpy_out_of_scope (struct finish_breakpoint_object *bpfinish_obj)
- {
- gdbpy_breakpoint_object *bp_obj = (gdbpy_breakpoint_object *) bpfinish_obj;
- PyObject *py_obj = (PyObject *) bp_obj;
- if (bpfinish_obj->py_bp.bp->enable_state == bp_enabled
- && PyObject_HasAttrString (py_obj, outofscope_func))
- {
- PyObject *meth_result;
- meth_result = PyObject_CallMethod (py_obj, outofscope_func, NULL);
- if (meth_result == NULL)
- gdbpy_print_stack ();
- Py_XDECREF (meth_result);
- }
- delete_breakpoint (bpfinish_obj->py_bp.bp);
- }
- static int
- bpfinishpy_detect_out_scope_cb (struct breakpoint *b, void *args)
- {
- volatile struct gdb_exception except;
- struct breakpoint *bp_stopped = (struct breakpoint *) args;
- PyObject *py_bp = (PyObject *) b->py_bp_object;
- struct gdbarch *garch = b->gdbarch ? b->gdbarch : get_current_arch ();
-
- if (py_bp != NULL && b->py_bp_object->is_finish_bp)
- {
- struct finish_breakpoint_object *finish_bp =
- (struct finish_breakpoint_object *) py_bp;
-
- if (b != bp_stopped)
- {
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- if (b->pspace == current_inferior ()->pspace
- && (!target_has_registers
- || frame_find_by_id (b->frame_id) == NULL))
- bpfinishpy_out_of_scope (finish_bp);
- }
- if (except.reason < 0)
- {
- gdbpy_convert_exception (except);
- gdbpy_print_stack ();
- }
- }
- }
- return 0;
- }
- static void
- bpfinishpy_handle_stop (struct bpstats *bs, int print_frame)
- {
- struct cleanup *cleanup = ensure_python_env (get_current_arch (),
- current_language);
- iterate_over_breakpoints (bpfinishpy_detect_out_scope_cb,
- bs == NULL ? NULL : bs->breakpoint_at);
- do_cleanups (cleanup);
- }
- static void
- bpfinishpy_handle_exit (struct inferior *inf)
- {
- struct cleanup *cleanup = ensure_python_env (target_gdbarch (),
- current_language);
- iterate_over_breakpoints (bpfinishpy_detect_out_scope_cb, NULL);
- do_cleanups (cleanup);
- }
- int
- gdbpy_initialize_finishbreakpoints (void)
- {
- if (PyType_Ready (&finish_breakpoint_object_type) < 0)
- return -1;
- if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
- (PyObject *) &finish_breakpoint_object_type) < 0)
- return -1;
- observer_attach_normal_stop (bpfinishpy_handle_stop);
- observer_attach_inferior_exit (bpfinishpy_handle_exit);
- return 0;
- }
- static PyGetSetDef finish_breakpoint_object_getset[] = {
- { "return_value", bpfinishpy_get_returnvalue, NULL,
- "gdb.Value object representing the return value, if any. \
- None otherwise.", NULL },
- { NULL }
- };
- static PyTypeObject finish_breakpoint_object_type =
- {
- PyVarObject_HEAD_INIT (NULL, 0)
- "gdb.FinishBreakpoint",
- sizeof (struct finish_breakpoint_object),
- 0,
- bpfinishpy_dealloc,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- "GDB finish breakpoint object",
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- finish_breakpoint_object_getset,
- &breakpoint_object_type,
- 0,
- 0,
- 0,
- 0,
- bpfinishpy_init,
- 0,
- 0
- };