aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorPhil Muldoon <pmuldoon@redhat.com>2010-01-14 08:03:37 +0000
committerPhil Muldoon <pmuldoon@redhat.com>2010-01-14 08:03:37 +0000
commitbe759fcf73cbf7ac59863c57389cd97c70c09a47 (patch)
treef3261b3c2096f57e5a2e09242ecc82a2cc7acb8b /gdb/python
parent009f105539b0fedd36d9d1de940a3822372ed818 (diff)
downloadgdb-be759fcf73cbf7ac59863c57389cd97c70c09a47.zip
gdb-be759fcf73cbf7ac59863c57389cd97c70c09a47.tar.gz
gdb-be759fcf73cbf7ac59863c57389cd97c70c09a47.tar.bz2
2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
PR python/10705 * python/python-internal.h: Add lazy_string_object_type definition. (create_lazy_string_object, gdbpy_initialize_lazy_string) (gdbpy_is_lazystring, gdbpy_extract_lazy_string): Define. * python/py-value.c (valpy_lazy_string): New function. (convert_value_from_python): Add lazy string conversion. * python/py-prettyprint.c (pretty_print_one_value): Check if return is also a lazy string. (print_string_repr): Add lazy string printing branch. (print_children): Likewise. * python/py-lazy-string.c: New file. Implement lazy strings. * python/python.c (_initialize_python): Call gdbpy_initialize_lazy_string. * varobj.c (value_get_print_value): Add lazy string printing branch. Account for encoding. * c-lang.c (c_printstr): Account for new encoding argument. If encoding is NULL, find encoding suited for type, otherwise use user encoding. * language.h (language_defn): Add encoding argument. (LA_PRINT_STRING): Likewise. * language.c (unk_lang_printstr): Update to reflect new encoding argument to language_defn. * ada-lang.h (ada_printstr): Likewise. * c-lang.h (c_printstr): Likewise. * p-lang.h (pascal_printstr); * f-lang.c (f_printstr): Likewise. * m2-lang.c (m2_printstr): Likewise. * objc-lang.c (objc_printstr): Likewise. * p-lang.c (pascal_printstr): Likewise. * scm-lang.c (scm_printstr): Likewise. * c-valprint.c (c_val_print): Update LA_PRINT_STRING call for encoding argument. * ada-valprint.c (ada_printstr): Likewise. * f-valprint.c (f_val_print): Likewise * m2-valprint.c (m2_val_print): Likewise. * p-valprint.c (pascal_val_print): Likewise. * expprint.c (print_subexp_standard): Likewise. * valprint.c (val_print_string): Likewise. * Makefile.in (SUBDIR_PYTHON_OBS): Add py-lazy-string. (SUBDIR_PYTHON_SRCS): Likewise. (py-lazy-string.o): New rule. 2010-01-13 Phil Muldoon <pmuldoon@redhat.com> * gdb.texinfo (Values From Inferior): Document lazy_string value method. (Python API): Add Lazy strings menu item. (Lazy Strings In Python): New node. 2010-01-13 Phil Muldoon <pmuldoon@redhat.com> * gdb.python/py-value.exp (test_lazy_strings): Add lazy string test. * gdb.python/py-prettyprint.py (pp_ls): New printer. * gdb.python/py-prettyprint.exp (run_lang_tests): Add lazy string test. * gdb.python/py-prettyprint.c: Define lazystring test structure. * gdb.python/py-mi.exp: Add lazy string test.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-lazy-string.c291
-rw-r--r--gdb/python/py-prettyprint.c73
-rw-r--r--gdb/python/py-value.c40
-rw-r--r--gdb/python/python-internal.h7
-rw-r--r--gdb/python/python.c1
5 files changed, 397 insertions, 15 deletions
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
new file mode 100644
index 0000000..c845273
--- /dev/null
+++ b/gdb/python/py-lazy-string.c
@@ -0,0 +1,291 @@
+/* Python interface to lazy strings.
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#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;
+
+ /* Holds the encoding that will be applied to the string
+ when the string is printed by GDB. If the encoding is set
+ to None then GDB will select the most appropriate
+ 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. */
+ long length;
+
+ /* This attribute holds the type that is represented by the lazy
+ string's type. */
+ struct type *type;
+} lazy_string_object;
+
+static PyTypeObject lazy_string_object_type;
+
+static PyObject *
+stpy_get_address (PyObject *self, void *closure)
+{
+ lazy_string_object *self_string = (lazy_string_object *) self;
+ return PyLong_FromUnsignedLongLong (self_string->address);
+}
+
+static PyObject *
+stpy_get_encoding (PyObject *self, void *closure)
+{
+ lazy_string_object *self_string = (lazy_string_object *) self;
+ PyObject *result;
+
+ /* An encoding can be set to NULL by the user, so check before
+ attempting a Python FromString call. If NULL return Py_None. */
+ if (self_string->encoding)
+ result = PyString_FromString (self_string->encoding);
+ else
+ {
+ result = Py_None;
+ Py_INCREF (result);
+ }
+
+ return result;
+}
+
+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 *
+stpy_get_type (PyObject *self, void *closure)
+{
+ lazy_string_object *str_obj = (lazy_string_object *) self;
+ return type_to_type_object (str_obj->type);
+}
+
+static PyObject *
+stpy_convert_to_value (PyObject *self, PyObject *args)
+{
+ lazy_string_object *self_string = (lazy_string_object *) self;
+ struct value *val;
+
+ val = value_at_lazy (self_string->type, self_string->address);
+ return value_to_value_object (val);
+}
+
+static void
+stpy_dealloc (PyObject *self)
+{
+ lazy_string_object *self_string = (lazy_string_object *) self;
+ xfree (self_string->encoding);
+}
+
+PyObject *
+gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
+ const char *encoding, struct type *type)
+{
+ lazy_string_object *str_obj = NULL;
+
+ if (address == 0)
+ {
+ PyErr_SetString (PyExc_MemoryError,
+ "Cannot create a lazy string from a GDB-side string.");
+ return NULL;
+ }
+
+ if (!type)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ "A lazy string's type cannot be NULL.");
+ return NULL;
+ }
+
+ str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
+ if (!str_obj)
+ return NULL;
+
+ str_obj->address = address;
+ str_obj->length = length;
+ if (encoding == NULL || !strcmp (encoding, ""))
+ str_obj->encoding = NULL;
+ else
+ str_obj->encoding = xstrdup (encoding);
+ str_obj->type = type;
+
+ return (PyObject *) str_obj;
+}
+
+void
+gdbpy_initialize_lazy_string (void)
+{
+ if (PyType_Ready (&lazy_string_object_type) < 0)
+ return;
+
+ Py_INCREF (&lazy_string_object_type);
+}
+
+/* Determine whether the printer object pointed to by OBJ is a
+ Python lazy string. */
+int
+gdbpy_is_lazy_string (PyObject *result)
+{
+ 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)
+{
+ 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_AsLongLong (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));
+
+ *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);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ errcode = read_string (addr, *length, width,
+ *length, byte_order, &buffer,
+ &bytes_read);
+ }
+ if (except.reason < 0)
+ {
+ PyErr_Format (except.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", except.message); \
+ goto error;
+
+ }
+
+ 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;
+}
+
+
+
+static PyMethodDef lazy_string_object_methods[] = {
+ { "value", stpy_convert_to_value, METH_NOARGS,
+ "Create a (lazy) value that contains a pointer to the string." },
+ {NULL} /* Sentinel */
+};
+
+
+static 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 },
+ { "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
+ { NULL } /* Sentinel */
+};
+
+static PyTypeObject lazy_string_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.LazyString", /*tp_name*/
+ sizeof (lazy_string_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ stpy_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB lazy string object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ lazy_string_object_methods, /* tp_methods */
+ 0, /* tp_members */
+ lazy_string_object_getset /* tp_getset */
+};
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 818cde1..193f97c 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -121,6 +121,8 @@ find_pretty_printer (PyObject *value)
return function;
}
+
+
/* Pretty-print a single value, via the printer object PRINTER.
If the function returns a string, a PyObject containing the string
is returned. Otherwise, if the function returns a value,
@@ -138,7 +140,7 @@ pretty_print_one_value (PyObject *printer, struct value **out_value)
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
if (result)
{
- if (! gdbpy_is_string (result))
+ if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result))
{
*out_value = convert_value_from_python (result);
if (PyErr_Occurred ())
@@ -191,21 +193,47 @@ print_string_repr (PyObject *printer, const char *hint,
py_str = pretty_print_one_value (printer, &replacement);
if (py_str)
{
- PyObject *string = python_string_to_target_python_string (py_str);
- if (string)
+ gdb_byte *output = NULL;
+ long length;
+ struct type *type;
+ char *encoding = NULL;
+ PyObject *string = NULL;
+ int is_lazy;
+
+ is_lazy = gdbpy_is_lazy_string (py_str);
+ if (is_lazy)
+ output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding);
+ else
{
- gdb_byte *output = PyString_AsString (string);
- int len = PyString_Size (string);
+ string = python_string_to_target_python_string (py_str);
+ if (string)
+ {
+ output = PyString_AsString (string);
+ length = PyString_Size (string);
+ type = builtin_type (gdbarch)->builtin_char;
+ }
+ else
+ gdbpy_print_stack ();
- if (hint && !strcmp (hint, "string"))
- LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
- output, len, 0, options);
+ }
+
+ if (output)
+ {
+ if (is_lazy || (hint && !strcmp (hint, "string")))
+ LA_PRINT_STRING (stream, type, output, length, encoding,
+ 0, options);
else
fputs_filtered (output, stream);
- Py_DECREF (string);
}
else
gdbpy_print_stack ();
+
+ if (string)
+ Py_DECREF (string);
+ else
+ xfree (output);
+
+ xfree (encoding);
Py_DECREF (py_str);
}
else if (replacement)
@@ -422,15 +450,30 @@ print_children (PyObject *printer, const char *hint,
fputs_filtered (" = ", stream);
}
- if (gdbpy_is_string (py_v))
+ if (gdbpy_is_lazy_string (py_v) || gdbpy_is_string (py_v))
{
- char *text = python_string_to_host_string (py_v);
- if (! text)
- gdbpy_print_stack ();
+ gdb_byte *output = NULL;
+
+ if (gdbpy_is_lazy_string (py_v))
+ {
+ struct type *type;
+ long length;
+ char *encoding = NULL;
+
+ output = gdbpy_extract_lazy_string (py_v, &type,
+ &length, &encoding);
+ if (!output)
+ gdbpy_print_stack ();
+ LA_PRINT_STRING (stream, type, output, length, encoding,
+ 0, options);
+ xfree (encoding);
+ xfree (output);
+ }
else
{
- fputs_filtered (text, stream);
- xfree (text);
+ output = python_string_to_host_string (py_v);
+ fputs_filtered (output, stream);
+ xfree (output);
}
}
else
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index af649b0..a792819 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -220,6 +220,36 @@ valpy_get_type (PyObject *self, void *closure)
return obj->type;
}
+/* Implementation of gdb.Value.lazy_string ([encoding] [, length]) ->
+ string. Return a PyObject representing a lazy_string_object type.
+ A lazy string is a pointer to a string with an optional encoding and
+ length. If ENCODING is not given, encoding is set to None. If an
+ ENCODING is provided the encoding parameter is set to ENCODING, but
+ the string is not encoded. If LENGTH is provided then the length
+ parameter is set to LENGTH, otherwise length will be set to -1 (first
+ null of appropriate with). */
+static PyObject *
+valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
+{
+ int length = -1;
+ struct value *value = ((value_object *) self)->value;
+ const char *user_encoding = NULL;
+ static char *keywords[] = { "encoding", "length", NULL };
+ PyObject *str_obj;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords,
+ &user_encoding, &length))
+ return NULL;
+
+ if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
+ value = value_ind (value);
+
+ str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
+ user_encoding, value_type (value));
+
+ return (PyObject *) str_obj;
+}
+
/* Implementation of gdb.Value.string ([encoding] [, errors]
[, length]) -> string. Return Unicode string with value contents.
If ENCODING is not given, the string is assumed to be encoded in
@@ -939,6 +969,13 @@ convert_value_from_python (PyObject *obj)
}
else if (PyObject_TypeCheck (obj, &value_object_type))
value = value_copy (((value_object *) obj)->value);
+ else if (gdbpy_is_lazy_string (obj))
+ {
+ PyObject *result;
+ PyObject *function = PyString_FromString ("value");
+ result = PyObject_CallMethodObjArgs (obj, function, NULL);
+ value = value_copy (((value_object *) result)->value);
+ }
else
PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
PyString_AsString (PyObject_Str (obj)));
@@ -1001,6 +1038,9 @@ static PyGetSetDef value_object_getset[] = {
static PyMethodDef value_object_methods[] = {
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
+ { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS,
+ "lazy_string ([encoding] [, length]) -> lazy_string\n\
+Return a lazy string representation of the value." },
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
"string ([encoding] [, errors] [, length]) -> string\n\
Return Unicode string representation of the value." },
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 62ed538..9196f08 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -71,6 +71,8 @@ PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
+PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
+ const char *encoding, struct type *type);
PyObject *value_to_value_object (struct value *v);
PyObject *type_to_type_object (struct type *);
@@ -88,6 +90,7 @@ void gdbpy_initialize_commands (void);
void gdbpy_initialize_types (void);
void gdbpy_initialize_functions (void);
void gdbpy_initialize_objfile (void);
+void gdbpy_initialize_lazy_string (void);
struct cleanup *make_cleanup_py_decref (PyObject *py);
@@ -117,6 +120,10 @@ PyObject *python_string_to_target_python_string (PyObject *obj);
char *python_string_to_host_string (PyObject *obj);
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
int gdbpy_is_string (PyObject *obj);
+int gdbpy_is_lazy_string (PyObject *result);
+gdb_byte *gdbpy_extract_lazy_string (PyObject *string,
+ struct type **str_type,
+ long *length, char **encoding);
/* Note that these are declared here, and not in python.h with the
other pretty-printer functions, because they refer to PyObject. */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 2ac9e99..827372c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -623,6 +623,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
gdbpy_initialize_functions ();
gdbpy_initialize_types ();
gdbpy_initialize_objfile ();
+ gdbpy_initialize_lazy_string ();
PyRun_SimpleString ("import gdb");
PyRun_SimpleString ("gdb.pretty_printers = []");