diff options
author | Thiago Jung Bauermann <bauerman@br.ibm.com> | 2009-02-05 12:16:25 +0000 |
---|---|---|
committer | Thiago Jung Bauermann <bauerman@br.ibm.com> | 2009-02-05 12:16:25 +0000 |
commit | ae6a3a4c2a48a78e57332eb9489c3065a8b9aca1 (patch) | |
tree | 0b6df2e50f43cdd7d0fa4a6c3fb1f608768e2902 /gdb/c-lang.c | |
parent | fa8a61dc873c4e7ede0738fc44d4d4a5bf0a77df (diff) | |
download | gdb-ae6a3a4c2a48a78e57332eb9489c3065a8b9aca1.zip gdb-ae6a3a4c2a48a78e57332eb9489c3065a8b9aca1.tar.gz gdb-ae6a3a4c2a48a78e57332eb9489c3065a8b9aca1.tar.bz2 |
2009-02-05 Thiago Jung Bauermann <bauerman@br.ibm.com>
* language.h (language_dfn): Add la_get_string member.
(LA_GET_STRING): New macro.
(default_get_string): New prototype.
* language.c (default_get_string): New function.
(unknown_language_defn, auto_language_defn, local_language_defn): Use
default_get_string for la_get_string.
* c-lang.c (c_get_string): New function.
(c_language_defn, cplus_language_defn, asm_language_defn): Use
c_get_string for la_get_string.
(minimal_language_defn): Likewise
* ada-lang.c (ada_language_defn): Likewise.
* f-lang.c (f_language_defn): Use default_get_string for
la_get_string.
* jv-lang.c (java_language_defn): Likewise.
* m2-lang.c (m2_language_defn): Likewise.
* objc-lang.c (objc_language_defn): Likewise.
* p-lang.c (p_language_defn): Likewise.
* scm-lang.c (scm_language_defn): Likewise.
* typeprint.c (type_to_string): New function.
* value.h (type_to_string): New prototype.
* valprint.c (val_print_string): Factor out code for reading string
from the inferior into its own function. Put 2 spaces after period
in comments.
(read_string): New function.
* valprint.h (read_string): New prototype.
Diffstat (limited to 'gdb/c-lang.c')
-rw-r--r-- | gdb/c-lang.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 309a0b0..8b5410f 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -181,6 +181,122 @@ c_printstr (struct ui_file *stream, const gdb_byte *string, if (force_ellipses || i < length) fputs_filtered ("...", stream); } + +/* 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 + read until a null character is found. If VALUE is an array with known + length, the function will not read past the end of the array. LENGTH + will contain the size of the string in bytes (not counting the null + character). + + Assumes strings are terminated by a null character. The size of a character + is determined by the length of the target type of the pointer or array. + This means that a null byte present in a multi-byte character will not + terminate the string unless the whole character is null. + + CHARSET is always set to the target charset. */ + +void +c_get_string (struct value *value, gdb_byte **buffer, int *length, + const char **charset) +{ + int err, width; + unsigned int fetchlimit; + struct type *type = check_typedef (value_type (value)); + struct type *element_type = TYPE_TARGET_TYPE (type); + + if (element_type == NULL) + goto error; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + /* If we know the size of the array, we can use it as a limit on the + number of characters to be fetched. */ + if (TYPE_NFIELDS (type) == 1 + && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_RANGE) + { + LONGEST low_bound, high_bound; + + get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), + &low_bound, &high_bound); + fetchlimit = high_bound - low_bound + 1; + } + else + fetchlimit = UINT_MAX; + } + else if (TYPE_CODE (type) == TYPE_CODE_PTR) + fetchlimit = UINT_MAX; + else + /* We work only with arrays and pointers. */ + goto error; + + element_type = check_typedef (element_type); + if (TYPE_CODE (element_type) != TYPE_CODE_INT + && TYPE_CODE (element_type) != TYPE_CODE_CHAR) + /* If the elements are not integers or characters, we don't consider it + a string. */ + goto error; + + width = TYPE_LENGTH (element_type); + + /* If the string lives in GDB's memory intead of the inferior's, then we + just need to copy it to BUFFER. Also, since such strings are arrays + with known size, FETCHLIMIT will hold the size of the array. */ + if ((VALUE_LVAL (value) == not_lval + || VALUE_LVAL (value) == lval_internalvar) + && fetchlimit != UINT_MAX) + { + int i; + const gdb_byte *contents = value_contents (value); + + /* Look for a null character. */ + for (i = 0; i < fetchlimit; i++) + if (extract_unsigned_integer (contents + i * width, width) == 0) + break; + + /* I is now either the number of non-null characters, or FETCHLIMIT. */ + *length = i * width; + *buffer = xmalloc (*length); + memcpy (*buffer, contents, *length); + err = 0; + } + else + { + err = read_string (value_as_address (value), -1, width, fetchlimit, + buffer, length); + if (err) + { + xfree (buffer); + error (_("Error reading string from inferior: %s"), + safe_strerror (err)); + } + } + + /* If the last character is null, subtract it from LENGTH. */ + if (*length > 0 + && extract_unsigned_integer (*buffer + *length - width, width) == 0) + *length -= width; + + *charset = target_charset (); + + return; + + error: + { + char *type_str; + + type_str = type_to_string (type); + if (type_str) + { + make_cleanup (xfree, type_str); + error (_("Trying to read string with inappropriate type `%s'."), + type_str); + } + else + error (_("Trying to read string with inappropriate type.")); + } +} + /* Preprocessing and parsing C and C++ expressions. */ @@ -314,6 +430,7 @@ const struct language_defn c_language_defn = c_language_arch_info, default_print_array_index, default_pass_by_reference, + c_get_string, LANG_MAGIC }; @@ -432,6 +549,7 @@ const struct language_defn cplus_language_defn = cplus_language_arch_info, default_print_array_index, cp_pass_by_reference, + c_get_string, LANG_MAGIC }; @@ -469,6 +587,7 @@ const struct language_defn asm_language_defn = c_language_arch_info, /* FIXME: la_language_arch_info. */ default_print_array_index, default_pass_by_reference, + c_get_string, LANG_MAGIC }; @@ -511,6 +630,7 @@ const struct language_defn minimal_language_defn = c_language_arch_info, default_print_array_index, default_pass_by_reference, + c_get_string, LANG_MAGIC }; |