OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [python/] [py-frame.c] - Rev 834

Go to most recent revision | Compare with Previous | Blame | View Log

/* Python interface to stack frames
 
   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
   This file is part of GDB.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
#include "defs.h"
#include "charset.h"
#include "block.h"
#include "frame.h"
#include "exceptions.h"
#include "symtab.h"
#include "stack.h"
#include "value.h"
#include "python-internal.h"
 
typedef struct {
  PyObject_HEAD
  struct frame_id frame_id;
  struct gdbarch *gdbarch;
 
  /* Marks that the FRAME_ID member actually holds the ID of the frame next
     to this, and not this frames' ID itself.  This is a hack to permit Python
     frame objects which represent invalid frames (i.e., the last frame_info
     in a corrupt stack).  The problem arises from the fact that this code
     relies on FRAME_ID to uniquely identify a frame, which is not always true
     for the last "frame" in a corrupt stack (it can have a null ID, or the same
     ID as the  previous frame).  Whenever get_prev_frame returns NULL, we
     record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1.  */
  int frame_id_is_next;
} frame_object;
 
/* Require a valid frame.  This must be called inside a TRY_CATCH, or
   another context in which a gdb exception is allowed.  */
#define FRAPY_REQUIRE_VALID(frame_obj, frame)		\
    do {						\
      frame = frame_object_to_frame_info (frame_obj);	\
      if (frame == NULL)				\
	error ("Frame is invalid.");			\
    } while (0)
 
static PyTypeObject frame_object_type;
 
/* Returns the frame_info object corresponding to the given Python Frame
   object.  If the frame doesn't exist anymore (the frame id doesn't
   correspond to any frame in the inferior), returns NULL.  */
 
static struct frame_info *
frame_object_to_frame_info (frame_object *frame_obj)
{
  struct frame_info *frame;
 
  frame = frame_find_by_id (frame_obj->frame_id);
  if (frame == NULL)
    return NULL;
 
  if (frame_obj->frame_id_is_next)
    frame = get_prev_frame (frame);
 
  return frame;
}
 
/* Called by the Python interpreter to obtain string representation
   of the object.  */
 
static PyObject *
frapy_str (PyObject *self)
{
  char *s;
  PyObject *result;
  struct ui_file *strfile;
 
  strfile = mem_fileopen ();
  fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
  s = ui_file_xstrdup (strfile, NULL);
  result = PyString_FromString (s);
  xfree (s);
 
  return result;
}
 
/* Implementation of gdb.Frame.is_valid (self) -> Boolean.
   Returns True if the frame corresponding to the frame_id of this
   object still exists in the inferior.  */
 
static PyObject *
frapy_is_valid (PyObject *self, PyObject *args)
{
  struct frame_info *frame;
 
  frame = frame_object_to_frame_info ((frame_object *) self);
  if (frame == NULL)
    Py_RETURN_FALSE;
 
  Py_RETURN_TRUE;
}
 
/* Implementation of gdb.Frame.name (self) -> String.
   Returns the name of the function corresponding to this frame.  */
 
static PyObject *
frapy_name (PyObject *self, PyObject *args)
{
  struct frame_info *frame;
  char *name;
  enum language lang;
  PyObject *result;
  volatile struct gdb_exception except;
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      find_frame_funname (frame, &name, &lang);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  if (name)
    result = PyUnicode_Decode (name, strlen (name), host_charset (), NULL);
  else
    {
      result = Py_None;
      Py_INCREF (Py_None);
    }
 
  return result;
}
 
/* Implementation of gdb.Frame.type (self) -> Integer.
   Returns the frame type, namely one of the gdb.*_FRAME constants.  */
 
static PyObject *
frapy_type (PyObject *self, PyObject *args)
{
  struct frame_info *frame;
  enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning.  */
  volatile struct gdb_exception except;
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      type = get_frame_type (frame);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  return PyInt_FromLong (type);
}
 
/* Implementation of gdb.Frame.unwind_stop_reason (self) -> Integer.
   Returns one of the gdb.FRAME_UNWIND_* constants.  */
 
static PyObject *
frapy_unwind_stop_reason (PyObject *self, PyObject *args)
{
  struct frame_info *frame = NULL;    /* Initialize to appease gcc warning.  */
  volatile struct gdb_exception except;
  enum unwind_stop_reason stop_reason;
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  stop_reason = get_frame_unwind_stop_reason (frame);
 
  return PyInt_FromLong (stop_reason);
}
 
/* Implementation of gdb.Frame.pc (self) -> Long.
   Returns the frame's resume address.  */
 
