xref: /dragonfly/contrib/gdb-7/gdb/python/py-frame.c (revision 81c11cd3)
1 /* Python interface to stack frames
2 
3    Copyright (C) 2008, 2009 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 #include "defs.h"
21 #include "charset.h"
22 #include "block.h"
23 #include "frame.h"
24 #include "exceptions.h"
25 #include "symtab.h"
26 #include "stack.h"
27 #include "value.h"
28 #include "python-internal.h"
29 
30 typedef struct {
31   PyObject_HEAD
32   struct frame_id frame_id;
33   struct gdbarch *gdbarch;
34 
35   /* Marks that the FRAME_ID member actually holds the ID of the frame next
36      to this, and not this frames' ID itself.  This is a hack to permit Python
37      frame objects which represent invalid frames (i.e., the last frame_info
38      in a corrupt stack).  The problem arises from the fact that this code
39      relies on FRAME_ID to uniquely identify a frame, which is not always true
40      for the last "frame" in a corrupt stack (it can have a null ID, or the same
41      ID as the  previous frame).  Whenever get_prev_frame returns NULL, we
42      record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1.  */
43   int frame_id_is_next;
44 } frame_object;
45 
46 /* Require a valid frame.  This must be called inside a TRY_CATCH, or
47    another context in which a gdb exception is allowed.  */
48 #define FRAPY_REQUIRE_VALID(frame_obj, frame)		\
49     do {						\
50       frame = frame_object_to_frame_info (frame_obj);	\
51       if (frame == NULL)				\
52 	error ("Frame is invalid.");			\
53     } while (0)
54 
55 static PyTypeObject frame_object_type;
56 
57 /* Returns the frame_info object corresponding to the given Python Frame
58    object.  If the frame doesn't exist anymore (the frame id doesn't
59    correspond to any frame in the inferior), returns NULL.  */
60 
61 static struct frame_info *
62 frame_object_to_frame_info (frame_object *frame_obj)
63 {
64   struct frame_info *frame;
65 
66   frame = frame_find_by_id (frame_obj->frame_id);
67   if (frame == NULL)
68     return NULL;
69 
70   if (frame_obj->frame_id_is_next)
71     frame = get_prev_frame (frame);
72 
73   return frame;
74 }
75 
76 /* Called by the Python interpreter to obtain string representation
77    of the object.  */
78 
79 static PyObject *
80 frapy_str (PyObject *self)
81 {
82   char *s;
83   PyObject *result;
84   struct ui_file *strfile;
85 
86   strfile = mem_fileopen ();
87   fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
88   s = ui_file_xstrdup (strfile, NULL);
89   result = PyString_FromString (s);
90   xfree (s);
91 
92   return result;
93 }
94 
95 /* Implementation of gdb.Frame.is_valid (self) -> Boolean.
96    Returns True if the frame corresponding to the frame_id of this
97    object still exists in the inferior.  */
98 
99 static PyObject *
100 frapy_is_valid (PyObject *self, PyObject *args)
101 {
102   struct frame_info *frame;
103 
104   frame = frame_object_to_frame_info ((frame_object *) self);
105   if (frame == NULL)
106     Py_RETURN_FALSE;
107 
108   Py_RETURN_TRUE;
109 }
110 
111 /* Implementation of gdb.Frame.name (self) -> String.
112    Returns the name of the function corresponding to this frame.  */
113 
114 static PyObject *
115 frapy_name (PyObject *self, PyObject *args)
116 {
117   struct frame_info *frame;
118   char *name;
119   enum language lang;
120   PyObject *result;
121   volatile struct gdb_exception except;
122 
123   TRY_CATCH (except, RETURN_MASK_ALL)
124     {
125       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
126 
127       find_frame_funname (frame, &name, &lang);
128     }
129   GDB_PY_HANDLE_EXCEPTION (except);
130 
131   if (name)
132     result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
133   else
134     {
135       result = Py_None;
136       Py_INCREF (Py_None);
137     }
138 
139   return result;
140 }
141 
142 /* Implementation of gdb.Frame.type (self) -> Integer.
143    Returns the frame type, namely one of the gdb.*_FRAME constants.  */
144 
145 static PyObject *
146 frapy_type (PyObject *self, PyObject *args)
147 {
148   struct frame_info *frame;
149   enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning.  */
150   volatile struct gdb_exception except;
151 
152   TRY_CATCH (except, RETURN_MASK_ALL)
153     {
154       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
155 
156       type = get_frame_type (frame);
157     }
158   GDB_PY_HANDLE_EXCEPTION (except);
159 
160   return PyInt_FromLong (type);
161 }
162 
163 /* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
164    Returns one of the gdb.FRAME_UNWIND_* constants.  */
165 
166 static PyObject *
167 frapy_unwind_stop_reason (PyObject *self, PyObject *args)
168 {
169   struct frame_info *frame = NULL;    /* Initialize to appease gcc warning.  */
170   volatile struct gdb_exception except;
171   enum unwind_stop_reason stop_reason;
172 
173   TRY_CATCH (except, RETURN_MASK_ALL)
174     {
175       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
176     }
177   GDB_PY_HANDLE_EXCEPTION (except);
178 
179   stop_reason = get_frame_unwind_stop_reason (frame);
180 
181   return PyInt_FromLong (stop_reason);
182 }
183 
184 /* Implementation of gdb.Frame.pc (self) -> Long.
185    Returns the frame's resume address.  */
186 
187 static PyObject *
188 frapy_pc (PyObject *self, PyObject *args)
189 {
190   CORE_ADDR pc = 0;	      /* Initialize to appease gcc warning.  */
191   struct frame_info *frame;
192   volatile struct gdb_exception except;
193 
194   TRY_CATCH (except, RETURN_MASK_ALL)
195     {
196       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
197 
198       pc = get_frame_pc (frame);
199     }
200   GDB_PY_HANDLE_EXCEPTION (except);
201 
202   return PyLong_FromUnsignedLongLong (pc);
203 }
204 
205 /* Convert a frame_info struct to a Python Frame object.
206    Sets a Python exception and returns NULL on error.  */
207 
208 static frame_object *
209 frame_info_to_frame_object (struct frame_info *frame)
210 {
211   frame_object *frame_obj;
212 
213   frame_obj = PyObject_New (frame_object, &frame_object_type);
214   if (frame_obj == NULL)
215     {
216       PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
217       return NULL;
218     }
219 
220   /* Try to get the previous frame, to determine if this is the last frame
221      in a corrupt stack.  If so, we need to store the frame_id of the next
222      frame and not of this one (which is possibly invalid).  */
223   if (get_prev_frame (frame) == NULL
224       && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
225       && get_next_frame (frame) != NULL)
226     {
227       frame_obj->frame_id = get_frame_id (get_next_frame (frame));
228       frame_obj->frame_id_is_next = 1;
229     }
230   else
231     {
232       frame_obj->frame_id = get_frame_id (frame);
233       frame_obj->frame_id_is_next = 0;
234     }
235 
236   frame_obj->gdbarch = get_frame_arch (frame);
237 
238   return frame_obj;
239 }
240 
241 /* Implementation of gdb.Frame.older (self) -> gdb.Frame.
242    Returns the frame immediately older (outer) to this frame, or None if
243    there isn't one.  */
244 
245 static PyObject *
246 frapy_older (PyObject *self, PyObject *args)
247 {
248   struct frame_info *frame, *prev;
249   volatile struct gdb_exception except;
250   PyObject *prev_obj = NULL;   /* Initialize to appease gcc warning.  */
251 
252   TRY_CATCH (except, RETURN_MASK_ALL)
253     {
254       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
255 
256       prev = get_prev_frame (frame);
257       if (prev)
258 	prev_obj = (PyObject *) frame_info_to_frame_object (prev);
259       else
260 	{
261 	  Py_INCREF (Py_None);
262 	  prev_obj = Py_None;
263 	}
264     }
265   GDB_PY_HANDLE_EXCEPTION (except);
266 
267   return prev_obj;
268 }
269 
270 /* Implementation of gdb.Frame.newer (self) -> gdb.Frame.
271    Returns the frame immediately newer (inner) to this frame, or None if
272    there isn't one.  */
273 
274 static PyObject *
275 frapy_newer (PyObject *self, PyObject *args)
276 {
277   struct frame_info *frame, *next;
278   volatile struct gdb_exception except;
279   PyObject *next_obj = NULL;   /* Initialize to appease gcc warning.  */
280 
281   TRY_CATCH (except, RETURN_MASK_ALL)
282     {
283       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
284 
285       next = get_next_frame (frame);
286       if (next)
287 	next_obj = (PyObject *) frame_info_to_frame_object (next);
288       else
289 	{
290 	  Py_INCREF (Py_None);
291 	  next_obj = Py_None;
292 	}
293     }
294   GDB_PY_HANDLE_EXCEPTION (except);
295 
296   return next_obj;
297 }
298 
299 /* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value.
300    Returns the value of the given variable in this frame.  The argument must be
301    a string.  Returns None if GDB can't find the specified variable.  */
302 
303 static PyObject *
304 frapy_read_var (PyObject *self, PyObject *args)
305 {
306   struct frame_info *frame;
307   PyObject *sym_obj;
308   struct symbol *var = NULL;	/* gcc-4.3.2 false warning.  */
309   struct value *val = NULL;
310   volatile struct gdb_exception except;
311 
312   if (!PyArg_ParseTuple (args, "O", &sym_obj))
313     return NULL;
314 
315   if (gdbpy_is_string (sym_obj))
316     {
317       char *var_name;
318       struct block *block = NULL;
319       struct cleanup *cleanup;
320       volatile struct gdb_exception except;
321 
322       var_name = python_string_to_target_string (sym_obj);
323       if (!var_name)
324 	return NULL;
325       cleanup = make_cleanup (xfree, var_name);
326 
327       TRY_CATCH (except, RETURN_MASK_ALL)
328 	{
329 	  FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
330 
331 	  block = block_for_pc (get_frame_address_in_block (frame));
332 	  var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
333 	}
334       GDB_PY_HANDLE_EXCEPTION (except);
335 
336       if (!var)
337 	{
338 	  PyErr_Format (PyExc_ValueError,
339 			_("variable '%s' not found"), var_name);
340 	  do_cleanups (cleanup);
341 
342 	  return NULL;
343 	}
344 
345       do_cleanups (cleanup);
346     }
347   else
348     {
349       PyErr_SetString (PyExc_TypeError,
350 		       _("argument must be a symbol or string"));
351       return NULL;
352     }
353 
354   TRY_CATCH (except, RETURN_MASK_ALL)
355     {
356       FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
357 
358       val = read_var_value (var, frame);
359     }
360   GDB_PY_HANDLE_EXCEPTION (except);
361 
362   if (val)
363     return value_to_value_object (val);
364 
365   Py_RETURN_NONE;
366 }
367 
368 /* Implementation of gdb.selected_frame () -> gdb.Frame.
369    Returns the selected frame object.  */
370 
371 PyObject *
372 gdbpy_selected_frame (PyObject *self, PyObject *args)
373 {
374   struct frame_info *frame;
375   frame_object *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
376   volatile struct gdb_exception except;
377 
378   TRY_CATCH (except, RETURN_MASK_ALL)
379     {
380       frame = get_selected_frame ("No frame is currently selected.");
381       frame_obj = frame_info_to_frame_object (frame);
382     }
383   GDB_PY_HANDLE_EXCEPTION (except);
384 
385   return (PyObject *) frame_obj;
386 }
387 
388 /* Implementation of gdb.stop_reason_string (Integer) -> String.
389    Return a string explaining the unwind stop reason.  */
390 
391 PyObject *
392 gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
393 {
394   int reason;
395   const char *str;
396 
397   if (!PyArg_ParseTuple (args, "i", &reason))
398     return NULL;
399 
400   if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
401     {
402       PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
403       return NULL;
404     }
405 
406   str = frame_stop_reason_string (reason);
407   return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
408 }
409 
410 /* Implements the equality comparison for Frame objects.
411    All other comparison operators will throw a TypeError Python exception,
412    as they aren't valid for frames.  */
413 
414 static PyObject *
415 frapy_richcompare (PyObject *self, PyObject *other, int op)
416 {
417   int result;
418 
419   if (!PyObject_TypeCheck (other, &frame_object_type)
420       || (op != Py_EQ && op != Py_NE))
421     {
422       Py_INCREF (Py_NotImplemented);
423       return Py_NotImplemented;
424     }
425 
426   if (frame_id_eq (((frame_object *) self)->frame_id,
427 		   ((frame_object *) other)->frame_id))
428     result = Py_EQ;
429   else
430     result = Py_NE;
431 
432   if (op == result)
433     Py_RETURN_TRUE;
434   Py_RETURN_FALSE;
435 }
436 
437 /* Sets up the Frame API in the gdb module.  */
438 
439 void
440 gdbpy_initialize_frames (void)
441 {
442   if (PyType_Ready (&frame_object_type) < 0)
443     return;
444 
445   /* Note: These would probably be best exposed as class attributes of Frame,
446      but I don't know how to do it except by messing with the type's dictionary.
447      That seems too messy.  */
448   PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
449   PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
450   PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
451   PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
452   PyModule_AddIntConstant (gdb_module,
453 			   "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
454   PyModule_AddIntConstant (gdb_module,
455 			   "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
456   PyModule_AddIntConstant (gdb_module,
457 			   "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
458   PyModule_AddIntConstant (gdb_module,
459 			   "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
460   PyModule_AddIntConstant (gdb_module,
461 			   "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
462   PyModule_AddIntConstant (gdb_module,
463 			   "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
464 
465   Py_INCREF (&frame_object_type);
466   PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
467 }
468 
469 
470 
471 static PyMethodDef frame_object_methods[] = {
472   { "is_valid", frapy_is_valid, METH_NOARGS,
473     "is_valid () -> Boolean.\n\
474 Return true if this frame is valid, false if not." },
475   { "name", frapy_name, METH_NOARGS,
476     "name () -> String.\n\
477 Return the function name of the frame, or None if it can't be determined." },
478   { "type", frapy_type, METH_NOARGS,
479     "type () -> Integer.\n\
480 Return the type of the frame." },
481   { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
482     "unwind_stop_reason () -> Integer.\n\
483 Return the reason why it's not possible to find frames older than this." },
484   { "pc", frapy_pc, METH_NOARGS,
485     "pc () -> Long.\n\
486 Return the frame's resume address." },
487   { "older", frapy_older, METH_NOARGS,
488     "older () -> gdb.Frame.\n\
489 Return the frame that called this frame." },
490   { "newer", frapy_newer, METH_NOARGS,
491     "newer () -> gdb.Frame.\n\
492 Return the frame called by this frame." },
493   { "read_var", frapy_read_var, METH_VARARGS,
494     "read_var (variable) -> gdb.Value.\n\
495 Return the value of the variable in this frame." },
496   {NULL}  /* Sentinel */
497 };
498 
499 static PyTypeObject frame_object_type = {
500   PyObject_HEAD_INIT (NULL)
501   0,				  /* ob_size */
502   "gdb.Frame",			  /* tp_name */
503   sizeof (frame_object),	  /* tp_basicsize */
504   0,				  /* tp_itemsize */
505   0,				  /* tp_dealloc */
506   0,				  /* tp_print */
507   0,				  /* tp_getattr */
508   0,				  /* tp_setattr */
509   0,				  /* tp_compare */
510   0,				  /* tp_repr */
511   0,				  /* tp_as_number */
512   0,				  /* tp_as_sequence */
513   0,				  /* tp_as_mapping */
514   0,				  /* tp_hash  */
515   0,				  /* tp_call */
516   frapy_str,			  /* tp_str */
517   0,				  /* tp_getattro */
518   0,				  /* tp_setattro */
519   0,				  /* tp_as_buffer */
520   Py_TPFLAGS_DEFAULT,		  /* tp_flags */
521   "GDB frame object",		  /* tp_doc */
522   0,				  /* tp_traverse */
523   0,				  /* tp_clear */
524   frapy_richcompare,		  /* tp_richcompare */
525   0,				  /* tp_weaklistoffset */
526   0,				  /* tp_iter */
527   0,				  /* tp_iternext */
528   frame_object_methods,		  /* tp_methods */
529   0,				  /* tp_members */
530   0,				  /* tp_getset */
531   0,				  /* tp_base */
532   0,				  /* tp_dict */
533   0,				  /* tp_descr_get */
534   0,				  /* tp_descr_set */
535   0,				  /* tp_dictoffset */
536   0,				  /* tp_init */
537   0,				  /* tp_alloc */
538   PyType_GenericNew		  /* tp_new */
539 };
540