X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fprintcmd.c;h=8c999188d71edc4d20674a34b5dfc56c02e167b5;hb=1871a62daf0561da0880ba1ad39e8191bc3cf1ac;hp=bab13fb1d2582f06b43a7de14bb389c479c2f5c1;hpb=01770bbde902e075e524b518ac6c1087a4cc1cfb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/printcmd.c b/gdb/printcmd.c index bab13fb1d2..8c999188d7 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1,6 +1,6 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986-2016 Free Software Foundation, Inc. + Copyright (C) 1986-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -38,8 +38,8 @@ #include "ui-out.h" #include "block.h" #include "disasm.h" -#include "dfp.h" -#include "observer.h" +#include "target-float.h" +#include "observable.h" #include "solist.h" #include "parser-defs.h" #include "charset.h" @@ -48,10 +48,7 @@ #include "cli/cli-script.h" #include "format.h" #include "source.h" - -#ifdef TUI -#include "tui/tui.h" /* For tui_active et al. */ -#endif +#include "common/byte-vector.h" /* Last specified output format. */ @@ -61,6 +58,10 @@ static char last_format = 0; static char last_size = 'w'; +/* Last specified count for the 'x' command. */ + +static int last_count; + /* Default address to examine next, and associated architecture. */ static struct gdbarch *next_gdbarch; @@ -77,7 +78,7 @@ static CORE_ADDR last_examine_address; /* Contents of last address examined. This is not valid past the end of the `x' command! */ -static struct value *last_examine_value; +static value_ref_ptr last_examine_value; /* Largest offset between a symbolic value and an address, that will be printed as `0x1234 '. */ @@ -157,10 +158,6 @@ static int display_number; B ? (TMP = B->next, 1): 0; \ B = TMP) -/* Prototypes for exported functions. */ - -void _initialize_printcmd (void); - /* Prototypes for local functions. */ static void do_one_display (struct display *); @@ -214,9 +211,7 @@ decode_format (const char **string_ptr, int oformat, int osize) break; } - while (*p == ' ' || *p == '\t') - p++; - *string_ptr = p; + *string_ptr = skip_spaces (p); /* Set defaults for format and size if not specified. */ if (val.format == '?') @@ -356,43 +351,12 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type, 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 (gdbarch); /* String printing should go through val_print_scalar_formatted. */ gdb_assert (options->format != 's'); - if (len > sizeof(LONGEST) - && (TYPE_CODE (type) == TYPE_CODE_INT - || TYPE_CODE (type) == TYPE_CODE_ENUM)) - { - switch (options->format) - { - case 'o': - print_octal_chars (stream, valaddr, len, byte_order); - return; - case 'u': - case 'd': - print_decimal_chars (stream, valaddr, len, byte_order); - return; - case 't': - print_binary_chars (stream, valaddr, len, byte_order); - return; - case 'x': - print_hex_chars (stream, valaddr, len, byte_order); - return; - case 'c': - print_char_chars (stream, type, valaddr, len, byte_order); - return; - default: - break; - }; - } - - if (options->format != 'f') - val_long = unpack_long (type, valaddr); - /* If the value is a pointer, and pointers and addresses are not the same, then at this point, the value's length (in target bytes) is gdbarch_addr_bit/TARGET_CHAR_BIT, not TYPE_LENGTH (type). */ @@ -402,61 +366,107 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type, /* 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' || TYPE_UNSIGNED (type)) + if (options->format != 'c' + && (options->format != 'd' || TYPE_UNSIGNED (type))) { - if (len < sizeof (LONGEST)) - val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1; + if (len < TYPE_LENGTH (type) && byte_order == BFD_ENDIAN_BIG) + valaddr += TYPE_LENGTH (type) - len; } - switch (options->format) + if (size != 0 && (options->format == 'x' || options->format == 't')) { - case 'x': - if (!size) + /* Truncate to fit. */ + unsigned newlen; + switch (size) { - /* No size specified, like in print. Print varying # of digits. */ - print_longest (stream, 'x', 1, val_long); + case 'b': + newlen = 1; + break; + case 'h': + newlen = 2; + break; + case 'w': + newlen = 4; + break; + case 'g': + newlen = 8; + break; + default: + error (_("Undefined output size \"%c\"."), size); } - else - switch (size) - { - case 'b': - case 'h': - case 'w': - case 'g': - print_longest (stream, size, 1, val_long); - break; - default: - error (_("Undefined output size \"%c\"."), size); - } - break; + if (newlen < len && byte_order == BFD_ENDIAN_BIG) + valaddr += len - newlen; + len = newlen; + } + + /* Historically gdb has printed floats by first casting them to a + long, and then printing the long. PR cli/16242 suggests changing + this to using C-style hex float format. */ + gdb::byte_vector converted_float_bytes; + if (TYPE_CODE (type) == TYPE_CODE_FLT + && (options->format == 'o' + || options->format == 'x' + || options->format == 't' + || options->format == 'z' + || options->format == 'd' + || options->format == 'u')) + { + LONGEST val_long = unpack_long (type, valaddr); + converted_float_bytes.resize (TYPE_LENGTH (type)); + store_signed_integer (converted_float_bytes.data (), TYPE_LENGTH (type), + byte_order, val_long); + valaddr = converted_float_bytes.data (); + } + /* Printing a non-float type as 'f' will interpret the data as if it were + of a floating-point type of the same length, if that exists. Otherwise, + the data is printed as integer. */ + char format = options->format; + if (format == 'f' && TYPE_CODE (type) != TYPE_CODE_FLT) + { + type = float_type_from_length (type); + if (TYPE_CODE (type) != TYPE_CODE_FLT) + format = 0; + } + + switch (format) + { + case 'o': + print_octal_chars (stream, valaddr, len, byte_order); + break; case 'd': - print_longest (stream, 'd', 1, val_long); + print_decimal_chars (stream, valaddr, len, true, byte_order); break; - case 'u': - print_longest (stream, 'u', 0, val_long); + print_decimal_chars (stream, valaddr, len, false, byte_order); break; - - case 'o': - if (val_long) - print_longest (stream, 'o', 1, val_long); - else - fprintf_filtered (stream, "0"); + case 0: + if (TYPE_CODE (type) != TYPE_CODE_FLT) + { + print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type), + byte_order); + break; + } + /* FALLTHROUGH */ + case 'f': + print_floating (valaddr, type, stream); break; - case 'a': - { - CORE_ADDR addr = unpack_pointer (type, valaddr); - - print_address (gdbarch, addr, stream); - } + case 't': + print_binary_chars (stream, valaddr, len, byte_order, size > 0); + break; + case 'x': + print_hex_chars (stream, valaddr, len, byte_order, size > 0); + break; + case 'z': + print_hex_chars (stream, valaddr, len, byte_order, true); break; - case 'c': { struct value_print_options opts = *options; + LONGEST val_long = unpack_long (type, valaddr); + opts.format = 0; if (TYPE_UNSIGNED (type)) type = builtin_type (gdbarch)->builtin_true_unsigned_char; @@ -467,68 +477,16 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type, } break; - case 'f': - type = float_type_from_length (type); - print_floating (valaddr, type, stream); - break; - - case 0: - internal_error (__FILE__, __LINE__, - _("failed internal consistency check")); - - case 't': - /* Binary; 't' stands for "two". */ + case 'a': { - char bits[8 * (sizeof val_long) + 1]; - char buf[8 * (sizeof val_long) + 32]; - 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); - } + CORE_ADDR addr = unpack_pointer (type, valaddr); - 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--; - } - strncpy (buf, cp, sizeof (bits)); - fputs_filtered (buf, stream); + print_address (gdbarch, addr, stream); } break; - case 'z': - print_hex_chars (stream, valaddr, len, byte_order); - break; - default: - error (_("Undefined output format \"%c\"."), options->format); + error (_("Undefined output format \"%c\"."), format); } } @@ -560,65 +518,52 @@ set_next_address (struct gdbarch *gdbarch, CORE_ADDR addr) int print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, struct ui_file *stream, - int do_demangle, char *leadin) + int do_demangle, const char *leadin) { - char *name = NULL; - char *filename = NULL; + std::string name, filename; int unmapped = 0; int offset = 0; int line = 0; - /* Throw away both name and filename. */ - struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &name); - make_cleanup (free_current_contents, &filename); - if (build_address_symbolic (gdbarch, addr, do_demangle, &name, &offset, &filename, &line, &unmapped)) - { - do_cleanups (cleanup_chain); - return 0; - } + return 0; fputs_filtered (leadin, stream); if (unmapped) fputs_filtered ("<*", stream); else fputs_filtered ("<", stream); - fputs_filtered (name, stream); + fputs_filtered (name.c_str (), stream); if (offset != 0) fprintf_filtered (stream, "+%u", (unsigned int) offset); /* Append source filename and line number if desired. Give specific line # of this addr, if we have it; else line # of the nearest symbol. */ - if (print_symbol_filename && filename != NULL) + if (print_symbol_filename && !filename.empty ()) { if (line != -1) - fprintf_filtered (stream, " at %s:%d", filename, line); + fprintf_filtered (stream, " at %s:%d", filename.c_str (), line); else - fprintf_filtered (stream, " in %s", filename); + fprintf_filtered (stream, " in %s", filename.c_str ()); } if (unmapped) fputs_filtered ("*>", stream); else 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 - 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. */ +/* See valprint.h. */ + int build_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr, /* IN */ int do_demangle, /* IN */ - char **name, /* OUT */ + std::string *name, /* OUT */ int *offset, /* OUT */ - char **filename, /* OUT */ + std::string *filename, /* OUT */ int *line, /* OUT */ int *unmapped) /* OUT */ { @@ -664,7 +609,7 @@ build_address_symbolic (struct gdbarch *gdbarch, pointer is . This matches the ISA behavior. */ addr = gdbarch_addr_bits_remove (gdbarch, addr); - name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)); + name_location = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (symbol)); if (do_demangle || asm_demangle) name_temp = SYMBOL_PRINT_NAME (symbol); else @@ -720,7 +665,7 @@ build_address_symbolic (struct gdbarch *gdbarch, *offset = addr - name_location; - *name = xstrdup (name_temp); + *name = name_temp; if (print_symbol_filename) { @@ -730,7 +675,7 @@ build_address_symbolic (struct gdbarch *gdbarch, if (sal.symtab) { - *filename = xstrdup (symtab_to_filename_for_display (sal.symtab)); + *filename = symtab_to_filename_for_display (sal.symtab); *line = sal.line; } } @@ -806,9 +751,8 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr, /* The vector PCS is used to store instruction addresses within a pc range. */ CORE_ADDR loop_start, loop_end, p; - VEC (CORE_ADDR) *pcs = NULL; + std::vector pcs; struct symtab_and_line sal; - struct cleanup *cleanup = make_cleanup (VEC_cleanup (CORE_ADDR), &pcs); *inst_read = 0; loop_start = loop_end = addr; @@ -822,7 +766,7 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr, instructions from INST_COUNT, and go to the next iteration. */ do { - VEC_truncate (CORE_ADDR, pcs, 0); + pcs.clear (); sal = find_pc_sect_line (loop_start, NULL, 1); if (sal.line <= 0) { @@ -844,12 +788,12 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr, LOOP_START to LOOP_END. */ for (p = loop_start; p < loop_end;) { - VEC_safe_push (CORE_ADDR, pcs, p); + pcs.push_back (p); p += gdb_insn_length (gdbarch, p); } - inst_count -= VEC_length (CORE_ADDR, pcs); - *inst_read += VEC_length (CORE_ADDR, pcs); + inst_count -= pcs.size (); + *inst_read += pcs.size (); } while (inst_count > 0); @@ -875,9 +819,7 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr, The case when the length of PCS is 0 means that we reached an area for which line info is not available. In such case, we return LOOP_START, which was the lowest instruction address that had line info. */ - p = VEC_length (CORE_ADDR, pcs) > 0 - ? VEC_index (CORE_ADDR, pcs, -inst_count) - : loop_start; + p = pcs.size () > 0 ? pcs[-inst_count] : loop_start; /* INST_READ includes all instruction addresses in a pc range. Need to exclude the beginning part up to the address we're returning. That @@ -885,7 +827,6 @@ find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr, if (inst_count < 0) *inst_read += inst_count; - do_cleanups (cleanup); return p; } @@ -952,8 +893,6 @@ find_string_backward (struct gdbarch *gdbarch, int *strings_counted) { const int chunk_size = 0x20; - gdb_byte *buffer = NULL; - struct cleanup *cleanup = NULL; int read_error = 0; int chars_read = 0; int chars_to_read = chunk_size; @@ -962,14 +901,13 @@ find_string_backward (struct gdbarch *gdbarch, CORE_ADDR string_start_addr = addr; gdb_assert (char_size == 1 || char_size == 2 || char_size == 4); - buffer = (gdb_byte *) xmalloc (chars_to_read * char_size); - cleanup = make_cleanup (xfree, buffer); + gdb::byte_vector buffer (chars_to_read * char_size); while (count > 0 && read_error == 0) { int i; addr -= chars_to_read * char_size; - chars_read = read_memory_backward (gdbarch, addr, buffer, + chars_read = read_memory_backward (gdbarch, addr, buffer.data (), chars_to_read * char_size); chars_read /= char_size; read_error = (chars_read == chars_to_read) ? 0 : 1; @@ -978,7 +916,7 @@ find_string_backward (struct gdbarch *gdbarch, { int offset = (chars_to_read - i - 1) * char_size; - if (integer_is_zero (buffer + offset, char_size) + if (integer_is_zero (&buffer[offset], char_size) || chars_counted == options->print_max) { /* Found '\0' or reached print_max. As OFFSET is the offset to @@ -1001,7 +939,6 @@ find_string_backward (struct gdbarch *gdbarch, string_start_addr -= chars_counted * char_size; } - do_cleanups (cleanup); return string_start_addr; } @@ -1141,9 +1078,6 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) object. */ last_examine_address = next_address; - if (last_examine_value) - value_free (last_examine_value); - /* The value to be displayed is not fetched greedily. Instead, to avoid the possibility of a fetched value not being used, its retrieval is delayed until the print code @@ -1153,12 +1087,10 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) the disassembler be modified so that LAST_EXAMINE_VALUE is left with the byte sequence from the last complete instruction fetched from memory? */ - last_examine_value = value_at_lazy (val_type, next_address); + last_examine_value + = release_value (value_at_lazy (val_type, next_address)); - if (last_examine_value) - release_value (last_examine_value); - - print_formatted (last_examine_value, size, &opts, gdb_stdout); + print_formatted (last_examine_value.get (), size, &opts, gdb_stdout); /* Display any branch delay slots following the final insn. */ if (format == 'i' && count == 1) @@ -1262,30 +1194,22 @@ print_command_1 (const char *exp, int voidprint) } static void -print_command (char *exp, int from_tty) +print_command (const char *exp, int from_tty) { print_command_1 (exp, 1); } /* Same as print, except it doesn't print void results. */ static void -call_command (char *exp, int from_tty) +call_command (const char *exp, int from_tty) { print_command_1 (exp, 0); } /* Implementation of the "output" command. */ -static void -output_command (char *exp, int from_tty) -{ - output_command_const (exp, from_tty); -} - -/* Like output_command, but takes a const string as argument. */ - void -output_command_const (const char *exp, int from_tty) +output_command (const char *exp, int from_tty) { char format = 0; struct value *val; @@ -1320,7 +1244,7 @@ output_command_const (const char *exp, int from_tty) } static void -set_command (char *exp, int from_tty) +set_command (const char *exp, int from_tty) { expression_up expr = parse_expression (exp); @@ -1344,7 +1268,7 @@ set_command (char *exp, int from_tty) } static void -sym_info (char *arg, int from_tty) +info_symbol_command (const char *arg, int from_tty) { struct minimal_symbol *msymbol; struct objfile *objfile; @@ -1372,8 +1296,7 @@ sym_info (char *arg, int from_tty) = lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym)) { const char *obj_name, *mapped, *sec_name, *msym_name; - char *loc_string; - struct cleanup *old_chain; + const char *loc_string; matches = 1; offset = sect_addr - MSYMBOL_VALUE_ADDRESS (objfile, msymbol); @@ -1383,14 +1306,14 @@ 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". */ + std::string string_holder; if (offset) - loc_string = xstrprintf ("%s + %u", msym_name, offset); + { + string_holder = string_printf ("%s + %u", msym_name, offset); + loc_string = string_holder.c_str (); + } else - 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); + loc_string = msym_name; gdb_assert (osect->objfile && objfile_name (osect->objfile)); obj_name = objfile_name (osect->objfile); @@ -1428,8 +1351,6 @@ sym_info (char *arg, int from_tty) else printf_filtered (_("%s in section %s\n"), loc_string, sec_name); - - do_cleanups (old_chain); } } if (matches == 0) @@ -1437,7 +1358,7 @@ sym_info (char *arg, int from_tty) } static void -address_info (char *exp, int from_tty) +info_address_command (const char *exp, int from_tty) { struct gdbarch *gdbarch; int regno; @@ -1598,7 +1519,7 @@ address_info (char *exp, int from_tty) case LOC_BLOCK: printf_filtered (_("a function at address ")); - load_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + load_addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)); fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout); if (section_is_overlay (section)) { @@ -1614,7 +1535,7 @@ address_info (char *exp, int from_tty) { struct bound_minimal_symbol msym; - msym = lookup_minimal_symbol_and_objfile (SYMBOL_LINKAGE_NAME (sym)); + msym = lookup_bound_minimal_symbol (SYMBOL_LINKAGE_NAME (sym)); if (msym.minsym == NULL) printf_filtered ("unresolved"); else @@ -1661,10 +1582,9 @@ address_info (char *exp, int from_tty) static void -x_command (char *exp, int from_tty) +x_command (const char *exp, int from_tty) { struct format_data fmt; - struct cleanup *old_chain; struct value *val; fmt.format = last_format ? last_format : 'x'; @@ -1672,6 +1592,11 @@ x_command (char *exp, int from_tty) fmt.count = 1; fmt.raw = 0; + /* If there is no expression and no format, use the most recent + count. */ + if (exp == nullptr && last_count > 0) + fmt.count = last_count; + if (exp && *exp == '/') { const char *tmp = exp + 1; @@ -1680,6 +1605,8 @@ x_command (char *exp, int from_tty) exp = (char *) tmp; } + last_count = fmt.count; + /* If we have an expression, evaluate it and use it as the address. */ if (exp != 0 && *exp != 0) @@ -1689,9 +1616,9 @@ x_command (char *exp, int from_tty) repeated with Newline. But don't clobber a user-defined command's definition. */ if (from_tty) - *exp = 0; + set_repeat_arguments (""); val = evaluate_expression (expr.get ()); - if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF) + if (TYPE_IS_REFERENCE (value_type (val))) val = coerce_ref (val); /* In rvalue contexts, such as this, functions are coerced into pointers to functions. This makes "x/i main" work. */ @@ -1719,12 +1646,12 @@ x_command (char *exp, int from_tty) last_format = fmt.format; /* Set a couple of internal variables if appropriate. */ - if (last_examine_value) + if (last_examine_value != nullptr) { /* Make last address examined available to the user as $_. Use the correct pointer type. */ struct type *pointer_type - = lookup_pointer_type (value_type (last_examine_value)); + = lookup_pointer_type (value_type (last_examine_value.get ())); set_internalvar (lookup_internalvar ("_"), value_from_pointer (pointer_type, last_examine_address)); @@ -1733,10 +1660,10 @@ x_command (char *exp, int from_tty) as $__. If the last value has not been fetched from memory then don't fetch it now; instead mark it by voiding the $__ variable. */ - if (value_lazy (last_examine_value)) + if (value_lazy (last_examine_value.get ())) clear_internalvar (lookup_internalvar ("__")); else - set_internalvar (lookup_internalvar ("__"), last_examine_value); + set_internalvar (lookup_internalvar ("__"), last_examine_value.get ()); } } @@ -1745,7 +1672,7 @@ x_command (char *exp, int from_tty) Specify the expression. */ static void -display_command (char *arg, int from_tty) +display_command (const char *arg, int from_tty) { struct format_data fmt; struct display *newobj; @@ -1774,14 +1701,14 @@ display_command (char *arg, int from_tty) fmt.raw = 0; } - innermost_block = NULL; + innermost_block.reset (); expression_up expr = parse_expression (exp); newobj = new display (); newobj->exp_string = xstrdup (exp); newobj->exp = std::move (expr); - newobj->block = innermost_block; + newobj->block = innermost_block.block (); newobj->pspace = current_program_space; newobj->number = ++display_number; newobj->format = fmt; @@ -1853,7 +1780,7 @@ delete_display (struct display *display) ARGS. DATA is passed unmodified to FUNCTION. */ static void -map_display_numbers (char *args, +map_display_numbers (const char *args, void (*function) (struct display *, void *), void *data) @@ -1898,7 +1825,7 @@ do_delete_display (struct display *d, void *data) /* "undisplay" command. */ static void -undisplay_command (char *args, int from_tty) +undisplay_command (const char *args, int from_tty) { if (args == NULL) { @@ -1942,9 +1869,9 @@ do_one_display (struct display *d) TRY { - innermost_block = NULL; + innermost_block.reset (); d->exp = parse_expression (d->exp_string); - d->block = innermost_block; + d->block = innermost_block.block (); } CATCH (ex, RETURN_MASK_ALL) { @@ -2104,7 +2031,7 @@ disable_current_display (void) } static void -display_info (char *ignore, int from_tty) +info_display_command (const char *ignore, int from_tty) { struct display *d; @@ -2143,7 +2070,7 @@ do_enable_disable_display (struct display *d, void *data) commands. ENABLE decides what to do. */ static void -enable_disable_display_command (char *args, int from_tty, int enable) +enable_disable_display_command (const char *args, int from_tty, int enable) { if (args == NULL) { @@ -2160,7 +2087,7 @@ enable_disable_display_command (char *args, int from_tty, int enable) /* The "enable display" command. */ static void -enable_display_command (char *args, int from_tty) +enable_display_command (const char *args, int from_tty) { enable_disable_display_command (args, from_tty, 1); } @@ -2168,7 +2095,7 @@ enable_display_command (char *args, int from_tty) /* The "disable display" command. */ static void -disable_display_command (char *args, int from_tty) +disable_display_command (const char *args, int from_tty) { enable_disable_display_command (args, from_tty, 0); } @@ -2271,6 +2198,14 @@ printf_c_string (struct ui_file *stream, const char *format, int j; tem = value_as_address (value); + if (tem == 0) + { + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL + fprintf_filtered (stream, format, "(null)"); + DIAGNOSTIC_POP + return; + } /* This is a %s argument. Find the length of the string. */ for (j = 0;; j++) @@ -2289,7 +2224,10 @@ printf_c_string (struct ui_file *stream, const char *format, read_memory (tem, str, j); str[j] = 0; + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, format, (char *) str); + DIAGNOSTIC_POP } /* Subroutine of ui_printf to simplify it. @@ -2309,10 +2247,16 @@ printf_wide_c_string (struct ui_file *stream, const char *format, "wchar_t", NULL, 0); int wcwidth = TYPE_LENGTH (wctype); gdb_byte *buf = (gdb_byte *) alloca (wcwidth); - struct obstack output; - struct cleanup *inner_cleanup; tem = value_as_address (value); + if (tem == 0) + { + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL + fprintf_filtered (stream, format, "(null)"); + DIAGNOSTIC_POP + return; + } /* This is a %s argument. Find the length of the string. */ for (j = 0;; j += wcwidth) @@ -2329,8 +2273,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format, read_memory (tem, str, j); memset (&str[j], 0, wcwidth); - obstack_init (&output); - inner_cleanup = make_cleanup_obstack_free (&output); + auto_obstack output; convert_between_encodings (target_wide_charset (gdbarch), host_charset (), @@ -2338,93 +2281,79 @@ printf_wide_c_string (struct ui_file *stream, const char *format, &output, translit_char); obstack_grow_str0 (&output, ""); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, format, obstack_base (&output)); - do_cleanups (inner_cleanup); + DIAGNOSTIC_POP } /* Subroutine of ui_printf to simplify it. - Print VALUE, a decimal floating point value, to STREAM using FORMAT. */ + Print VALUE, a floating point value, to STREAM using FORMAT. */ static void -printf_decfloat (struct ui_file *stream, const char *format, - struct value *value) +printf_floating (struct ui_file *stream, const char *format, + struct value *value, enum argclass argclass) { - 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; - } + /* Determine target type corresponding to the format string. */ + struct type *fmt_type; + switch (argclass) + { + case double_arg: + fmt_type = builtin_type (gdbarch)->builtin_double; + break; + case long_double_arg: + fmt_type = builtin_type (gdbarch)->builtin_long_double; + break; + case dec32float_arg: + fmt_type = builtin_type (gdbarch)->builtin_decfloat; + break; + case dec64float_arg: + fmt_type = builtin_type (gdbarch)->builtin_decdouble; + break; + case dec128float_arg: + fmt_type = builtin_type (gdbarch)->builtin_declong; + break; + default: + gdb_assert_not_reached ("unexpected argument class"); } - /* 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"); + /* To match the traditional GDB behavior, the conversion is + done differently depending on the type of the parameter: - dfp_value = value_from_decfloat (dfp_type, dec); + - if the parameter has floating-point type, it's value + is converted to the target type; - dfp_ptr = (gdb_byte *) value_contents (dfp_value); + - otherwise, if the parameter has a type that is of the + same size as a built-in floating-point type, the value + bytes are interpreted as if they were of that type, and + then converted to the target type (this is not done for + decimal floating-point argument classes); - decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr); + - otherwise, if the source value has an integer value, + it's value is converted to the target type; - /* Print the DFP value. */ - fprintf_filtered (stream, "%s", decstr); -#endif + - otherwise, an error is raised. + + In either case, the result of the conversion is a byte buffer + formatted in the target format for the target type. */ + + if (TYPE_CODE (fmt_type) == TYPE_CODE_FLT) + { + param_type = float_type_from_length (param_type); + if (param_type != value_type (value)) + value = value_from_contents (param_type, value_contents (value)); + } + + value = value_cast (fmt_type, value); + + /* Convert the value to a string and print it. */ + std::string str + = target_float_to_string (value_contents (value), fmt_type, format); + fputs_filtered (str.c_str (), stream); } /* Subroutine of ui_printf to simplify it. @@ -2469,8 +2398,9 @@ printf_pointer (struct ui_file *stream, const char *format, if (val != 0) *fmt_p++ = '#'; - /* Copy any width. */ - while (*p >= '0' && *p < '9') + /* Copy any width or flags. Only the "-" flag is valid for pointers + -- see the format_pieces constructor. */ + while (*p == '-' || (*p >= '0' && *p < '9')) *fmt_p++ = *p++; gdb_assert (*p == 'p' && *(p + 1) == '\0'); @@ -2482,13 +2412,19 @@ printf_pointer (struct ui_file *stream, const char *format, *fmt_p++ = 'l'; *fmt_p++ = 'x'; *fmt_p++ = '\0'; + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, fmt, val); + DIAGNOSTIC_POP } else { *fmt_p++ = 's'; *fmt_p++ = '\0'; + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, fmt, "(nil)"); + DIAGNOSTIC_POP } } @@ -2497,49 +2433,40 @@ printf_pointer (struct ui_file *stream, const char *format, 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; - - val_args = XNEWVEC (struct value *, allocated_args); - old_cleanups = make_cleanup (free_current_contents, &val_args); + std::vector val_args; if (s == 0) error_no_arg (_("format-control string and values to print")); - s = skip_spaces_const (s); + s = skip_spaces (s); /* A format string should follow, enveloped in double quotes. */ if (*s++ != '"') error (_("Bad format string, missing '\"'.")); - fpieces = parse_format_string (&s); - - make_cleanup (free_format_pieces_cleanup, &fpieces); + format_pieces fpieces (&s); if (*s++ != '"') error (_("Bad format string, non-terminated '\"'.")); - s = skip_spaces_const (s); + s = skip_spaces (s); if (*s != ',' && *s != 0) error (_("Invalid argument syntax")); if (*s == ',') s++; - s = skip_spaces_const (s); + s = skip_spaces (s); { - int nargs = 0; int nargs_wanted; - int i, fr; - char *current_substring; + int i; + const char *current_substring; nargs_wanted = 0; - for (fr = 0; fpieces[fr].string != NULL; fr++) - if (fpieces[fr].argclass != literal_piece) + for (auto &&piece : fpieces) + if (piece.argclass != literal_piece) ++nargs_wanted; /* Now, parse all arguments and evaluate them. @@ -2549,28 +2476,23 @@ ui_printf (const char *arg, struct ui_file *stream) { const char *s1; - if (nargs == allocated_args) - val_args = (struct value **) xrealloc ((char *) val_args, - (allocated_args *= 2) - * sizeof (struct value *)); s1 = s; - val_args[nargs] = parse_to_comma_and_eval (&s1); + val_args.push_back (parse_to_comma_and_eval (&s1)); - nargs++; s = s1; if (*s == ',') s++; } - if (nargs != nargs_wanted) + if (val_args.size () != nargs_wanted) error (_("Wrong number of arguments for specified format-string")); /* Now actually print them. */ i = 0; - for (fr = 0; fpieces[fr].string != NULL; fr++) + for (auto &&piece : fpieces) { - current_substring = fpieces[fr].string; - switch (fpieces[fr].argclass) + current_substring = piece.string; + switch (piece.argclass) { case string_arg: printf_c_string (stream, current_substring, val_args[i]); @@ -2585,8 +2507,6 @@ ui_printf (const char *arg, struct ui_file *stream) 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]); @@ -2596,8 +2516,7 @@ ui_printf (const char *arg, struct ui_file *stream) bytes = value_contents (val_args[i]); - obstack_init (&output); - inner_cleanup = make_cleanup_obstack_free (&output); + auto_obstack output; convert_between_encodings (target_wide_charset (gdbarch), host_charset (), @@ -2606,54 +2525,22 @@ ui_printf (const char *arg, struct ui_file *stream) &output, translit_char); obstack_grow_str0 (&output, ""); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, current_substring, obstack_base (&output)); - do_cleanups (inner_cleanup); + DIAGNOSTIC_POP } break; - case double_arg: - { - struct type *type = value_type (val_args[i]); - DOUBLEST val; - int inv; - - /* If format string wants a float, unchecked-convert the value - to floating point of the same size. */ - 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.")); - - fprintf_filtered (stream, current_substring, (double) val); - break; - } - case long_double_arg: -#ifdef HAVE_LONG_DOUBLE - { - struct type *type = value_type (val_args[i]); - DOUBLEST val; - int inv; - - /* If format string wants a float, unchecked-convert the value - to floating point of the same size. */ - 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.")); - - fprintf_filtered (stream, current_substring, - (long double) val); - break; - } -#else - error (_("long double not supported in printf")); -#endif case long_long_arg: #ifdef PRINTF_HAS_LONG_LONG { long long val = value_as_long (val_args[i]); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, current_substring, val); + DIAGNOSTIC_POP break; } #else @@ -2663,19 +2550,30 @@ ui_printf (const char *arg, struct ui_file *stream) { int val = value_as_long (val_args[i]); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, current_substring, val); + DIAGNOSTIC_POP break; } case long_arg: { long val = value_as_long (val_args[i]); + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, current_substring, val); + DIAGNOSTIC_POP break; } - /* Handles decimal floating values. */ - case decfloat_arg: - printf_decfloat (stream, current_substring, val_args[i]); + /* Handles floating-point values. */ + case double_arg: + case long_double_arg: + case dec32float_arg: + case dec64float_arg: + case dec128float_arg: + printf_floating (stream, current_substring, val_args[i], + piece.argclass); break; case ptr_arg: printf_pointer (stream, current_substring, val_args[i]); @@ -2689,24 +2587,26 @@ ui_printf (const char *arg, struct ui_file *stream) have modified GCC to include -Wformat-security by default, which will warn here if there is no argument. */ + DIAGNOSTIC_PUSH + DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL fprintf_filtered (stream, current_substring, 0); + DIAGNOSTIC_POP break; default: internal_error (__FILE__, __LINE__, _("failed internal consistency check")); } /* Maybe advance to the next argument. */ - if (fpieces[fr].argclass != literal_piece) + if (piece.argclass != literal_piece) ++i; } } - do_cleanups (old_cleanups); } /* Implement the "printf" command. */ static void -printf_command (char *arg, int from_tty) +printf_command (const char *arg, int from_tty) { ui_printf (arg, gdb_stdout); gdb_flush (gdb_stdout); @@ -2715,20 +2615,15 @@ printf_command (char *arg, int from_tty) /* Implement the "eval" command. */ static void -eval_command (char *arg, int from_tty) +eval_command (const char *arg, int from_tty) { - struct ui_file *ui_out = mem_fileopen (); - struct cleanup *cleanups = make_cleanup_ui_file_delete (ui_out); - - ui_printf (arg, ui_out); - - std::string expanded = ui_file_as_string (ui_out); + string_file stb; - expanded = insert_user_defined_cmd_args (expanded.c_str ()); + ui_printf (arg, &stb); - execute_command (&expanded[0], from_tty); + std::string expanded = insert_user_defined_cmd_args (stb.c_str ()); - do_cleanups (cleanups); + execute_command (expanded.c_str (), from_tty); } void @@ -2738,12 +2633,12 @@ _initialize_printcmd (void) current_display_number = -1; - observer_attach_free_objfile (clear_dangling_display_expressions); + gdb::observers::free_objfile.attach (clear_dangling_display_expressions); - add_info ("address", address_info, + add_info ("address", info_address_command, _("Describe where symbol SYM is stored.")); - add_info ("symbol", sym_info, _("\ + add_info ("symbol", info_symbol_command, _("\ Describe what symbol is at location ADDR.\n\ Only for symbols with fixed locations (global or static scope).")); @@ -2767,7 +2662,7 @@ with this command or \"print\".")); _("Print line number and file of definition of variable.")); #endif - add_info ("display", display_info, _("\ + add_info ("display", info_display_command, _("\ Expressions to display when program stops, with code numbers.")); add_cmd ("undisplay", class_vars, undisplay_command, _("\ @@ -2806,8 +2701,9 @@ No argument means cancel all automatic-display expressions.\n\ Do \"info display\" to see current list of code numbers."), &deletelist); add_com ("printf", class_vars, printf_command, _("\ -printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ -This is useful for formatted output in user-defined commands.")); +Formatted printing, like the C \"printf\" function.\n\ +Usage: printf \"format string\", arg1, arg2, arg3, ..., argn\n\ +This supports most C printf format specifications, like %s, %d, etc.")); add_com ("output", class_vars, output_command, _("\ Like \"print\" but don't put in value history and don't print newline.\n\ @@ -2851,6 +2747,7 @@ with $), a register (a few standard names starting with $), or an actual\n\ variable in the program being debugged. EXP is any valid expression.\n\ This may usually be abbreviated to simply \"set\"."), &setlist); + add_alias_cmd ("var", "variable", class_vars, 0, &setlist); c = add_com ("print", class_vars, print_command, _("\ Print value of expression EXP.\n\