diff options
author | Doug Evans <dje@google.com> | 2017-03-15 15:35:13 -0700 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2017-03-16 09:28:11 -0700 |
commit | 34b433203b5f56149c27a8dfea21a921392cb158 (patch) | |
tree | c45039a326c7863be84bcbe3e552b2a28ee209ae /gdb/python/py-lazy-string.c | |
parent | a3a5feccd26be653efbdf1408874b98962baaa50 (diff) | |
download | binutils-34b433203b5f56149c27a8dfea21a921392cb158.zip binutils-34b433203b5f56149c27a8dfea21a921392cb158.tar.gz binutils-34b433203b5f56149c27a8dfea21a921392cb158.tar.bz2 |
Fix various python lazy string bugs.
gdb/ChangeLog:
PR python/17728, python/18439, python/18779
* python/py-lazy-string.c (lazy_string_object): Clarify use of LENGTH
member. Change type of TYPE member to PyObject *. All uses updated.
(stpy_convert_to_value): Fix handling of TYPE_CODE_PTR.
(gdbpy_create_lazy_string_object): Flag bad length values.
Handle TYPE_CODE_ARRAY with possibly different user-provided length.
Handle typedefs in incoming type.
(stpy_lazy_string_elt_type): New function.
(gdbpy_extract_lazy_string): Call it.
* python/py-value.c (valpy_lazy_string): Flag bad length values.
Fix handling of TYPE_CODE_PTR. Handle TYPE_CODE_ARRAY. Handle
typedefs in incoming type.
gdb/testsuite/ChangeLog:
PR python/17728, python/18439, python/18779
* gdb.python/py-value.c (main) Delete locals sptr, sn.
* gdb.python/py-lazy-string.c (pointer): New typedef.
(main): New locals ptr, array, typedef_ptr.
* gdb.python/py-value.exp: Move lazy string tests to ...
* gdb.python/py-lazy-string.exp: ... here. Add more tests for pointer,
array, typedef lazy strings.
Diffstat (limited to 'gdb/python/py-lazy-string.c')
-rw-r--r-- | gdb/python/py-lazy-string.c | 117 |
1 files changed, 104 insertions, 13 deletions
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c index 4af4566..ab3f411 100644 --- a/gdb/python/py-lazy-string.c +++ b/gdb/python/py-lazy-string.c @@ -26,6 +26,7 @@ typedef struct { PyObject_HEAD + /* Holds the address of the lazy string. */ CORE_ADDR address; @@ -35,14 +36,21 @@ typedef struct { encoding when the sting is printed. */ char *encoding; - /* Holds the length of the string in characters. If the - length is -1, then the string will be fetched and encoded up to - the first null of appropriate width. */ + /* If TYPE is an array: If the length is known, then this value is the + array's length, otherwise it is -1. + If TYPE is not an array: Then this value represents the string's length. + In either case, if the value is -1 then the string will be fetched and + encoded up to the first null of appropriate width. */ long length; - /* This attribute holds the type that is represented by the lazy - string's type. */ - struct type *type; + /* This attribute holds the type of the string. + For example if the lazy string was created from a C "char*" then TYPE + represents a C "char*". + To get the type of the character in the string call + stpy_lazy_string_elt_type. + This is recorded as a PyObject so that we take advantage of support for + preserving the type should its owning objfile go away. */ + PyObject *type; } lazy_string_object; extern PyTypeObject lazy_string_object_type @@ -88,11 +96,12 @@ stpy_get_type (PyObject *self, void *closure) { lazy_string_object *str_obj = (lazy_string_object *) self; - return type_to_type_object (str_obj->type); + Py_INCREF (str_obj->type); + return str_obj->type; } static PyObject * -stpy_convert_to_value (PyObject *self, PyObject *args) +stpy_convert_to_value (PyObject *self, PyObject *args) { lazy_string_object *self_string = (lazy_string_object *) self; struct value *val = NULL; @@ -106,7 +115,32 @@ stpy_convert_to_value (PyObject *self, PyObject *args) TRY { - val = value_at_lazy (self_string->type, self_string->address); + struct type *type = type_object_to_type (self_string->type); + struct type *realtype; + + gdb_assert (type != NULL); + realtype = check_typedef (type); + switch (TYPE_CODE (realtype)) + { + case TYPE_CODE_PTR: + /* If a length is specified we need to convert this to an array + of the specified size. */ + if (self_string->length != -1) + { + /* PR 20786: There's no way to specify an array of length zero. + Record a length of [0,-1] which is how Ada does it. Anything + we do is broken, but this is one possible solution. */ + type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype), + 0, self_string->length - 1); + val = value_at_lazy (type, self_string->address); + } + else + val = value_from_pointer (type, self_string->address); + break; + default: + val = value_at_lazy (type, self_string->address); + break; + } } CATCH (except, RETURN_MASK_ALL) { @@ -125,11 +159,24 @@ stpy_dealloc (PyObject *self) xfree (self_string->encoding); } +/* Low level routine to create a <gdb.LazyString> object. + + Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the + size of the array, which may itself be unknown in which case a length of + -1 is still used) or must be the length of the array. */ + PyObject * gdbpy_create_lazy_string_object (CORE_ADDR address, long length, - const char *encoding, struct type *type) + const char *encoding, struct type *type) { lazy_string_object *str_obj = NULL; + struct type *realtype; + + if (length < -1) + { + PyErr_SetString (PyExc_ValueError, _("Invalid length.")); + return NULL; + } if (address == 0 && length != 0) { @@ -146,6 +193,27 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length, return NULL; } + realtype = check_typedef (type); + switch (TYPE_CODE (realtype)) + { + case TYPE_CODE_ARRAY: + { + LONGEST array_length = -1; + LONGEST low_bound, high_bound; + + if (get_array_bounds (realtype, &low_bound, &high_bound)) + array_length = high_bound - low_bound + 1; + if (length == -1) + length = array_length; + else if (length != array_length) + { + PyErr_SetString (PyExc_ValueError, _("Invalid length.")); + return NULL; + } + break; + } + } + str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type); if (!str_obj) return NULL; @@ -156,7 +224,7 @@ gdbpy_create_lazy_string_object (CORE_ADDR address, long length, str_obj->encoding = NULL; else str_obj->encoding = xstrdup (encoding); - str_obj->type = type; + str_obj->type = type_to_type_object (type); return (PyObject *) str_obj; } @@ -179,12 +247,35 @@ gdbpy_is_lazy_string (PyObject *result) return PyObject_TypeCheck (result, &lazy_string_object_type); } +/* Return the type of a character in lazy string LAZY. */ + +static struct type * +stpy_lazy_string_elt_type (lazy_string_object *lazy) +{ + struct type *type = type_object_to_type (lazy->type); + struct type *realtype; + + gdb_assert (type != NULL); + realtype = check_typedef (type); + + switch (TYPE_CODE (realtype)) + { + case TYPE_CODE_PTR: + case TYPE_CODE_ARRAY: + return TYPE_TARGET_TYPE (realtype); + default: + /* This is done to preserve existing behaviour. PR 20769. + E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */ + return realtype; + } +} + /* Extract the parameters from the lazy string object STRING. ENCODING may be set to NULL, if no encoding is found. */ void gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, - struct type **str_type, + struct type **str_elt_type, long *length, gdb::unique_xmalloc_ptr<char> *encoding) { @@ -195,7 +286,7 @@ gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr, lazy = (lazy_string_object *) string; *addr = lazy->address; - *str_type = lazy->type; + *str_elt_type = stpy_lazy_string_elt_type (lazy); *length = lazy->length; encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL); } |