From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18531 invoked by alias); 4 Feb 2016 17:29:53 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 18446 invoked by uid 89); 4 Feb 2016 17:29:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=Dictionary, tuple, 226,6, 2266 X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 04 Feb 2016 17:29:44 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 368CCAD8E for ; Thu, 4 Feb 2016 17:29:40 +0000 (UTC) Received: by starscream.home.jeffm.io (Postfix, from userid 1000) id 8D4B38998D; Thu, 4 Feb 2016 12:29:34 -0500 (EST) From: jeffm@suse.com To: gdb-patches@sourceware.org Cc: Jeff Mahoney Subject: [PATCH 7/7] py-regcache: Add interface to regcache Date: Thu, 04 Feb 2016 17:29:00 -0000 Message-Id: <1454606973-31017-8-git-send-email-jeffm@suse.com> In-Reply-To: <1454606973-31017-1-git-send-email-jeffm@suse.com> References: <1454606973-31017-1-git-send-email-jeffm@suse.com> X-IsSubscribed: yes X-SW-Source: 2016-02/txt/msg00122.txt.bz2 From: Jeff Mahoney 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, ®cache_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, ®cache_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, ®ister_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, ®ister_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 (®ister_object_type) < 0) + return -1; + if (PyType_Ready (®cache_object_type) < 0) + return -1; + + if (gdb_pymodule_addobject(gdb_module, "Register", + (PyObject *)®ister_object_type)) + return -1; + return gdb_pymodule_addobject(gdb_module, "Regcache", + (PyObject *)®cache_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