GDB (xrefs)
py-finishbreakpoint.c
Go to the documentation of this file.
1 /* Python interface to finish breakpoints
2 
3  Copyright (C) 2011-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 
20 
21 
22 #include "defs.h"
23 #include "python-internal.h"
24 #include "breakpoint.h"
25 #include "frame.h"
26 #include "gdbthread.h"
27 #include "arch-utils.h"
28 #include "language.h"
29 #include "observer.h"
30 #include "inferior.h"
31 #include "block.h"
32 
33 /* Function that is called when a Python finish bp is found out of scope. */
34 static char * const outofscope_func = "out_of_scope";
35 
36 /* struct implementing the gdb.FinishBreakpoint object by extending
37  the gdb.Breakpoint class. */
39 {
40  /* gdb.Breakpoint base class. */
42  /* gdb.Type object of the value return by the breakpointed function.
43  May be NULL if no debug information was available or return type
44  was VOID. */
45  PyObject *return_type;
46  /* gdb.Value object of the function finished by this breakpoint. Will be
47  NULL if return_type is NULL. */
48  PyObject *function_value;
49  /* When stopped at this FinishBreakpoint, gdb.Value object returned by
50  the function; Py_None if the value is not computable; NULL if GDB is
51  not stopped at a FinishBreakpoint. */
52  PyObject *return_value;
53 };
54 
55 extern PyTypeObject finish_breakpoint_object_type
56  CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("finish_breakpoint_object");
57 
58 /* Python function to get the 'return_value' attribute of
59  FinishBreakpoint. */
60 
61 static PyObject *
62 bpfinishpy_get_returnvalue (PyObject *self, void *closure)
63 {
64  struct finish_breakpoint_object *self_finishbp =
65  (struct finish_breakpoint_object *) self;
66 
67  if (!self_finishbp->return_value)
68  Py_RETURN_NONE;
69 
70  Py_INCREF (self_finishbp->return_value);
71  return self_finishbp->return_value;
72 }
73 
74 /* Deallocate FinishBreakpoint object. */
75 
76 static void
77 bpfinishpy_dealloc (PyObject *self)
78 {
79  struct finish_breakpoint_object *self_bpfinish =
80  (struct finish_breakpoint_object *) self;
81 
82  Py_XDECREF (self_bpfinish->function_value);
83  Py_XDECREF (self_bpfinish->return_type);
84  Py_XDECREF (self_bpfinish->return_value);
85 }
86 
87 /* Triggered when gdbpy_should_stop is about to execute the `stop' callback
88  of the gdb.FinishBreakpoint object BP_OBJ. Will compute and cache the
89  `return_value', if possible. */
90 
91 void
93 {
94  struct finish_breakpoint_object *self_finishbp =
95  (struct finish_breakpoint_object *) bp_obj;
96 
97  /* Can compute return_value only once. */
98  gdb_assert (!self_finishbp->return_value);
99 
100  if (!self_finishbp->return_type)
101  return;
102 
103  TRY
104  {
105  struct value *function =
106  value_object_to_value (self_finishbp->function_value);
107  struct type *value_type =
108  type_object_to_type (self_finishbp->return_type);
109 
110  /* bpfinishpy_init cannot finish into DUMMY_FRAME (throws an error
111  in such case) so it is OK to always pass CTX_SAVER as NULL. */
112  struct value *ret = get_return_value (function, value_type, NULL);
113 
114  if (ret)
115  {
116  self_finishbp->return_value = value_to_value_object (ret);
117  if (!self_finishbp->return_value)
119  }
120  else
121  {
122  Py_INCREF (Py_None);
123  self_finishbp->return_value = Py_None;
124  }
125  }
126  CATCH (except, RETURN_MASK_ALL)
127  {
128  gdbpy_convert_exception (except);
130  }
131  END_CATCH
132 }
133 
134 /* Triggered when gdbpy_should_stop has triggered the `stop' callback
135  of the gdb.FinishBreakpoint object BP_OBJ. */
136 
137 void
139 {
140 
141  TRY
142  {
143  /* Can't delete it here, but it will be removed at the next stop. */
144  disable_breakpoint (bp_obj->bp);
145  gdb_assert (bp_obj->bp->disposition == disp_del);
146  }
147  CATCH (except, RETURN_MASK_ALL)
148  {
149  gdbpy_convert_exception (except);
151  }
152  END_CATCH
153 }
154 
155 /* Python function to create a new breakpoint. */
156 
157 static int
158 bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
159 {
160  static char *keywords[] = { "frame", "internal", NULL };
161  struct finish_breakpoint_object *self_bpfinish =
162  (struct finish_breakpoint_object *) self;
163  int type = bp_breakpoint;
164  PyObject *frame_obj = NULL;
165  int thread;
166  struct frame_info *frame = NULL; /* init for gcc -Wall */
167  struct frame_info *prev_frame = NULL;
168  struct frame_id frame_id;
169  PyObject *internal = NULL;
170  int internal_bp = 0;
171  CORE_ADDR finish_pc, pc;
172  char *addr_str, small_buf[100];
173  struct symbol *function;
174 
175  if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
176  &frame_obj, &internal))
177  return -1;
178 
179  TRY
180  {
181  /* Default frame to newest frame if necessary. */
182  if (frame_obj == NULL)
183  frame = get_current_frame ();
184  else
185  frame = frame_object_to_frame_info (frame_obj);
186 
187  if (frame == NULL)
188  {
189  PyErr_SetString (PyExc_ValueError,
190  _("Invalid ID for the `frame' object."));
191  }
192  else
193  {
194  prev_frame = get_prev_frame (frame);
195  if (prev_frame == 0)
196  {
197  PyErr_SetString (PyExc_ValueError,
198  _("\"FinishBreakpoint\" not "
199  "meaningful in the outermost "
200  "frame."));
201  }
202  else if (get_frame_type (prev_frame) == DUMMY_FRAME)
203  {
204  PyErr_SetString (PyExc_ValueError,
205  _("\"FinishBreakpoint\" cannot "
206  "be set on a dummy frame."));
207  }
208  else
209  {
210  frame_id = get_frame_id (prev_frame);
211  if (frame_id_eq (frame_id, null_frame_id))
212  PyErr_SetString (PyExc_ValueError,
213  _("Invalid ID for the `frame' object."));
214  }
215  }
216  }
217  CATCH (except, RETURN_MASK_ALL)
218  {
219  gdbpy_convert_exception (except);
220  return -1;
221  }
222  END_CATCH
223 
224  if (PyErr_Occurred ())
225  return -1;
226 
227  thread = pid_to_thread_id (inferior_ptid);
228  if (thread == 0)
229  {
230  PyErr_SetString (PyExc_ValueError,
231  _("No thread currently selected."));
232  return -1;
233  }
234 
235  if (internal)
236  {
237  internal_bp = PyObject_IsTrue (internal);
238  if (internal_bp == -1)
239  {
240  PyErr_SetString (PyExc_ValueError,
241  _("The value of `internal' must be a boolean."));
242  return -1;
243  }
244  }
245 
246  /* Find the function we will return from. */
247  self_bpfinish->return_type = NULL;
248  self_bpfinish->function_value = NULL;
249 
250  TRY
251  {
252  if (get_frame_pc_if_available (frame, &pc))
253  {
254  function = find_pc_function (pc);
255  if (function != NULL)
256  {
257  struct type *ret_type =
258  TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
259 
260  /* Remember only non-void return types. */
261  if (TYPE_CODE (ret_type) != TYPE_CODE_VOID)
262  {
263  struct value *func_value;
264 
265  /* Ignore Python errors at this stage. */
266  self_bpfinish->return_type = type_to_type_object (ret_type);
267  PyErr_Clear ();
268  func_value = read_var_value (function, frame);
269  self_bpfinish->function_value =
270  value_to_value_object (func_value);
271  PyErr_Clear ();
272  }
273  }
274  }
275  }
276  CATCH (except, RETURN_MASK_ALL)
277  {
278  /* Just swallow. Either the return type or the function value
279  remain NULL. */
280  }
281  END_CATCH
282 
283  if (self_bpfinish->return_type == NULL || self_bpfinish->function_value == NULL)
284  {
285  /* Won't be able to compute return value. */
286  Py_XDECREF (self_bpfinish->return_type);
287  Py_XDECREF (self_bpfinish->function_value);
288 
289  self_bpfinish->return_type = NULL;
290  self_bpfinish->function_value = NULL;
291  }
292 
293  bppy_pending_object = &self_bpfinish->py_bp;
295  bppy_pending_object->bp = NULL;
296 
297  TRY
298  {
299  /* Set a breakpoint on the return address. */
300  finish_pc = get_frame_pc (prev_frame);
301  xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc));
302  addr_str = small_buf;
303 
305  addr_str, NULL, thread, NULL,
306  0,
307  1 /*temp_flag*/,
309  0,
312  0, 1, internal_bp, 0);
313  }
314  CATCH (except, RETURN_MASK_ALL)
315  {
317  }
318  END_CATCH
319 
320  self_bpfinish->py_bp.bp->frame_id = frame_id;
321  self_bpfinish->py_bp.is_finish_bp = 1;
322 
323  /* Bind the breakpoint with the current program space. */
324  self_bpfinish->py_bp.bp->pspace = current_program_space;
325 
326  return 0;
327 }
328 
329 /* Called when GDB notices that the finish breakpoint BP_OBJ is out of
330  the current callstack. Triggers the method OUT_OF_SCOPE if implemented,
331  then delete the breakpoint. */
332 
333 static void
335 {
336  gdbpy_breakpoint_object *bp_obj = (gdbpy_breakpoint_object *) bpfinish_obj;
337  PyObject *py_obj = (PyObject *) bp_obj;
338 
339  if (bpfinish_obj->py_bp.bp->enable_state == bp_enabled
341  {
342  PyObject *meth_result;
343 
344  meth_result = PyObject_CallMethod (py_obj, outofscope_func, NULL);
345  if (meth_result == NULL)
347  Py_XDECREF (meth_result);
348  }
349 
350  delete_breakpoint (bpfinish_obj->py_bp.bp);
351 }
352 
353 /* Callback for `bpfinishpy_detect_out_scope'. Triggers Python's
354  `B->out_of_scope' function if B is a FinishBreakpoint out of its scope. */
355 
356 static int
358 {
359  struct breakpoint *bp_stopped = (struct breakpoint *) args;
360  PyObject *py_bp = (PyObject *) b->py_bp_object;
361  struct gdbarch *garch = b->gdbarch ? b->gdbarch : get_current_arch ();
362 
363  /* Trigger out_of_scope if this is a FinishBreakpoint and its frame is
364  not anymore in the current callstack. */
365  if (py_bp != NULL && b->py_bp_object->is_finish_bp)
366  {
367  struct finish_breakpoint_object *finish_bp =
368  (struct finish_breakpoint_object *) py_bp;
369 
370  /* Check scope if not currently stopped at the FinishBreakpoint. */
371  if (b != bp_stopped)
372  {
373  TRY
374  {
375  if (b->pspace == current_inferior ()->pspace
377  || frame_find_by_id (b->frame_id) == NULL))
378  bpfinishpy_out_of_scope (finish_bp);
379  }
380  CATCH (except, RETURN_MASK_ALL)
381  {
382  gdbpy_convert_exception (except);
384  }
385  END_CATCH
386  }
387  }
388 
389  return 0;
390 }
391 
392 /* Attached to `stop' notifications, check if the execution has run
393  out of the scope of any FinishBreakpoint before it has been hit. */
394 
395 static void
397 {
400 
402  bs == NULL ? NULL : bs->breakpoint_at);
403 
404  do_cleanups (cleanup);
405 }
406 
407 /* Attached to `exit' notifications, triggers all the necessary out of
408  scope notifications. */
409 
410 static void
412 {
415 
417 
418  do_cleanups (cleanup);
419 }
420 
421 /* Initialize the Python finish breakpoint code. */
422 
423 int
425 {
426  if (PyType_Ready (&finish_breakpoint_object_type) < 0)
427  return -1;
428 
429  if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
430  (PyObject *) &finish_breakpoint_object_type) < 0)
431  return -1;
432 
435 
436  return 0;
437 }
438 
439 static PyGetSetDef finish_breakpoint_object_getset[] = {
440  { "return_value", bpfinishpy_get_returnvalue, NULL,
441  "gdb.Value object representing the return value, if any. \
442 None otherwise.", NULL },
443  { NULL } /* Sentinel. */
444 };
445 
447 {
448  PyVarObject_HEAD_INIT (NULL, 0)
449  "gdb.FinishBreakpoint", /*tp_name*/
450  sizeof (struct finish_breakpoint_object), /*tp_basicsize*/
451  0, /*tp_itemsize*/
452  bpfinishpy_dealloc, /*tp_dealloc*/
453  0, /*tp_print*/
454  0, /*tp_getattr*/
455  0, /*tp_setattr*/
456  0, /*tp_compare*/
457  0, /*tp_repr*/
458  0, /*tp_as_number*/
459  0, /*tp_as_sequence*/
460  0, /*tp_as_mapping*/
461  0, /*tp_hash */
462  0, /*tp_call*/
463  0, /*tp_str*/
464  0, /*tp_getattro*/
465  0, /*tp_setattro */
466  0, /*tp_as_buffer*/
467  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
468  "GDB finish breakpoint object", /* tp_doc */
469  0, /* tp_traverse */
470  0, /* tp_clear */
471  0, /* tp_richcompare */
472  0, /* tp_weaklistoffset */
473  0, /* tp_iter */
474  0, /* tp_iternext */
475  0, /* tp_methods */
476  0, /* tp_members */
477  finish_breakpoint_object_getset,/* tp_getset */
478  &breakpoint_object_type, /* tp_base */
479  0, /* tp_dict */
480  0, /* tp_descr_get */
481  0, /* tp_descr_set */
482  0, /* tp_dictoffset */
483  bpfinishpy_init, /* tp_init */
484  0, /* tp_alloc */
485  0 /* tp_new */
486 };
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5143
struct frame_info * frame_find_by_id(struct frame_id id)
Definition: frame.c:733
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition: py-utils.c:437
#define target_has_registers
Definition: target.h:1710
void bpfinishpy_pre_stop_hook(struct gdbpy_breakpoint_object *bp_obj)
int gdbpy_initialize_finishbreakpoints(void)
CORE_ADDR get_frame_pc(struct frame_info *frame)
Definition: frame.c:2217
struct frame_info * get_current_frame(void)
Definition: frame.c:1461
bfd_vma CORE_ADDR
Definition: common-types.h:41
gdbpy_breakpoint_object * bppy_pending_object
Definition: py-breakpoint.c:39
struct frame_info * get_prev_frame(struct frame_info *this_frame)
Definition: frame.c:2122
struct type * type_object_to_type(PyObject *obj)
Definition: py-type.c:1394
const struct frame_id null_frame_id
Definition: frame.c:506
int get_frame_pc_if_available(struct frame_info *frame, CORE_ADDR *pc)
Definition: frame.c:2224
static void bpfinishpy_handle_exit(struct inferior *inf)
static int bpfinishpy_detect_out_scope_cb(struct breakpoint *b, void *args)
struct value * read_var_value(struct symbol *var, struct frame_info *frame)
Definition: findvar.c:613
struct observer * observer_attach_inferior_exit(observer_inferior_exit_ftype *f)
struct gdbpy_breakpoint_object * py_bp_object
Definition: breakpoint.h:762
#define _(String)
Definition: gdb_locale.h:40
static void bpfinishpy_handle_stop(struct bpstats *bs, int print_frame)
#define END_CATCH
struct gdbarch * gdbarch
Definition: breakpoint.h:718
struct program_space * pspace
Definition: breakpoint.h:703
static int bpfinishpy_init(PyObject *self, PyObject *args, PyObject *kwargs)
enum bpdisp disposition
Definition: breakpoint.h:673
#define TRY
int frame_id_eq(struct frame_id l, struct frame_id r)
Definition: frame.c:604
gdbpy_breakpoint_object py_bp
enum frame_type get_frame_type(struct frame_info *frame)
Definition: frame.c:2463
struct value * get_return_value(struct value *function, struct type *value_type, struct dummy_frame_context_saver *ctx_saver)
Definition: infcmd.c:1516
struct frame_id get_frame_id(struct frame_info *fi)
Definition: frame.c:473
#define CATCH(EXCEPTION, MASK)
struct program_space * pspace
Definition: inferior.h:317
struct breakpoint * iterate_over_breakpoints(int(*callback)(struct breakpoint *, void *), void *data)
Definition: breakpoint.c:15504
struct symbol * find_pc_function(CORE_ADDR pc)
Definition: blockframe.c:150
void disable_breakpoint(struct breakpoint *bpt)
Definition: breakpoint.c:14486
Definition: gdbtypes.h:749
#define GDB_PY_SET_HANDLE_EXCEPTION(Exception)
Definition: gnu-nat.c:163
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:781
struct gdbarch * python_gdbarch
Definition: python.c:201
struct cleanup * ensure_python_env(struct gdbarch *gdbarch, const struct language_defn *language)
Definition: python.c:247
#define gdb_assert(expr)
Definition: gdb_assert.h:33
PyObject * value_to_value_object(struct value *val)
Definition: py-value.c:1523
static PyObject * bpfinishpy_get_returnvalue(PyObject *self, void *closure)
struct breakpoint_ops bkpt_breakpoint_ops
Definition: breakpoint.c:313
Definition: value.c:172
struct breakpoint * bp
struct breakpoint * breakpoint_at
Definition: breakpoint.h:1095
PyTypeObject finish_breakpoint_object_type
PyTypeObject breakpoint_object_type
static void print_frame(struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal)
const struct language_defn * current_language
Definition: language.c:85
int create_breakpoint(struct gdbarch *gdbarch, char *arg, char *cond_string, int thread, char *extra_string, int parse_arg, int tempflag, enum bptype type_wanted, int ignore_count, enum auto_boolean pending_break_support, const struct breakpoint_ops *ops, int from_tty, int enabled, int internal, unsigned flags)
Definition: breakpoint.c:9585
#define TYPE_TARGET_TYPE(thistype)
Definition: gdbtypes.h:1229
PyObject_HEAD int number
void gdbpy_convert_exception(struct gdb_exception exception)
Definition: py-utils.c:295
int xsnprintf(char *str, size_t size, const char *format,...)
Definition: common-utils.c:134
#define TYPE_CODE(thistype)
Definition: gdbtypes.h:1240
ptid_t inferior_ptid
Definition: infcmd.c:124
void gdbpy_print_stack(void)
Definition: python.c:1199
static void bpfinishpy_out_of_scope(struct finish_breakpoint_object *bpfinish_obj)
struct inferior * current_inferior(void)
Definition: inferior.c:57
struct program_space * current_program_space
Definition: progspace.c:35
int pid_to_thread_id(ptid_t ptid)
Definition: thread.c:459
struct observer * observer_attach_normal_stop(observer_normal_stop_ftype *f)
static void bpfinishpy_dealloc(PyObject *self)
struct type * value_type(const struct value *value)
Definition: value.c:1021
#define SYMBOL_TYPE(symbol)
Definition: symtab.h:799
Definition: symtab.h:703
PyObject * gdb_module
Definition: python.c:112
struct value * value_object_to_value(PyObject *self)
Definition: py-value.c:1544
PyTypeObject finish_breakpoint_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("finish_breakpoint_object")
struct frame_info * frame_object_to_frame_info(PyObject *obj)
Definition: py-frame.c:62
enum enable_state enable_state
Definition: breakpoint.h:671
struct frame_id frame_id
Definition: value.c:266
void delete_breakpoint(struct breakpoint *bpt)
Definition: breakpoint.c:13539
static char *const outofscope_func
#define PyObject_HasAttrString(obj, attr)
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:175
static PyGetSetDef finish_breakpoint_object_getset[]
void bpfinishpy_post_stop_hook(struct gdbpy_breakpoint_object *bp_obj)
struct frame_id frame_id
Definition: breakpoint.h:698
#define PyVarObject_HEAD_INIT(type, size)
PyObject * type_to_type_object(struct type *type)
Definition: py-type.c:1382