X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprintcmd.c;h=10d3c230ee6d680f9e17a6e72ec8668bccf1f65e;hb=9f1b45b0da430a7a7abf9e54acbe6f2ef9d3a763;hp=5268b1da19c19df601b6120dfe2887bf83654085;hpb=36dc683c524086a6ed9b74375d6501a33e875182;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 5268b1da19..10d3c230ee 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1,8 +1,6 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +18,7 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" +#include #include "frame.h" #include "symtab.h" #include "gdbtypes.h" @@ -32,6 +30,7 @@ #include "target.h" #include "breakpoint.h" #include "demangle.h" +#include "gdb-demangle.h" #include "valprint.h" #include "annotate.h" #include "symfile.h" /* for overlay functions */ @@ -42,43 +41,42 @@ #include "block.h" #include "disasm.h" #include "dfp.h" -#include "valprint.h" #include "exceptions.h" #include "observer.h" #include "solist.h" -#include "solib.h" #include "parser-defs.h" +#include "charset.h" +#include "arch-utils.h" +#include "cli/cli-utils.h" +#include "format.h" +#include "source.h" #ifdef TUI -#include "tui/tui.h" /* For tui_active et.al. */ -#endif - -#if defined(__MINGW32__) && !defined(PRINTF_HAS_LONG_LONG) -# define USE_PRINTF_I64 1 -# define PRINTF_HAS_LONG_LONG -#else -# define USE_PRINTF_I64 0 +#include "tui/tui.h" /* For tui_active et al. */ #endif -extern int asm_demangle; /* Whether to demangle syms in asm printouts */ - struct format_data { int count; char format; char size; + + /* True if the value should be printed raw -- that is, bypassing + python-based formatters. */ + unsigned char raw; }; /* Last specified output format. */ -static char last_format = 'x'; +static char last_format = 0; /* Last specified examination size. 'b', 'h', 'w' or `q'. */ static char last_size = 'w'; -/* Default address to examine next. */ +/* Default address to examine next, and associated architecture. */ +static struct gdbarch *next_gdbarch; static CORE_ADDR next_address; /* Number of delay instructions following current disassembled insn. */ @@ -102,8 +100,9 @@ static void show_max_symbolic_offset (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -The largest offset that will be printed in form is %s.\n"), + fprintf_filtered (file, + _("The largest offset that will be " + "printed in form is %s.\n"), value); } @@ -114,32 +113,41 @@ static void show_print_symbol_filename (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("\ -Printing of source filename and line number with is %s.\n"), + fprintf_filtered (file, _("Printing of source filename and " + "line number with is %s.\n"), value); } /* Number of auto-display expression currently being displayed. - So that we can disable it if we get an error or a signal within it. + So that we can disable it if we get a signal within it. -1 when not doing one. */ -int current_display_number; +static int current_display_number; struct display { /* Chain link to next auto-display item. */ struct display *next; + /* The expression as the user typed it. */ char *exp_string; + /* 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) */ + + /* Program space associated with `block'. */ + struct program_space *pspace; + + /* Innermost block required by this expression when evaluated. */ + const struct block *block; + + /* Status of this display (enabled or disabled). */ int enabled_p; }; @@ -150,13 +158,23 @@ static struct display *display_chain; static int display_number; -/* Prototypes for exported functions. */ +/* Walk the following statement or block through all displays. + ALL_DISPLAYS_SAFE does so even if the statement deletes the current + display. */ -void output_command (char *, int); +#define ALL_DISPLAYS(B) \ + for (B = display_chain; B; B = B->next) + +#define ALL_DISPLAYS_SAFE(B,TMP) \ + for (B = display_chain; \ + B ? (TMP = B->next, 1): 0; \ + B = TMP) + +/* Prototypes for exported functions. */ void _initialize_printcmd (void); -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ static void do_one_display (struct display *); @@ -172,14 +190,15 @@ static void do_one_display (struct display *); past the specification and past all whitespace following it. */ static struct format_data -decode_format (char **string_ptr, int oformat, int osize) +decode_format (const char **string_ptr, int oformat, int osize) { struct format_data val; - char *p = *string_ptr; + const char *p = *string_ptr; val.format = '?'; val.size = '?'; val.count = 1; + val.raw = 0; if (*p >= '0' && *p <= '9') val.count = atoi (p); @@ -192,6 +211,11 @@ decode_format (char **string_ptr, int oformat, int osize) { if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') val.size = *p++; + else if (*p == 'r') + { + val.raw = 1; + p++; + } else if (*p >= 'a' && *p <= 'z') val.format = *p++; else @@ -220,18 +244,10 @@ decode_format (char **string_ptr, int oformat, int osize) switch (val.format) { case 'a': - case 's': - /* Pick the appropriate size for an address. */ - if (gdbarch_ptr_bit (current_gdbarch) == 64) - val.size = osize ? 'g' : osize; - else if (gdbarch_ptr_bit (current_gdbarch) == 32) - val.size = osize ? 'w' : osize; - else if (gdbarch_ptr_bit (current_gdbarch) == 16) - val.size = osize ? 'h' : osize; - else - /* Bad value for gdbarch_ptr_bit. */ - internal_error (__FILE__, __LINE__, - _("failed internal consistency check")); + /* Pick the appropriate size for an address. This is deferred + until do_examine when we know the actual architecture to use. + A special size value of 'a' is used to indicate this case. */ + val.size = osize ? 'a' : osize; break; case 'f': /* Floating point has to be word or giantword. */ @@ -246,6 +262,12 @@ decode_format (char **string_ptr, int oformat, int osize) /* Characters default to one byte. */ val.size = osize ? 'b' : osize; break; + case 's': + /* Display strings with byte size chars unless explicitly + specified. */ + val.size = '\0'; + break; + default: /* The default is the size most recently specified. */ val.size = osize; @@ -269,24 +291,29 @@ print_formatted (struct value *val, int size, int len = TYPE_LENGTH (type); if (VALUE_LVAL (val) == lval_memory) - next_address = VALUE_ADDRESS (val) + len; + next_address = value_address (val) + len; if (size) { switch (options->format) { case 's': - /* FIXME: Need to handle wchar_t's here... */ - next_address = VALUE_ADDRESS (val) - + val_print_string (VALUE_ADDRESS (val), -1, 1, stream, - options); + { + struct type *elttype = value_type (val); + + next_address = (value_address (val) + + val_print_string (elttype, NULL, + value_address (val), -1, + stream, options) * len); + } return; case 'i': /* We often wrap here if there are long symbolic names. */ wrap_here (" "); - next_address = (VALUE_ADDRESS (val) - + gdb_print_insn (VALUE_ADDRESS (val), stream, + next_address = (value_address (val) + + gdb_print_insn (get_type_arch (type), + value_address (val), stream, &branch_delay_insns)); return; } @@ -301,58 +328,49 @@ print_formatted (struct value *val, int size, || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) value_print (val, stream, options); else - /* User specified format, so don't look to the the type to - tell us what to do. */ - print_scalar_formatted (value_contents (val), type, - options, size, stream); + /* User specified format, so don't look to the type to tell us + what to do. */ + val_print_scalar_formatted (type, + value_contents_for_printing (val), + value_embedded_offset (val), + val, + options, size, stream); } /* Return builtin floating point type of same length as TYPE. If no such type is found, return TYPE itself. */ static struct type * -float_type_from_length (struct gdbarch *gdbarch, struct type *type) +float_type_from_length (struct type *type) { + struct gdbarch *gdbarch = get_type_arch (type); const struct builtin_type *builtin = builtin_type (gdbarch); - unsigned int len = TYPE_LENGTH (type); - if (len == TYPE_LENGTH (builtin->builtin_float)) + if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_float)) type = builtin->builtin_float; - else if (len == TYPE_LENGTH (builtin->builtin_double)) + else if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_double)) type = builtin->builtin_double; - else if (len == TYPE_LENGTH (builtin->builtin_long_double)) + else if (TYPE_LENGTH (type) == TYPE_LENGTH (builtin->builtin_long_double)) type = builtin->builtin_long_double; return type; } /* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, - according to OPTIONS and SIZE on STREAM. - 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. */ + according to OPTIONS and SIZE on STREAM. Formats s and i are not + supported at this level. */ void print_scalar_formatted (const void *valaddr, struct type *type, const struct value_print_options *options, int size, struct ui_file *stream) { + struct gdbarch *gdbarch = get_type_arch (type); LONGEST val_long = 0; unsigned int len = TYPE_LENGTH (type); - enum bfd_endian byte_order = gdbarch_byte_order (current_gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - /* If we get here with a string format, try again without it. Go - all the way back to the language printers, which may call us - again. */ - if (options->format == 's') - { - struct value_print_options opts = *options; - opts.format = 0; - opts.deref_ref = 0; - val_print (type, valaddr, 0, 0, stream, 0, &opts, - current_language); - return; - } + /* String printing should go through val_print_scalar_formatted. */ + gdb_assert (options->format != 's'); if (len > sizeof(LONGEST) && (TYPE_CODE (type) == TYPE_CODE_INT @@ -374,7 +392,7 @@ print_scalar_formatted (const void *valaddr, struct type *type, print_hex_chars (stream, valaddr, len, byte_order); return; case 'c': - print_char_chars (stream, valaddr, len, byte_order); + print_char_chars (stream, type, valaddr, len, byte_order); return; default: break; @@ -388,12 +406,12 @@ print_scalar_formatted (const void *valaddr, struct type *type, same, then at this point, the value's length (in target bytes) is gdbarch_addr_bit/TARGET_CHAR_BIT, not TYPE_LENGTH (type). */ if (TYPE_CODE (type) == TYPE_CODE_PTR) - len = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT; + len = gdbarch_addr_bit (gdbarch) / TARGET_CHAR_BIT; /* If we are printing it as unsigned, truncate it in case it is actually a negative signed value (e.g. "print/u (short)-1" should print 65535 (if shorts are 16 bits) instead of 4294967295). */ - if (options->format != 'd') + if (options->format != 'd' || TYPE_UNSIGNED (type)) { if (len < sizeof (LONGEST)) val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1; @@ -439,26 +457,27 @@ print_scalar_formatted (const void *valaddr, struct type *type, case 'a': { CORE_ADDR addr = unpack_pointer (type, valaddr); - print_address (addr, stream); + + print_address (gdbarch, addr, stream); } break; case 'c': { struct value_print_options opts = *options; + opts.format = 0; if (TYPE_UNSIGNED (type)) - value_print (value_from_longest (builtin_type_true_unsigned_char, - val_long), - stream, &opts); - else - value_print (value_from_longest (builtin_type_true_char, val_long), - stream, &opts); + type = builtin_type (gdbarch)->builtin_true_unsigned_char; + else + type = builtin_type (gdbarch)->builtin_true_char; + + value_print (value_from_longest (type, val_long), stream, &opts); } break; case 'f': - type = float_type_from_length (current_gdbarch, type); + type = float_type_from_length (type); print_floating (valaddr, type, stream); break; @@ -508,11 +527,15 @@ print_scalar_formatted (const void *valaddr, struct type *type, if (*cp == '\0') cp--; } - strcpy (buf, cp); + strncpy (buf, cp, sizeof (bits)); fputs_filtered (buf, stream); } break; + case 'z': + print_hex_chars (stream, valaddr, len, byte_order); + break; + default: error (_("Undefined output format \"%c\"."), options->format); } @@ -526,6 +549,7 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr) { struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + next_gdbarch = gdbarch; next_address = addr; /* Make address available to the user as $_. */ @@ -539,10 +563,12 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr) DO_DEMANGLE controls whether to print a symbol in its native "raw" form, or to interpret it as a possible C++ name and convert it back to source form. However note that DO_DEMANGLE can be overridden by the specific - settings of the demangle and asm_demangle variables. */ + settings of the demangle and asm_demangle variables. Returns + non-zero if anything was printed; zero otherwise. */ -void -print_address_symbolic (CORE_ADDR addr, struct ui_file *stream, +int +print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, + struct ui_file *stream, int do_demangle, char *leadin) { char *name = NULL; @@ -555,11 +581,11 @@ print_address_symbolic (CORE_ADDR addr, struct ui_file *stream, struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &name); make_cleanup (free_current_contents, &filename); - if (build_address_symbolic (addr, do_demangle, &name, &offset, + if (build_address_symbolic (gdbarch, addr, do_demangle, &name, &offset, &filename, &line, &unmapped)) { do_cleanups (cleanup_chain); - return; + return 0; } fputs_filtered (leadin, stream); @@ -586,16 +612,18 @@ print_address_symbolic (CORE_ADDR addr, struct ui_file *stream, fputs_filtered (">", stream); do_cleanups (cleanup_chain); + return 1; } /* Given an address ADDR return all the elements needed to print the - address in a symbolic form. NAME can be mangled or not depending + address in a symbolic form. NAME can be mangled or not depending on DO_DEMANGLE (and also on the asm_demangle global variable, - manipulated via ''set print asm-demangle''). Return 0 in case of - success, when all the info in the OUT paramters is valid. Return 1 - otherwise. */ + manipulated via ''set print asm-demangle''). Return 0 in case of + success, when all the info in the OUT paramters is valid. Return 1 + otherwise. */ int -build_address_symbolic (CORE_ADDR addr, /* IN */ +build_address_symbolic (struct gdbarch *gdbarch, + CORE_ADDR addr, /* IN */ int do_demangle, /* IN */ char **name, /* OUT */ int *offset, /* OUT */ @@ -607,7 +635,7 @@ build_address_symbolic (CORE_ADDR addr, /* IN */ struct symbol *symbol; CORE_ADDR name_location = 0; struct obj_section *section = NULL; - char *name_temp = ""; + const char *name_temp = ""; /* Let's say it is mapped (not unmapped). */ *unmapped = 0; @@ -633,11 +661,18 @@ build_address_symbolic (CORE_ADDR addr, /* IN */ save some memory, but for many debug format--ELF/DWARF or anything/stabs--it would be inconvenient to eliminate those minimal symbols anyway). */ - msymbol = lookup_minimal_symbol_by_pc_section (addr, section); + msymbol = lookup_minimal_symbol_by_pc_section (addr, section).minsym; symbol = find_pc_sect_function (addr, section); if (symbol) { + /* If this is a function (i.e. a code address), strip out any + non-address bits. For instance, display a pointer to the + first instruction of a Thumb function as ; the + second instruction will be , even though the + pointer is . This matches the ISA behavior. */ + addr = gdbarch_addr_bits_remove (gdbarch, addr); + name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)); if (do_demangle || asm_demangle) name_temp = SYMBOL_PRINT_NAME (symbol); @@ -645,10 +680,29 @@ build_address_symbolic (CORE_ADDR addr, /* IN */ name_temp = SYMBOL_LINKAGE_NAME (symbol); } + if (msymbol != NULL + && MSYMBOL_HAS_SIZE (msymbol) + && MSYMBOL_SIZE (msymbol) == 0 + && MSYMBOL_TYPE (msymbol) != mst_text + && MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc + && MSYMBOL_TYPE (msymbol) != mst_file_text) + msymbol = NULL; + if (msymbol != NULL) { if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL) { + /* If this is a function (i.e. a code address), strip out any + non-address bits. For instance, display a pointer to the + first instruction of a Thumb function as ; the + second instruction will be , even though the + pointer is . This matches the ISA behavior. */ + if (MSYMBOL_TYPE (msymbol) == mst_text + || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc + || MSYMBOL_TYPE (msymbol) == mst_file_text + || MSYMBOL_TYPE (msymbol) == mst_solib_trampoline) + addr = gdbarch_addr_bits_remove (gdbarch, addr); + /* The msymbol is closer to the address than the symbol; use the msymbol instead. */ symbol = 0; @@ -685,7 +739,7 @@ build_address_symbolic (CORE_ADDR addr, /* IN */ if (sal.symtab) { - *filename = xstrdup (sal.symtab->filename); + *filename = xstrdup (symtab_to_filename_for_display (sal.symtab)); *line = sal.line; } } @@ -698,54 +752,58 @@ build_address_symbolic (CORE_ADDR addr, /* IN */ after the number. */ void -print_address (CORE_ADDR addr, struct ui_file *stream) +print_address (struct gdbarch *gdbarch, + CORE_ADDR addr, struct ui_file *stream) { - fputs_filtered (paddress (addr), stream); - print_address_symbolic (addr, stream, asm_demangle, " "); + fputs_filtered (paddress (gdbarch, addr), stream); + print_address_symbolic (gdbarch, addr, stream, asm_demangle, " "); } -/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE - controls whether to print the symbolic name "raw" or demangled. - Global setting "addressprint" controls whether to print hex address - or not. */ +/* Return a prefix for instruction address: + "=> " for current instruction, else " ". */ -void -print_address_demangle (CORE_ADDR addr, struct ui_file *stream, - int do_demangle) +const char * +pc_prefix (CORE_ADDR addr) { - struct value_print_options opts; - get_user_print_options (&opts); - if (addr == 0) + if (has_stack_frames ()) { - fprintf_filtered (stream, "0"); + struct frame_info *frame; + CORE_ADDR pc; + + frame = get_selected_frame (NULL); + if (get_frame_pc_if_available (frame, &pc) && pc == addr) + return "=> "; } - else if (opts.addressprint) + return " "; +} + +/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE + controls whether to print the symbolic name "raw" or demangled. + Return non-zero if anything was printed; zero otherwise. */ + +int +print_address_demangle (const struct value_print_options *opts, + struct gdbarch *gdbarch, CORE_ADDR addr, + struct ui_file *stream, int do_demangle) +{ + if (opts->addressprint) { - fputs_filtered (paddress (addr), stream); - print_address_symbolic (addr, stream, do_demangle, " "); + fputs_filtered (paddress (gdbarch, addr), stream); + print_address_symbolic (gdbarch, addr, stream, do_demangle, " "); } else { - print_address_symbolic (addr, stream, do_demangle, ""); + return print_address_symbolic (gdbarch, addr, stream, do_demangle, ""); } + return 1; } -/* These are the types that $__ will get after an examine command of one - of these sizes. */ - -static struct type *examine_i_type; - -static struct type *examine_b_type; -static struct type *examine_h_type; -static struct type *examine_w_type; -static struct type *examine_g_type; - /* Examine data at address ADDR in format FMT. Fetch it from memory and print on gdb_stdout. */ static void -do_examine (struct format_data fmt, CORE_ADDR addr) +do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) { char format = 0; char size; @@ -758,23 +816,61 @@ do_examine (struct format_data fmt, CORE_ADDR addr) format = fmt.format; size = fmt.size; count = fmt.count; + next_gdbarch = gdbarch; next_address = addr; - /* String or instruction format implies fetch single bytes - regardless of the specified size. */ - if (format == 's' || format == 'i') + /* Instruction format implies fetch single bytes + regardless of the specified size. + The case of strings is handled in decode_format, only explicit + size operator are not changed to 'b'. */ + if (format == 'i') size = 'b'; - if (format == 'i') - val_type = examine_i_type; - else if (size == 'b') - val_type = examine_b_type; + if (size == 'a') + { + /* Pick the appropriate size for an address. */ + if (gdbarch_ptr_bit (next_gdbarch) == 64) + size = 'g'; + else if (gdbarch_ptr_bit (next_gdbarch) == 32) + size = 'w'; + else if (gdbarch_ptr_bit (next_gdbarch) == 16) + size = 'h'; + else + /* Bad value for gdbarch_ptr_bit. */ + internal_error (__FILE__, __LINE__, + _("failed internal consistency check")); + } + + if (size == 'b') + val_type = builtin_type (next_gdbarch)->builtin_int8; else if (size == 'h') - val_type = examine_h_type; + val_type = builtin_type (next_gdbarch)->builtin_int16; else if (size == 'w') - val_type = examine_w_type; + val_type = builtin_type (next_gdbarch)->builtin_int32; else if (size == 'g') - val_type = examine_g_type; + val_type = builtin_type (next_gdbarch)->builtin_int64; + + if (format == 's') + { + struct type *char_type = NULL; + + /* Search for "char16_t" or "char32_t" types or fall back to 8-bit char + if type is not found. */ + if (size == 'h') + char_type = builtin_type (next_gdbarch)->builtin_char16; + else if (size == 'w') + char_type = builtin_type (next_gdbarch)->builtin_char32; + if (char_type) + val_type = char_type; + else + { + if (size != '\0' && size != 'b') + warning (_("Unable to display strings with " + "size '%c', using 'b' instead."), size); + size = 'b'; + val_type = builtin_type (next_gdbarch)->builtin_int8; + } + } maxelts = 8; if (size == 'w') @@ -792,7 +888,9 @@ do_examine (struct format_data fmt, CORE_ADDR addr) while (count > 0) { QUIT; - print_address (next_address, gdb_stdout); + if (format == 'i') + fputs_filtered (pc_prefix (next_address), gdb_stdout); + print_address (next_gdbarch, next_address, gdb_stdout); printf_filtered (":"); for (i = maxelts; i > 0 && count > 0; @@ -814,7 +912,7 @@ do_examine (struct format_data fmt, CORE_ADDR addr) the address stored in LAST_EXAMINE_VALUE. FIXME: Should the disassembler be modified so that LAST_EXAMINE_VALUE is left with the byte sequence from the last complete - instruction fetched from memory? */ + instruction fetched from memory? */ last_examine_value = value_at_lazy (val_type, next_address); if (last_examine_value) @@ -849,14 +947,13 @@ validate_format (struct format_data fmt, char *cmdname) first argument ("/x myvar" for example, to print myvar in hex). */ static void -print_command_1 (char *exp, int inspect, int voidprint) +print_command_1 (const char *exp, int voidprint) { struct expression *expr; - struct cleanup *old_chain = 0; + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); char format = 0; struct value *val; struct format_data fmt; - int cleanup = 0; if (exp && *exp == '/') { @@ -870,14 +967,13 @@ print_command_1 (char *exp, int inspect, int voidprint) fmt.count = 1; fmt.format = 0; fmt.size = 0; + fmt.raw = 0; } if (exp && *exp) { - struct type *type; expr = parse_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - cleanup = 1; + make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); } else @@ -894,17 +990,14 @@ print_command_1 (char *exp, int inspect, int voidprint) else annotate_value_begin (value_type (val)); - if (inspect) - printf_unfiltered ("\031(gdb-makebuffer \"%s\" %d '(\"", - exp, histindex); - else if (histindex >= 0) + if (histindex >= 0) printf_filtered ("$%d = ", histindex); if (histindex >= 0) annotate_value_history_value (); get_formatted_print_options (&opts, format); - opts.inspect_it = inspect; + opts.raw = fmt.raw; print_formatted (val, fmt.size, &opts, gdb_stdout); printf_filtered ("\n"); @@ -913,39 +1006,36 @@ print_command_1 (char *exp, int inspect, int voidprint) annotate_value_history_end (); else annotate_value_end (); - - if (inspect) - printf_unfiltered ("\") )\030"); } - if (cleanup) - do_cleanups (old_chain); + do_cleanups (old_chain); } static void print_command (char *exp, int from_tty) { - print_command_1 (exp, 0, 1); + print_command_1 (exp, 1); } -/* Same as print, except in epoch, it gets its own window. */ +/* Same as print, except it doesn't print void results. */ static void -inspect_command (char *exp, int from_tty) +call_command (char *exp, int from_tty) { - extern int epoch_interface; - - print_command_1 (exp, epoch_interface, 1); + print_command_1 (exp, 0); } -/* Same as print, except it doesn't print void results. */ +/* Implementation of the "output" command. */ + static void -call_command (char *exp, int from_tty) +output_command (char *exp, int from_tty) { - print_command_1 (exp, 0, 0); + output_command_const (exp, from_tty); } +/* Like output_command, but takes a const string as argument. */ + void -output_command (char *exp, int from_tty) +output_command_const (const char *exp, int from_tty) { struct expression *expr; struct cleanup *old_chain; @@ -955,6 +1045,7 @@ output_command (char *exp, int from_tty) struct value_print_options opts; fmt.size = 0; + fmt.raw = 0; if (exp && *exp == '/') { @@ -972,6 +1063,7 @@ output_command (char *exp, int from_tty) annotate_value_begin (value_type (val)); get_formatted_print_options (&opts, format); + opts.raw = fmt.raw; print_formatted (val, fmt.size, &opts, gdb_stdout); annotate_value_end (); @@ -988,6 +1080,23 @@ set_command (char *exp, int from_tty) struct expression *expr = parse_expression (exp); struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); + + if (expr->nelts >= 1) + switch (expr->elts[0].opcode) + { + case UNOP_PREINCREMENT: + case UNOP_POSTINCREMENT: + case UNOP_PREDECREMENT: + case UNOP_POSTDECREMENT: + case BINOP_ASSIGN: + case BINOP_ASSIGN_MODIFY: + case BINOP_COMMA: + break; + default: + warning + (_("Expression is not an assignment (and might have no effect)")); + } + evaluate_expression (expr); do_cleanups (old_chain); } @@ -1017,7 +1126,8 @@ sym_info (char *arg, int from_tty) if (obj_section_addr (osect) <= sect_addr && sect_addr < obj_section_endaddr (osect) - && (msymbol = lookup_minimal_symbol_by_pc_section (sect_addr, osect))) + && (msymbol + = lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym)) { const char *obj_name, *mapped, *sec_name, *msym_name; char *loc_string; @@ -1032,16 +1142,16 @@ sym_info (char *arg, int from_tty) /* Don't print the offset if it is zero. We assume there's no need to handle i18n of "sym + offset". */ if (offset) - xasprintf (&loc_string, "%s + %u", msym_name, offset); + loc_string = xstrprintf ("%s + %u", msym_name, offset); else - xasprintf (&loc_string, "%s", msym_name); + loc_string = xstrprintf ("%s", msym_name); /* Use a cleanup to free loc_string in case the user quits a pagination request inside printf_filtered. */ old_chain = make_cleanup (xfree, loc_string); - gdb_assert (osect->objfile && osect->objfile->name); - obj_name = osect->objfile->name; + gdb_assert (osect->objfile && objfile_name (osect->objfile)); + obj_name = objfile_name (osect->objfile); if (MULTI_OBJFILE_P ()) if (pc_in_unmapped_range (addr, osect)) @@ -1087,22 +1197,23 @@ sym_info (char *arg, int from_tty) static void address_info (char *exp, int from_tty) { + struct gdbarch *gdbarch; + int regno; struct symbol *sym; - struct minimal_symbol *msymbol; + struct bound_minimal_symbol msymbol; long val; struct obj_section *section; - CORE_ADDR load_addr; - int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero - if exp is a field of `this'. */ + CORE_ADDR load_addr, context_pc = 0; + struct field_of_this_result is_a_field_of_this; if (exp == 0) error (_("Argument required.")); - sym = lookup_symbol (exp, get_selected_block (0), VAR_DOMAIN, + sym = lookup_symbol (exp, get_selected_block (&context_pc), VAR_DOMAIN, &is_a_field_of_this); if (sym == NULL) { - if (is_a_field_of_this) + if (is_a_field_of_this.type != NULL) { printf_filtered ("Symbol \""); fprintf_symbol_filtered (gdb_stdout, exp, @@ -1115,24 +1226,27 @@ address_info (char *exp, int from_tty) return; } - msymbol = lookup_minimal_symbol (exp, NULL, NULL); + msymbol = lookup_bound_minimal_symbol (exp); - if (msymbol != NULL) + if (msymbol.minsym != NULL) { - load_addr = SYMBOL_VALUE_ADDRESS (msymbol); + struct objfile *objfile = msymbol.objfile; + + gdbarch = get_objfile_arch (objfile); + load_addr = SYMBOL_VALUE_ADDRESS (msymbol.minsym); printf_filtered ("Symbol \""); fprintf_symbol_filtered (gdb_stdout, exp, current_language->la_language, DMGL_ANSI); printf_filtered ("\" is at "); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (" in a file compiled without debugging"); - section = SYMBOL_OBJ_SECTION (msymbol); + section = SYMBOL_OBJ_SECTION (objfile, msymbol.minsym); if (section_is_overlay (section)) { load_addr = overlay_unmapped_address (load_addr, section); printf_filtered (",\n -- loaded at "); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (" in overlay section %s", section->the_bfd_section->name); } @@ -1148,7 +1262,16 @@ address_info (char *exp, int from_tty) current_language->la_language, DMGL_ANSI); printf_filtered ("\" is "); val = SYMBOL_VALUE (sym); - section = SYMBOL_OBJ_SECTION (sym); + section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym); + gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile); + + if (SYMBOL_COMPUTED_OPS (sym) != NULL) + { + SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, context_pc, + gdb_stdout); + printf_filtered (".\n"); + return; + } switch (SYMBOL_CLASS (sym)) { @@ -1159,53 +1282,57 @@ address_info (char *exp, int from_tty) case LOC_LABEL: printf_filtered ("a label at address "); - fputs_filtered (paddress (load_addr = SYMBOL_VALUE_ADDRESS (sym)), - gdb_stdout); + load_addr = SYMBOL_VALUE_ADDRESS (sym); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); if (section_is_overlay (section)) { load_addr = overlay_unmapped_address (load_addr, section); printf_filtered (",\n -- loaded at "); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (" in overlay section %s", section->the_bfd_section->name); } break; case LOC_COMPUTED: - /* FIXME: cagney/2004-01-26: It should be possible to - unconditionally call the SYMBOL_OPS method when available. - Unfortunately DWARF 2 stores the frame-base (instead of the - function) location in a function's symbol. Oops! For the - moment enable this when/where applicable. */ - SYMBOL_OPS (sym)->describe_location (sym, gdb_stdout); - break; + gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method")); case LOC_REGISTER: + /* GDBARCH is the architecture associated with the objfile the symbol + is defined in; the target architecture may be different, and may + provide additional registers. However, we do not know the target + architecture at this point. We assume the objfile architecture + will contain all the standard registers that occur in debug info + in that objfile. */ + regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); + if (SYMBOL_IS_ARGUMENT (sym)) printf_filtered (_("an argument in register %s"), - gdbarch_register_name (current_gdbarch, val)); + gdbarch_register_name (gdbarch, regno)); else printf_filtered (_("a variable in register %s"), - gdbarch_register_name (current_gdbarch, val)); + gdbarch_register_name (gdbarch, regno)); break; case LOC_STATIC: printf_filtered (_("static storage at address ")); - fputs_filtered (paddress (load_addr = SYMBOL_VALUE_ADDRESS (sym)), - gdb_stdout); + load_addr = SYMBOL_VALUE_ADDRESS (sym); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); if (section_is_overlay (section)) { load_addr = overlay_unmapped_address (load_addr, section); printf_filtered (_(",\n -- loaded at ")); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (_(" in overlay section %s"), section->the_bfd_section->name); } break; case LOC_REGPARM_ADDR: + /* Note comment at LOC_REGISTER. */ + regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); printf_filtered (_("address of an argument in register %s"), - gdbarch_register_name (current_gdbarch, val)); + gdbarch_register_name (gdbarch, regno)); break; case LOC_ARG: @@ -1227,12 +1354,12 @@ address_info (char *exp, int from_tty) case LOC_BLOCK: printf_filtered (_("a function at address ")); load_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); if (section_is_overlay (section)) { load_addr = overlay_unmapped_address (load_addr, section); printf_filtered (_(",\n -- loaded at ")); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (_(" in overlay section %s"), section->the_bfd_section->name); } @@ -1240,30 +1367,31 @@ address_info (char *exp, int from_tty) case LOC_UNRESOLVED: { - struct minimal_symbol *msym; + struct bound_minimal_symbol msym; - msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym), NULL, NULL); - if (msym == NULL) + msym = lookup_minimal_symbol_and_objfile (SYMBOL_LINKAGE_NAME (sym)); + if (msym.minsym == NULL) printf_filtered ("unresolved"); else { - section = SYMBOL_OBJ_SECTION (msym); - load_addr = SYMBOL_VALUE_ADDRESS (msym); + section = SYMBOL_OBJ_SECTION (msym.objfile, msym.minsym); + load_addr = SYMBOL_VALUE_ADDRESS (msym.minsym); if (section && (section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0) printf_filtered (_("a thread-local variable at offset %s " "in the thread-local storage for `%s'"), - paddr_nz (load_addr), section->objfile->name); + paddress (gdbarch, load_addr), + objfile_name (section->objfile)); else { printf_filtered (_("static storage at address ")); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); if (section_is_overlay (section)) { load_addr = overlay_unmapped_address (load_addr, section); printf_filtered (_(",\n -- loaded at ")); - fputs_filtered (paddress (load_addr), gdb_stdout); + fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); printf_filtered (_(" in overlay section %s"), section->the_bfd_section->name); } @@ -1292,14 +1420,17 @@ x_command (char *exp, int from_tty) struct cleanup *old_chain; struct value *val; - fmt.format = last_format; + fmt.format = last_format ? last_format : 'x'; fmt.size = last_size; fmt.count = 1; + fmt.raw = 0; if (exp && *exp == '/') { - exp++; - fmt = decode_format (&exp, last_format, last_size); + const char *tmp = exp + 1; + + fmt = decode_format (&tmp, last_format, last_size); + exp = (char *) tmp; } /* If we have an expression, evaluate it and use it as the address. */ @@ -1315,26 +1446,34 @@ x_command (char *exp, int from_tty) old_chain = make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF) - val = value_ind (val); + val = coerce_ref (val); /* In rvalue contexts, such as this, functions are coerced into pointers to functions. This makes "x/i main" work. */ if (/* last_format == 'i' && */ TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC && VALUE_LVAL (val) == lval_memory) - next_address = VALUE_ADDRESS (val); + next_address = value_address (val); else next_address = value_as_address (val); + + next_gdbarch = expr->gdbarch; do_cleanups (old_chain); } - do_examine (fmt, next_address); + if (!next_gdbarch) + error_no_arg (_("starting display address")); + + do_examine (fmt, next_gdbarch, next_address); /* If the examine succeeds, we remember its size and format for next - time. */ - last_size = fmt.size; + time. Set last_size to 'b' for strings. */ + if (fmt.format == 's') + last_size = 'b'; + else + last_size = fmt.size; last_format = fmt.format; - /* Set a couple of internal variables if appropriate. */ + /* Set a couple of internal variables if appropriate. */ if (last_examine_value) { /* Make last address examined available to the user as $_. Use @@ -1350,8 +1489,7 @@ x_command (char *exp, int from_tty) then don't fetch it now; instead mark it by voiding the $__ variable. */ if (value_lazy (last_examine_value)) - set_internalvar (lookup_internalvar ("__"), - allocate_value (builtin_type_void)); + clear_internalvar (lookup_internalvar ("__")); else set_internalvar (lookup_internalvar ("__"), last_examine_value); } @@ -1362,12 +1500,13 @@ x_command (char *exp, int from_tty) Specify the expression. */ static void -display_command (char *exp, int from_tty) +display_command (char *arg, int from_tty) { struct format_data fmt; struct expression *expr; struct display *new; int display_it = 1; + const char *exp = arg; #if defined(TUI) /* NOTE: cagney/2003-02-13 The `tui_active' was previously @@ -1398,6 +1537,7 @@ display_command (char *exp, int from_tty) fmt.format = 0; fmt.size = 0; fmt.count = 0; + fmt.raw = 0; } innermost_block = NULL; @@ -1408,6 +1548,7 @@ display_command (char *exp, int from_tty) new->exp_string = xstrdup (exp); new->exp = expr; new->block = innermost_block; + new->pspace = current_program_space; new->next = display_chain; new->number = ++display_number; new->format = fmt; @@ -1444,89 +1585,123 @@ clear_displays (void) } } -/* Delete the auto-display number NUM. */ +/* Delete the auto-display DISPLAY. */ static void -delete_display (int num) +delete_display (struct display *display) { - struct display *d1, *d; + struct display *d; - if (!display_chain) - error (_("No display number %d."), num); + gdb_assert (display != NULL); - if (display_chain->number == num) - { - d1 = display_chain; - display_chain = d1->next; - free_display (d1); - } - else - for (d = display_chain;; d = d->next) + if (display_chain == display) + display_chain = display->next; + + ALL_DISPLAYS (d) + if (d->next == display) { - if (d->next == 0) - error (_("No display number %d."), num); - if (d->next->number == num) - { - d1 = d->next; - d->next = d1->next; - free_display (d1); - break; - } + d->next = display->next; + break; } + + free_display (display); } -/* Delete some values from the auto-display chain. - Specify the element numbers. */ +/* Call FUNCTION on each of the displays whose numbers are given in + ARGS. DATA is passed unmodified to FUNCTION. */ static void -undisplay_command (char *args, int from_tty) +map_display_numbers (char *args, + void (*function) (struct display *, + void *), + void *data) { - char *p = args; - char *p1; + struct get_number_or_range_state state; int num; - if (args == 0) + if (args == NULL) + error_no_arg (_("one or more display numbers")); + + init_number_or_range (&state, args); + + while (!state.finished) { - if (query (_("Delete all auto-display expressions? "))) - clear_displays (); - dont_repeat (); - return; + char *p = state.string; + + num = get_number_or_range (&state); + if (num == 0) + warning (_("bad display number at or near '%s'"), p); + else + { + struct display *d, *tmp; + + ALL_DISPLAYS_SAFE (d, tmp) + if (d->number == num) + break; + if (d == NULL) + printf_unfiltered (_("No display number %d.\n"), num); + else + function (d, data); + } } +} - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); +/* Callback for map_display_numbers, that deletes a display. */ - num = atoi (p); +static void +do_delete_display (struct display *d, void *data) +{ + delete_display (d); +} - delete_display (num); +/* "undisplay" command. */ - p = p1; - while (*p == ' ' || *p == '\t') - p++; +static void +undisplay_command (char *args, int from_tty) +{ + if (args == NULL) + { + if (query (_("Delete all auto-display expressions? "))) + clear_displays (); + dont_repeat (); + return; } + + map_display_numbers (args, do_delete_display, NULL); dont_repeat (); } /* Display a single auto-display. Do nothing if the display cannot be printed in the current context, - or if the display is disabled. */ + or if the display is disabled. */ static void do_one_display (struct display *d) { + struct cleanup *old_chain; int within_current_scope; if (d->enabled_p == 0) return; + /* The expression carries the architecture that was used at parse time. + This is a problem if the expression depends on architecture features + (e.g. register numbers), and the current architecture is now different. + For example, a display statement like "display/i $pc" is expected to + display the PC register of the current architecture, not the arch at + the time the display command was given. Therefore, we re-parse the + expression if the current architecture has changed. */ + if (d->exp != NULL && d->exp->gdbarch != get_current_arch ()) + { + xfree (d->exp); + d->exp = NULL; + d->block = NULL; + } + if (d->exp == NULL) { volatile struct gdb_exception ex; + TRY_CATCH (ex, RETURN_MASK_ALL) { innermost_block = NULL; @@ -1544,12 +1719,18 @@ do_one_display (struct display *d) } if (d->block) - within_current_scope = contained_in (get_selected_block (0), d->block); + { + if (d->pspace == current_program_space) + within_current_scope = contained_in (get_selected_block (0), d->block); + else + within_current_scope = 0; + } else within_current_scope = 1; if (!within_current_scope) return; + old_chain = make_cleanup_restore_integer (¤t_display_number); current_display_number = d->number; annotate_display_begin (); @@ -1558,8 +1739,7 @@ do_one_display (struct display *d) printf_filtered (": "); if (d->format.size) { - CORE_ADDR addr; - struct value *val; + volatile struct gdb_exception ex; annotate_display_format (); @@ -1581,18 +1761,26 @@ do_one_display (struct display *d) else printf_filtered (" "); - val = evaluate_expression (d->exp); - addr = value_as_address (val); - if (d->format.format == 'i') - addr = gdbarch_addr_bits_remove (current_gdbarch, addr); - annotate_display_value (); - do_examine (d->format, addr); + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + struct value *val; + CORE_ADDR addr; + + val = evaluate_expression (d->exp); + addr = value_as_address (val); + if (d->format.format == 'i') + addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr); + do_examine (d->format, d->exp->gdbarch, addr); + } + if (ex.reason < 0) + fprintf_filtered (gdb_stdout, _("\n"), ex.message); } else { struct value_print_options opts; + volatile struct gdb_exception ex; annotate_display_format (); @@ -1609,15 +1797,24 @@ do_one_display (struct display *d) annotate_display_expression (); get_formatted_print_options (&opts, d->format.format); - print_formatted (evaluate_expression (d->exp), - d->format.size, &opts, gdb_stdout); + opts.raw = d->format.raw; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + struct value *val; + + val = evaluate_expression (d->exp); + print_formatted (val, d->format.size, &opts, gdb_stdout); + } + if (ex.reason < 0) + fprintf_filtered (gdb_stdout, _(""), ex.message); printf_filtered ("\n"); } annotate_display_end (); gdb_flush (gdb_stdout); - current_display_number = -1; + do_cleanups (old_chain); } /* Display all of the values on the auto-display chain which can be @@ -1655,8 +1852,9 @@ disable_current_display (void) if (current_display_number >= 0) { disable_display (current_display_number); - fprintf_unfiltered (gdb_stderr, _("\ -Disabling display %d to avoid infinite recursion.\n"), + fprintf_unfiltered (gdb_stderr, + _("Disabling display %d to " + "avoid infinite recursion.\n"), current_display_number); } current_display_number = -1; @@ -1689,115 +1887,47 @@ Num Enb Expression\n")); } } +/* Callback fo map_display_numbers, that enables or disables the + passed in display D. */ + static void -enable_display (char *args, int from_tty) +do_enable_disable_display (struct display *d, void *data) { - char *p = args; - char *p1; - int num; - struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d = d->next) - d->enabled_p = 1; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); - - num = atoi (p); - - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->enabled_p = 1; - goto win; - } - printf_unfiltered (_("No display number %d.\n"), num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + d->enabled_p = *(int *) data; } +/* Implamentation of both the "disable display" and "enable display" + commands. ENABLE decides what to do. */ + static void -disable_display_command (char *args, int from_tty) +enable_disable_display_command (char *args, int from_tty, int enable) { - char *p = args; - char *p1; - struct display *d; - - if (p == 0) + if (args == NULL) { - for (d = display_chain; d; d = d->next) - d->enabled_p = 0; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error (_("Arguments must be display numbers.")); + struct display *d; - disable_display (atoi (p)); + ALL_DISPLAYS (d) + d->enabled_p = enable; + return; + } - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } + map_display_numbers (args, do_enable_disable_display, &enable); } -/* Return 1 if D uses SOLIB (and will become dangling when SOLIB - is unloaded), otherwise return 0. */ +/* The "enable display" command. */ -static int -display_uses_solib_p (const struct display *d, - const struct so_list *solib) +static void +enable_display_command (char *args, int from_tty) { - int endpos; - struct expression *const exp = d->exp; - const union exp_element *const elts = exp->elts; - - if (d->block != NULL - && solib_contains_address_p (solib, d->block->startaddr)) - return 1; - - for (endpos = exp->nelts; endpos > 0; ) - { - int i, args, oplen = 0; - - exp->language_defn->la_exp_desc->operator_length (exp, endpos, - &oplen, &args); - gdb_assert (oplen > 0); - - i = endpos - oplen; - if (elts[i].opcode == OP_VAR_VALUE) - { - const struct block *const block = elts[i + 1].block; - const struct symbol *const symbol = elts[i + 2].symbol; - const struct obj_section *const section = - SYMBOL_OBJ_SECTION (symbol); - - if (block != NULL - && solib_contains_address_p (solib, block->startaddr)) - return 1; + enable_disable_display_command (args, from_tty, 1); +} - if (section && section->objfile == solib->objfile) - return 1; - } - endpos -= oplen; - } +/* The "disable display" command. */ - return 0; +static void +disable_display_command (char *args, int from_tty) +{ + enable_disable_display_command (args, from_tty, 0); } /* display_chain items point to blocks and expressions. Some expressions in @@ -1809,19 +1939,33 @@ display_uses_solib_p (const struct display *d, an item by re-parsing .exp_string field in the new execution context. */ static void -clear_dangling_display_expressions (struct so_list *solib) +clear_dangling_display_expressions (struct objfile *objfile) { struct display *d; - struct objfile *objfile = NULL; + struct program_space *pspace; - for (d = display_chain; d; d = d->next) + /* With no symbol file we cannot have a block or expression from it. */ + if (objfile == NULL) + return; + pspace = objfile->pspace; + if (objfile->separate_debug_objfile_backlink) { - if (d->exp && display_uses_solib_p (d, solib)) - { - xfree (d->exp); - d->exp = NULL; - d->block = NULL; - } + objfile = objfile->separate_debug_objfile_backlink; + gdb_assert (objfile->pspace == pspace); + } + + for (d = display_chain; d != NULL; d = d->next) + { + if (d->pspace != pspace) + continue; + + if (lookup_objfile_from_block (d->block) == objfile + || (d->exp && exp_uses_objfile (d->exp, objfile))) + { + xfree (d->exp); + d->exp = NULL; + d->block = NULL; + } } } @@ -1830,351 +1974,332 @@ clear_dangling_display_expressions (struct so_list *solib) struct symbol. NAME is the name to print; if NULL then VAR's print name will be used. STREAM is the ui_file on which to print the value. INDENT specifies the number of indent levels to print - before printing the variable name. */ + before printing the variable name. + + This function invalidates FRAME. */ void print_variable_and_value (const char *name, struct symbol *var, struct frame_info *frame, struct ui_file *stream, int indent) { - struct value *val; - struct value_print_options opts; + volatile struct gdb_exception except; if (!name) name = SYMBOL_PRINT_NAME (var); fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name); + TRY_CATCH (except, RETURN_MASK_ERROR) + { + struct value *val; + struct value_print_options opts; + + val = read_var_value (var, frame); + get_user_print_options (&opts); + opts.deref_ref = 1; + common_val_print (val, stream, indent, &opts, current_language); - val = read_var_value (var, frame); - get_user_print_options (&opts); - common_val_print (val, stream, indent, &opts, current_language); + /* common_val_print invalidates FRAME when a pretty printer calls inferior + function. */ + frame = NULL; + } + if (except.reason < 0) + fprintf_filtered(stream, "", name, + except.message); fprintf_filtered (stream, "\n"); } +/* Subroutine of ui_printf to simplify it. + Print VALUE to STREAM using FORMAT. + VALUE is a C-style string on the target. */ + static void -printf_command (char *arg, int from_tty) +printf_c_string (struct ui_file *stream, const char *format, + struct value *value) { - char *f = NULL; - char *s = arg; - char *string = NULL; - struct value **val_args; - char *substrings; - char *current_substring; - int nargs = 0; - int allocated_args = 20; - struct cleanup *old_cleanups; + gdb_byte *str; + CORE_ADDR tem; + int j; - val_args = xmalloc (allocated_args * sizeof (struct value *)); - old_cleanups = make_cleanup (free_current_contents, &val_args); + tem = value_as_address (value); - if (s == 0) - error_no_arg (_("format-control string and values to print")); + /* This is a %s argument. Find the length of the string. */ + for (j = 0;; j++) + { + gdb_byte c; - /* Skip white space before format string */ - while (*s == ' ' || *s == '\t') - s++; + QUIT; + read_memory (tem + j, &c, 1); + if (c == 0) + break; + } - /* A format string should follow, enveloped in double quotes. */ - if (*s++ != '"') - error (_("Bad format string, missing '\"'.")); + /* Copy the string contents into a string inside GDB. */ + str = (gdb_byte *) alloca (j + 1); + if (j != 0) + read_memory (tem, str, j); + str[j] = 0; - /* Parse the format-control string and copy it into the string STRING, - processing some kinds of escape sequence. */ + fprintf_filtered (stream, format, (char *) str); +} - f = string = (char *) alloca (strlen (s) + 1); +/* Subroutine of ui_printf to simplify it. + Print VALUE to STREAM using FORMAT. + VALUE is a wide C-style string on the target. */ - while (*s != '"') +static void +printf_wide_c_string (struct ui_file *stream, const char *format, + struct value *value) +{ + gdb_byte *str; + CORE_ADDR tem; + int j; + struct gdbarch *gdbarch = get_type_arch (value_type (value)); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct type *wctype = lookup_typename (current_language, gdbarch, + "wchar_t", NULL, 0); + int wcwidth = TYPE_LENGTH (wctype); + gdb_byte *buf = alloca (wcwidth); + struct obstack output; + struct cleanup *inner_cleanup; + + tem = value_as_address (value); + + /* This is a %s argument. Find the length of the string. */ + for (j = 0;; j += wcwidth) { - int c = *s++; - switch (c) - { - case '\0': - error (_("Bad format string, non-terminated '\"'.")); + QUIT; + read_memory (tem + j, buf, wcwidth); + if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0) + break; + } - case '\\': - switch (c = *s++) - { - case '\\': - *f++ = '\\'; - break; - case 'a': - *f++ = '\a'; - break; - case 'b': - *f++ = '\b'; - break; - case 'f': - *f++ = '\f'; - break; - case 'n': - *f++ = '\n'; - break; - case 'r': - *f++ = '\r'; - break; - case 't': - *f++ = '\t'; - break; - case 'v': - *f++ = '\v'; - break; - case '"': - *f++ = '"'; - break; - default: - /* ??? TODO: handle other escape sequences */ - error (_("Unrecognized escape character \\%c in format string."), - c); - } - break; + /* Copy the string contents into a string inside GDB. */ + str = (gdb_byte *) alloca (j + wcwidth); + if (j != 0) + read_memory (tem, str, j); + memset (&str[j], 0, wcwidth); - default: - *f++ = c; + obstack_init (&output); + inner_cleanup = make_cleanup_obstack_free (&output); + + convert_between_encodings (target_wide_charset (gdbarch), + host_charset (), + str, j, wcwidth, + &output, translit_char); + obstack_grow_str0 (&output, ""); + + fprintf_filtered (stream, format, obstack_base (&output)); + do_cleanups (inner_cleanup); +} + +/* Subroutine of ui_printf to simplify it. + Print VALUE, a decimal floating point value, to STREAM using FORMAT. */ + +static void +printf_decfloat (struct ui_file *stream, const char *format, + struct value *value) +{ + const gdb_byte *param_ptr = value_contents (value); + +#if defined (PRINTF_HAS_DECFLOAT) + /* If we have native support for Decimal floating + printing, handle it here. */ + fprintf_filtered (stream, format, param_ptr); +#else + /* As a workaround until vasprintf has native support for DFP + we convert the DFP values to string and print them using + the %s format specifier. */ + const char *p; + + /* Parameter data. */ + struct type *param_type = value_type (value); + struct gdbarch *gdbarch = get_type_arch (param_type); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + /* DFP output data. */ + struct value *dfp_value = NULL; + gdb_byte *dfp_ptr; + int dfp_len = 16; + gdb_byte dec[16]; + struct type *dfp_type = NULL; + char decstr[MAX_DECIMAL_STRING]; + + /* Points to the end of the string so that we can go back + and check for DFP length modifiers. */ + p = format + strlen (format); + + /* Look for the float/double format specifier. */ + while (*p != 'f' && *p != 'e' && *p != 'E' + && *p != 'g' && *p != 'G') + p--; + + /* Search for the '%' char and extract the size and type of + the output decimal value based on its modifiers + (%Hf, %Df, %DDf). */ + while (*--p != '%') + { + if (*p == 'H') + { + dfp_len = 4; + dfp_type = builtin_type (gdbarch)->builtin_decfloat; + } + else if (*p == 'D' && *(p - 1) == 'D') + { + dfp_len = 16; + dfp_type = builtin_type (gdbarch)->builtin_declong; + p--; + } + else + { + dfp_len = 8; + dfp_type = builtin_type (gdbarch)->builtin_decdouble; } } - /* Skip over " and following space and comma. */ - s++; - *f++ = '\0'; - while (*s == ' ' || *s == '\t') - s++; + /* Conversion between different DFP types. */ + if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT) + decimal_convert (param_ptr, TYPE_LENGTH (param_type), + byte_order, dec, dfp_len, byte_order); + else + /* If this is a non-trivial conversion, just output 0. + A correct converted value can be displayed by explicitly + casting to a DFP type. */ + decimal_from_string (dec, dfp_len, byte_order, "0"); - if (*s != ',' && *s != 0) - error (_("Invalid argument syntax")); + dfp_value = value_from_decfloat (dfp_type, dec); - if (*s == ',') - s++; - while (*s == ' ' || *s == '\t') - s++; + dfp_ptr = (gdb_byte *) value_contents (dfp_value); - /* Need extra space for the '\0's. Doubling the size is sufficient. */ - substrings = alloca (strlen (string) * 2); - current_substring = substrings; + decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr); - { - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] classifies the %-specs so we can give printf_filtered - something of the right size. */ + /* Print the DFP value. */ + fprintf_filtered (stream, "%s", decstr); +#endif +} - enum argclass - { - int_arg, long_arg, long_long_arg, ptr_arg, string_arg, - double_arg, long_double_arg, decfloat_arg - }; - enum argclass *argclass; - enum argclass this_argclass; - char *last_arg; - int nargs_wanted; - int i; +/* Subroutine of ui_printf to simplify it. + Print VALUE, a target pointer, to STREAM using FORMAT. */ - argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass); - nargs_wanted = 0; - f = string; - last_arg = string; - while (*f) - if (*f++ == '%') +static void +printf_pointer (struct ui_file *stream, const char *format, + struct value *value) +{ + /* We avoid the host's %p because pointers are too + likely to be the wrong size. The only interesting + modifier for %p is a width; extract that, and then + handle %p as glibc would: %#x or a literal "(nil)". */ + + const char *p; + char *fmt, *fmt_p; +#ifdef PRINTF_HAS_LONG_LONG + long long val = value_as_long (value); +#else + long val = value_as_long (value); +#endif + + fmt = alloca (strlen (format) + 5); + + /* Copy up to the leading %. */ + p = format; + fmt_p = fmt; + while (*p) + { + int is_percent = (*p == '%'); + + *fmt_p++ = *p++; + if (is_percent) { - int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0; - int seen_space = 0, seen_plus = 0; - int seen_big_l = 0, seen_h = 0, seen_big_h = 0; - int seen_big_d = 0, seen_double_big_d = 0; - int bad = 0; - - /* Check the validity of the format specifier, and work - out what argument it expects. We only accept C89 - format strings, with the exception of long long (which - we autoconf for). */ - - /* Skip over "%%". */ - if (*f == '%') - { - f++; - continue; - } + if (*p == '%') + *fmt_p++ = *p++; + else + break; + } + } - /* The first part of a format specifier is a set of flag - characters. */ - while (strchr ("0-+ #", *f)) - { - if (*f == '#') - seen_hash = 1; - else if (*f == '0') - seen_zero = 1; - else if (*f == ' ') - seen_space = 1; - else if (*f == '+') - seen_plus = 1; - f++; - } + if (val != 0) + *fmt_p++ = '#'; - /* The next part of a format specifier is a width. */ - while (strchr ("0123456789", *f)) - f++; + /* Copy any width. */ + while (*p >= '0' && *p < '9') + *fmt_p++ = *p++; - /* The next part of a format specifier is a precision. */ - if (*f == '.') - { - seen_prec = 1; - f++; - while (strchr ("0123456789", *f)) - f++; - } + gdb_assert (*p == 'p' && *(p + 1) == '\0'); + if (val != 0) + { +#ifdef PRINTF_HAS_LONG_LONG + *fmt_p++ = 'l'; +#endif + *fmt_p++ = 'l'; + *fmt_p++ = 'x'; + *fmt_p++ = '\0'; + fprintf_filtered (stream, fmt, val); + } + else + { + *fmt_p++ = 's'; + *fmt_p++ = '\0'; + fprintf_filtered (stream, fmt, "(nil)"); + } +} - /* The next part of a format specifier is a length modifier. */ - if (*f == 'h') - { - seen_h = 1; - f++; - } - else if (*f == 'l') - { - f++; - lcount++; - if (*f == 'l') - { - f++; - lcount++; - } - } - else if (*f == 'L') - { - seen_big_l = 1; - f++; - } - /* Decimal32 modifier. */ - else if (*f == 'H') - { - seen_big_h = 1; - f++; - } - /* Decimal64 and Decimal128 modifiers. */ - else if (*f == 'D') - { - f++; - - /* Check for a Decimal128. */ - if (*f == 'D') - { - f++; - seen_double_big_d = 1; - } - else - seen_big_d = 1; - } +/* printf "printf format string" ARG to STREAM. */ - switch (*f) - { - case 'u': - if (seen_hash) - bad = 1; - /* FALLTHROUGH */ - - case 'o': - case 'x': - case 'X': - if (seen_space || seen_plus) - bad = 1; - /* FALLTHROUGH */ - - case 'd': - case 'i': - if (lcount == 0) - this_argclass = int_arg; - else if (lcount == 1) - this_argclass = long_arg; - else - this_argclass = long_long_arg; - - if (seen_big_l) - bad = 1; - break; +static void +ui_printf (const char *arg, struct ui_file *stream) +{ + struct format_piece *fpieces; + const char *s = arg; + struct value **val_args; + int allocated_args = 20; + struct cleanup *old_cleanups; - case 'c': - this_argclass = int_arg; - if (lcount || seen_h || seen_big_l) - bad = 1; - if (seen_prec || seen_zero || seen_space || seen_plus) - bad = 1; - break; + val_args = xmalloc (allocated_args * sizeof (struct value *)); + old_cleanups = make_cleanup (free_current_contents, &val_args); - case 'p': - this_argclass = ptr_arg; - if (lcount || seen_h || seen_big_l) - bad = 1; - if (seen_prec || seen_zero || seen_space || seen_plus) - bad = 1; - break; + if (s == 0) + error_no_arg (_("format-control string and values to print")); - case 's': - this_argclass = string_arg; - if (lcount || seen_h || seen_big_l) - bad = 1; - if (seen_zero || seen_space || seen_plus) - bad = 1; - break; + s = skip_spaces_const (s); - case 'e': - case 'f': - case 'g': - case 'E': - case 'G': - if (seen_big_h || seen_big_d || seen_double_big_d) - this_argclass = decfloat_arg; - else if (seen_big_l) - this_argclass = long_double_arg; - else - this_argclass = double_arg; - - if (lcount || seen_h) - bad = 1; - break; + /* A format string should follow, enveloped in double quotes. */ + if (*s++ != '"') + error (_("Bad format string, missing '\"'.")); - case '*': - error (_("`*' not supported for precision or width in printf")); + fpieces = parse_format_string (&s); - case 'n': - error (_("Format specifier `n' not supported in printf")); + make_cleanup (free_format_pieces_cleanup, &fpieces); - case '\0': - error (_("Incomplete format specifier at end of format string")); + if (*s++ != '"') + error (_("Bad format string, non-terminated '\"'.")); + + s = skip_spaces_const (s); - default: - error (_("Unrecognized format specifier '%c' in printf"), *f); - } + if (*s != ',' && *s != 0) + error (_("Invalid argument syntax")); - if (bad) - error (_("Inappropriate modifiers to format specifier '%c' in printf"), - *f); + if (*s == ',') + s++; + s = skip_spaces_const (s); - f++; + { + int nargs = 0; + int nargs_wanted; + int i, fr; + char *current_substring; - if (lcount > 1 && USE_PRINTF_I64) - { - /* Windows' printf does support long long, but not the usual way. - Convert %lld to %I64d. */ - int length_before_ll = f - last_arg - 1 - lcount; - strncpy (current_substring, last_arg, length_before_ll); - strcpy (current_substring + length_before_ll, "I64"); - current_substring[length_before_ll + 3] = - last_arg[length_before_ll + lcount]; - current_substring += length_before_ll + 4; - } - else - { - strncpy (current_substring, last_arg, f - last_arg); - current_substring += f - last_arg; - } - *current_substring++ = '\0'; - last_arg = f; - argclass[nargs_wanted++] = this_argclass; - } + nargs_wanted = 0; + for (fr = 0; fpieces[fr].string != NULL; fr++) + if (fpieces[fr].argclass != literal_piece) + ++nargs_wanted; /* Now, parse all arguments and evaluate them. Store the VALUEs in VAL_ARGS. */ while (*s != '\0') { - char *s1; + const char *s1; + if (nargs == allocated_args) val_args = (struct value **) xrealloc ((char *) val_args, (allocated_args *= 2) @@ -2192,35 +2317,49 @@ printf_command (char *arg, int from_tty) error (_("Wrong number of arguments for specified format-string")); /* Now actually print them. */ - current_substring = substrings; - for (i = 0; i < nargs; i++) + i = 0; + for (fr = 0; fpieces[fr].string != NULL; fr++) { - switch (argclass[i]) + current_substring = fpieces[fr].string; + switch (fpieces[fr].argclass) { case string_arg: + printf_c_string (stream, current_substring, val_args[i]); + break; + case wide_string_arg: + printf_wide_c_string (stream, current_substring, val_args[i]); + break; + case wide_char_arg: { - gdb_byte *str; - CORE_ADDR tem; - int j; - tem = value_as_address (val_args[i]); - - /* This is a %s argument. Find the length of the string. */ - for (j = 0;; j++) - { - gdb_byte c; - QUIT; - read_memory (tem + j, &c, 1); - if (c == 0) - break; - } - - /* Copy the string contents into a string inside GDB. */ - str = (gdb_byte *) alloca (j + 1); - if (j != 0) - read_memory (tem, str, j); - str[j] = 0; - - printf_filtered (current_substring, (char *) str); + struct gdbarch *gdbarch + = get_type_arch (value_type (val_args[i])); + struct type *wctype = lookup_typename (current_language, gdbarch, + "wchar_t", NULL, 0); + struct type *valtype; + struct obstack output; + struct cleanup *inner_cleanup; + const gdb_byte *bytes; + + valtype = value_type (val_args[i]); + if (TYPE_LENGTH (valtype) != TYPE_LENGTH (wctype) + || TYPE_CODE (valtype) != TYPE_CODE_INT) + error (_("expected wchar_t argument for %%lc")); + + bytes = value_contents (val_args[i]); + + obstack_init (&output); + inner_cleanup = make_cleanup_obstack_free (&output); + + convert_between_encodings (target_wide_charset (gdbarch), + host_charset (), + bytes, TYPE_LENGTH (valtype), + TYPE_LENGTH (valtype), + &output, translit_char); + obstack_grow_str0 (&output, ""); + + fprintf_filtered (stream, current_substring, + obstack_base (&output)); + do_cleanups (inner_cleanup); } break; case double_arg: @@ -2231,12 +2370,12 @@ printf_command (char *arg, int from_tty) /* If format string wants a float, unchecked-convert the value to floating point of the same size. */ - type = float_type_from_length (current_gdbarch, type); + type = float_type_from_length (type); val = unpack_double (type, value_contents (val_args[i]), &inv); if (inv) error (_("Invalid floating value found in program.")); - printf_filtered (current_substring, (double) val); + fprintf_filtered (stream, current_substring, (double) val); break; } case long_double_arg: @@ -2248,22 +2387,24 @@ printf_command (char *arg, int from_tty) /* If format string wants a float, unchecked-convert the value to floating point of the same size. */ - type = float_type_from_length (current_gdbarch, type); + type = float_type_from_length (type); val = unpack_double (type, value_contents (val_args[i]), &inv); if (inv) error (_("Invalid floating value found in program.")); - printf_filtered (current_substring, (long double) val); + fprintf_filtered (stream, current_substring, + (long double) val); break; } #else error (_("long double not supported in printf")); #endif case long_long_arg: -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) +#ifdef PRINTF_HAS_LONG_LONG { long long val = value_as_long (val_args[i]); - printf_filtered (current_substring, val); + + fprintf_filtered (stream, current_substring, val); break; } #else @@ -2272,187 +2413,75 @@ printf_command (char *arg, int from_tty) case int_arg: { int val = value_as_long (val_args[i]); - printf_filtered (current_substring, val); + + fprintf_filtered (stream, current_substring, val); break; } case long_arg: { long val = value_as_long (val_args[i]); - printf_filtered (current_substring, val); - break; - } - - /* Handles decimal floating values. */ - case decfloat_arg: - { - const gdb_byte *param_ptr = value_contents (val_args[i]); -#if defined (PRINTF_HAS_DECFLOAT) - /* If we have native support for Decimal floating - printing, handle it here. */ - printf_filtered (current_substring, param_ptr); -#else - - /* As a workaround until vasprintf has native support for DFP - we convert the DFP values to string and print them using - the %s format specifier. */ - - char *eos, *sos; - int nnull_chars = 0; - - /* Parameter data. */ - struct type *param_type = value_type (val_args[i]); - unsigned int param_len = TYPE_LENGTH (param_type); - - /* DFP output data. */ - struct value *dfp_value = NULL; - gdb_byte *dfp_ptr; - int dfp_len = 16; - gdb_byte dec[16]; - struct type *dfp_type = NULL; - char decstr[MAX_DECIMAL_STRING]; - - /* Points to the end of the string so that we can go back - and check for DFP length modifiers. */ - eos = current_substring + strlen (current_substring); - - /* Look for the float/double format specifier. */ - while (*eos != 'f' && *eos != 'e' && *eos != 'E' - && *eos != 'g' && *eos != 'G') - eos--; - - sos = eos; - - /* Search for the '%' char and extract the size and type of - the output decimal value based on its modifiers - (%Hf, %Df, %DDf). */ - while (*--sos != '%') - { - if (*sos == 'H') - { - dfp_len = 4; - dfp_type = builtin_type (current_gdbarch)->builtin_decfloat; - } - else if (*sos == 'D' && *(sos - 1) == 'D') - { - dfp_len = 16; - dfp_type = builtin_type (current_gdbarch)->builtin_declong; - sos--; - } - else - { - dfp_len = 8; - dfp_type = builtin_type (current_gdbarch)->builtin_decdouble; - } - } - - /* Replace %Hf, %Df and %DDf with %s's. */ - *++sos = 's'; - - /* Go through the whole format string and pull the correct - number of chars back to compensate for the change in the - format specifier. */ - while (nnull_chars < nargs - i) - { - if (*eos == '\0') - nnull_chars++; - - *++sos = *++eos; - } - - /* Conversion between different DFP types. */ - if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT) - decimal_convert (param_ptr, param_len, dec, dfp_len); - else - /* If this is a non-trivial conversion, just output 0. - A correct converted value can be displayed by explicitly - casting to a DFP type. */ - decimal_from_string (dec, dfp_len, "0"); - - dfp_value = value_from_decfloat (dfp_type, dec); - - dfp_ptr = (gdb_byte *) value_contents (dfp_value); - - decimal_to_string (dfp_ptr, dfp_len, decstr); - - /* Print the DFP value. */ - printf_filtered (current_substring, decstr); + fprintf_filtered (stream, current_substring, val); break; -#endif } - + /* Handles decimal floating values. */ + case decfloat_arg: + printf_decfloat (stream, current_substring, val_args[i]); + break; case ptr_arg: - { - /* We avoid the host's %p because pointers are too - likely to be the wrong size. The only interesting - modifier for %p is a width; extract that, and then - handle %p as glibc would: %#x or a literal "(nil)". */ - - char *p, *fmt, *fmt_p; -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) - long long val = value_as_long (val_args[i]); -#else - long val = value_as_long (val_args[i]); -#endif - - fmt = alloca (strlen (current_substring) + 5); - - /* Copy up to the leading %. */ - p = current_substring; - fmt_p = fmt; - while (*p) - { - int is_percent = (*p == '%'); - *fmt_p++ = *p++; - if (is_percent) - { - if (*p == '%') - *fmt_p++ = *p++; - else - break; - } - } - - if (val != 0) - *fmt_p++ = '#'; - - /* Copy any width. */ - while (*p >= '0' && *p < '9') - *fmt_p++ = *p++; - - gdb_assert (*p == 'p' && *(p + 1) == '\0'); - if (val != 0) - { -#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) - *fmt_p++ = 'l'; -#endif - *fmt_p++ = 'l'; - *fmt_p++ = 'x'; - *fmt_p++ = '\0'; - printf_filtered (fmt, val); - } - else - { - *fmt_p++ = 's'; - *fmt_p++ = '\0'; - printf_filtered (fmt, "(nil)"); - } - - break; - } + printf_pointer (stream, current_substring, val_args[i]); + break; + case literal_piece: + /* Print a portion of the format string that has no + directives. Note that this will not include any + ordinary %-specs, but it might include "%%". That is + why we use printf_filtered and not puts_filtered here. + Also, we pass a dummy argument because some platforms + have modified GCC to include -Wformat-security by + default, which will warn here if there is no + argument. */ + fprintf_filtered (stream, current_substring, 0); + break; default: internal_error (__FILE__, __LINE__, _("failed internal consistency check")); } - /* Skip to the next substring. */ - current_substring += strlen (current_substring) + 1; + /* Maybe advance to the next argument. */ + if (fpieces[fr].argclass != literal_piece) + ++i; } - /* Print the portion of the format string after the last argument. */ - puts_filtered (last_arg); } do_cleanups (old_cleanups); } +/* Implement the "printf" command. */ + +static void +printf_command (char *arg, int from_tty) +{ + ui_printf (arg, gdb_stdout); + gdb_flush (gdb_stdout); +} + +/* Implement the "eval" command. */ + +static void +eval_command (char *arg, int from_tty) +{ + struct ui_file *ui_out = mem_fileopen (); + struct cleanup *cleanups = make_cleanup_ui_file_delete (ui_out); + char *expanded; + + ui_printf (arg, ui_out); + + expanded = ui_file_xstrdup (ui_out, NULL); + make_cleanup (xfree, expanded); + + execute_command (expanded, from_tty); + + do_cleanups (cleanups); +} + void _initialize_printcmd (void) { @@ -2460,7 +2489,7 @@ _initialize_printcmd (void) current_display_number = -1; - observer_attach_solib_unloaded (clear_dangling_display_expressions); + observer_attach_free_objfile (clear_dangling_display_expressions); add_info ("address", address_info, _("Describe where symbol SYM is stored.")); @@ -2474,7 +2503,8 @@ Examine memory: x/FMT ADDRESS.\n\ ADDRESS is an expression for the memory address to examine.\n\ FMT is a repeat count followed by a format letter and a size letter.\n\ Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ - t(binary), f(float), a(address), i(instruction), c(char) and s(string).\n\ + t(binary), f(float), a(address), i(instruction), c(char), s(string)\n\ + and z(hex, zero padded on the left).\n\ Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\ The specified number of objects of the specified size are printed\n\ according to the format.\n\n\ @@ -2507,7 +2537,7 @@ and examining is done as in the \"x\" command.\n\n\ With no argument, display all currently requested auto-display expressions.\n\ Use \"undisplay\" to cancel display requests previously made.")); - add_cmd ("display", class_vars, enable_display, _("\ + add_cmd ("display", class_vars, enable_display_command, _("\ Enable some expressions to be displayed when program stops.\n\ Arguments are the code numbers of the expressions to resume displaying.\n\ No argument means enable all automatic-display expressions.\n\ @@ -2555,7 +2585,7 @@ Use \"set variable\" for variables with names identical to set subcommands.\n\ \nWith a subcommand, this command modifies parts of the gdb environment.\n\ You can see these environment settings with the \"show\" command.")); - /* "call" is the same as "set", but handy for dbx users to call fns. */ + /* "call" is the same as "set", but handy for dbx users to call fns. */ c = add_com ("call", class_vars, call_command, _("\ Call a function in the program.\n\ The argument is the function name and arguments, in the notation of the\n\ @@ -2596,16 +2626,17 @@ EXP may be preceded with /FMT, where FMT is a format letter\n\ but no count or size letter (see \"x\" command).")); set_cmd_completer (c, expression_completer); add_com_alias ("p", "print", class_vars, 1); - - c = add_com ("inspect", class_vars, inspect_command, _("\ -Same as \"print\" command, except that if you are running in the epoch\n\ -environment, the value is printed in its own window.")); - set_cmd_completer (c, expression_completer); + add_com_alias ("inspect", "print", class_vars, 1); add_setshow_uinteger_cmd ("max-symbolic-offset", no_class, &max_symbolic_offset, _("\ Set the largest offset that will be printed in form."), _("\ -Show the largest offset that will be printed in form."), NULL, +Show the largest offset that will be printed in form."), _("\ +Tell GDB to only display the symbolic form of an address if the\n\ +offset between the closest earlier symbol and the address is less than\n\ +the specified maximum offset. The default is \"unlimited\", which tells GDB\n\ +to always print the symbolic form of an address if any symbol precedes\n\ +it. Zero is equivalent to \"unlimited\"."), NULL, show_max_symbolic_offset, &setprintlist, &showprintlist); @@ -2617,14 +2648,7 @@ Show printing of source filename and line number with ."), NULL, show_print_symbol_filename, &setprintlist, &showprintlist); - /* For examine/instruction a single byte quantity is specified as - the data. This avoids problems with value_at_lazy() requiring a - valid data type (and rejecting VOID). */ - examine_i_type = init_type (TYPE_CODE_INT, 1, 0, "examine_i_type", NULL); - - examine_b_type = init_type (TYPE_CODE_INT, 1, 0, "examine_b_type", NULL); - examine_h_type = init_type (TYPE_CODE_INT, 2, 0, "examine_h_type", NULL); - examine_w_type = init_type (TYPE_CODE_INT, 4, 0, "examine_w_type", NULL); - examine_g_type = init_type (TYPE_CODE_INT, 8, 0, "examine_g_type", NULL); - + add_com ("eval", no_class, eval_command, _("\ +Convert \"printf format string\", arg1, arg2, arg3, ..., argn to\n\ +a command line, and call it.")); }