2009-07-10 Phil Muldoon <pmuldoon@redhat.com>
* python/python-internal.h (apply_varobj_pretty_printer): Update definition. (python_string_to_target_python_string): Add definition. * python/python-utils.c (unicode_to_encoded_python_string) (unicode_to_target_python_string) (python_string_to_target_python_string): New Functions. * python/python-prettyprint.c (pretty_print_one_value): Likewise. (print_string_repr): Refactor to logic to account for PyObject returned strings. (apply_varobj_pretty_printer): Likewise. * python/python-value.c (valpy_string): Parse length keyword. Use length keyword in LA_GET_STRING. * varobj.c (value_get_print_value): Refactor logic to account for PyObject returned strings. * c-lang.c (c_get_string): If the length parameter is specified, use that. Return value in characters. Update comments. * language.h: Update c_get_string prototype comments. 2009-07-10 Phil Muldoon <pmuldoon@redhat.com> * gdb.texinfo (Values From Inferior): Add length parameter description. 2009-07-10 Phil Muldoon <pmuldoon@redhat.com> * gdb.python/python-prettyprint.c: Add counted null string structure. * gdb.python/python-prettyprint.exp: Print null string. Test for embedded nulls. * gdb.python/python-prettyprint.py (pp_ns): New Function. * gdb.python/python-value.exp (test_value_in_inferior): Add variable length string fetch tests. * gdb.python/python-value.c (main): Add strings for string fetch tests.
This commit is contained in:
parent
041de40dc8
commit
fbb8f2990c
16 changed files with 267 additions and 83 deletions
|
@ -1,3 +1,23 @@
|
||||||
|
2009-07-10 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
|
* python/python-internal.h (apply_varobj_pretty_printer): Update
|
||||||
|
definition.
|
||||||
|
(python_string_to_target_python_string): Add definition.
|
||||||
|
* python/python-utils.c (unicode_to_encoded_python_string)
|
||||||
|
(unicode_to_target_python_string)
|
||||||
|
(python_string_to_target_python_string): New Functions.
|
||||||
|
* python/python-prettyprint.c (pretty_print_one_value): Likewise.
|
||||||
|
(print_string_repr): Refactor to logic to account for PyObject
|
||||||
|
returned strings.
|
||||||
|
(apply_varobj_pretty_printer): Likewise.
|
||||||
|
* python/python-value.c (valpy_string): Parse length keyword. Use
|
||||||
|
length keyword in LA_GET_STRING.
|
||||||
|
* varobj.c (value_get_print_value): Refactor logic to account for
|
||||||
|
PyObject returned strings.
|
||||||
|
* c-lang.c (c_get_string): If the length parameter is specified,
|
||||||
|
use that. Return value in characters. Update comments.
|
||||||
|
* language.h: Update c_get_string prototype comments.
|
||||||
|
|
||||||
2009-07-09 Doug Evans <dje@google.com>
|
2009-07-09 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
* i386-tdep.c (i386_displaced_step_fixup): Fix order of arguments
|
* i386-tdep.c (i386_displaced_step_fixup): Fix order of arguments
|
||||||
|
|
48
gdb/c-lang.c
48
gdb/c-lang.c
|
@ -604,18 +604,17 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain a C string from the inferior storing it in a newly allocated
|
/* Obtain a C string from the inferior storing it in a newly allocated
|
||||||
buffer in BUFFER, which should be freed by the caller. The string is
|
buffer in BUFFER, which should be freed by the caller. If the
|
||||||
read until a null character is found. If VALUE is an array with known
|
in- and out-parameter *LENGTH is specified at -1, the string is read
|
||||||
length, the function will not read past the end of the array. LENGTH
|
until a null character of the appropriate width is found, otherwise
|
||||||
will contain the size of the string in bytes (not counting the null
|
the string is read to the length of characters specified.
|
||||||
character).
|
The size of a character is determined by the length of the target
|
||||||
|
type of the pointer or array. If VALUE is an array with a known
|
||||||
Assumes strings are terminated by a null character. The size of a character
|
length, the function will not read past the end of the array.
|
||||||
is determined by the length of the target type of the pointer or array.
|
On completion, *LENGTH will be set to the size of the string read in
|
||||||
This means that a null byte present in a multi-byte character will not
|
characters. (If a length of -1 is specified, the length returned
|
||||||
terminate the string unless the whole character is null.
|
will not include the null character). CHARSET is always set to the
|
||||||
|
target charset. */
|
||||||
CHARSET is always set to the target charset. */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
|
@ -625,6 +624,7 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
unsigned int fetchlimit;
|
unsigned int fetchlimit;
|
||||||
struct type *type = check_typedef (value_type (value));
|
struct type *type = check_typedef (value_type (value));
|
||||||
struct type *element_type = TYPE_TARGET_TYPE (type);
|
struct type *element_type = TYPE_TARGET_TYPE (type);
|
||||||
|
int req_length = *length;
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
||||||
|
|
||||||
if (element_type == NULL)
|
if (element_type == NULL)
|
||||||
|
@ -661,7 +661,7 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
|
|
||||||
width = TYPE_LENGTH (element_type);
|
width = TYPE_LENGTH (element_type);
|
||||||
|
|
||||||
/* If the string lives in GDB's memory intead of the inferior's, then we
|
/* If the string lives in GDB's memory instead of the inferior's, then we
|
||||||
just need to copy it to BUFFER. Also, since such strings are arrays
|
just need to copy it to BUFFER. Also, since such strings are arrays
|
||||||
with known size, FETCHLIMIT will hold the size of the array. */
|
with known size, FETCHLIMIT will hold the size of the array. */
|
||||||
if ((VALUE_LVAL (value) == not_lval
|
if ((VALUE_LVAL (value) == not_lval
|
||||||
|
@ -671,13 +671,18 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
int i;
|
int i;
|
||||||
const gdb_byte *contents = value_contents (value);
|
const gdb_byte *contents = value_contents (value);
|
||||||
|
|
||||||
/* Look for a null character. */
|
/* If a length is specified, use that. */
|
||||||
|
if (*length >= 0)
|
||||||
|
i = *length;
|
||||||
|
else
|
||||||
|
/* Otherwise, look for a null character. */
|
||||||
for (i = 0; i < fetchlimit; i++)
|
for (i = 0; i < fetchlimit; i++)
|
||||||
if (extract_unsigned_integer (contents + i * width, width,
|
if (extract_unsigned_integer (contents + i * width, width,
|
||||||
byte_order) == 0)
|
byte_order) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* I is now either the number of non-null characters, or FETCHLIMIT. */
|
/* I is now either a user-defined length, the number of non-null
|
||||||
|
characters, or FETCHLIMIT. */
|
||||||
*length = i * width;
|
*length = i * width;
|
||||||
*buffer = xmalloc (*length);
|
*buffer = xmalloc (*length);
|
||||||
memcpy (*buffer, contents, *length);
|
memcpy (*buffer, contents, *length);
|
||||||
|
@ -685,7 +690,7 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = read_string (value_as_address (value), -1, width, fetchlimit,
|
err = read_string (value_as_address (value), *length, width, fetchlimit,
|
||||||
byte_order, buffer, length);
|
byte_order, buffer, length);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -695,12 +700,23 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the LENGTH is specified at -1, we want to return the string
|
||||||
|
length up to the terminating null character. If an actual length
|
||||||
|
was specified, we want to return the length of exactly what was
|
||||||
|
read. */
|
||||||
|
if (req_length == -1)
|
||||||
/* If the last character is null, subtract it from LENGTH. */
|
/* If the last character is null, subtract it from LENGTH. */
|
||||||
if (*length > 0
|
if (*length > 0
|
||||||
&& extract_unsigned_integer (*buffer + *length - width, width,
|
&& extract_unsigned_integer (*buffer + *length - width, width,
|
||||||
byte_order) == 0)
|
byte_order) == 0)
|
||||||
*length -= width;
|
*length -= width;
|
||||||
|
|
||||||
|
/* The read_string function will return the number of bytes read.
|
||||||
|
If length returned from read_string was > 0, return the number of
|
||||||
|
characters read by dividing the number of bytes by width. */
|
||||||
|
if (*length != 0)
|
||||||
|
*length = *length / width;
|
||||||
|
|
||||||
*charset = target_charset ();
|
*charset = target_charset ();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2009-07-10 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Values From Inferior): Add length parameter
|
||||||
|
description.
|
||||||
|
|
||||||
2009-07-04 Chris Genly <chris@genly.us>
|
2009-07-04 Chris Genly <chris@genly.us>
|
||||||
|
|
||||||
* gdb.texinfo (GDB/MI Variable Objects): Document child definition
|
* gdb.texinfo (GDB/MI Variable Objects): Document child definition
|
||||||
|
|
|
@ -18894,7 +18894,7 @@ The result @code{bar} will be a @code{gdb.Value} object holding the
|
||||||
value pointed to by @code{foo}.
|
value pointed to by @code{foo}.
|
||||||
@end defmethod
|
@end defmethod
|
||||||
|
|
||||||
@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]}
|
@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} @r{[}length@r{]}
|
||||||
If this @code{gdb.Value} represents a string, then this method
|
If this @code{gdb.Value} represents a string, then this method
|
||||||
converts the contents to a Python string. Otherwise, this method will
|
converts the contents to a Python string. Otherwise, this method will
|
||||||
throw an exception.
|
throw an exception.
|
||||||
|
@ -18905,7 +18905,9 @@ language.
|
||||||
|
|
||||||
For C-like languages, a value is a string if it is a pointer to or an
|
For C-like languages, a value is a string if it is a pointer to or an
|
||||||
array of characters or ints. The string is assumed to be terminated
|
array of characters or ints. The string is assumed to be terminated
|
||||||
by a zero of the appropriate width.
|
by a zero of the appropriate width. However if the optional length
|
||||||
|
argument is given, the string will be converted to that given length,
|
||||||
|
ignoring any embedded zeros that the string may contain.
|
||||||
|
|
||||||
If the optional @var{encoding} argument is given, it must be a string
|
If the optional @var{encoding} argument is given, it must be a string
|
||||||
naming the encoding of the string in the @code{gdb.Value}, such as
|
naming the encoding of the string in the @code{gdb.Value}, such as
|
||||||
|
@ -18919,6 +18921,9 @@ will be used, if the current language is able to supply one.
|
||||||
|
|
||||||
The optional @var{errors} argument is the same as the corresponding
|
The optional @var{errors} argument is the same as the corresponding
|
||||||
argument to Python's @code{string.decode} method.
|
argument to Python's @code{string.decode} method.
|
||||||
|
|
||||||
|
If the optional @var{length} argument is given, the string will be
|
||||||
|
fetched and converted to the given length.
|
||||||
@end defmethod
|
@end defmethod
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
|
|
@ -284,10 +284,15 @@ struct language_defn
|
||||||
int (*la_pass_by_reference) (struct type *type);
|
int (*la_pass_by_reference) (struct type *type);
|
||||||
|
|
||||||
/* Obtain a string from the inferior, storing it in a newly allocated
|
/* Obtain a string from the inferior, storing it in a newly allocated
|
||||||
buffer in BUFFER, which should be freed by the caller. LENGTH will
|
buffer in BUFFER, which should be freed by the caller. If the
|
||||||
hold the size in bytes of the string (only actual characters, excluding
|
in- and out-parameter *LENGTH is specified at -1, the string is
|
||||||
an eventual terminating null character). CHARSET will hold the encoding
|
read until a null character of the appropriate width is found -
|
||||||
used in the string. */
|
otherwise the string is read to the length of characters specified.
|
||||||
|
On completion, *LENGTH will hold the size of the string in characters.
|
||||||
|
If a *LENGTH of -1 was specified it will count only actual
|
||||||
|
characters, excluding any eventual terminating null character.
|
||||||
|
Otherwise *LENGTH will include all characters - including any nulls.
|
||||||
|
CHARSET will hold the encoding used in the string. */
|
||||||
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
|
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
|
||||||
const char **charset);
|
const char **charset);
|
||||||
|
|
||||||
|
|
|
@ -113,13 +113,14 @@ void gdbpy_print_stack (void);
|
||||||
PyObject *python_string_to_unicode (PyObject *obj);
|
PyObject *python_string_to_unicode (PyObject *obj);
|
||||||
char *unicode_to_target_string (PyObject *unicode_str);
|
char *unicode_to_target_string (PyObject *unicode_str);
|
||||||
char *python_string_to_target_string (PyObject *obj);
|
char *python_string_to_target_string (PyObject *obj);
|
||||||
|
PyObject *python_string_to_target_python_string (PyObject *obj);
|
||||||
char *python_string_to_host_string (PyObject *obj);
|
char *python_string_to_host_string (PyObject *obj);
|
||||||
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
|
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
|
||||||
int gdbpy_is_string (PyObject *obj);
|
int gdbpy_is_string (PyObject *obj);
|
||||||
|
|
||||||
/* Note that these are declared here, and not in python.h with the
|
/* Note that these are declared here, and not in python.h with the
|
||||||
other pretty-printer functions, because they refer to PyObject. */
|
other pretty-printer functions, because they refer to PyObject. */
|
||||||
char *apply_varobj_pretty_printer (PyObject *print_obj,
|
PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
|
||||||
struct value **replacement);
|
struct value **replacement);
|
||||||
PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
|
PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
|
||||||
char *gdbpy_get_display_hint (PyObject *printer);
|
char *gdbpy_get_display_hint (PyObject *printer);
|
||||||
|
|
|
@ -121,34 +121,35 @@ find_pretty_printer (PyObject *value)
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
/* Pretty-print a single value, via the printer object PRINTER.
|
||||||
/* Pretty-print a single value, via the printer object PRINTER. If
|
If the function returns a string, a PyObject containing the string
|
||||||
the function returns a string, an xmalloc()d copy is returned.
|
is returned. Otherwise, if the function returns a value,
|
||||||
Otherwise, if the function returns a value, a *OUT_VALUE is set to
|
*OUT_VALUE is set to the value, and NULL is returned. On error,
|
||||||
the value, and NULL is returned. On error, *OUT_VALUE is set to
|
*OUT_VALUE is set to NULL, and NULL is returned. */
|
||||||
NULL and NULL is returned. */
|
static PyObject *
|
||||||
static char *
|
|
||||||
pretty_print_one_value (PyObject *printer, struct value **out_value)
|
pretty_print_one_value (PyObject *printer, struct value **out_value)
|
||||||
{
|
{
|
||||||
char *output = NULL;
|
|
||||||
volatile struct gdb_exception except;
|
volatile struct gdb_exception except;
|
||||||
|
PyObject *result = NULL;
|
||||||
|
|
||||||
|
*out_value = NULL;
|
||||||
TRY_CATCH (except, RETURN_MASK_ALL)
|
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||||
{
|
{
|
||||||
PyObject *result;
|
|
||||||
|
|
||||||
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
|
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (gdbpy_is_string (result))
|
if (! gdbpy_is_string (result))
|
||||||
output = python_string_to_host_string (result);
|
{
|
||||||
else
|
|
||||||
*out_value = convert_value_from_python (result);
|
*out_value = convert_value_from_python (result);
|
||||||
|
if (PyErr_Occurred ())
|
||||||
|
*out_value = NULL;
|
||||||
Py_DECREF (result);
|
Py_DECREF (result);
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the display hint for the object printer, PRINTER. Return
|
/* Return the display hint for the object printer, PRINTER. Return
|
||||||
|
@ -184,19 +185,28 @@ print_string_repr (PyObject *printer, const char *hint,
|
||||||
const struct language_defn *language,
|
const struct language_defn *language,
|
||||||
struct gdbarch *gdbarch)
|
struct gdbarch *gdbarch)
|
||||||
{
|
{
|
||||||
char *output;
|
|
||||||
struct value *replacement = NULL;
|
struct value *replacement = NULL;
|
||||||
|
PyObject *py_str = NULL;
|
||||||
|
|
||||||
output = pretty_print_one_value (printer, &replacement);
|
py_str = pretty_print_one_value (printer, &replacement);
|
||||||
if (output)
|
if (py_str)
|
||||||
{
|
{
|
||||||
|
PyObject *string = python_string_to_target_python_string (py_str);
|
||||||
|
if (string)
|
||||||
|
{
|
||||||
|
gdb_byte *output = PyString_AsString (string);
|
||||||
|
int len = PyString_Size (string);
|
||||||
|
|
||||||
if (hint && !strcmp (hint, "string"))
|
if (hint && !strcmp (hint, "string"))
|
||||||
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
|
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
|
||||||
(gdb_byte *) output, strlen (output),
|
output, len, 0, options);
|
||||||
0, options);
|
|
||||||
else
|
else
|
||||||
fputs_filtered (output, stream);
|
fputs_filtered (output, stream);
|
||||||
xfree (output);
|
Py_DECREF (string);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdbpy_print_stack ();
|
||||||
|
Py_DECREF (py_str);
|
||||||
}
|
}
|
||||||
else if (replacement)
|
else if (replacement)
|
||||||
common_val_print (replacement, stream, recurse, options, language);
|
common_val_print (replacement, stream, recurse, options, language);
|
||||||
|
@ -511,26 +521,30 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the
|
/* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the
|
||||||
print object. It must have a 'to_string' method (but this is
|
print object. It must have a 'to_string' method (but this is
|
||||||
checked by varobj, not here) which takes no arguments and
|
checked by varobj, not here) which takes no arguments and
|
||||||
returns a string. This function returns an xmalloc()d string if
|
returns a string. The printer will return a value and in the case
|
||||||
the printer returns a string. The printer may return a replacement
|
of a Python string being returned, this function will return a
|
||||||
value instead; in this case *REPLACEMENT is set to the replacement
|
PyObject containing the string. For any other type, *REPLACEMENT is
|
||||||
value, and this function returns NULL. On error, *REPLACEMENT is
|
set to the replacement value and this function returns NULL. On
|
||||||
set to NULL and this function also returns NULL. */
|
error, *REPLACEMENT is set to NULL and this function also returns
|
||||||
char *
|
NULL. */
|
||||||
|
PyObject *
|
||||||
apply_varobj_pretty_printer (PyObject *printer_obj,
|
apply_varobj_pretty_printer (PyObject *printer_obj,
|
||||||
struct value **replacement)
|
struct value **replacement)
|
||||||
{
|
{
|
||||||
char *result;
|
int size = 0;
|
||||||
|
PyObject *py_str = NULL;
|
||||||
|
|
||||||
*replacement = NULL;
|
*replacement = NULL;
|
||||||
result = pretty_print_one_value (printer_obj, replacement);
|
py_str = pretty_print_one_value (printer_obj, replacement);
|
||||||
if (result == NULL);
|
|
||||||
|
if (*replacement == NULL && py_str == NULL)
|
||||||
gdbpy_print_stack ();
|
gdbpy_print_stack ();
|
||||||
|
|
||||||
return result;
|
return py_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a pretty-printer object for the varobj module. Returns a new
|
/* Find a pretty-printer object for the varobj module. Returns a new
|
||||||
|
|
|
@ -104,6 +104,23 @@ unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns a PyObject with the contents of the given unicode string
|
||||||
|
object converted to a named charset. If an error occurs during
|
||||||
|
the conversion, NULL will be returned and a python exception will
|
||||||
|
be set. */
|
||||||
|
static PyObject *
|
||||||
|
unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
|
||||||
|
{
|
||||||
|
PyObject *string;
|
||||||
|
|
||||||
|
/* Translate string to named charset. */
|
||||||
|
string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
|
||||||
|
if (string == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns a newly allocated string with the contents of the given unicode
|
/* Returns a newly allocated string with the contents of the given unicode
|
||||||
string object converted to the target's charset. If an error occurs during
|
string object converted to the target's charset. If an error occurs during
|
||||||
the conversion, NULL will be returned and a python exception will be set.
|
the conversion, NULL will be returned and a python exception will be set.
|
||||||
|
@ -115,6 +132,16 @@ unicode_to_target_string (PyObject *unicode_str)
|
||||||
return unicode_to_encoded_string (unicode_str, target_charset ());
|
return unicode_to_encoded_string (unicode_str, target_charset ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns a PyObject with the contents of the given unicode string
|
||||||
|
object converted to the target's charset. If an error occurs
|
||||||
|
during the conversion, NULL will be returned and a python exception
|
||||||
|
will be set. */
|
||||||
|
PyObject *
|
||||||
|
unicode_to_target_python_string (PyObject *unicode_str)
|
||||||
|
{
|
||||||
|
return unicode_to_encoded_python_string (unicode_str, target_charset ());
|
||||||
|
}
|
||||||
|
|
||||||
/* Converts a python string (8-bit or unicode) to a target string in
|
/* Converts a python string (8-bit or unicode) to a target string in
|
||||||
the target's charset. Returns NULL on error, with a python exception set.
|
the target's charset. Returns NULL on error, with a python exception set.
|
||||||
|
|
||||||
|
@ -134,6 +161,24 @@ python_string_to_target_string (PyObject *obj)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Converts a python string (8-bit or unicode) to a target string in the
|
||||||
|
target's charset. Returns NULL on error, with a python exception
|
||||||
|
set. */
|
||||||
|
PyObject *
|
||||||
|
python_string_to_target_python_string (PyObject *obj)
|
||||||
|
{
|
||||||
|
PyObject *str;
|
||||||
|
PyObject *result;
|
||||||
|
|
||||||
|
str = python_string_to_unicode (obj);
|
||||||
|
if (str == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
result = unicode_to_target_python_string (str);
|
||||||
|
Py_DECREF (str);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Converts a python string (8-bit or unicode) to a target string in
|
/* Converts a python string (8-bit or unicode) to a target string in
|
||||||
the host's charset. Returns NULL on error, with a python exception set.
|
the host's charset. Returns NULL on error, with a python exception set.
|
||||||
|
|
||||||
|
|
|
@ -189,13 +189,16 @@ valpy_get_type (PyObject *self, void *closure)
|
||||||
return obj->type;
|
return obj->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implementation of gdb.Value.string ([encoding] [, errors]) -> string
|
/* Implementation of gdb.Value.string ([encoding] [, errors]
|
||||||
Return Unicode string with value contents. If ENCODING is not given,
|
[, length]) -> string. Return Unicode string with value contents.
|
||||||
the string is assumed to be encoded in the target's charset. */
|
If ENCODING is not given, the string is assumed to be encoded in
|
||||||
|
the target's charset. If LENGTH is provided, only fetch string to
|
||||||
|
the length provided. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
valpy_string (PyObject *self, PyObject *args, PyObject *kw)
|
valpy_string (PyObject *self, PyObject *args, PyObject *kw)
|
||||||
{
|
{
|
||||||
int length, ret = 0;
|
int length = -1, ret = 0;
|
||||||
gdb_byte *buffer;
|
gdb_byte *buffer;
|
||||||
struct value *value = ((value_object *) self)->value;
|
struct value *value = ((value_object *) self)->value;
|
||||||
volatile struct gdb_exception except;
|
volatile struct gdb_exception except;
|
||||||
|
@ -204,10 +207,10 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw)
|
||||||
const char *errors = NULL;
|
const char *errors = NULL;
|
||||||
const char *user_encoding = NULL;
|
const char *user_encoding = NULL;
|
||||||
const char *la_encoding = NULL;
|
const char *la_encoding = NULL;
|
||||||
static char *keywords[] = { "encoding", "errors" };
|
static char *keywords[] = { "encoding", "errors", "length" };
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords (args, kw, "|ss", keywords,
|
if (!PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords,
|
||||||
&user_encoding, &errors))
|
&user_encoding, &errors, &length))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
TRY_CATCH (except, RETURN_MASK_ALL)
|
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||||
|
@ -937,7 +940,7 @@ static PyMethodDef value_object_methods[] = {
|
||||||
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
|
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
|
||||||
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
|
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
|
||||||
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
|
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
|
||||||
"string ([encoding] [, errors]) -> string\n\
|
"string ([encoding] [, errors] [, length]) -> string\n\
|
||||||
Return Unicode string representation of the value." },
|
Return Unicode string representation of the value." },
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
2009-07-10 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
|
|
||||||
|
* gdb.python/python-prettyprint.c: Add counted null string
|
||||||
|
structure.
|
||||||
|
* gdb.python/python-prettyprint.exp: Print null string. Test for
|
||||||
|
embedded nulls.
|
||||||
|
* gdb.python/python-prettyprint.py (pp_ns): New Function.
|
||||||
|
* gdb.python/python-value.exp (test_value_in_inferior): Add
|
||||||
|
variable length string fetch tests.
|
||||||
|
* gdb.python/python-value.c (main): Add strings for string fetch tests.
|
||||||
|
|
||||||
2009-07-09 Jan Kratochvil <jan.kratochvil@redhat.com>
|
2009-07-09 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
* gdb.base/dump.exp (inaccessible memory is reported): New test.
|
* gdb.base/dump.exp (inaccessible memory is reported): New test.
|
||||||
|
|
|
@ -27,6 +27,11 @@ struct ss
|
||||||
struct s b;
|
struct s b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ns {
|
||||||
|
const char *null_str;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
struct S : public s {
|
struct S : public s {
|
||||||
int zs;
|
int zs;
|
||||||
|
@ -156,6 +161,10 @@ main ()
|
||||||
init_ss(ssa+0, 3, 4);
|
init_ss(ssa+0, 3, 4);
|
||||||
init_ss(ssa+1, 5, 6);
|
init_ss(ssa+1, 5, 6);
|
||||||
|
|
||||||
|
struct ns ns;
|
||||||
|
ns.null_str = "embedded\0null\0string";
|
||||||
|
ns.length = 20;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
S cps;
|
S cps;
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ proc run_lang_tests {lang} {
|
||||||
gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
|
gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
|
||||||
gdb_test "print derived" \
|
gdb_test "print derived" \
|
||||||
" = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
|
" = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
|
||||||
|
gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
|
||||||
}
|
}
|
||||||
|
|
||||||
gdb_test "print x" " = $hex \"this is x\""
|
gdb_test "print x" " = $hex \"this is x\""
|
||||||
|
|
|
@ -92,6 +92,19 @@ class pp_vbase1:
|
||||||
def to_string (self):
|
def to_string (self):
|
||||||
return "pp class name: " + self.val.type.tag
|
return "pp class name: " + self.val.type.tag
|
||||||
|
|
||||||
|
class pp_ns:
|
||||||
|
"Print a std::basic_string of some kind"
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
len = self.val['length']
|
||||||
|
return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
|
||||||
|
|
||||||
|
def display_hint (self):
|
||||||
|
return 'string'
|
||||||
|
|
||||||
def lookup_function (val):
|
def lookup_function (val):
|
||||||
"Look-up and return a pretty-printer that can print val."
|
"Look-up and return a pretty-printer that can print val."
|
||||||
|
|
||||||
|
@ -145,6 +158,8 @@ def register_pretty_printers ():
|
||||||
pretty_printers_dict[re.compile ('^string_repr$')] = string_print
|
pretty_printers_dict[re.compile ('^string_repr$')] = string_print
|
||||||
pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
|
pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
|
||||||
|
|
||||||
|
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
|
||||||
|
pretty_printers_dict[re.compile ('^ns$')] = pp_ns
|
||||||
pretty_printers_dict = {}
|
pretty_printers_dict = {}
|
||||||
|
|
||||||
register_pretty_printers ()
|
register_pretty_printers ()
|
||||||
|
|
|
@ -44,6 +44,8 @@ main (int argc, char *argv[])
|
||||||
struct s s;
|
struct s s;
|
||||||
union u u;
|
union u u;
|
||||||
PTR x = &s;
|
PTR x = &s;
|
||||||
|
char st[17] = "divide et impera";
|
||||||
|
char nullst[17] = "divide\0et\0impera";
|
||||||
|
|
||||||
s.a = 3;
|
s.a = 3;
|
||||||
s.b = 5;
|
s.b = 5;
|
||||||
|
|
|
@ -234,6 +234,25 @@ proc test_value_in_inferior {} {
|
||||||
|
|
||||||
# Test address attribute
|
# Test address attribute
|
||||||
gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
|
gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
|
||||||
|
|
||||||
|
# Test string fetches, both partial and whole.
|
||||||
|
gdb_test "print st" "\"divide et impera\""
|
||||||
|
gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
|
||||||
|
gdb_test "python print st.string ()" "divide et impera" "Test string with no length"
|
||||||
|
gdb_test "python print st.string (length = -1)" "divide et impera" "Test string (length = -1) is all of the string"
|
||||||
|
gdb_test "python print st.string (length = 6)" "divide"
|
||||||
|
gdb_test "python print \"---\"+st.string (length = 0)+\"---\"" "------" "Test string (length = 0) is empty"
|
||||||
|
gdb_test "python print len(st.string (length = 0))" "0" "Test length is 0"
|
||||||
|
|
||||||
|
|
||||||
|
# Fetch a string that has embedded nulls.
|
||||||
|
gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*"
|
||||||
|
gdb_py_test_silent_cmd "python nullst = gdb.history (0)" "get value from history" 1
|
||||||
|
gdb_test "python print nullst.string ()" "divide" "Test string to first null"
|
||||||
|
# Python cannot print strings that contain the null (\0) character.
|
||||||
|
# For the purposes of this test, use repr()
|
||||||
|
gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
|
||||||
|
gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
|
||||||
}
|
}
|
||||||
|
|
||||||
# A few objfile tests.
|
# A few objfile tests.
|
||||||
|
|
21
gdb/varobj.c
21
gdb/varobj.c
|
@ -2221,8 +2221,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
long dummy;
|
long dummy;
|
||||||
struct ui_file *stb;
|
struct ui_file *stb;
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
char *thevalue = NULL;
|
gdb_byte *thevalue = NULL;
|
||||||
struct value_print_options opts;
|
struct value_print_options opts;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2238,6 +2239,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
char *hint;
|
char *hint;
|
||||||
struct value *replacement;
|
struct value *replacement;
|
||||||
int string_print = 0;
|
int string_print = 0;
|
||||||
|
PyObject *output = NULL;
|
||||||
|
|
||||||
hint = gdbpy_get_display_hint (value_formatter);
|
hint = gdbpy_get_display_hint (value_formatter);
|
||||||
if (hint)
|
if (hint)
|
||||||
|
@ -2247,8 +2249,20 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
xfree (hint);
|
xfree (hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
thevalue = apply_varobj_pretty_printer (value_formatter,
|
output = apply_varobj_pretty_printer (value_formatter,
|
||||||
&replacement);
|
&replacement);
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
PyObject *py_str = python_string_to_target_python_string (output);
|
||||||
|
if (py_str)
|
||||||
|
{
|
||||||
|
char *s = PyString_AsString (py_str);
|
||||||
|
len = PyString_Size (py_str);
|
||||||
|
thevalue = xmemdup (s, len + 1, len + 1);
|
||||||
|
Py_DECREF (py_str);
|
||||||
|
}
|
||||||
|
Py_DECREF (output);
|
||||||
|
}
|
||||||
if (thevalue && !string_print)
|
if (thevalue && !string_print)
|
||||||
{
|
{
|
||||||
do_cleanups (back_to);
|
do_cleanups (back_to);
|
||||||
|
@ -2272,8 +2286,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
struct gdbarch *gdbarch = get_type_arch (value_type (value));
|
struct gdbarch *gdbarch = get_type_arch (value_type (value));
|
||||||
make_cleanup (xfree, thevalue);
|
make_cleanup (xfree, thevalue);
|
||||||
LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
|
LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
|
||||||
(gdb_byte *) thevalue, strlen (thevalue),
|
thevalue, len, 0, &opts);
|
||||||
0, &opts);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
common_val_print (value, stb, 0, &opts, current_language);
|
common_val_print (value, stb, 0, &opts, current_language);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue