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.
This commit is contained in:
parent
a3a5feccd2
commit
34b433203b
8 changed files with 240 additions and 51 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue