diff options
Diffstat (limited to 'gdb/valprint.c')
-rw-r--r-- | gdb/valprint.c | 395 |
1 files changed, 355 insertions, 40 deletions
diff --git a/gdb/valprint.c b/gdb/valprint.c index 8087ef8..1aae021 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -33,6 +33,7 @@ static int print_max; static void type_print_varspec_suffix (); static void type_print_varspec_prefix (); static void type_print_base (); +static void type_print_method_args (); START_FILE @@ -82,7 +83,7 @@ value_print (val, stream, format) if (i) fprintf (stream, ", "); val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, stream, format); + VALUE_ADDRESS (val) + typelen * i, stream, format, 1); } if (i < n) fprintf (stream, "..."); @@ -92,15 +93,21 @@ value_print (val, stream, format) else { /* A simple (nonrepeated) value */ - /* If it is a pointer, indicate what it points to. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR) + /* If it is a pointer, indicate what it points to. + + C++: print type also if it is a reference. + + If it is a member pointer, we will take care + of that when we print it. */ + if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR + || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF) { fprintf (stream, "("); type_print (VALUE_TYPE (val), "", stream, -1); fprintf (stream, ") "); } return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format); + VALUE_ADDRESS (val), stream, format, 1); } } @@ -110,18 +117,22 @@ value_print (val, stream, format) (a letter or 0 for natural format). If the data are a string pointer, returns the number of - sting characters printed. */ + sting characters printed. + + If DEREF_REF is nonzero, then dereference references, + otherwise just print them like pointers. */ int -val_print (type, valaddr, address, stream, format) +val_print (type, valaddr, address, stream, format, deref_ref) struct type *type; char *valaddr; CORE_ADDR address; FILE *stream; char format; + int deref_ref; { register int i; - int len; + int len, n_baseclasses; struct type *elttype; int eltlen; int val; @@ -158,7 +169,7 @@ val_print (type, valaddr, address, stream, format) { if (i) fprintf (stream, ", "); val_print (elttype, valaddr + i * eltlen, - 0, stream, format); + 0, stream, format, deref_ref); } if (i < len) fprintf (stream, "..."); @@ -174,53 +185,205 @@ val_print (type, valaddr, address, stream, format) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - fprintf (stream, "0x%x", * (int *) valaddr); - /* For a pointer to char or unsigned char, - also print the string pointed to, unless pointer is null. */ - - /* For an array of chars, print with string syntax. */ - elttype = TYPE_TARGET_TYPE (type); - if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0 - && unpack_long (type, valaddr) != 0) + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) { - fputc (' ', stream); - fputc ('"', stream); - for (i = 0; i < print_max; i++) + struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); + struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); + struct fn_field *f; + int j, len2; + char *kind = ""; + + val = unpack_long (builtin_type_int, valaddr); + if (TYPE_CODE (target) == TYPE_CODE_FUNC) { - QUIT; - read_memory (unpack_long (type, valaddr) + i, &c, 1); - if (c == 0) - break; - printchar (c, stream, '"'); + if (val < 128) + { + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (TYPE_FN_FIELD_VOFFSET (f, j) == val) + { + kind = "virtual"; + goto common; + } + } + } + } + else + { + struct symbol *sym = find_pc_function (val); + if (sym == 0) + error ("invalid pointer to member function"); + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) + goto common; + } + } + } + common: + if (i < len) + { + fputc ('&', stream); + type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); + fprintf (stream, kind); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (domain, i), stream); + else + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (domain, i), stream); + break; + } + } + else + { + /* VAL is a byte offset into the structure type DOMAIN. + Find the name of the field for that offset and + print it. */ + int extra = 0; + int bits = 0; + len = TYPE_NFIELDS (domain); + val <<= 3; /* @@ Make VAL into bit offset */ + for (i = 0; i < len; i++) + { + int bitpos = TYPE_FIELD_BITPOS (domain, i); + QUIT; + if (val == bitpos) + break; + if (val < bitpos && i > 0) + { + int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); + /* Somehow pointing into a field. */ + i -= 1; + extra = (val - TYPE_FIELD_BITPOS (domain, i)); + if (extra & 0x3) + bits = 1; + else + extra >>= 3; + break; + } + } + if (i < len) + { + fputc ('&', stream); + type_print_base (domain, stream, 0, 0); + fprintf (stream, "::"); + fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); + if (extra) + fprintf (stream, " + %d bytes", extra); + if (bits) + fprintf (stream, " (offset in bits)"); + break; + } + } + fputc ('(', stream); + type_print (type, "", stream, -1); + fprintf (stream, ") %d", val >> 3); + } + else + { + fprintf (stream, "0x%x", * (int *) valaddr); + /* For a pointer to char or unsigned char, + also print the string pointed to, unless pointer is null. */ + + /* For an array of chars, print with string syntax. */ + elttype = TYPE_TARGET_TYPE (type); + if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT + && format == 0 + && unpack_long (type, valaddr) != 0) + { + fputc (' ', stream); + fputc ('"', stream); + for (i = 0; i < print_max; i++) + { + QUIT; + read_memory (unpack_long (type, valaddr) + i, &c, 1); + if (c == 0) + break; + printchar (c, stream, '"'); + } + fputc ('"', stream); + if (i == print_max) + fprintf (stream, "..."); + fflush (stream); + /* Return number of characters printed, plus one for the + terminating null if we have "reached the end". */ + return i + (i != print_max); } - fputc ('"', stream); - if (i == print_max) - fprintf (stream, "..."); - fflush (stream); - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return i + (i != print_max); } break; + case TYPE_CODE_MEMBER: + error ("not implemented: member type in val_print"); + break; + + case TYPE_CODE_REF: + fprintf (stream, "0x%x", * (int *) valaddr); + /* De-reference the reference. */ + if (deref_ref) + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) + { + value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr); + fprintf (stream, " = "); + val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), + VALUE_ADDRESS (val), stream, format, deref_ref); + } + else + fprintf (stream, " = ???"); + break; + case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: fprintf (stream, "{"); len = TYPE_NFIELDS (type); - for (i = 0; i < len; i++) + n_baseclasses = TYPE_N_BASECLASSES (type); + for (i = 1; i <= n_baseclasses; i++) { - if (i) fprintf (stream, ", "); + fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i))); + val_print (TYPE_FIELD_TYPE (type, 0), + valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8, + 0, stream, 0, 0); + } + if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type)); + for (i -= 1; i < len; i++) + { + if (i > n_baseclasses) fprintf (stream, ", "); fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); - if (TYPE_FIELD_PACKED (type, i)) + /* check if static field */ + if (TYPE_FIELD_STATIC (type, i)) + { + value v; + + v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); + val_print (TYPE_FIELD_TYPE (type, i), + VALUE_CONTENTS (v), 0, stream, format, deref_ref); + } + else if (TYPE_FIELD_PACKED (type, i)) { val = unpack_field_as_long (type, valaddr, i); - val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format); + val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format, deref_ref); } else val_print (TYPE_FIELD_TYPE (type, i), valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format); + 0, stream, format, deref_ref); } fprintf (stream, "}"); break; @@ -367,13 +530,96 @@ type_print_1 (type, varstring, stream, show, level) ((show > 0 || TYPE_NAME (type) == 0) && (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC - || code == TYPE_CODE_ARRAY))) + || code == TYPE_CODE_ARRAY + || code == TYPE_CODE_MEMBER + || code == TYPE_CODE_REF))) fprintf (stream, " "); type_print_varspec_prefix (type, stream, show, 0); fprintf (stream, "%s", varstring); type_print_varspec_suffix (type, stream, show, 0); } +/* Print the method arguments ARGS to the file STREAM. */ +static void +type_print_method_args (args, prefix, varstring, stream) + struct type **args; + char *prefix, *varstring; + FILE *stream; +{ + int i; + + fprintf (stream, " %s%s (", prefix, varstring); + if (args[1] && args[1]->code != TYPE_CODE_VOID) + { + i = 1; /* skip the class variable */ + while (1) + { + type_print (args[i++], "", stream, 0); + if (!args[i]) + { + fprintf (stream, " ..."); + break; + } + else if (args[i]->code != TYPE_CODE_VOID) + { + fprintf (stream, ", "); + } + else break; + } + } + fprintf (stream, ")"); +} + +/* If TYPE is a derived type, then print out derivation + information. Print out all layers of the type heirarchy + until we encounter one with multiple inheritance. + At that point, print out that ply, and return. */ +static void +type_print_derivation_info (stream, type) + FILE *stream; + struct type *type; +{ + char *name; + int i, n_baseclasses = TYPE_N_BASECLASSES (type); + struct type *basetype = 0; + + while (type && n_baseclasses == 1) + { + basetype = TYPE_BASECLASS (type, 1); + if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) + { + while (*name != ' ') name++; + fprintf (stream, ": %s%s %s ", + TYPE_VIA_PUBLIC (basetype) ? "public" : "private", + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", + name + 1); + } + n_baseclasses = TYPE_N_BASECLASSES (basetype); + type = basetype; + } + + if (type) + { + if (n_baseclasses != 0) + fprintf (stream, ": "); + for (i = 1; i <= n_baseclasses; i++) + { + basetype = TYPE_BASECLASS (type, i); + if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) + { + while (*name != ' ') name++; + fprintf (stream, "%s%s %s", + TYPE_VIA_PUBLIC (basetype) ? "public" : "private", + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", + name + 1); + } + if (i < n_baseclasses) + fprintf (stream, ", "); + } + putc (' ', stream); + } +} + /* Print any asterisks or open-parentheses needed before the variable name (to describe its type). @@ -404,6 +650,20 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr) fputc ('*', stream); break; + case TYPE_CODE_MEMBER: + type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, + passed_a_ptr); + fputc (' ', stream); + type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, + passed_a_ptr); + fprintf (stream, "::"); + break; + + case TYPE_CODE_REF: + type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + fputc ('&', stream); + break; + case TYPE_CODE_FUNC: case TYPE_CODE_ARRAY: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); @@ -445,7 +705,14 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr) fprintf (stream, "]"); break; + case TYPE_CODE_MEMBER: + if (passed_a_ptr) + fputc (')', stream); + type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); + break; + case TYPE_CODE_PTR: + case TYPE_CODE_REF: type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); break; @@ -501,6 +768,8 @@ type_print_base (type, stream, show, level) { case TYPE_CODE_ARRAY: case TYPE_CODE_PTR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_REF: case TYPE_CODE_FUNC: type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); break; @@ -521,12 +790,23 @@ type_print_base (type, stream, show, level) fprintf (stream, "{...}"); else { + int i; + + type_print_derivation_info (stream, type); + fprintf (stream, "{"); len = TYPE_NFIELDS (type); - fprintf (stream, "\n"); - for (i = 0; i < len; i++) + if (len) fprintf (stream, "\n"); + else fprintf (stream, "<no data fields>\n"); + + for (i = TYPE_N_BASECLASSES (type); i < len; i++) { QUIT; + /* Don't print out virtual function table. */ + if (! strncmp (TYPE_FIELD_NAME (type, i), + "_vptr$", 6)) + continue; + print_spaces (level + 4, stream); /* If this is a bit-field and there is a gap before it, @@ -550,6 +830,10 @@ type_print_base (type, stream, show, level) /* Print the declaration of this field. */ + if (TYPE_FIELD_STATIC (type, i)) + { + fprintf (stream, "static "); + } type_print_1 (TYPE_FIELD_TYPE (type, i), TYPE_FIELD_NAME (type, i), stream, show - 1, level + 4); @@ -561,6 +845,37 @@ type_print_base (type, stream, show, level) fprintf (stream, ";\n"); } + + /* C++: print out the methods */ + len = TYPE_NFN_FIELDS (type); + if (len) fprintf (stream, "\n"); + for (i = 0; i < len; i++) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); + + for (j = 0; j < len2; j++) + { + QUIT; + print_spaces (level + 4, stream); + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + fprintf (stream, "virtual "); + type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (type, i), stream); + else + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (type, i), stream); + + fprintf (stream, ";\n"); + } + if (len2) fprintf (stream, "\n"); + } + print_spaces (level, stream); fputc ('}', stream); } |