📄 valprint.c
字号:
/* Print values for GDB, the GNU debugger. Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include <string.h>#include "symtab.h"#include "gdbtypes.h"#include "value.h"#include "gdbcore.h"#include "gdbcmd.h"#include "target.h"#include "obstack.h"#include "language.h"#include "demangle.h"#include <errno.h>/* Prototypes for local functions */static voidprint_string PARAMS ((FILE *, char *, unsigned int, int));static voidshow_print PARAMS ((char *, int));static voidset_print PARAMS ((char *, int));static voidset_radix PARAMS ((char *, int, struct cmd_list_element *));static voidset_output_radix PARAMS ((char *, int, struct cmd_list_element *));static voidtype_print_base PARAMS ((struct type *, FILE *, int, int));static voidtype_print_args PARAMS ((struct type *, FILE *));static voidtype_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int, int));static voidtype_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));static voidtype_print_derivation_info PARAMS ((FILE *, struct type *));static voidtype_print_method_args PARAMS ((struct type **, char *, char *, int, FILE *));static voidcplus_val_print PARAMS ((struct type *, char *, FILE *, int, int, enum val_prettyprint, struct type **));static voidval_print_fields PARAMS ((struct type *, char *, FILE *, int, int, enum val_prettyprint, struct type **));static intis_vtbl_member PARAMS ((struct type *));static intis_vtbl_ptr_type PARAMS ((struct type *));static voidprint_hex_chars PARAMS ((FILE *, unsigned char *, unsigned));extern int demangle; /* whether to print C++ syms raw or source-form *//* Maximum number of chars to print for a string pointer value or vector contents, or UINT_MAX for no limit. */static unsigned int print_max;/* Default input and output radixes, and output format letter. */unsigned input_radix = 10;unsigned output_radix = 10;int output_format = 0;/* Print repeat counts if there are more than this many repetitions of an element in an array. */#define REPEAT_COUNT_THRESHOLD 10/* Define a mess of print controls. */int prettyprint; /* Controls pretty printing of structures */int vtblprint; /* Controls printing of vtbl's */int unionprint; /* Controls printing of nested unions. */int arrayprint; /* Controls pretty printing of arrays. */int addressprint; /* Controls pretty printing of addresses. */int objectprint; /* Controls looking up an object's derived type using what we find in its vtables. */struct obstack dont_print_obstack;/* Print the character string STRING, printing at most LENGTH characters. Printing stops early if the number hits print_max; repeat counts are printed as appropriate. Print ellipses at the end if we had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */static voidprint_string (stream, string, length, force_ellipses) FILE *stream; char *string; unsigned int length; int force_ellipses;{ register unsigned int i; unsigned int things_printed = 0; int in_quotes = 0; int need_comma = 0; extern int inspect_it; if (length == 0) { fputs_filtered ("\"\"", stdout); return; } for (i = 0; i < length && things_printed < print_max; ++i) { /* Position of the character we are examining to see whether it is repeated. */ unsigned int rep1; /* Number of repetitions we have detected so far. */ unsigned int reps; QUIT; if (need_comma) { fputs_filtered (", ", stream); need_comma = 0; } rep1 = i + 1; reps = 1; while (rep1 < length && string[rep1] == string[i]) { ++rep1; ++reps; } if (reps > REPEAT_COUNT_THRESHOLD) { if (in_quotes) { if (inspect_it) fputs_filtered ("\\\", ", stream); else fputs_filtered ("\", ", stream); in_quotes = 0; } fputs_filtered ("'", stream); printchar (string[i], stream, '\''); fprintf_filtered (stream, "' <repeats %u times>", reps); i = rep1 - 1; things_printed += REPEAT_COUNT_THRESHOLD; need_comma = 1; } else { if (!in_quotes) { if (inspect_it) fputs_filtered ("\\\"", stream); else fputs_filtered ("\"", stream); in_quotes = 1; } printchar (string[i], stream, '"'); ++things_printed; } } /* Terminate the quotes if necessary. */ if (in_quotes) { if (inspect_it) fputs_filtered ("\\\"", stream); else fputs_filtered ("\"", stream); } if (force_ellipses || i < length) fputs_filtered ("...", stream);}/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR, on STREAM. */voidprint_floating (valaddr, type, stream) char *valaddr; struct type *type; FILE *stream;{ double doub; int inv; unsigned len = TYPE_LENGTH (type); #if defined (IEEE_FLOAT) /* Check for NaN's. Note that this code does not depend on us being on an IEEE conforming system. It only depends on the target machine using IEEE representation. This means (a) cross-debugging works right, and (2) IEEE_FLOAT can (and should) be defined for systems like the 68881, which uses IEEE representation, but is not IEEE conforming. */ { long low, high; /* Is the sign bit 0? */ int nonnegative; /* Is it is a NaN (i.e. the exponent is all ones and the fraction is nonzero)? */ int is_nan; if (len == sizeof (float)) { /* It's single precision. */ memcpy ((char *) &low, valaddr, sizeof (low)); /* target -> host. */ SWAP_TARGET_AND_HOST (&low, sizeof (float)); nonnegative = low >= 0; is_nan = ((((low >> 23) & 0xFF) == 0xFF) && 0 != (low & 0x7FFFFF)); low &= 0x7fffff; high = 0; } else { /* It's double precision. Get the high and low words. */#if TARGET_BYTE_ORDER == BIG_ENDIAN memcpy (&low, valaddr+4, sizeof (low)); memcpy (&high, valaddr+0, sizeof (high));#else memcpy (&low, valaddr+0, sizeof (low)); memcpy (&high, valaddr+4, sizeof (high));#endif SWAP_TARGET_AND_HOST (&low, sizeof (low)); SWAP_TARGET_AND_HOST (&high, sizeof (high)); nonnegative = high >= 0; is_nan = (((high >> 20) & 0x7ff) == 0x7ff && ! ((((high & 0xfffff) == 0)) && (low == 0))); high &= 0xfffff; } if (is_nan) { /* The meaning of the sign and fraction is not defined by IEEE. But the user might know what they mean. For example, they (in an implementation-defined manner) distinguish between signaling and quiet NaN's. */ if (high) fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonnegative, high, low); else fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low); return; } }#endif /* IEEE_FLOAT. */ doub = unpack_double (type, valaddr, &inv); if (inv) fprintf_filtered (stream, "<invalid float value>"); else fprintf_filtered (stream, len <= sizeof(float) ? "%.9g" : "%.17g", doub);}/* VALADDR points to an integer of LEN bytes. Print it in hex on stream. */static voidprint_hex_chars (stream, valaddr, len) FILE *stream; unsigned char *valaddr; unsigned len;{ unsigned char *p; fprintf_filtered (stream, "0x");#if TARGET_BYTE_ORDER == BIG_ENDIAN for (p = valaddr; p < valaddr + len; p++)#else /* Little endian. */ for (p = valaddr + len - 1; p >= valaddr; p--)#endif { fprintf_filtered (stream, "%02x", *p); }}/* Print the value VAL in C-ish syntax on stream STREAM. FORMAT is a format-letter, or 0 for print in natural format of data type. If the object printed is a string pointer, returns the number of string bytes printed. */intvalue_print (val, stream, format, pretty) value val; FILE *stream; int format; enum val_prettyprint pretty;{ register unsigned int i, n, typelen; if (val == 0) { printf_filtered ("<address of value unknown>"); return 0; } if (VALUE_OPTIMIZED_OUT (val)) { printf_filtered ("<value optimized out>"); return 0; } /* A "repeated" value really contains several values in a row. They are made by the @ operator. Print such values as if they were arrays. */ else if (VALUE_REPEATED (val)) { n = VALUE_REPETITIONS (val); typelen = TYPE_LENGTH (VALUE_TYPE (val)); fprintf_filtered (stream, "{"); /* Print arrays of characters using string syntax. */ if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT && format == 0) print_string (stream, VALUE_CONTENTS (val), n, 0); else { unsigned int things_printed = 0; for (i = 0; i < n && things_printed < print_max; i++) { /* Position of the array element we are examining to see whether it is repeated. */ unsigned int rep1; /* Number of repetitions we have detected so far. */ unsigned int reps; if (i != 0) fprintf_filtered (stream, ", "); wrap_here (""); rep1 = i + 1; reps = 1; while (rep1 < n && !memcmp (VALUE_CONTENTS (val) + typelen * i, VALUE_CONTENTS (val) + typelen * rep1, typelen)) { ++reps; ++rep1; } if (reps > REPEAT_COUNT_THRESHOLD) { val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, VALUE_ADDRESS (val) + typelen * i, stream, format, 1, 0, pretty); fprintf (stream, " <repeats %u times>", reps); i = rep1 - 1; things_printed += REPEAT_COUNT_THRESHOLD; } else { val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, VALUE_ADDRESS (val) + typelen * i, stream, format, 1, 0, pretty); things_printed++; } } if (i < n) fprintf_filtered (stream, "..."); } fprintf_filtered (stream, "}"); return n * typelen; } else { struct type *type = VALUE_TYPE (val); /* If it is a pointer, indicate what it points to. Print type also if it is a reference. C++: if it is a member pointer, we will take care of that when we print it. */ if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF) { /* Hack: remove (char *) for char strings. Their type is indicated by the quoted string anyway. */ if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT && !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type))) { /* Print nothing */ } else { fprintf_filtered (stream, "("); type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); } } return val_print (type, VALUE_CONTENTS (val), VALUE_ADDRESS (val), stream, format, 1, 0, pretty); }}/* Return truth value for assertion that TYPE is of the type "pointer to virtual function". */static intis_vtbl_ptr_type(type) struct type *type;{ char *typename = type_name_no_tag (type); static const char vtbl_ptr_name[] = { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; return (typename != NULL && !strcmp(typename, vtbl_ptr_name));}/* Return truth value for the assertion that TYPE is of the type "pointer to virtual function table". */static intis_vtbl_member(type) struct type *type;{ if (TYPE_CODE (type) == TYPE_CODE_PTR) type = TYPE_TARGET_TYPE (type); else return 0; if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT) /* Virtual functions tables are full of pointers to virtual functions. */ return is_vtbl_ptr_type (TYPE_TARGET_TYPE (type)); return 0;}/* Mutually recursive subroutines of cplus_val_print and val_print to print out a structure's fields: val_print_fields and cplus_val_print. TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the same meanings as in cplus_val_print and val_print. DONT_PRINT is an array of baseclass types that we should not print, or zero if called from top level. */static voidval_print_fields (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; FILE *stream; int format; int recurse; enum val_prettyprint pretty; struct type **dont_print;{ int i, len, n_baseclasses; check_stub_type (type); fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); n_baseclasses = TYPE_N_BASECLASSES (type); /* Print out baseclasses such that we don't print duplicates of virtual baseclasses. */ if (n_baseclasses > 0) cplus_val_print (type, valaddr, stream, format, recurse+1, pretty, dont_print); if (!len && n_baseclasses == 1) fprintf_filtered (stream, "<No data fields>"); else { extern int inspect_it; int fields_seen = 0; for (i = n_baseclasses; i < len; i++) { /* Check if static field */ if (TYPE_FIELD_STATIC (type, i)) continue; if (fields_seen) fprintf_filtered (stream, ", "); else if (n_baseclasses > 0) { if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 + 2 * recurse, stream); fputs_filtered ("members of ", stream); fputs_filtered (type_name_no_tag (type), stream); fputs_filtered (": ", stream); } } fields_seen = 1; if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 + 2 * recurse, stream); } else { wrap_here (n_spaces (2 + 2 * recurse)); } if (inspect_it) { if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR) fputs_filtered ("\"( ptr \"", stream); else fputs_filtered ("\"( nodef \"", stream); fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); fputs_filtered ("\" \"", stream); fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); fputs_filtered ("\") \"", stream); } else { fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); fputs_filtered (" = ", stream); } if (TYPE_FIELD_PACKED (type, i)) { value v;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -