This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 7/7] py-regcache: Add interface to regcache


From: Jeff Mahoney <jeffm@suse.com>

This patch adds new gdb.Register and gdb.RegCache objects to access
the register cache associated with a thread.  We can resolve regcache
objects via gdb.InferiorThread.
---
 gdb/Makefile.in              |   6 +
 gdb/python/py-infthread.c    |  31 ++++
 gdb/python/py-regcache.c     | 367 +++++++++++++++++++++++++++++++++++++++++++
 gdb/python/python-internal.h |   6 +
 gdb/python/python.c          |   3 +-
 5 files changed, 412 insertions(+), 1 deletion(-)
 create mode 100644 gdb/python/py-regcache.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c2f7eef..e005485 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -406,6 +406,7 @@ SUBDIR_PYTHON_OBS = \
 	py-param.o \
 	py-prettyprint.o \
 	py-progspace.o \
+	py-regcache.o \
 	py-signalevent.o \
 	py-stopevent.o \
 	py-symbol.o \
@@ -447,6 +448,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-param.c \
 	python/py-prettyprint.c \
 	python/py-progspace.c \
+	python/py-regcache.c \
 	python/py-signalevent.c \
 	python/py-stopevent.c \
 	python/py-symbol.c \
@@ -2661,6 +2663,10 @@ py-progspace.o: $(srcdir)/python/py-progspace.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-progspace.c
 	$(POSTCOMPILE)
 
+py-regcache.o: $(srcdir)/python/py-regcache.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-regcache.c
+	$(POSTCOMPILE)
+
 py-signalevent.o: $(srcdir)/python/py-signalevent.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-signalevent.c
 	$(POSTCOMPILE)
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index e5db354..aa28ec6 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -47,6 +47,7 @@ create_thread_object (struct thread_info *tp)
 
   thread_obj->thread = tp;
   thread_obj->inf_obj = find_inferior_object (ptid_get_pid (tp->ptid));
+  thread_obj->regcache = NULL;
 
   return thread_obj;
 }
@@ -226,6 +227,34 @@ thpy_is_valid (PyObject *self, PyObject *args)
   Py_RETURN_TRUE;
 }
 
+static PyObject *
+thpy_get_regcache (PyObject *self, void *closure)
+{
+  thread_object *thread_obj = (thread_object *)self;
+  struct regcache *rc;
+  struct thread_info *tp;
+  TRY
+    {
+      THPY_REQUIRE_VALID(thread_obj);
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+  END_CATCH
+
+  if (thread_obj->regcache) {
+    Py_INCREF(thread_obj->regcache);
+    return thread_obj->regcache;
+  }
+
+  tp = thread_obj->thread;
+  rc = get_thread_regcache(tp->ptid);
+  thread_obj->regcache = regcache_to_regcache_object(rc);
+//  Py_INCREF(thread_obj->regcache);
+  return thread_obj->regcache;
+}
+
 /* Return a reference to a new Python object representing a ptid_t.
    The object is a tuple containing (pid, lwp, tid). */
 PyObject *
@@ -285,6 +314,8 @@ static PyGetSetDef thread_object_getset[] =
   { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL },
   { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.",
     NULL },
+  { "regcache", thpy_get_regcache, NULL, "Register cache for this thread.",
+    NULL },
 
   { NULL }
 };