static PyObject *
frapy_pc (PyObject *self, PyObject *args)
{
  CORE_ADDR pc = 0;	      /* Initialize to appease gcc warning.  */
  struct frame_info *frame;
  volatile struct gdb_exception except;
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      pc = get_frame_pc (frame);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  return PyLong_FromUnsignedLongLong (pc);
}
 
/* Convert a frame_info struct to a Python Frame object.
   Sets a Python exception and returns NULL on error.  */
 
static frame_object *
frame_info_to_frame_object (struct frame_info *frame)
{
  frame_object *frame_obj;
 
  frame_obj = PyObject_New (frame_object, &frame_object_type);
  if (frame_obj == NULL)
    {
      PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
      return NULL;
    }
 
  /* Try to get the previous frame, to determine if this is the last frame
     in a corrupt stack.  If so, we need to store the frame_id of the next
     frame and not of this one (which is possibly invalid).  */
  if (get_prev_frame (frame) == NULL
      && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
      && get_next_frame (frame) != NULL)
    {
      frame_obj->frame_id = get_frame_id (get_next_frame (frame));
      frame_obj->frame_id_is_next = 1;
    }
  else
    {
      frame_obj->frame_id = get_frame_id (frame);
      frame_obj->frame_id_is_next = 0;
    }
 
  frame_obj->gdbarch = get_frame_arch (frame);
 
  return frame_obj;
}
 
/* Implementation of gdb.Frame.older (self) -> gdb.Frame.
   Returns the frame immediately older (outer) to this frame, or None if
   there isn't one.  */
 
static PyObject *
frapy_older (PyObject *self, PyObject *args)
{
  struct frame_info *frame, *prev;
  volatile struct gdb_exception except;
  PyObject *prev_obj = NULL;   /* Initialize to appease gcc warning.  */
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      prev = get_prev_frame (frame);
      if (prev)
	prev_obj = (PyObject *) frame_info_to_frame_object (prev);
      else
	{
	  Py_INCREF (Py_None);
	  prev_obj = Py_None;
	}
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  return prev_obj;
}
 
/* Implementation of gdb.Frame.newer (self) -> gdb.Frame.
   Returns the frame immediately newer (inner) to this frame, or None if
   there isn't one.  */
 
static PyObject *
frapy_newer (PyObject *self, PyObject *args)
{
  struct frame_info *frame, *next;
  volatile struct gdb_exception except;
  PyObject *next_obj = NULL;   /* Initialize to appease gcc warning.  */
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      next = get_next_frame (frame);
      if (next)
	next_obj = (PyObject *) frame_info_to_frame_object (next);
      else
	{
	  Py_INCREF (Py_None);
	  next_obj = Py_None;
	}
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  return next_obj;
}
 
/* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value.
   Returns the value of the given variable in this frame.  The argument must be
   a string.  Returns None if GDB can't find the specified variable.  */
 
static PyObject *
frapy_read_var (PyObject *self, PyObject *args)
{
  struct frame_info *frame;
  PyObject *sym_obj;
  struct symbol *var = NULL;	/* gcc-4.3.2 false warning.  */
  struct value *val = NULL;
  volatile struct gdb_exception except;
 
  if (!PyArg_ParseTuple (args, "O", &sym_obj))
    return NULL;
 
  if (gdbpy_is_string (sym_obj))
    {
      char *var_name;
      struct block *block = NULL;
      struct cleanup *cleanup;
      volatile struct gdb_exception except;
 
      var_name = python_string_to_target_string (sym_obj);
      if (!var_name)
	return NULL;
      cleanup = make_cleanup (xfree, var_name);
 
      TRY_CATCH (except, RETURN_MASK_ALL)
	{
	  FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
	  block = block_for_pc (get_frame_address_in_block (frame));
	  var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
	}
      GDB_PY_HANDLE_EXCEPTION (except);
 
      if (!var)
	{
	  PyErr_Format (PyExc_ValueError,
			_("variable '%s' not found"), var_name);
	  do_cleanups (cleanup);
 
	  return NULL;
	}
 
      do_cleanups (cleanup);
    }
  else
    {
      PyErr_SetString (PyExc_TypeError,
		       _("argument must be a symbol or string"));
      return NULL;
    }
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
 
      val = read_var_value (var, frame);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  if (val)
    return value_to_value_object (val);
 
  Py_RETURN_NONE;
}
 
/* Implementation of gdb.selected_frame () -> gdb.Frame.
   Returns the selected frame object.  */
 
PyObject *
gdbpy_selected_frame (PyObject *self, PyObject *args)
{
  struct frame_info *frame;
  frame_object *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
  volatile struct gdb_exception except;
 
  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      frame = get_selected_frame ("No frame is currently selected.");
      frame_obj = frame_info_to_frame_object (frame);
    }
  GDB_PY_HANDLE_EXCEPTION (except);
 
  return (PyObject *) frame_obj;
}
 
