/* Python interface to lazy strings.
- Copyright (C) 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "python-internal.h"
#include "charset.h"
#include "value.h"
-#include "exceptions.h"
#include "valprint.h"
#include "language.h"
typedef struct {
PyObject_HEAD
+
/* Holds the address of the lazy string. */
CORE_ADDR address;
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;
-static PyTypeObject lazy_string_object_type;
+extern PyTypeObject lazy_string_object_type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
static PyObject *
stpy_get_address (PyObject *self, void *closure)
{
lazy_string_object *self_string = (lazy_string_object *) self;
- return PyLong_FromUnsignedLongLong (self_string->address);
+
+ return gdb_py_long_from_ulongest (self_string->address);
}
static PyObject *
stpy_get_length (PyObject *self, void *closure)
{
lazy_string_object *self_string = (lazy_string_object *) self;
+
return PyLong_FromLong (self_string->length);
}
-PyObject *
+static PyObject *
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;
+ struct value *val = NULL;
+
+ if (self_string->address == 0)
+ {
+ PyErr_SetString (gdbpy_gdb_memory_error,
+ _("Cannot create a value from NULL."));
+ return NULL;
+ }
+
+ TRY
+ {
+ 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)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
- val = value_at_lazy (self_string->type, self_string->address);
return value_to_value_object (val);
}
stpy_dealloc (PyObject *self)
{
lazy_string_object *self_string = (lazy_string_object *) 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 (address == 0)
+ if (length < -1)
{
- PyErr_SetString (PyExc_MemoryError,
- "Cannot create a lazy string from a GDB-side string.");
+ PyErr_SetString (PyExc_ValueError, _("Invalid length."));
+ return NULL;
+ }
+
+ if (address == 0 && length != 0)
+ {
+ PyErr_SetString (gdbpy_gdb_memory_error,
+ _("Cannot create a lazy string with address 0x0, " \
+ "and a non-zero length."));
return NULL;
}
if (!type)
{
PyErr_SetString (PyExc_RuntimeError,
- "A lazy string's type cannot be NULL.");
+ _("A lazy string's type cannot be NULL."));
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;
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;
}
-void
+int
gdbpy_initialize_lazy_string (void)
{
if (PyType_Ready (&lazy_string_object_type) < 0)
- return;
+ return -1;
Py_INCREF (&lazy_string_object_type);
+ return 0;
}
/* Determine whether the printer object pointed to by OBJ is a
return PyObject_TypeCheck (result, &lazy_string_object_type);
}
-/* Extract and return the actual string from the lazy string object
- STRING. Addtionally, the string type is written to *STR_TYPE, the
- string length is written to *LENGTH, and the string encoding is
- written to *ENCODING. On error, NULL is returned. The caller is
- responsible for freeing the returned buffer. */
-gdb_byte *
-gdbpy_extract_lazy_string (PyObject *string, struct type **str_type,
- long *length, char **encoding)
+/* Return the type of a character in lazy string LAZY. */
+
+static struct type *
+stpy_lazy_string_elt_type (lazy_string_object *lazy)
{
- int width;
- int bytes_read;
- gdb_byte *buffer = NULL;
- int errcode = 0;
- CORE_ADDR addr;
- struct gdbarch *gdbarch;
- enum bfd_endian byte_order;
- PyObject *py_len = NULL, *py_encoding = NULL;
- PyObject *py_addr = NULL, *py_type = NULL;
- volatile struct gdb_exception except;
-
- py_len = PyObject_GetAttrString (string, "length");
- py_encoding = PyObject_GetAttrString (string, "encoding");
- py_addr = PyObject_GetAttrString (string, "address");
- py_type = PyObject_GetAttrString (string, "type");
-
- /* A NULL encoding, length, address or type is not ok. */
- if (!py_len || !py_encoding || !py_addr || !py_type)
- goto error;
-
- *length = PyLong_AsLong (py_len);
- addr = PyLong_AsUnsignedLongLong (py_addr);
-
- /* If the user supplies Py_None an encoding, set encoding to NULL.
- This will trigger the resulting LA_PRINT_CALL to automatically
- select an encoding. */
- if (py_encoding == Py_None)
- *encoding = NULL;
- else
- *encoding = xstrdup (PyString_AsString (py_encoding));
+ struct type *type = type_object_to_type (lazy->type);
+ struct type *realtype;
- *str_type = type_object_to_type (py_type);
- gdbarch = get_type_arch (*str_type);
- byte_order = gdbarch_byte_order (gdbarch);
- width = TYPE_LENGTH (*str_type);
+ gdb_assert (type != NULL);
+ realtype = check_typedef (type);
- TRY_CATCH (except, RETURN_MASK_ALL)
+ switch (TYPE_CODE (realtype))
{
- errcode = read_string (addr, *length, width,
- *length, byte_order, &buffer,
- &bytes_read);
+ 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;
}
- if (except.reason < 0)
- {
- PyErr_Format (except.reason == RETURN_QUIT \
- ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
- "%s", except.message); \
- goto error;
+}
- }
+/* 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_elt_type,
+ long *length,
+ gdb::unique_xmalloc_ptr<char> *encoding)
+{
+ lazy_string_object *lazy;
+
+ gdb_assert (gdbpy_is_lazy_string (string));
+
+ lazy = (lazy_string_object *) string;
- if (errcode)
- goto error;
-
- *length = bytes_read / width;
-
- Py_DECREF (py_encoding);
- Py_DECREF (py_len);
- Py_DECREF (py_addr);
- Py_DECREF (py_type);
- return buffer;
-
- error:
- Py_XDECREF (py_encoding);
- Py_XDECREF (py_len);
- Py_XDECREF (py_addr);
- Py_XDECREF (py_type);
- xfree (buffer);
- *length = 0;
- *str_type = NULL;
- return NULL;
+ *addr = lazy->address;
+ *str_elt_type = stpy_lazy_string_elt_type (lazy);
+ *length = lazy->length;
+ encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
}
\f
};
-static PyGetSetDef lazy_string_object_getset[] = {
+static gdb_PyGetSetDef lazy_string_object_getset[] = {
{ "address", stpy_get_address, NULL, "Address of the string.", NULL },
{ "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
{ "length", stpy_get_length, NULL, "Length of the string.", NULL },
{ NULL } /* Sentinel */
};
-static PyTypeObject lazy_string_object_type = {
- PyObject_HEAD_INIT (NULL)
- 0, /*ob_size*/
+PyTypeObject lazy_string_object_type = {
+ PyVarObject_HEAD_INIT (NULL, 0)
"gdb.LazyString", /*tp_name*/
sizeof (lazy_string_object), /*tp_basicsize*/
0, /*tp_itemsize*/