diff --git a/gdb/python/py-regcache.c b/gdb/python/py-regcache.c
new file mode 100644
index 0000000..9447404
--- /dev/null
+++ b/gdb/python/py-regcache.c
@@ -0,0 +1,367 @@
+#include "defs.h"
+#include "python-internal.h"
+#include "regcache.h"
+
+extern PyTypeObject regcache_object_type;
+extern PyTypeObject register_object_type;
+
+typedef struct {
+  PyObject_HEAD
+  struct regcache *regcache;
+} regcache_object;
+
+typedef struct {
+  PyObject_HEAD
+  struct regcache *regcache;
+  const char *name;
+  int regnum;
+} register_object;
+
+/* Require a valid regcache.  All access to regcache_object->regcache should
+   be gated by this call. */
+#define RCPY_REQUIRE_VALID(regcache_obj, regcache)		\
+   do {								\
+     regcache = regcache_object_to_regcache (regcache_obj);	\
+     if (regcache == NULL)					\
+      {								\
+	PyErr_SetString (PyExc_RuntimeError,			\
+			 _("Regcache is invalid."));		\
+	return NULL;						\
+      }								\
+    } while (0)
+
+static void
+set_regcache(regcache_object *obj, struct regcache *rc)
+{
+  obj->regcache = rc;
+}
+
+PyObject *
+regcache_to_regcache_object (struct regcache *rc)
+{
+  regcache_object *regcache_obj;
+
+  regcache_obj = PyObject_New (regcache_object, &regcache_object_type);
+  if (regcache_obj)
+    set_regcache (regcache_obj, rc);
+  return (PyObject *) regcache_obj;
+}
+
+static regcache_object *
+regcache_object_to_regcache (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &regcache_object_type))
+    return NULL;
+  return ((regcache_object *) obj);
+}
+
+#define RCPY_REG_REQUIRE_VALID(register_obj, reg, ret)		\
+  do {								\
+    reg = register_object_to_register(register_obj);		\
+    if (reg == NULL)						\
+      {								\
+	PyErr_SetString (PyExc_RuntimeError,			\
+			 _("Regcache is invalid."));		\
+	return ret;						\
+      }								\
+  } while(0)
+
+static void
+set_register(register_object *obj, struct regcache *rc,
+	     const char *name, int regnum)
+{
+  obj->regcache = rc;
+  obj->name = name;
+  obj->regnum = regnum;
+}
+
+static PyObject *
+register_to_register_object (struct regcache *rc, const char *name, int reg)
+{
+  register_object *register_obj;
+
+  register_obj = PyObject_New (register_object, &register_object_type);
+  if (register_obj)
+    set_register (register_obj, rc, name, reg);
+  return (PyObject *) register_obj;
+
+}
+
+static register_object *
+register_object_to_register (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &register_object_type))
+    return NULL;
+  return ((register_object *) obj);
+}
+
+
+static PyObject *
+rcpy_get_registers (PyObject *self, void *closure)
+{
+  regcache_object *obj;
+  struct gdbarch *gdbarch;
+  int i, numregs;
+  PyObject *d;
+
+  RCPY_REQUIRE_VALID(self, obj);
+  gdbarch = get_regcache_arch(obj->regcache);
+  numregs = gdbarch_num_regs(gdbarch);
+
+  d = PyDict_New();
+  for (i = 0; i < numregs; i++)
+    {
+      struct register_object *robj;
+      const char *name = gdbarch_register_name(gdbarch, i);
+      PyObject *reg;
+
+      if (!name || !*name)
+	      continue;
+      reg = register_to_register_object (obj->regcache, name, i);
+      if (!reg) {
+	Py_DECREF(d);
+	return NULL;
+      }
+      if (PyDict_SetItemString(d, name, reg)) {
+	Py_DECREF(reg);
+	Py_DECREF(d);
+	return NULL;
+      }
+    }
+
+    return d;
+}
+
+static PyGetSetDef regcache_object_getset[] = {
+  { "registers", rcpy_get_registers, NULL, "Dictionary of registers.", NULL },
+  { NULL }  /* Sentinal */
+};
+
+PyTypeObject regcache_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "gdb.RegCache",		  /*tp_name*/
+  sizeof(regcache_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_delalloc*/
+  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*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,  		  /*tp_flags*/
+  "GDB regcache object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,	  			  /* tp_methods */
+  0,				  /* tp_members */
+  regcache_object_getset,	  /* tp_getset */
+};
+
+static PyObject *
+register_get_name(PyObject *self, void *closure)
+{
+  register_object *obj;
+  RCPY_REG_REQUIRE_VALID(self, obj, NULL);
+
+  return PyString_FromString(obj->name);
+}
+
+static PyObject *
+register_get_value(PyObject *self, void *closure)
+{
+  register_object *obj;
+  struct value *value = NULL;
+
+  RCPY_REG_REQUIRE_VALID(self, obj, NULL);
+
+  TRY
+    {
+      /*
+       * We don't want raw read since that expects to
+       * read it from the core file
+       */
+      value = regcache_cooked_read_value(obj->regcache, obj->regnum);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      GDB_PY_HANDLE_EXCEPTION (ex);
+    }
+  END_CATCH
+
+  return value_to_value_object(value);
+}
+
+static const char *
+type_prefix (struct type *type)
+{
+  switch (TYPE_CODE(type))
+    {
+      case TYPE_CODE_UNION:
+	return "union ";
+      case TYPE_CODE_STRUCT:
+	return "struct ";
+      case TYPE_CODE_ENUM:
+	return "enum ";
+      }
+
+    return "";
+}
+
+static int
+register_set_value(PyObject *self, PyObject *value_obj, void *closure)
+{
+  register_object *obj;
+  struct type *type, *vtype = NULL;
+  struct value *value;
+  struct gdbarch *gdbarch;
+
+  RCPY_REG_REQUIRE_VALID(self, obj, -1);
+
+  value = value_object_to_value(value_obj);
+  if (value)
+    vtype = value_type(value);
+
+  gdbarch = get_regcache_arch(obj->regcache);
+  type = register_type (gdbarch, obj->regnum);
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR || is_integral_type (type))
+    {
+      unsigned long ul_value;
+      if (PyLong_Check(value_obj))
+	{
+	  ul_value = PyLong_AsUnsignedLong (value_obj);
+	  regcache_raw_supply (obj->regcache, obj->regnum, &ul_value);
+	}
+      else if (PyInt_Check (value_obj))
+	{
+	  ul_value = PyInt_AsUnsignedLongMask (value_obj);
+	  regcache_raw_supply (obj->regcache, obj->regnum, &ul_value);
+	}
+      else if (vtype && (TYPE_CODE(vtype) == TYPE_CODE_PTR ||
+			 is_integral_type (vtype)))
+	{
+	  regcache_raw_supply (obj->regcache, obj->regnum,
+			       value_contents (value));
+	}
+      else
+	{
+	  PyErr_SetString (PyExc_TypeError,
+			   "value must be pointer, int, long, or gdb.Value describing pointer or integral type");
+	  return -1;
+	}
+    }
+  else if (vtype && types_equal (type, vtype))
+    {
+      regcache_raw_supply (obj->regcache, obj->regnum, value_contents(value));
+    }
+  else
+    {
+      PyErr_Format (PyExc_TypeError,
+		    "value type for register must be gdb.Value describing `%s%s'",
+		    type_prefix (type), type_name_no_tag (type));
+      return -1;
+    }
+
+  return 0;
+}
+
+static PyObject *
+register_get_size(PyObject *self, void *closure)
+{
+  register_object *obj;
+  struct gdbarch *gdbarch;
+  RCPY_REG_REQUIRE_VALID(self, obj, NULL);
+  gdbarch = get_regcache_arch(obj->regcache);
+  return PyInt_FromLong(register_size(gdbarch, obj->regnum));
+}
+
+static PyObject *
+register_get_regnum(PyObject *self, void *closure)
+{
+  register_object *obj;
+  RCPY_REG_REQUIRE_VALID(self, obj, NULL);
+  return PyInt_FromLong(obj->regnum);
+}
+
+static PyObject *
+register_get_regtype(PyObject *self, void *closure)
+{
+  register_object *obj;
+  struct gdbarch *gdbarch;
+  struct type *type;
+  RCPY_REG_REQUIRE_VALID(self, obj, NULL);
+
+  gdbarch = get_regcache_arch(obj->regcache);
+  type = register_type(gdbarch, obj->regnum);
+
+  return type_to_type_object(type);
+}
+
+static PyGetSetDef register_object_getset[] = {
+  { "name", register_get_name, NULL, "Register name.", NULL },
+  { "value", register_get_value, register_set_value, "Register value.", NULL },
+  { "size", register_get_size, NULL, "Register size.", NULL },
+  { "regnum", register_get_regnum, NULL, "Register number.", NULL },
+  { "type", register_get_regtype, NULL, "Register type.", NULL },
+  { NULL }  /* Sentinal */
+};
+
+PyTypeObject register_object_type = {
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "gdb.Register",		  /*tp_name*/
+  sizeof(register_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_delalloc*/
+  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*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB register object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,	  			  /* tp_methods */
+  0,				  /* tp_members */
+  register_object_getset,	  /* tp_getset */
+};
+
+int gdbpy_initialize_regcache (void)
+{
+    if (PyType_Ready (&register_object_type) < 0)
+      return -1;
+    if (PyType_Ready (&regcache_object_type) < 0)
+      return -1;
+
+    if (gdb_pymodule_addobject(gdb_module, "Register",
+			       (PyObject *)&register_object_type))
+      return -1;
+    return gdb_pymodule_addobject(gdb_module, "Regcache",
+				  (PyObject *)&regcache_object_type);
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 2fae31d..51f08ee 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -302,6 +302,9 @@ typedef struct
   /* The thread we represent.  */
   struct thread_info *thread;
 
+  /* Regcache */
+  PyObject *regcache;
+
   /* The Inferior object to which this thread belongs.  */
   PyObject *inf_obj;
 } thread_object;
@@ -504,6 +507,8 @@ int gdbpy_initialize_xmethods (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_unwind (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_regcache (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 struct cleanup *make_cleanup_py_xdecref (PyObject *py);
@@ -600,4 +605,5 @@ struct varobj;
 struct varobj_iter *py_varobj_get_iterator (struct varobj *var,
 					    PyObject *printer);
 
+PyObject *regcache_to_regcache_object (struct regcache *rc);
 #endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 30a86e1..8218beb 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1832,7 +1832,8 @@ message == an error message without a stack will be printed."),
       || gdbpy_initialize_clear_objfiles_event ()  < 0
       || gdbpy_initialize_arch () < 0
       || gdbpy_initialize_xmethods () < 0
-      || gdbpy_initialize_unwind () < 0)
+      || gdbpy_initialize_unwind () < 0
+      || gdbpy_initialize_regcache () < 0)
     goto fail;
 
   gdbpy_to_string_cst = PyString_FromString ("to_string");
-- 
2.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]