/* Implementation of gdb.stop_reason_string (Integer) -> String.
   Return a string explaining the unwind stop reason.  */
 
PyObject *
gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
{
  int reason;
  const char *str;
 
  if (!PyArg_ParseTuple (args, "i", &reason))
    return NULL;
 
  if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
    {
      PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
      return NULL;
    }
 
  str = frame_stop_reason_string (reason);
  return PyUnicode_Decode (str, strlen (str), host_charset (), NULL);
}
 
/* Implements the equality comparison for Frame objects.
   All other comparison operators will throw a TypeError Python exception,
   as they aren't valid for frames.  */
 
static PyObject *
frapy_richcompare (PyObject *self, PyObject *other, int op)
{
  int result;
 
  if (!PyObject_TypeCheck (other, &frame_object_type)
      || (op != Py_EQ && op != Py_NE))
    {
      Py_INCREF (Py_NotImplemented);
      return Py_NotImplemented;
    }
 
  if (frame_id_eq (((frame_object *) self)->frame_id,
		   ((frame_object *) other)->frame_id))
    result = Py_EQ;
  else
    result = Py_NE;
 
  if (op == result)
    Py_RETURN_TRUE;
  Py_RETURN_FALSE;
}
 
/* Sets up the Frame API in the gdb module.  */
 
void
gdbpy_initialize_frames (void)
{
  if (PyType_Ready (&frame_object_type) < 0)
    return;
 
  /* Note: These would probably be best exposed as class attributes of Frame,
     but I don't know how to do it except by messing with the type's dictionary.
     That seems too messy.  */
  PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
  PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
  PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
  PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
  PyModule_AddIntConstant (gdb_module,
			   "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
 
  Py_INCREF (&frame_object_type);
  PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
}
 

 
static PyMethodDef frame_object_methods[] = {
  { "is_valid", frapy_is_valid, METH_NOARGS,
    "is_valid () -> Boolean.\n\
Return true if this frame is valid, false if not." },
  { "name", frapy_name, METH_NOARGS,
    "name () -> String.\n\
Return the function name of the frame, or None if it can't be determined." },
  { "type", frapy_type, METH_NOARGS,
    "type () -> Integer.\n\
Return the type of the frame." },
  { "unwind_stop_reason", frapy_unwind_stop_reason, METH_NOARGS,
    "unwind_stop_reason () -> Integer.\n\
Return the reason why it's not possible to find frames older than this." },
  { "pc", frapy_pc, METH_NOARGS,
    "pc () -> Long.\n\
Return the frame's resume address." },
  { "older", frapy_older, METH_NOARGS,
    "older () -> gdb.Frame.\n\
Return the frame that called this frame." },
  { "newer", frapy_newer, METH_NOARGS,
    "newer () -> gdb.Frame.\n\
Return the frame called by this frame." },
  { "read_var", frapy_read_var, METH_VARARGS,
    "read_var (variable) -> gdb.Value.\n\
Return the value of the variable in this frame." },
  {NULL}  /* Sentinel */
};
 
static PyTypeObject frame_object_type = {
  PyObject_HEAD_INIT (NULL)
  0,				  /* ob_size */
  "gdb.Frame",			  /* tp_name */
  sizeof (frame_object),	  /* tp_basicsize */
  0,				  /* tp_itemsize */
  0,				  /* tp_dealloc */
  0,				  /* tp_print */
  0,				  /* tp_getattr */
  0,				  /* tp_setattr */
  0,				  /* tp_compare */
  0,				  /* tp_repr */
  0,				  /* tp_as_number */
  0,				  /* tp_as_sequence */
  0,				  /* tp_as_mapping */
  0,				  /* tp_hash  */
  0,				  /* tp_call */
  frapy_str,			  /* tp_str */
  0,				  /* tp_getattro */
  0,				  /* tp_setattro */
  0,				  /* tp_as_buffer */
  Py_TPFLAGS_DEFAULT,		  /* tp_flags */
  "GDB frame object",		  /* tp_doc */
  0,				  /* tp_traverse */
  0,				  /* tp_clear */
  frapy_richcompare,		  /* tp_richcompare */
  0,				  /* tp_weaklistoffset */
  0,				  /* tp_iter */
  0,				  /* tp_iternext */
  frame_object_methods,		  /* tp_methods */
  0,				  /* tp_members */
  0,				  /* tp_getset */
  0,				  /* tp_base */
  0,				  /* tp_dict */
  0,				  /* tp_descr_get */
  0,				  /* tp_descr_set */
  0,				  /* tp_dictoffset */
  0,				  /* tp_init */
  0,				  /* tp_alloc */
  PyType_GenericNew		  /* tp_new */
};
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.