X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fpython%2Fpy-finishbreakpoint.c;h=7f818213bd20376fd52a46d4a3df1543d0888b43;hb=33d569b709886a1208145806da80b689d9cae9da;hp=7b2d319039e3815d3f9e2a0a1aeca60190409024;hpb=f5656eadf4383cc733b96ff49ba8efbea6922ad3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c index 7b2d319039..7f818213bd 100644 --- a/gdb/python/py-finishbreakpoint.c +++ b/gdb/python/py-finishbreakpoint.c @@ -1,6 +1,6 @@ /* Python interface to finish breakpoints - Copyright (C) 2011-2012 Free Software Foundation, Inc. + Copyright (C) 2011-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -20,28 +20,26 @@ #include "defs.h" -#include "exceptions.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 "observable.h" #include "inferior.h" #include "block.h" - -static PyTypeObject finish_breakpoint_object_type; +#include "location.h" /* Function that is called when a Python finish bp is found out of scope. */ -static char * const outofscope_func = "out_of_scope"; +static const char outofscope_func[] = "out_of_scope"; /* struct implementing the gdb.FinishBreakpoint object by extending the gdb.Breakpoint class. */ struct finish_breakpoint_object { /* gdb.Breakpoint base class. */ - breakpoint_object py_bp; + gdbpy_breakpoint_object py_bp; /* gdb.Type object of the value return by the breakpointed function. May be NULL if no debug information was available or return type was VOID. */ @@ -55,6 +53,9 @@ struct finish_breakpoint_object PyObject *return_value; }; +extern PyTypeObject finish_breakpoint_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("finish_breakpoint_object"); + /* Python function to get the 'return_value' attribute of FinishBreakpoint. */ @@ -89,11 +90,10 @@ bpfinishpy_dealloc (PyObject *self) `return_value', if possible. */ void -bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj) +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; /* Can compute return_value only once. */ gdb_assert (!self_finishbp->return_value); @@ -101,7 +101,7 @@ bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj) if (!self_finishbp->return_type) return; - TRY_CATCH (except, RETURN_MASK_ALL) + try { struct value *function = value_object_to_value (self_finishbp->function_value); @@ -121,7 +121,7 @@ bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj) self_finishbp->return_value = Py_None; } } - if (except.reason < 0) + catch (const gdb_exception &except) { gdbpy_convert_exception (except); gdbpy_print_stack (); @@ -132,17 +132,16 @@ bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj) of the gdb.FinishBreakpoint object BP_OBJ. */ void -bpfinishpy_post_stop_hook (struct breakpoint_object *bp_obj) +bpfinishpy_post_stop_hook (struct gdbpy_breakpoint_object *bp_obj) { - volatile struct gdb_exception except; - TRY_CATCH (except, RETURN_MASK_ALL) + try { /* Can't delete it here, but it will be removed at the next stop. */ disable_breakpoint (bp_obj->bp); gdb_assert (bp_obj->bp->disposition == disp_del); } - if (except.reason < 0) + catch (const gdb_exception &except) { gdbpy_convert_exception (except); gdbpy_print_stack (); @@ -154,81 +153,85 @@ bpfinishpy_post_stop_hook (struct breakpoint_object *bp_obj) static int bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) { - static char *keywords[] = { "frame", "internal", NULL }; + static const 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, *prev_frame = NULL; + struct frame_info *frame = NULL; /* init for gcc -Wall */ + 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]; + CORE_ADDR pc; struct symbol *function; - if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords, - &frame_obj, &internal)) + if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords, + &frame_obj, &internal)) return -1; - /* Default frame to gdb.newest_frame if necessary. */ - if (!frame_obj) - frame_obj = gdbpy_newest_frame (NULL, NULL); - else - Py_INCREF (frame_obj); - - frame = frame_object_to_frame_info (frame_obj); - Py_DECREF (frame_obj); - - if (frame == NULL) - goto invalid_frame; - - TRY_CATCH (except, RETURN_MASK_ALL) + try { - 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.")); - } + /* Default frame to newest frame if necessary. */ + if (frame_obj == NULL) + frame = get_current_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.")); - } + 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) + catch (const gdb_exception &except) { gdbpy_convert_exception (except); return -1; } - else if (PyErr_Occurred ()) + + if (PyErr_Occurred ()) return -1; - thread = pid_to_thread_id (inferior_ptid); - if (thread == 0) + if (inferior_ptid == null_ptid) { PyErr_SetString (PyExc_ValueError, _("No thread currently selected.")); return -1; } + thread = inferior_thread ()->global_num; + if (internal) { internal_bp = PyObject_IsTrue (internal); - if (internal_bp == -1) + if (internal_bp == -1) { - PyErr_SetString (PyExc_ValueError, + PyErr_SetString (PyExc_ValueError, _("The value of `internal' must be a boolean.")); return -1; } @@ -238,7 +241,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) self_bpfinish->return_type = NULL; self_bpfinish->function_value = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) + try { if (get_frame_pc_if_available (frame, &pc)) { @@ -246,7 +249,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) if (function != NULL) { struct type *ret_type = - TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (function))); /* Remember only non-void return types. */ if (TYPE_CODE (ret_type) != TYPE_CODE_VOID) @@ -256,7 +259,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) /* Ignore Python errors at this stage. */ self_bpfinish->return_type = type_to_type_object (ret_type); PyErr_Clear (); - func_value = read_var_value (function, frame); + func_value = read_var_value (function, NULL, frame); self_bpfinish->function_value = value_to_value_object (func_value); PyErr_Clear (); @@ -264,8 +267,13 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) } } } - if (except.reason < 0 - || !self_bpfinish->return_type || !self_bpfinish->function_value) + catch (const gdb_exception &except) + { + /* Just swallow. Either the return type or the function value + remain NULL. */ + } + + if (self_bpfinish->return_type == NULL || self_bpfinish->function_value == NULL) { /* Won't be able to compute return value. */ Py_XDECREF (self_bpfinish->return_type); @@ -279,15 +287,13 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) bppy_pending_object->number = -1; bppy_pending_object->bp = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) + try { /* Set a breakpoint on the return address. */ - finish_pc = get_frame_pc (prev_frame); - xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc)); - addr_str = small_buf; - + event_location_up location + = new_address_location (get_frame_pc (prev_frame), NULL, 0); create_breakpoint (python_gdbarch, - addr_str, NULL, thread, NULL, + location.get (), NULL, thread, NULL, 0, 1 /*temp_flag*/, bp_breakpoint, @@ -296,20 +302,18 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) &bkpt_breakpoint_ops, 0, 1, internal_bp, 0); } - GDB_PY_SET_HANDLE_EXCEPTION (except); - + catch (const gdb_exception &except) + { + GDB_PY_SET_HANDLE_EXCEPTION (except); + } + self_bpfinish->py_bp.bp->frame_id = frame_id; self_bpfinish->py_bp.is_finish_bp = 1; - + /* Bind the breakpoint with the current program space. */ self_bpfinish->py_bp.bp->pspace = current_program_space; return 0; - - invalid_frame: - PyErr_SetString (PyExc_ValueError, - _("Invalid ID for the `frame' object.")); - return -1; } /* Called when GDB notices that the finish breakpoint BP_OBJ is out of @@ -319,14 +323,16 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) static void bpfinishpy_out_of_scope (struct finish_breakpoint_object *bpfinish_obj) { - breakpoint_object *bp_obj = (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)) { - if (!PyObject_CallMethod (py_obj, outofscope_func, NULL)) - gdbpy_print_stack (); + gdbpy_ref<> meth_result (PyObject_CallMethod (py_obj, outofscope_func, + NULL)); + if (meth_result == NULL) + gdbpy_print_stack (); } delete_breakpoint (bpfinish_obj->py_bp.bp); @@ -335,14 +341,12 @@ bpfinishpy_out_of_scope (struct finish_breakpoint_object *bpfinish_obj) /* Callback for `bpfinishpy_detect_out_scope'. Triggers Python's `B->out_of_scope' function if B is a FinishBreakpoint out of its scope. */ -static int -bpfinishpy_detect_out_scope_cb (struct breakpoint *b, void *args) +static bool +bpfinishpy_detect_out_scope_cb (struct breakpoint *b, + struct breakpoint *bp_stopped) { - 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 (); - + /* Trigger out_of_scope if this is a FinishBreakpoint and its frame is not anymore in the current callstack. */ if (py_bp != NULL && b->py_bp_object->is_finish_bp) @@ -353,14 +357,14 @@ bpfinishpy_detect_out_scope_cb (struct breakpoint *b, void *args) /* Check scope if not currently stopped at the FinishBreakpoint. */ if (b != bp_stopped) { - TRY_CATCH (except, RETURN_MASK_ALL) + try { 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) + catch (const gdb_exception &except) { gdbpy_convert_exception (except); gdbpy_print_stack (); @@ -377,13 +381,13 @@ bpfinishpy_detect_out_scope_cb (struct breakpoint *b, void *args) 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); + gdbpy_enter enter_py (get_current_arch (), current_language); - do_cleanups (cleanup); + iterate_over_breakpoints ([&] (breakpoint *bp) + { + return bpfinishpy_detect_out_scope_cb + (bp, bs == NULL ? NULL : bs->breakpoint_at); + }); } /* Attached to `exit' notifications, triggers all the necessary out of @@ -392,41 +396,42 @@ bpfinishpy_handle_stop (struct bpstats *bs, int print_frame) 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); + gdbpy_enter enter_py (target_gdbarch (), current_language); - do_cleanups (cleanup); + iterate_over_breakpoints ([&] (breakpoint *bp) + { + return bpfinishpy_detect_out_scope_cb (bp, nullptr); + }); } /* Initialize the Python finish breakpoint code. */ -void +int gdbpy_initialize_finishbreakpoints (void) { if (PyType_Ready (&finish_breakpoint_object_type) < 0) - return; - - Py_INCREF (&finish_breakpoint_object_type); - PyModule_AddObject (gdb_module, "FinishBreakpoint", - (PyObject *) &finish_breakpoint_object_type); - - observer_attach_normal_stop (bpfinishpy_handle_stop); - observer_attach_inferior_exit (bpfinishpy_handle_exit); + return -1; + + if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint", + (PyObject *) &finish_breakpoint_object_type) < 0) + return -1; + + gdb::observers::normal_stop.attach (bpfinishpy_handle_stop); + gdb::observers::inferior_exit.attach (bpfinishpy_handle_exit); + + return 0; } -static PyGetSetDef finish_breakpoint_object_getset[] = { +static gdb_PyGetSetDef finish_breakpoint_object_getset[] = { { "return_value", bpfinishpy_get_returnvalue, NULL, "gdb.Value object representing the return value, if any. \ None otherwise.", NULL }, { NULL } /* Sentinel. */ }; -static PyTypeObject finish_breakpoint_object_type = +PyTypeObject finish_breakpoint_object_type = { - PyObject_HEAD_INIT (NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT (NULL, 0) "gdb.FinishBreakpoint", /*tp_name*/ sizeof (struct finish_breakpoint_object), /*tp_basicsize*/ 0, /*tp_itemsize*/