
Python 2 has a bit flag Py_TPFLAGS_HAVE_ITER which can be passed as part of the tp_flags field when defining a new object type. This flag is not defined in Python 3 and so we define it to 0 in python-internal.h (when IS_PY3K is defined). The meaning of this flag is that the object has the fields tp_iter and tp_iternext. Note the use of "has" here, the flag says nothing about the values in those fields, just that the type object has the fields. In early versions of Python 2 these fields were no part of the PyTypeObject struct, they were added in version 2.2 (see https://docs.python.org/release/2.3/api/type-structs.html). And so, there could be a some code compiled out there which has a PyTypeObject structure within it that doesn't even have the tp_iter and tp_iternext fields, attempting to access these fields would be undefined behaviour. And so Python added the Py_TPFLAGS_HAVE_ITER flag. If the flag is present then Python is free to access the tp_iter and tp_iternext fields. If we consider GDB then we always assume that the tp_iter and tp_iternext fields are part of PyTypeObject. If someone was crazy enough to try and compile GDB against Python 2.1 then we'd get lots of build errors saying that we were passing too many fields when initializing PyTypeObject structures. And so, I claim, we can be sure that GDB will always be compiled with a version of Python that has the tp_iter and tp_iternext fields in PyTypeObject. Next we can look at the Py_TPFLAGS_DEFAULT flag. In Python 2, each time additional fields are added to PyTypeObject a new Py_TPFLAGS_* flag would be defined to indicate whether those flags are present or not. And, those new flags would be added to Py_TPFLAGS_DEFAULT. And so, in the latest version of Python 2 the Py_TPFLAGS_DEFAULT flag includes Py_TPFLAGS_HAVE_ITER (see https://docs.python.org/2.7/c-api/typeobj.html). In GDB we pass Py_TPFLAGS_DEFAULT as part of the tp_flags for all objects we define. And so, in this commit, I propose to remove all uses of Py_TPFLAGS_HAVE_ITER from GDB, it's simply not needed. There should be no user visible changes after this commit.
618 lines
18 KiB
C
618 lines
18 KiB
C
/* Python interface to register, and register group information.
|
|
|
|
Copyright (C) 2020-2021 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 "gdbarch.h"
|
|
#include "arch-utils.h"
|
|
#include "disasm.h"
|
|
#include "reggroups.h"
|
|
#include "python-internal.h"
|
|
#include "user-regs.h"
|
|
#include <unordered_map>
|
|
|
|
/* Token to access per-gdbarch data related to register descriptors. */
|
|
static struct gdbarch_data *gdbpy_register_object_data = NULL;
|
|
|
|
/* Structure for iterator over register descriptors. */
|
|
struct register_descriptor_iterator_object {
|
|
PyObject_HEAD
|
|
|
|
/* The register group that the user is iterating over. This will never
|
|
be NULL. */
|
|
struct reggroup *reggroup;
|
|
|
|
/* The next register number to lookup. Starts at 0 and counts up. */
|
|
int regnum;
|
|
|
|
/* Pointer back to the architecture we're finding registers for. */
|
|
struct gdbarch *gdbarch;
|
|
};
|
|
|
|
extern PyTypeObject register_descriptor_iterator_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("register_descriptor_iterator_object");
|
|
|
|
/* A register descriptor. */
|
|
struct register_descriptor_object {
|
|
PyObject_HEAD
|
|
|
|
/* The register this is a descriptor for. */
|
|
int regnum;
|
|
|
|
/* The architecture this is a register for. */
|
|
struct gdbarch *gdbarch;
|
|
};
|
|
|
|
extern PyTypeObject register_descriptor_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("register_descriptor_object");
|
|
|
|
/* Structure for iterator over register groups. */
|
|
struct reggroup_iterator_object {
|
|
PyObject_HEAD
|
|
|
|
/* The last register group returned. Initially this will be NULL. */
|
|
struct reggroup *reggroup;
|
|
|
|
/* Pointer back to the architecture we're finding registers for. */
|
|
struct gdbarch *gdbarch;
|
|
};
|
|
|
|
extern PyTypeObject reggroup_iterator_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_iterator_object");
|
|
|
|
/* A register group object. */
|
|
struct reggroup_object {
|
|
PyObject_HEAD
|
|
|
|
/* The register group being described. */
|
|
struct reggroup *reggroup;
|
|
};
|
|
|
|
extern PyTypeObject reggroup_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object");
|
|
|
|
/* Associates a vector of gdb.RegisterDescriptor objects with GDBARCH as
|
|
gdbarch_data via the gdbarch post init registration mechanism
|
|
(gdbarch_data_register_post_init). */
|
|
|
|
static void *
|
|
gdbpy_register_object_data_init (struct gdbarch *gdbarch)
|
|
{
|
|
return new std::vector<gdbpy_ref<>>;
|
|
}
|
|
|
|
/* Return a gdb.RegisterGroup object wrapping REGGROUP. The register
|
|
group objects are cached, and the same Python object will always be
|
|
returned for the same REGGROUP pointer. */
|
|
|
|
static gdbpy_ref<>
|
|
gdbpy_get_reggroup (struct reggroup *reggroup)
|
|
{
|
|
/* Map from GDB's internal reggroup objects to the Python representation.
|
|
GDB's reggroups are global, and are never deleted, so using a map like
|
|
this is safe. */
|
|
static std::unordered_map<struct reggroup *,gdbpy_ref<>>
|
|
gdbpy_reggroup_object_map;
|
|
|
|
/* If there is not already a suitable Python object in the map then
|
|
create a new one, and add it to the map. */
|
|
if (gdbpy_reggroup_object_map[reggroup] == nullptr)
|
|
{
|
|
/* Create a new object and fill in its details. */
|
|
gdbpy_ref<reggroup_object> group
|
|
(PyObject_New (reggroup_object, ®group_object_type));
|
|
if (group == NULL)
|
|
return NULL;
|
|
group->reggroup = reggroup;
|
|
gdbpy_reggroup_object_map[reggroup]
|
|
= gdbpy_ref<> ((PyObject *) group.release ());
|
|
}
|
|
|
|
/* Fetch the Python object wrapping REGGROUP from the map, increasing
|
|
the reference count is handled by the gdbpy_ref class. */
|
|
return gdbpy_reggroup_object_map[reggroup];
|
|
}
|
|
|
|
/* Convert a gdb.RegisterGroup to a string, it just returns the name of
|
|
the register group. */
|
|
|
|
static PyObject *
|
|
gdbpy_reggroup_to_string (PyObject *self)
|
|
{
|
|
reggroup_object *group = (reggroup_object *) self;
|
|
struct reggroup *reggroup = group->reggroup;
|
|
|
|
const char *name = reggroup_name (reggroup);
|
|
return PyString_FromString (name);
|
|
}
|
|
|
|
/* Implement gdb.RegisterGroup.name (self) -> String.
|
|
Return a string that is the name of this register group. */
|
|
|
|
static PyObject *
|
|
gdbpy_reggroup_name (PyObject *self, void *closure)
|
|
{
|
|
return gdbpy_reggroup_to_string (self);
|
|
}
|
|
|
|
/* Return a gdb.RegisterDescriptor object for REGNUM from GDBARCH. For
|
|
each REGNUM (in GDBARCH) only one descriptor is ever created, which is
|
|
then cached on the GDBARCH. */
|
|
|
|
static gdbpy_ref<>
|
|
gdbpy_get_register_descriptor (struct gdbarch *gdbarch,
|
|
int regnum)
|
|
{
|
|
auto &vec
|
|
= *(std::vector<gdbpy_ref<>> *) gdbarch_data (gdbarch,
|
|
gdbpy_register_object_data);
|
|
|
|
/* Ensure that we have enough entries in the vector. */
|
|
if (vec.size () <= regnum)
|
|
vec.resize ((regnum + 1), nullptr);
|
|
|
|
/* If we don't already have a descriptor for REGNUM in GDBARCH then
|
|
create one now. */
|
|
if (vec[regnum] == nullptr)
|
|
{
|
|
gdbpy_ref <register_descriptor_object> reg
|
|
(PyObject_New (register_descriptor_object,
|
|
®ister_descriptor_object_type));
|
|
if (reg == NULL)
|
|
return NULL;
|
|
reg->regnum = regnum;
|
|
reg->gdbarch = gdbarch;
|
|
vec[regnum] = gdbpy_ref<> ((PyObject *) reg.release ());
|
|
}
|
|
|
|
/* Grab the register descriptor from the vector, the reference count is
|
|
automatically incremented thanks to gdbpy_ref. */
|
|
return vec[regnum];
|
|
}
|
|
|
|
/* Convert the register descriptor to a string. */
|
|
|
|
static PyObject *
|
|
gdbpy_register_descriptor_to_string (PyObject *self)
|
|
{
|
|
register_descriptor_object *reg
|
|
= (register_descriptor_object *) self;
|
|
struct gdbarch *gdbarch = reg->gdbarch;
|
|
int regnum = reg->regnum;
|
|
|
|
const char *name = gdbarch_register_name (gdbarch, regnum);
|
|
return PyString_FromString (name);
|
|
}
|
|
|
|
/* Implement gdb.RegisterDescriptor.name attribute get function. Return a
|
|
string that is the name of this register. Due to checking when register
|
|
descriptors are created the name will never by the empty string. */
|
|
|
|
static PyObject *
|
|
gdbpy_register_descriptor_name (PyObject *self, void *closure)
|
|
{
|
|
return gdbpy_register_descriptor_to_string (self);
|
|
}
|
|
|
|
/* Return a reference to the gdb.RegisterGroupsIterator object. */
|
|
|
|
static PyObject *
|
|
gdbpy_reggroup_iter (PyObject *self)
|
|
{
|
|
Py_INCREF (self);
|
|
return self;
|
|
}
|
|
|
|
/* Return the next gdb.RegisterGroup object from the iterator. */
|
|
|
|
static PyObject *
|
|
gdbpy_reggroup_iter_next (PyObject *self)
|
|
{
|
|
reggroup_iterator_object *iter_obj
|
|
= (reggroup_iterator_object *) self;
|
|
struct gdbarch *gdbarch = iter_obj->gdbarch;
|
|
|
|
struct reggroup *next_group = reggroup_next (gdbarch, iter_obj->reggroup);
|
|
if (next_group == NULL)
|
|
{
|
|
PyErr_SetString (PyExc_StopIteration, _("No more groups"));
|
|
return NULL;
|
|
}
|
|
|
|
iter_obj->reggroup = next_group;
|
|
return gdbpy_get_reggroup (iter_obj->reggroup).release ();
|
|
}
|
|
|
|
/* Return a new gdb.RegisterGroupsIterator over all the register groups in
|
|
GDBARCH. */
|
|
|
|
PyObject *
|
|
gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch)
|
|
{
|
|
gdb_assert (gdbarch != nullptr);
|
|
|
|
/* Create a new object and fill in its internal state. */
|
|
reggroup_iterator_object *iter
|
|
= PyObject_New (reggroup_iterator_object,
|
|
®group_iterator_object_type);
|
|
if (iter == NULL)
|
|
return NULL;
|
|
iter->reggroup = NULL;
|
|
iter->gdbarch = gdbarch;
|
|
return (PyObject *) iter;
|
|
}
|
|
|
|
/* Create and return a new gdb.RegisterDescriptorIterator object which
|
|
will iterate over all registers in GROUP_NAME for GDBARCH. If
|
|
GROUP_NAME is either NULL or the empty string then the ALL_REGGROUP is
|
|
used, otherwise lookup the register group matching GROUP_NAME and use
|
|
that.
|
|
|
|
This function can return NULL if GROUP_NAME isn't found. */
|
|
|
|
PyObject *
|
|
gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
|
|
const char *group_name)
|
|
{
|
|
struct reggroup *grp = NULL;
|
|
|
|
/* Lookup the requested register group, or find the default. */
|
|
if (group_name == NULL || *group_name == '\0')
|
|
grp = all_reggroup;
|
|
else
|
|
{
|
|
grp = reggroup_find (gdbarch, group_name);
|
|
if (grp == NULL)
|
|
{
|
|
PyErr_SetString (PyExc_ValueError,
|
|
_("Unknown register group name."));
|
|
return NULL;
|
|
}
|
|
}
|
|
/* Create a new iterator object initialised for this architecture and
|
|
fill in all of the details. */
|
|
register_descriptor_iterator_object *iter
|
|
= PyObject_New (register_descriptor_iterator_object,
|
|
®ister_descriptor_iterator_object_type);
|
|
if (iter == NULL)
|
|
return NULL;
|
|
iter->regnum = 0;
|
|
iter->gdbarch = gdbarch;
|
|
gdb_assert (grp != NULL);
|
|
iter->reggroup = grp;
|
|
|
|
return (PyObject *) iter;
|
|
}
|
|
|
|
/* Return a reference to the gdb.RegisterDescriptorIterator object. */
|
|
|
|
static PyObject *
|
|
gdbpy_register_descriptor_iter (PyObject *self)
|
|
{
|
|
Py_INCREF (self);
|
|
return self;
|
|
}
|
|
|
|
/* Return the next register name. */
|
|
|
|
static PyObject *
|
|
gdbpy_register_descriptor_iter_next (PyObject *self)
|
|
{
|
|
register_descriptor_iterator_object *iter_obj
|
|
= (register_descriptor_iterator_object *) self;
|
|
struct gdbarch *gdbarch = iter_obj->gdbarch;
|
|
|
|
do
|
|
{
|
|
if (iter_obj->regnum >= gdbarch_num_cooked_regs (gdbarch))
|
|
{
|
|
PyErr_SetString (PyExc_StopIteration, _("No more registers"));
|
|
return NULL;
|
|
}
|
|
|
|
const char *name = nullptr;
|
|
int regnum = iter_obj->regnum;
|
|
if (gdbarch_register_reggroup_p (gdbarch, regnum,
|
|
iter_obj->reggroup))
|
|
name = gdbarch_register_name (gdbarch, regnum);
|
|
iter_obj->regnum++;
|
|
|
|
if (name != nullptr && *name != '\0')
|
|
return gdbpy_get_register_descriptor (gdbarch, regnum).release ();
|
|
}
|
|
while (true);
|
|
}
|
|
|
|
/* Implement:
|
|
|
|
gdb.RegisterDescriptorIterator.find (self, name) -> gdb.RegisterDescriptor
|
|
|
|
Look up a descriptor for register with NAME. If no matching register is
|
|
found then return None. */
|
|
|
|
static PyObject *
|
|
register_descriptor_iter_find (PyObject *self, PyObject *args, PyObject *kw)
|
|
{
|
|
static const char *keywords[] = { "name", NULL };
|
|
const char *register_name = NULL;
|
|
|
|
register_descriptor_iterator_object *iter_obj
|
|
= (register_descriptor_iterator_object *) self;
|
|
struct gdbarch *gdbarch = iter_obj->gdbarch;
|
|
|
|
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords,
|
|
®ister_name))
|
|
return NULL;
|
|
|
|
if (register_name != NULL && *register_name != '\0')
|
|
{
|
|
int regnum = user_reg_map_name_to_regnum (gdbarch, register_name,
|
|
strlen (register_name));
|
|
if (regnum >= 0)
|
|
return gdbpy_get_register_descriptor (gdbarch, regnum).release ();
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* See python-internal.h. */
|
|
|
|
bool
|
|
gdbpy_parse_register_id (struct gdbarch *gdbarch, PyObject *pyo_reg_id,
|
|
int *reg_num)
|
|
{
|
|
gdb_assert (pyo_reg_id != NULL);
|
|
|
|
/* The register could be a string, its name. */
|
|
if (gdbpy_is_string (pyo_reg_id))
|
|
{
|
|
gdb::unique_xmalloc_ptr<char> reg_name (gdbpy_obj_to_string (pyo_reg_id));
|
|
|
|
if (reg_name != NULL)
|
|
{
|
|
*reg_num = user_reg_map_name_to_regnum (gdbarch, reg_name.get (),
|
|
strlen (reg_name.get ()));
|
|
return *reg_num >= 0;
|
|
}
|
|
}
|
|
/* The register could be its internal GDB register number. */
|
|
else if (PyInt_Check (pyo_reg_id))
|
|
{
|
|
long value;
|
|
if (gdb_py_int_as_long (pyo_reg_id, &value) && (int) value == value)
|
|
{
|
|
if (user_reg_map_regnum_to_name (gdbarch, value) != NULL)
|
|
{
|
|
*reg_num = (int) value;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
/* The register could be a gdb.RegisterDescriptor object. */
|
|
else if (PyObject_IsInstance (pyo_reg_id,
|
|
(PyObject *) ®ister_descriptor_object_type))
|
|
{
|
|
register_descriptor_object *reg
|
|
= (register_descriptor_object *) pyo_reg_id;
|
|
if (reg->gdbarch == gdbarch)
|
|
{
|
|
*reg_num = reg->regnum;
|
|
return true;
|
|
}
|
|
else
|
|
PyErr_SetString (PyExc_ValueError,
|
|
_("Invalid Architecture in RegisterDescriptor"));
|
|
}
|
|
|
|
gdb_assert (PyErr_Occurred ());
|
|
return false;
|
|
}
|
|
|
|
void _initialize_py_registers ();
|
|
void
|
|
_initialize_py_registers ()
|
|
{
|
|
gdbpy_register_object_data
|
|
= gdbarch_data_register_post_init (gdbpy_register_object_data_init);
|
|
}
|
|
|
|
/* Initializes the new Python classes from this file in the gdb module. */
|
|
|
|
int
|
|
gdbpy_initialize_registers ()
|
|
{
|
|
register_descriptor_object_type.tp_new = PyType_GenericNew;
|
|
if (PyType_Ready (®ister_descriptor_object_type) < 0)
|
|
return -1;
|
|
if (gdb_pymodule_addobject
|
|
(gdb_module, "RegisterDescriptor",
|
|
(PyObject *) ®ister_descriptor_object_type) < 0)
|
|
return -1;
|
|
|
|
reggroup_iterator_object_type.tp_new = PyType_GenericNew;
|
|
if (PyType_Ready (®group_iterator_object_type) < 0)
|
|
return -1;
|
|
if (gdb_pymodule_addobject
|
|
(gdb_module, "RegisterGroupsIterator",
|
|
(PyObject *) ®group_iterator_object_type) < 0)
|
|
return -1;
|
|
|
|
reggroup_object_type.tp_new = PyType_GenericNew;
|
|
if (PyType_Ready (®group_object_type) < 0)
|
|
return -1;
|
|
if (gdb_pymodule_addobject
|
|
(gdb_module, "RegisterGroup",
|
|
(PyObject *) ®group_object_type) < 0)
|
|
return -1;
|
|
|
|
register_descriptor_iterator_object_type.tp_new = PyType_GenericNew;
|
|
if (PyType_Ready (®ister_descriptor_iterator_object_type) < 0)
|
|
return -1;
|
|
return (gdb_pymodule_addobject
|
|
(gdb_module, "RegisterDescriptorIterator",
|
|
(PyObject *) ®ister_descriptor_iterator_object_type));
|
|
}
|
|
|
|
static PyMethodDef register_descriptor_iterator_object_methods [] = {
|
|
{ "find", (PyCFunction) register_descriptor_iter_find,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"registers (name) -> gdb.RegisterDescriptor.\n\
|
|
Return a register descriptor for the register NAME, or None if no register\n\
|
|
with that name exists in this iterator." },
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
PyTypeObject register_descriptor_iterator_object_type = {
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.RegisterDescriptorIterator", /*tp_name*/
|
|
sizeof (register_descriptor_iterator_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*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
"GDB architecture register descriptor iterator object", /*tp_doc */
|
|
0, /*tp_traverse */
|
|
0, /*tp_clear */
|
|
0, /*tp_richcompare */
|
|
0, /*tp_weaklistoffset */
|
|
gdbpy_register_descriptor_iter, /*tp_iter */
|
|
gdbpy_register_descriptor_iter_next, /*tp_iternext */
|
|
register_descriptor_iterator_object_methods /*tp_methods */
|
|
};
|
|
|
|
static gdb_PyGetSetDef gdbpy_register_descriptor_getset[] = {
|
|
{ "name", gdbpy_register_descriptor_name, NULL,
|
|
"The name of this register.", NULL },
|
|
{ NULL } /* Sentinel */
|
|
};
|
|
|
|
PyTypeObject register_descriptor_object_type = {
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.RegisterDescriptor", /*tp_name*/
|
|
sizeof (register_descriptor_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*/
|
|
gdbpy_register_descriptor_to_string, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
"GDB architecture register descriptor 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 */
|
|
gdbpy_register_descriptor_getset /*tp_getset */
|
|
};
|
|
|
|
PyTypeObject reggroup_iterator_object_type = {
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.RegisterGroupsIterator", /*tp_name*/
|
|
sizeof (reggroup_iterator_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*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
"GDB register groups iterator object", /*tp_doc */
|
|
0, /*tp_traverse */
|
|
0, /*tp_clear */
|
|
0, /*tp_richcompare */
|
|
0, /*tp_weaklistoffset */
|
|
gdbpy_reggroup_iter, /*tp_iter */
|
|
gdbpy_reggroup_iter_next, /*tp_iternext */
|
|
0 /*tp_methods */
|
|
};
|
|
|
|
static gdb_PyGetSetDef gdbpy_reggroup_getset[] = {
|
|
{ "name", gdbpy_reggroup_name, NULL,
|
|
"The name of this register group.", NULL },
|
|
{ NULL } /* Sentinel */
|
|
};
|
|
|
|
PyTypeObject reggroup_object_type = {
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.RegisterGroup", /*tp_name*/
|
|
sizeof (reggroup_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*/
|
|
gdbpy_reggroup_to_string, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
"GDB register group 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 */
|
|
gdbpy_reggroup_getset /*tp_getset */
|
|
};
|