diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/python/py-value.c | 72 |
2 files changed, 67 insertions, 10 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f311a24..5d845e9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ 2019-02-26 Kevin Buettner <kevinb@redhat.com> + * 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. * python/python-internal.h (Py_buffer_deleter): New struct. (Py_buffer_up): New typedef. diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 20ef582..445be72 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 be 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_ValueError, + _("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 (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "O|O", keywords, + &val_obj, &type_obj)) + return nullptr; - if (PyTuple_Size (args) != 1) + 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_TypeError, + _("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; |