| Index: gdb/printcmd.c
|
| diff --git a/gdb/printcmd.c b/gdb/printcmd.c
|
| index d5b5b63122a7d99f7c53e8cf187544eb3927aee0..001c0777a59fdef1516c0d4f31da066a56432f3f 100644
|
| --- a/gdb/printcmd.c
|
| +++ b/gdb/printcmd.c
|
| @@ -1,6 +1,6 @@
|
| /* Print values for GNU debugger GDB.
|
|
|
| - Copyright (C) 1986-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1986-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -18,7 +18,7 @@
|
| along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
| #include "defs.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "frame.h"
|
| #include "symtab.h"
|
| #include "gdbtypes.h"
|
| @@ -50,6 +50,7 @@
|
| #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. */
|
| @@ -122,7 +123,7 @@ show_print_symbol_filename (struct ui_file *file, int from_tty,
|
| 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
|
| {
|
| @@ -145,7 +146,7 @@ struct display
|
| struct program_space *pspace;
|
|
|
| /* Innermost block required by this expression when evaluated. */
|
| - struct block *block;
|
| + const struct block *block;
|
|
|
| /* Status of this display (enabled or disabled). */
|
| int enabled_p;
|
| @@ -172,8 +173,6 @@ static int display_number;
|
|
|
| /* Prototypes for exported functions. */
|
|
|
| -void output_command (char *, int);
|
| -
|
| void _initialize_printcmd (void);
|
|
|
| /* Prototypes for local functions. */
|
| @@ -192,10 +191,10 @@ 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 = '?';
|
| @@ -346,13 +345,12 @@ 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;
|
| @@ -535,6 +533,10 @@ print_scalar_formatted (const void *valaddr, struct type *type,
|
| }
|
| break;
|
|
|
| + case 'z':
|
| + print_hex_chars (stream, valaddr, len, byte_order);
|
| + break;
|
| +
|
| default:
|
| error (_("Undefined output format \"%c\"."), options->format);
|
| }
|
| @@ -660,7 +662,7 @@ build_address_symbolic (struct gdbarch *gdbarch,
|
| 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)
|
| @@ -680,6 +682,7 @@ build_address_symbolic (struct gdbarch *gdbarch,
|
| }
|
|
|
| if (msymbol != NULL
|
| + && MSYMBOL_HAS_SIZE (msymbol)
|
| && MSYMBOL_SIZE (msymbol) == 0
|
| && MSYMBOL_TYPE (msymbol) != mst_text
|
| && MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc
|
| @@ -690,6 +693,17 @@ build_address_symbolic (struct gdbarch *gdbarch,
|
| {
|
| 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 <function>; the
|
| + second instruction will be <function+2>, even though the
|
| + pointer is <function+3>. 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;
|
| @@ -726,7 +740,7 @@ build_address_symbolic (struct gdbarch *gdbarch,
|
|
|
| if (sal.symtab)
|
| {
|
| - *filename = xstrdup (sal.symtab->filename);
|
| + *filename = xstrdup (symtab_to_filename_for_display (sal.symtab));
|
| *line = sal.line;
|
| }
|
| }
|
| @@ -934,14 +948,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 == '/')
|
| {
|
| @@ -961,8 +974,7 @@ print_command_1 (char *exp, int inspect, int voidprint)
|
| if (exp && *exp)
|
| {
|
| 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
|
| @@ -979,17 +991,13 @@ 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);
|
| @@ -999,39 +1007,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;
|
| @@ -1122,7 +1127,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;
|
| @@ -1145,8 +1151,8 @@ sym_info (char *arg, int from_tty)
|
| 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))
|
| @@ -1195,12 +1201,11 @@ 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, context_pc = 0;
|
| - int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero
|
| - if exp is a field of `this'. */
|
| + struct field_of_this_result is_a_field_of_this;
|
|
|
| if (exp == 0)
|
| error (_("Argument required."));
|
| @@ -1209,7 +1214,7 @@ address_info (char *exp, int from_tty)
|
| &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,
|
| @@ -1222,12 +1227,14 @@ 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)
|
| {
|
| - gdbarch = get_objfile_arch (msymbol_objfile (msymbol));
|
| - 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,
|
| @@ -1235,7 +1242,7 @@ address_info (char *exp, int from_tty)
|
| printf_filtered ("\" is at ");
|
| 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);
|
| @@ -1256,9 +1263,17 @@ 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))
|
| {
|
| case LOC_CONST:
|
| @@ -1281,14 +1296,7 @@ address_info (char *exp, int from_tty)
|
| break;
|
|
|
| case LOC_COMPUTED:
|
| - /* FIXME: cagney/2004-01-26: It should be possible to
|
| - unconditionally call the SYMBOL_COMPUTED_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_COMPUTED_OPS (sym)->describe_location (sym, context_pc,
|
| - 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
|
| @@ -1360,22 +1368,22 @@ 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'"),
|
| paddress (gdbarch, load_addr),
|
| - section->objfile->name);
|
| + objfile_name (section->objfile));
|
| else
|
| {
|
| printf_filtered (_("static storage at address "));
|
| @@ -1420,8 +1428,10 @@ x_command (char *exp, int from_tty)
|
|
|
| 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. */
|
| @@ -1491,12 +1501,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
|
| @@ -1929,21 +1940,24 @@ disable_display_command (char *args, int from_tty)
|
| 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 objfile *objfile = solib->objfile;
|
| struct display *d;
|
| + struct program_space *pspace;
|
|
|
| /* 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)
|
| - objfile = objfile->separate_debug_objfile_backlink;
|
| - gdb_assert (objfile->pspace == solib->pspace);
|
| + {
|
| + objfile = objfile->separate_debug_objfile_backlink;
|
| + gdb_assert (objfile->pspace == pspace);
|
| + }
|
|
|
| for (d = display_chain; d != NULL; d = d->next)
|
| {
|
| - if (d->pspace != solib->pspace)
|
| + if (d->pspace != pspace)
|
| continue;
|
|
|
| if (lookup_objfile_from_block (d->block) == objfile
|
| @@ -1996,13 +2010,247 @@ print_variable_and_value (const char *name, struct symbol *var,
|
| 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_c_string (struct ui_file *stream, const char *format,
|
| + struct value *value)
|
| +{
|
| + gdb_byte *str;
|
| + CORE_ADDR tem;
|
| + int j;
|
| +
|
| + tem = value_as_address (value);
|
| +
|
| + /* 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;
|
| +
|
| + fprintf_filtered (stream, format, (char *) str);
|
| +}
|
| +
|
| +/* Subroutine of ui_printf to simplify it.
|
| + Print VALUE to STREAM using FORMAT.
|
| + VALUE is a wide C-style string on the target. */
|
| +
|
| +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)
|
| + {
|
| + QUIT;
|
| + read_memory (tem + j, buf, wcwidth);
|
| + if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
|
| + 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);
|
| +
|
| + 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;
|
| + }
|
| + }
|
| +
|
| + /* 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");
|
| +
|
| + dfp_value = value_from_decfloat (dfp_type, dec);
|
| +
|
| + dfp_ptr = (gdb_byte *) value_contents (dfp_value);
|
| +
|
| + decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
|
| +
|
| + /* Print the DFP value. */
|
| + fprintf_filtered (stream, "%s", decstr);
|
| +#endif
|
| +}
|
| +
|
| +/* Subroutine of ui_printf to simplify it.
|
| + Print VALUE, a target pointer, to STREAM using FORMAT. */
|
| +
|
| +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)
|
| + {
|
| + 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)
|
| + {
|
| +#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)");
|
| + }
|
| +}
|
| +
|
| /* printf "printf format string" ARG to STREAM. */
|
|
|
| static void
|
| -ui_printf (char *arg, struct ui_file *stream)
|
| +ui_printf (const char *arg, struct ui_file *stream)
|
| {
|
| struct format_piece *fpieces;
|
| - char *s = arg;
|
| + const char *s = arg;
|
| struct value **val_args;
|
| int allocated_args = 20;
|
| struct cleanup *old_cleanups;
|
| @@ -2013,7 +2261,7 @@ ui_printf (char *arg, struct ui_file *stream)
|
| if (s == 0)
|
| error_no_arg (_("format-control string and values to print"));
|
|
|
| - s = skip_spaces (s);
|
| + s = skip_spaces_const (s);
|
|
|
| /* A format string should follow, enveloped in double quotes. */
|
| if (*s++ != '"')
|
| @@ -2026,14 +2274,14 @@ ui_printf (char *arg, struct ui_file *stream)
|
| if (*s++ != '"')
|
| error (_("Bad format string, non-terminated '\"'."));
|
|
|
| - s = skip_spaces (s);
|
| + s = skip_spaces_const (s);
|
|
|
| if (*s != ',' && *s != 0)
|
| error (_("Invalid argument syntax"));
|
|
|
| if (*s == ',')
|
| s++;
|
| - s = skip_spaces (s);
|
| + s = skip_spaces_const (s);
|
|
|
| {
|
| int nargs = 0;
|
| @@ -2051,7 +2299,7 @@ ui_printf (char *arg, struct ui_file *stream)
|
|
|
| while (*s != '\0')
|
| {
|
| - char *s1;
|
| + const char *s1;
|
|
|
| if (nargs == allocated_args)
|
| val_args = (struct value **) xrealloc ((char *) val_args,
|
| @@ -2077,78 +2325,10 @@ ui_printf (char *arg, struct ui_file *stream)
|
| switch (fpieces[fr].argclass)
|
| {
|
| case string_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;
|
| -
|
| - fprintf_filtered (stream, current_substring, (char *) str);
|
| - }
|
| + printf_c_string (stream, current_substring, val_args[i]);
|
| break;
|
| case wide_string_arg:
|
| - {
|
| - gdb_byte *str;
|
| - CORE_ADDR tem;
|
| - int j;
|
| - struct gdbarch *gdbarch
|
| - = get_type_arch (value_type (val_args[i]));
|
| - 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 (val_args[i]);
|
| -
|
| - /* This is a %s argument. Find the length of the string. */
|
| - for (j = 0;; j += wcwidth)
|
| - {
|
| - QUIT;
|
| - read_memory (tem + j, buf, wcwidth);
|
| - if (extract_unsigned_integer (buf, wcwidth, byte_order) == 0)
|
| - 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);
|
| -
|
| - 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, current_substring,
|
| - obstack_base (&output));
|
| - do_cleanups (inner_cleanup);
|
| - }
|
| + printf_wide_c_string (stream, current_substring, val_args[i]);
|
| break;
|
| case wide_char_arg:
|
| {
|
| @@ -2221,7 +2401,7 @@ ui_printf (char *arg, struct ui_file *stream)
|
| 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]);
|
|
|
| @@ -2245,170 +2425,13 @@ ui_printf (char *arg, struct ui_file *stream)
|
| fprintf_filtered (stream, 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. */
|
| - fprintf_filtered (stream, 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);
|
| - 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. */
|
| - 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 (gdbarch)->builtin_decfloat;
|
| - }
|
| - else if (*sos == 'D' && *(sos - 1) == 'D')
|
| - {
|
| - dfp_len = 16;
|
| - dfp_type = builtin_type (gdbarch)->builtin_declong;
|
| - sos--;
|
| - }
|
| - else
|
| - {
|
| - dfp_len = 8;
|
| - dfp_type = builtin_type (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, 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");
|
| -
|
| - dfp_value = value_from_decfloat (dfp_type, dec);
|
| -
|
| - dfp_ptr = (gdb_byte *) value_contents (dfp_value);
|
| -
|
| - decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
|
| -
|
| - /* Print the DFP value. */
|
| - fprintf_filtered (stream, current_substring, decstr);
|
| -
|
| - break;
|
| -#endif
|
| - }
|
| -
|
| + 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';
|
| - fprintf_filtered (stream, fmt, val);
|
| - }
|
| - else
|
| - {
|
| - *fmt_p++ = 's';
|
| - *fmt_p++ = '\0';
|
| - fprintf_filtered (stream, 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
|
| @@ -2438,6 +2461,7 @@ static void
|
| printf_command (char *arg, int from_tty)
|
| {
|
| ui_printf (arg, gdb_stdout);
|
| + gdb_flush (gdb_stdout);
|
| }
|
|
|
| /* Implement the "eval" command. */
|
| @@ -2466,7 +2490,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."));
|
| @@ -2480,7 +2504,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\
|
| @@ -2602,16 +2627,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 <symbol+1234> form."), _("\
|
| -Show the largest offset that will be printed in <symbol+1234> form."), NULL,
|
| +Show the largest offset that will be printed in <symbol+1234> 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);
|
|
|