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