This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 2/4] Define gdb.Value(bufobj, type) constructor
- From: Kevin Buettner <kevinb at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 18 Feb 2019 08:06:36 -0700
- Subject: [PATCH 2/4] Define gdb.Value(bufobj, type) constructor
- References: <20190218075816.6f67f3d9@f29-4.lan>
Provided a buffer BUFOBJ and a type TYPE, construct a gdb.Value object
with type TYPE, where the value's contents are taken from BUFOBJ.
E.g...
(gdb) python import struct
(gdb) python unsigned_int_type=gdb.lookup_type('unsigned int')
(gdb) python b=struct.pack('=I',0xdeadbeef)
(gdb) python v=gdb.Value(b, unsigned_int_type) ; print("%#x" % v)
0xdeadbeef
This two argument form of the gdb.Value constructor may also be used
to obtain gdb values from selected portions of buffers read with
Inferior.read_memory(). The test case (which is in a separate patch)
demonstrates this use case.
gdb/ChangeLog:
* python/py-value.c (convert_buffer_and_type_to_value): New
function.
(valpy_new): Parse arguments via gdb_PyArg_ParseTupleAndKeywords.
Add support for handling an optional second argument. Call
convert_buffer_and_type_to_value as appropriate.
---
gdb/python/py-value.c | 72 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 10 deletions(-)
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 20ef5822f8..154b175a21 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -107,22 +107,68 @@ note_value (value_object *value_obj)
values_in_python = value_obj;
}
+/* Convert a python object OBJ with type TYPE to a gdb value. The
+ python object in question must conform to the python buffer
+ protocol. On success, return the converted value, otherwise
+ nullptr. */
+
+static struct value *
+convert_buffer_and_type_to_value (PyObject *obj, struct type *type)
+{
+ Py_buffer_up buffer_up;
+ Py_buffer py_buf;
+
+ if (PyObject_CheckBuffer (obj)
+ && PyObject_GetBuffer (obj, &py_buf, PyBUF_SIMPLE) == 0)
+ {
+ /* Got a buffer, py_buf, out of obj. Cause it to released
+ when it goes out of scope. */
+ buffer_up.reset (&py_buf);
+ }
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Object must support the python buffer protocol."));
+ return nullptr;
+ }
+
+ if (TYPE_LENGTH (type) > py_buf.len)
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Size of type is larger than that of buffer object."));
+ return nullptr;
+ }
+
+ return value_from_contents (type, (const gdb_byte *) py_buf.buf);
+}
+
/* Called when a new gdb.Value object needs to be allocated. Returns NULL on
error, with a python exception set. */
static PyObject *
-valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
+valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
{
- struct value *value = NULL; /* Initialize to appease gcc warning. */
- value_object *value_obj;
+ static const char *keywords[] = { "val", "type", NULL };
+ PyObject *val_obj = nullptr;
+ PyObject *type_obj = nullptr;
- if (PyTuple_Size (args) != 1)
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "O|O", keywords,
+ &val_obj, &type_obj))
+ return nullptr;
+
+ struct type *type = nullptr;
+
+ if (type_obj != nullptr)
{
- PyErr_SetString (PyExc_TypeError, _("Value object creation takes only "
- "1 argument"));
- return NULL;
+ type = type_object_to_type (type_obj);
+ if (type == nullptr)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("type argument must be a gdb.Type."));
+ return nullptr;
+ }
}
- value_obj = (value_object *) subtype->tp_alloc (subtype, 1);
+ value_object *value_obj = (value_object *) subtype->tp_alloc (subtype, 1);
if (value_obj == NULL)
{
PyErr_SetString (PyExc_MemoryError, _("Could not allocate memory to "
@@ -130,8 +176,14 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
return NULL;
}
- value = convert_value_from_python (PyTuple_GetItem (args, 0));
- if (value == NULL)
+ struct value *value;
+
+ if (type == nullptr)
+ value = convert_value_from_python (val_obj);
+ else
+ value = convert_buffer_and_type_to_value (val_obj, type);
+
+ if (value == nullptr)
{
subtype->tp_free (value_obj);
return NULL;