Message ID | 20190218080636.02e3847f@f29-4.lan |
---|---|
State | New |
Headers | show |
>>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes:
FWIW I think this whole series looks quite reasonable and would be a
good addition.
Kevin> + Py_buffer py_buf;
Elsewhere in the Python code, Py_buffer is only used conditionally on
"#ifdef IS_PY3K". I don't know exactly why, though. Py_buffer seems to
be in Python 2.7, maybe it wasn't in some earlier version that gdb still
supports?
I don't know whether anyone still relies on older versions of Python
(2.7 was released in 2010 so it seems plenty old at this point; after
all we require compilers released after this).
However, this seems like a decision to make consciously.
I'm not completely sure how to proceed, though one idea might be to find
the most recent Python 2.[456] compatibility patch and then asking the
author whether this support is still relevant.
thanks,
Tom
On Mon, 18 Feb 2019 15:45:57 -0700 Tom Tromey <tom@tromey.com> wrote: > >>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes: > > FWIW I think this whole series looks quite reasonable and would be a > good addition. Thanks for looking it over. > Kevin> + Py_buffer py_buf; > > Elsewhere in the Python code, Py_buffer is only used conditionally on > "#ifdef IS_PY3K". I don't know exactly why, though. Py_buffer seems to > be in Python 2.7, maybe it wasn't in some earlier version that gdb still > supports? FWIW, I've tested my patch using both Python 2.7 and Python 3.7, which are what I have on my F29 machine. > I don't know whether anyone still relies on older versions of Python > (2.7 was released in 2010 so it seems plenty old at this point; after > all we require compilers released after this). > > However, this seems like a decision to make consciously. > I'm not completely sure how to proceed, though one idea might be to find > the most recent Python 2.[456] compatibility patch and then asking the > author whether this support is still relevant. I didn't know of that compatibility patch, though I'll try to track it down. (A pointer would be appreciated if you have one handy.) I decided that I had better educate myself about the old buffer protocol. I came across this page, which describes Python's old buffer protocol: https://docs.python.org/2/c-api/objbuffer.html The old buffer protocol includes the functions PyObject_CheckReadBuffer() and PyObject_AsReadBuffer() which are used in the non-IS_PY3K code in GDB. According to that page, the old buffer protocol was introduced in Python 1.6, but is deprecated in the 2.X series. It also indicates that support for the new buffer protocol, which is what I used in my patch, has been backported to Python 2.6. 2.6 was released in Oct of 2008. (I'm thinking that indicating that the old buffer protocol is deprecated in 2.X is a typo. I think they meant 3.X.) I'll try removing use of the old buffer protocol from GDB and then see if anything breaks with Python 2.7 (and maybe even 2.6 if I can figure out how to make that happen). If we get rid of the IS_PY3K ifdefs from GDB, we'll definitely be making this decision consciously. Kevin
On 2019-02-18 10:06, Kevin Buettner wrote: > +/* 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. */ Seems to be missing a "be" in "Cause it to be released". Simon
>>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes: >> However, this seems like a decision to make consciously. >> I'm not completely sure how to proceed, though one idea might be to find >> the most recent Python 2.[456] compatibility patch and then asking the >> author whether this support is still relevant. Kevin> I didn't know of that compatibility patch, though I'll try to track it Kevin> down. (A pointer would be appreciated if you have one handy.) I just recall it happening from time to time. Using: git log --grep 'Python 2\.[4-6]' ... shows a couple maybe uninteresting patches, followed by: commit 49840f2a6669ae2366c522da41edf615785b3626 Author: Ulrich Weigand <ulrich.weigand@de.ibm.com> Date: Sun Mar 16 15:01:24 2014 +0100 Fix Python 2.4 build break This fixes a build failure against Python 2.4 by casting away "const" on the second argument to PyObject_GetAttrString. Similar casts to support Python 2.4 were already present in a number of other places. gdb/ 2014-03-16 Ulrich Weigand <uweigand@de.ibm.com> * python/py-value.c (get_field_flag): Cast flag_name argument to PyObject_GetAttrString to support Python 2.4. So, I've CC'd Ulrich. Tom
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;