📄 printcmd.c
字号:
/* Print values for GNU debugger GDB. Copyright 1986, 1987, 1988, 1989, 1990, 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 "frame.h"#include "symtab.h"#include "gdbtypes.h"#include "value.h"#include "language.h"#include "expression.h"#include "gdbcore.h"#include "gdbcmd.h"#include "target.h"#include "breakpoint.h"#include "demangle.h"extern int asm_demangle; /* Whether to demangle syms in asm printouts */extern int addressprint; /* Whether to print hex addresses in HLL " */struct format_data{ int count; char format; char size;};/* Last specified output format. */static char last_format = 'x';/* Last specified examination size. 'b', 'h', 'w' or `q'. */static char last_size = 'w';/* Default address to examine next. */static CORE_ADDR next_address;/* Last address examined. */static CORE_ADDR last_examine_address;/* Contents of last address examined. This is not valid past the end of the `x' command! */static value last_examine_value;/* Number of auto-display expression currently being displayed. So that we can deleted it if we get an error or a signal within it. -1 when not doing one. */int current_display_number;/* Flag to low-level print routines that this value is being printed in an epoch window. We'd like to pass this as a parameter, but every routine would need to take it. Perhaps we can encapsulate this in the I/O stream once we have GNU stdio. */int inspect_it = 0;struct display{ /* Chain link to next auto-display item. */ struct display *next; /* Expression to be evaluated and displayed. */ struct expression *exp; /* Item number of this auto-display item. */ int number; /* Display format specified. */ struct format_data format; /* Innermost block required by this expression when evaluated */ struct block *block; /* Status of this display (enabled or disabled) */ enum enable status;};/* Chain of expressions whose values should be displayed automatically each time the program stops. */static struct display *display_chain;static int display_number;/* Prototypes for local functions */static voiddelete_display PARAMS ((int));static voidenable_display PARAMS ((char *, int));static voiddisable_display_command PARAMS ((char *, int));static voiddisassemble_command PARAMS ((char *, int));static intcontaining_function_bounds PARAMS ((CORE_ADDR, CORE_ADDR *, CORE_ADDR *));static voidprintf_command PARAMS ((char *, int));static voidprint_frame_nameless_args PARAMS ((struct frame_info *, CORE_ADDR, long, int, int, FILE *));static voiddisplay_info PARAMS ((char *, int));static voiddo_one_display PARAMS ((struct display *));static voidundisplay_command PARAMS ((char *, int));static voidfree_display PARAMS ((struct display *));static voiddisplay_command PARAMS ((char *, int));static voidptype_command PARAMS ((char *, int));static struct type *ptype_eval PARAMS ((struct expression *));static voidwhatis_command PARAMS ((char *, int));static voidwhatis_exp PARAMS ((char *, int));static voidx_command PARAMS ((char *, int));static voidaddress_info PARAMS ((char *, int));static voidset_command PARAMS ((char *, int));static voidoutput_command PARAMS ((char *, int));static voidcall_command PARAMS ((char *, int));static voidinspect_command PARAMS ((char *, int));static voidprint_command PARAMS ((char *, int));static voidprint_command_1 PARAMS ((char *, int, int));static voidvalidate_format PARAMS ((struct format_data, char *));static voiddo_examine PARAMS ((struct format_data, CORE_ADDR));static voidprint_formatted PARAMS ((value, int, int));static struct format_datadecode_format PARAMS ((char **, int, int));/* Decode a format specification. *STRING_PTR should point to it. OFORMAT and OSIZE are used as defaults for the format and size if none are given in the format specification. If OSIZE is zero, then the size field of the returned value should be set only if a size is explicitly specified by the user. The structure returned describes all the data found in the specification. In addition, *STRING_PTR is advanced past the specification and past all whitespace following it. */static struct format_datadecode_format (string_ptr, oformat, osize) char **string_ptr; int oformat; int osize;{ struct format_data val; register char *p = *string_ptr; val.format = '?'; val.size = '?'; val.count = 1; if (*p >= '0' && *p <= '9') val.count = atoi (p); while (*p >= '0' && *p <= '9') p++; /* Now process size or format letters that follow. */ while (1) { if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') val.size = *p++;#ifdef LONG_LONG else if (*p == 'l') { val.size = 'g'; p++; }#endif else if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')) val.format = *p++; else break; }#ifndef LONG_LONG /* Make sure 'g' size is not used on integer types. Well, actually, we can handle hex. */ if (val.size == 'g' && val.format != 'f' && val.format != 'x') val.size = 'w';#endif while (*p == ' ' || *p == '\t') p++; *string_ptr = p; /* Set defaults for format and size if not specified. */ if (val.format == '?') { if (val.size == '?') { /* Neither has been specified. */ val.format = oformat; val.size = osize; } else /* If a size is specified, any format makes a reasonable default except 'i'. */ val.format = oformat == 'i' ? 'x' : oformat; } else if (val.size == '?') switch (val.format) { case 'a': case 's': case 'A': /* Addresses must be words. */ val.size = osize ? 'w' : osize; break; case 'f': /* Floating point has to be word or giantword. */ if (osize == 'w' || osize == 'g') val.size = osize; else /* Default it to giantword if the last used size is not appropriate. */ val.size = osize ? 'g' : osize; break; case 'c': /* Characters default to one byte. */ val.size = osize ? 'b' : osize; break; default: /* The default is the size most recently specified. */ val.size = osize; } return val;}/* Print value VAL on stdout according to FORMAT, a letter or 0. Do not end with a newline. 0 means print VAL according to its own type. SIZE is the letter for the size of datum being printed. This is used to pad hex numbers so they line up. */static voidprint_formatted (val, format, size) register value val; register int format; int size;{ int len = TYPE_LENGTH (VALUE_TYPE (val)); if (VALUE_LVAL (val) == lval_memory) next_address = VALUE_ADDRESS (val) + len; switch (format) { case 's': next_address = VALUE_ADDRESS (val) + value_print (value_addr (val), stdout, format, Val_pretty_default); break; case 'i': wrap_here (""); /* Force output out, print_insn not using _filtered */ next_address = VALUE_ADDRESS (val) + print_insn (VALUE_ADDRESS (val), stdout); break; default: if (format == 0 || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION || VALUE_REPEATED (val)) value_print (val, stdout, format, Val_pretty_default); else print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), format, size, stdout); }}/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, according to letters FORMAT and SIZE on STREAM. FORMAT may not be zero. Formats s and i are not supported at this level. This is how the elements of an array or structure are printed with a format. */voidprint_scalar_formatted (valaddr, type, format, size, stream) char *valaddr; struct type *type; int format; int size; FILE *stream;{ LONGEST val_long; int len = TYPE_LENGTH (type); /* If no size is specified, try to guess a reasonable one from the type. */ if (size == 0 && len <= 4) { /* XXX This array is machine dependent. (FIXME) */ static unsigned char sizetab[] = { 0, 'b', 'h', 0, 'w' }; size = sizetab[len]; } if (size == 'g' && sizeof (LONGEST) < 8 && format == 'x') { /* ok, we're going to have to get fancy here. Assumption: a long is four bytes. FIXME. */ unsigned long v1, v2; v1 = unpack_long (builtin_type_long, valaddr); v2 = unpack_long (builtin_type_long, valaddr + 4);#if TARGET_BYTE_ORDER == LITTLE_ENDIAN /* Swap the two for printing */ { unsigned long tmp; tmp = v1; v1 = v2; v2 = tmp; }#endif switch (format) { case 'x': fprintf_filtered (stream, local_hex_format_custom("08x%08"), v1, v2); break; default: error ("Output size \"g\" unimplemented for format \"%c\".", format); } return; } val_long = unpack_long (type, valaddr); /* If value is unsigned, truncate it in case negative. */ if (format != 'd') { if (len == sizeof (char)) val_long &= (1 << 8 * sizeof(char)) - 1; else if (len == sizeof (short)) val_long &= (1 << 8 * sizeof(short)) - 1; else if (len == sizeof (long)) val_long &= (unsigned long) - 1; } switch (format) { case 'x': if (!size) { /* no size specified, like in print. Print varying # of digits. */#if defined (LONG_LONG) fprintf_filtered (stream, local_hex_format_custom("ll"), val_long);#else /* not LONG_LONG. */ fprintf_filtered (stream, local_hex_format_custom("l"), val_long);#endif /* not LONG_LONG. */ } else#if defined (LONG_LONG) switch (size) { case 'b': fprintf_filtered (stream, local_hex_format_custom("02ll"), val_long); break; case 'h': fprintf_filtered (stream, local_hex_format_custom("04ll"), val_long); break; case 'w': fprintf_filtered (stream, local_hex_format_custom("08ll"), val_long); break; case 'g': fprintf_filtered (stream, local_hex_format_custom("016ll"), val_long); break; default: error ("Undefined output size \"%c\".", size); }#else /* not LONG_LONG. */ switch (size) { case 'b': fprintf_filtered (stream, local_hex_format_custom("02"), val_long); break; case 'h': fprintf_filtered (stream, local_hex_format_custom("04"), val_long); break; case 'w': fprintf_filtered (stream, local_hex_format_custom("08"), val_long); break; case 'g': fprintf_filtered (stream, local_hex_format_custom("016"), val_long); break; default: error ("Undefined output size \"%c\".", size); }#endif /* not LONG_LONG */ break; case 'd':#ifdef LONG_LONG fprintf_filtered (stream, "%lld", val_long);#else fprintf_filtered (stream, "%d", val_long);#endif break; case 'u':#ifdef LONG_LONG fprintf_filtered (stream, "%llu", val_long);#else fprintf_filtered (stream, "%u", val_long);#endif break; case 'o': if (val_long)#ifdef LONG_LONG fprintf_filtered (stream, local_octal_format_custom("ll"), val_long);#else fprintf_filtered (stream, local_octal_format(), val_long);#endif else fprintf_filtered (stream, "0"); break; case 'a': print_address (unpack_pointer (type, valaddr), stream); break; case 'A': print_address_symbolic (unpack_pointer (type, valaddr), stream, asm_demangle, " "); break; case 'c': value_print (value_from_longest (builtin_type_char, val_long), stream, 0, Val_pretty_default); break; case 'f': if (len == sizeof (float)) type = builtin_type_float; else if (len == sizeof (double)) type = builtin_type_double; print_floating (valaddr, type, stream); break; case 0: abort (); case 't': /* Binary; 't' stands for "two". */ { char bits[8*(sizeof val_long) + 1]; char *cp = bits; int width; if (!size) width = 8*(sizeof val_long); else switch (size) { case 'b': width = 8; break; case 'h': width = 16; break; case 'w': width = 32; break; case 'g': width = 64; break; default: error ("Undefined output size \"%c\".", size); } bits[width] = '\0'; while (width-- > 0) { bits[width] = (val_long & 1) ? '1' : '0'; val_long >>= 1; } if (!size) { while (*cp && *cp == '0') cp++; if (*cp == '\0') cp--; } fprintf_filtered (stream, cp); } break; default: error ("Undefined output format \"%c\".", format); }}/* Specify default address for `x' command. `info lines' uses this. */voidset_next_address (addr) CORE_ADDR addr;{ next_address = addr; /* Make address available to the user as $_. */ set_internalvar (lookup_internalvar ("_"), value_from_longest (lookup_pointer_type (builtin_type_void),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -