GDB (xrefs)
py-finishbreakpoint.c
Go to the documentation of this file.
1 /* Python interface to finish breakpoints
2 
3  Copyright (C) 2011-2018 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 #include "location.h"
33 #include "py-ref.h"
34 
35 /* Function that is called when a Python finish bp is found out of scope. */
36 static const char outofscope_func[] = "out_of_scope";
37 
38 /* struct implementing the gdb.FinishBreakpoint object by extending
39  the gdb.Breakpoint class. */
41 {
42  /* gdb.Breakpoint base class. */
44  /* gdb.Type object of the value return by the breakpointed function.
45  May be NULL if no debug information was available or return type
46  was VOID. */
47  PyObject *return_type;
48  /* gdb.Value object of the function finished by this breakpoint. Will be
49  NULL if return_type is NULL. */
50  PyObject *function_value;
51  /* When stopped at this FinishBreakpoint, gdb.Value object returned by
52  the function; Py_None if the value is not computable; NULL if GDB is
53  not stopped at a FinishBreakpoint. */
54  PyObject *return_value;
55 };
56 
57 extern PyTypeObject finish_breakpoint_object_type
58  CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("finish_breakpoint_object");
59 
60 /* Python function to get the 'return_value' attribute of
61  FinishBreakpoint. */
62 
63 static PyObject *
64 bpfinishpy_get_returnvalue (PyObject *self, void *closure)
65 {
66  struct finish_breakpoint_object *self_finishbp =
67  (struct finish_breakpoint_object *) self;
68 
69  if (!self_finishbp->return_value)
70  Py_RETURN_NONE;
71 
72  Py_INCREF (self_finishbp->return_value);
73  return self_finishbp->return_value;
74 }
75 
76 /* Deallocate FinishBreakpoint object. */
77 
78 static void
79 bpfinishpy_dealloc (PyObject *self)
80 {
81  struct finish_breakpoint_object *self_bpfinish =
82  (struct finish_breakpoint_object *) self;
83 
84  Py_XDECREF (self_bpfinish->function_value);
85  Py_XDECREF (self_bpfinish->return_type);
86  Py_XDECREF (self_bpfinish->return_value);
87 }
88 
89 /* Triggered when gdbpy_should_stop is about to execute the `stop' callback
90  of the gdb.FinishBreakpoint object BP_OBJ. Will compute and cache the
91  `return_value', if possible. */
92 
93 void
95 {
96  struct finish_breakpoint_object *self_finishbp =
97  (struct finish_breakpoint_object *) bp_obj;
98 
99  /* Can compute return_value only once. */
100  gdb_assert (!self_finishbp->return_value);
101 
102  if (!self_finishbp->return_type)
103  return;
104 
105  TRY
106  {
107  struct value *function =
108  value_object_to_value (self_finishbp->function_value);
109  struct type *value_type =
110  type_object_to_type (self_finishbp->return_type);
111  struct value *ret = get_return_value (function, value_type);
112 
113  if (ret)
114  {
115  self_finishbp->return_value = value_to_value_object (ret);
116  if (!self_finishbp->return_value)
118  }
119  else
120  {
121  Py_INCREF (Py_None);
122  self_finishbp->return_value = Py_None;
123  }
124  }
125  CATCH (except, RETURN_MASK_ALL)
126  {
127  gdbpy_convert_exception (except);
129  }
130  END_CATCH
131 }
132 
133 /* Triggered when gdbpy_should_stop has triggered the `stop' callback
134  of the gdb.FinishBreakpoint object BP_OBJ. */
135 
136 void
138 {
139 
140  TRY
141  {
142  /* Can't delete it here, but it will be removed at the next stop. */
143  disable_breakpoint (bp_obj->bp);
144  gdb_assert (bp_obj->bp->disposition == disp_del);
145  }
146  CATCH (except, RETURN_MASK_ALL)
147  {
148  gdbpy_convert_exception (except);
150  }
151  END_CATCH
152 }
153 
154 /* Python function to create a new breakpoint. */
155 
156 static int
157 bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
158 {
159  static const char *keywords[] = { "frame", "internal", NULL };
160  struct finish_breakpoint_object *self_bpfinish =
161  (struct finish_breakpoint_object *) self;
162  PyObject *frame_obj = NULL;
163  int thread;
164  struct frame_info *frame = NULL; /* init for gcc -Wall */
165  struct frame_info *prev_frame = NULL;
166  struct frame_id frame_id;
167  PyObject *internal = NULL;
168  int internal_bp = 0;
169  CORE_ADDR pc;
170  struct symbol *function;
171 
172  if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
173  &frame_obj, &internal))
174  return -1;
175 
176  TRY
177  {
178  /* Default frame to newest frame if necessary. */
179  if (frame_obj == NULL)
180  frame = get_current_frame ();
181  else
182  frame = frame_object_to_frame_info (frame_obj);
183 
184  if (frame == NULL)
185  {
186  PyErr_SetString (PyExc_ValueError,
187  _("Invalid ID for the `frame' object."));
188  }
189  else
190  {
191  prev_frame = get_prev_frame (frame);
192  if (prev_frame == 0)
193  {
194  PyErr_SetString (PyExc_ValueError,
195  _("\"FinishBreakpoint\" not "
196  "meaningful in the outermost "
197  "frame."));
198  }
199  else if (get_frame_type (prev_frame) == DUMMY_FRAME)
200  {
201  PyErr_SetString (PyExc_ValueError,
202  _("\"FinishBreakpoint\" cannot "
203  "be set on a dummy frame."));
204  }
205  else
206  {
207  frame_id = get_frame_id (prev_frame);
209  PyErr_SetString (PyExc_ValueError,
210  _("Invalid ID for the `frame' object."));
211  }
212  }
213  }
214  CATCH (except, RETURN_MASK_ALL)
215  {
216  gdbpy_convert_exception (except);
217  return -1;
218  }
219  END_CATCH
220 
221  if (PyErr_Occurred ())
222  return -1;
223 
225  if (thread == 0)
226  {
227  PyErr_SetString (PyExc_ValueError,
228  _("No thread currently selected."));
229  return -1;
230  }
231 
232  if (internal)
233  {
234  internal_bp = PyObject_IsTrue (internal);
235  if (internal_bp == -1)
236  {
237  PyErr_SetString (PyExc_ValueError,
238  _("The value of `internal' must be a boolean."));
239  return -1;
240  }
241  }
242 
243  /* Find the function we will return from. */
244  self_bpfinish->return_type = NULL;
245  self_bpfinish->function_value = NULL;
246 
247  TRY
248  {
249  if (get_frame_pc_if_available (frame, &pc))
250  {
251  function = find_pc_function (pc);
252  if (function != NULL)
253  {
254  struct type *ret_type =
255  TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
256 
257  /* Remember only non-void return types. */
258  if (TYPE_CODE (ret_type) != TYPE_CODE_VOID)
259  {
260  struct value *func_value;
261 
262  /* Ignore Python errors at this stage. */
263  self_bpfinish->return_type = type_to_type_object (ret_type);
264  PyErr_Clear ();
265  func_value = read_var_value (function, NULL, frame);
266  self_bpfinish->function_value =
267  value_to_value_object (func_value);
268  PyErr_Clear ();
269  }
270  }
271  }
272  }
273  CATCH (except, RETURN_MASK_ALL)
274  {
275  /* Just swallow. Either the return type or the function value
276  remain NULL. */
277  }
278  END_CATCH
279 
280  if (self_bpfinish->return_type == NULL || self_bpfinish->function_value == NULL)
281  {
282  /* Won't be able to compute return value. */
283  Py_XDECREF (self_bpfinish->return_type);
284  Py_XDECREF (self_bpfinish->function_value);
285 
286  self_bpfinish->return_type = NULL;
287  self_bpfinish->function_value = NULL;
288  }
289 
290  bppy_pending_object = &self_bpfinish->py_bp;
292  bppy_pending_object->bp = NULL;
293 
294  TRY
295  {
296  /* Set a breakpoint on the return address. */
298  = new_address_location (get_frame_pc (prev_frame), NULL, 0);
300  location.get (), NULL, thread, NULL,
301  0,
302  1 /*temp_flag*/,
304  0,
307  0, 1, internal_bp, 0);
308  }
309  CATCH (except, RETURN_MASK_ALL)
310  {
312  }
313  END_CATCH
314 
315  self_bpfinish->py_bp.bp->frame_id = frame_id;
316  self_bpfinish->py_bp.is_finish_bp = 1;
317 
318  /* Bind the breakpoint with the current program space. */
319  self_bpfinish->py_bp.bp->pspace = current_program_space;
320 
321  return 0;
322 }
323 
324 /* Called when GDB notices that the finish breakpoint BP_OBJ is out of
325  the current callstack. Triggers the method OUT_OF_SCOPE if implemented,
326  then delete the breakpoint. */
327 
328 static void
330 {
331  gdbpy_breakpoint_object *bp_obj = (gdbpy_breakpoint_object *) bpfinish_obj;
332  PyObject *py_obj = (PyObject *) bp_obj;
333 
334  if (bpfinish_obj->py_bp.bp->enable_state == bp_enabled
336  {
337  gdbpy_ref<> meth_result (PyObject_CallMethod (py_obj, outofscope_func,
338  NULL));
339  if (meth_result == NULL)
341  }
342 
343  delete_breakpoint (bpfinish_obj->py_bp.bp);
344 }
345 
346 /* Callback for `bpfinishpy_detect_out_scope'. Triggers Python's
347  `B->out_of_scope' function if B is a FinishBreakpoint out of its scope. */
348 
349 static int
351 {
352  struct breakpoint *bp_stopped = (struct breakpoint *) args;
353  PyObject *py_bp = (PyObject *) b->py_bp_object;
354 
355  /* Trigger out_of_scope if this is a FinishBreakpoint and its frame is
356  not anymore in the current callstack. */
357  if (py_bp != NULL && b->py_bp_object->is_finish_bp)
358  {
359  struct finish_breakpoint_object *finish_bp =
360  (struct finish_breakpoint_object *) py_bp;
361 
362  /* Check scope if not currently stopped at the FinishBreakpoint. */
363  if (b != bp_stopped)
364  {
365  TRY
366  {
367  if (b->pspace == current_inferior ()->pspace
369  || frame_find_by_id (b->frame_id) == NULL))
370  bpfinishpy_out_of_scope (finish_bp);
371  }
372  CATCH (except, RETURN_MASK_ALL)
373  {
374  gdbpy_convert_exception (except);
376  }
377  END_CATCH
378  }
379  }
380 
381  return 0;
382 }
383 
384 /* Attached to `stop' notifications, check if the execution has run
385  out of the scope of any FinishBreakpoint before it has been hit. */
386 
387 static void
389 {
391 
393  bs == NULL ? NULL : bs->breakpoint_at);
394 }
395 
396 /* Attached to `exit' notifications, triggers all the necessary out of
397  scope notifications. */
398 
399 static void
401 {
403 
405 }
406 
407 /* Initialize the Python finish breakpoint code. */
408 
409 int
411 {
412  if (PyType_Ready (&finish_breakpoint_object_type) < 0)
413  return -1;
414 
415  if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
416  (PyObject *) &finish_breakpoint_object_type) < 0)
417  return -1;
418 
421 
422  return 0;
423 }
424 
426  { "return_value", bpfinishpy_get_returnvalue, NULL,
427  "gdb.Value object representing the return value, if any. \
428 None otherwise.", NULL },
429  { NULL } /* Sentinel. */
430 };
431 
433 {
434  PyVarObject_HEAD_INIT (NULL, 0)
435  "gdb.FinishBreakpoint", /*tp_name*/
436  sizeof (struct finish_breakpoint_object), /*tp_basicsize*/
437  0, /*tp_itemsize*/
438  bpfinishpy_dealloc, /*tp_dealloc*/
439  0, /*tp_print*/
440  0, /*tp_getattr*/
441  0, /*tp_setattr*/
442  0, /*tp_compare*/
443  0, /*tp_repr*/
444  0, /*tp_as_number*/
445  0, /*tp_as_sequence*/
446  0, /*tp_as_mapping*/
447  0, /*tp_hash */
448  0, /*tp_call*/
449  0, /*tp_str*/
450  0, /*tp_getattro*/
451  0, /*tp_setattro */
452  0, /*tp_as_buffer*/
453  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
454  "GDB finish breakpoint object", /* tp_doc */
455  0, /* tp_traverse */
456  0, /* tp_clear */
457  0, /* tp_richcompare */
458  0, /* tp_weaklistoffset */
459  0, /* tp_iter */
460  0, /* tp_iternext */
461  0, /* tp_methods */
462  0, /* tp_members */
463  finish_breakpoint_object_getset,/* tp_getset */
464  &breakpoint_object_type, /* tp_base */
465  0, /* tp_dict */
466  0, /* tp_descr_get */
467  0, /* tp_descr_set */
468  0, /* tp_dictoffset */
469  bpfinishpy_init, /* tp_init */
470  0, /* tp_alloc */
471  0 /* tp_new */
472 };
struct gdbarch * target_gdbarch(void)
Definition: gdbarch.c:5467
struct frame_info * frame_find_by_id(struct frame_id id)
Definition: frame.c:803
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition: py-utils.c:376
struct value * get_return_value(struct value *function, struct type *value_type)
Definition: infcmd.c:1625
#define target_has_registers
Definition: target.h:1740
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:2376
struct frame_info * get_current_frame(void)
Definition: frame.c:1563
bfd_vma CORE_ADDR
Definition: common-types.h:41
gdbpy_breakpoint_object * bppy_pending_object
Definition: py-breakpoint.c:42
program_space * pspace
Definition: breakpoint.h:727
union value::@186 location
struct frame_info * get_prev_frame(struct frame_info *this_frame)
Definition: frame.c:2254
if(!(yy_init))
Definition: ada-lex.c:1075
struct type * type_object_to_type(PyObject *obj)
Definition: py-type.c:1332
const struct frame_id null_frame_id
Definition: frame.c:575
int get_frame_pc_if_available(struct frame_info *frame, CORE_ADDR *pc)
Definition: frame.c:2383
static void bpfinishpy_handle_exit(struct inferior *inf)
static gdb_PyGetSetDef finish_breakpoint_object_getset[]
static int bpfinishpy_detect_out_scope_cb(struct breakpoint *b, void *args)
struct observer * observer_attach_inferior_exit(observer_inferior_exit_ftype *f)
#define _(String)
Definition: gdb_locale.h:35
static int gdb_PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, const char **keywords,...)
static void bpfinishpy_handle_stop(struct bpstats *bs, int print_frame)
#define PyVarObject_HEAD_INIT(type, size)
#define END_CATCH
static const char outofscope_func[]
struct program_space * pspace
Definition: inferior.h:349
static int bpfinishpy_init(PyObject *self, PyObject *args, PyObject *kwargs)
#define TRY
int frame_id_eq(struct frame_id l, struct frame_id r)
Definition: frame.c:674
gdbpy_breakpoint_object py_bp
enum frame_type get_frame_type(struct frame_info *frame)
Definition: frame.c:2619
struct frame_id get_frame_id(struct frame_info *fi)
Definition: frame.c:520
#define CATCH(EXCEPTION, MASK)
bpdisp disposition
Definition: breakpoint.h:697
struct breakpoint * iterate_over_breakpoints(int(*callback)(struct breakpoint *, void *), void *data)
Definition: breakpoint.c:15347
struct value * read_var_value(struct symbol *var, const struct block *var_block, struct frame_info *frame)
Definition: findvar.c:807
struct symbol * find_pc_function(CORE_ADDR pc)
Definition: blockframe.c:150
gdbpy_breakpoint_object * py_bp_object
Definition: breakpoint.h:785
int ptid_to_global_thread_id(ptid_t ptid)
Definition: thread.c:605
void disable_breakpoint(struct breakpoint *bpt)
Definition: breakpoint.c:14330
Definition: gdbtypes.h:749
#define GDB_PY_SET_HANDLE_EXCEPTION(Exception)
Definition: gnu-nat.c:174
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:798
struct gdbarch * python_gdbarch
Definition: python.c:203
PyObject * value_to_value_object(struct value *val)
Definition: py-value.c:1579
static PyObject * bpfinishpy_get_returnvalue(PyObject *self, void *closure)
std::unique_ptr< event_location, event_location_deleter > event_location_up
Definition: location.h:140
struct breakpoint_ops bkpt_breakpoint_ops
Definition: breakpoint.c:255
event_location_up new_address_location(CORE_ADDR addr, const char *addr_string, int addr_string_len)
Definition: location.c:121
#define gdb_assert(expr)
Definition: gdb_assert.h:32
Definition: value.c:169
struct breakpoint * bp
struct breakpoint * breakpoint_at
Definition: breakpoint.h:1122
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:81
#define TYPE_TARGET_TYPE(thistype)
Definition: gdbtypes.h:1226
PyObject_HEAD int number
void gdbpy_convert_exception(struct gdb_exception exception)
Definition: py-utils.c:235
#define TYPE_CODE(thistype)
Definition: gdbtypes.h:1238
ptid_t inferior_ptid
Definition: infcmd.c:94
void gdbpy_print_stack(void)
Definition: python.c:1262
int create_breakpoint(struct gdbarch *gdbarch, const struct event_location *location, const char *cond_string, int thread, const char *extra_string, int parse_extra, 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:9325
static void bpfinishpy_out_of_scope(struct finish_breakpoint_object *bpfinish_obj)
struct inferior * current_inferior(void)
Definition: inferior.c:58
struct program_space * current_program_space
Definition: progspace.c:35
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:1095
#define SYMBOL_TYPE(symbol)
Definition: symtab.h:1161
PyObject * gdb_module
Definition: python.c:116
struct value * value_object_to_value(PyObject *self)
Definition: py-value.c:1600
PyTypeObject finish_breakpoint_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("finish_breakpoint_object")
#define PyObject_CallMethod
struct frame_info * frame_object_to_frame_info(PyObject *obj)
Definition: py-frame.c:63
enum enable_state enable_state
Definition: breakpoint.h:695
void delete_breakpoint(struct breakpoint *bpt)
Definition: breakpoint.c:13226
#define PyObject_HasAttrString(obj, attr)
void bpfinishpy_post_stop_hook(struct gdbpy_breakpoint_object *bp_obj)
struct frame_id frame_id
Definition: breakpoint.h:722
PyObject * type_to_type_object(struct type *type)
Definition: py-type.c:1320