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 Free Software Foundation, Inc.
+ 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GDB.
#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"
#ifdef TUI
#include "tui/tui.h" /* For tui_active et.al. */
#endif
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) && !defined(PRINTF_HAS_LONG_LONG)
# define USE_PRINTF_I64 1
# define PRINTF_HAS_LONG_LONG
#else
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. */
{
/* 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;
+
+ /* Program space associated with `block'. */
+ struct program_space *pspace;
+
/* Innermost block required by this expression when evaluated */
struct block *block;
+
/* Status of this display (enabled or disabled) */
int enabled_p;
};
val.format = '?';
val.size = '?';
val.count = 1;
+ val.raw = 0;
if (*p >= '0' && *p <= '9')
val.count = atoi (p);
{
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
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. */
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,
+ value_address (val), -1,
+ stream, options));
+ }
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;
}
/* 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);
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
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;
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;
case 'a':
{
CORE_ADDR addr = unpack_pointer (type, valaddr);
- print_address (addr, stream);
+ print_address (gdbarch, addr, stream);
}
break;
{
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;
{
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+ next_gdbarch = gdbarch;
next_address = addr;
/* Make address available to the user as $_. */
settings of the demangle and asm_demangle variables. */
void
-print_address_symbolic (CORE_ADDR addr, struct ui_file *stream,
+print_address_symbolic (struct gdbarch *gdbarch, CORE_ADDR addr,
+ struct ui_file *stream,
int do_demangle, char *leadin)
{
char *name = NULL;
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);
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 */
struct obj_section *section = NULL;
char *name_temp = "";
- /* Let's say it is unmapped. */
+ /* Let's say it is mapped (not unmapped). */
*unmapped = 0;
/* Determine if the address is in an overlay, and whether it is
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 <function>; the
+ second instruction will be <function+2>, even though the
+ pointer is <function+3>. 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);
<SYMBOL + OFFSET> 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, " ");
+}
+
+/* Return a prefix for instruction address:
+ "=> " for current instruction, else " ". */
+
+const char *
+pc_prefix (CORE_ADDR addr)
+{
+ if (has_stack_frames ())
+ {
+ struct frame_info *frame;
+ CORE_ADDR pc;
+
+ frame = get_selected_frame (NULL);
+ pc = get_frame_pc (frame);
+
+ if (pc == addr)
+ return "=> ";
+ }
+ return " ";
}
/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE
or not. */
void
-print_address_demangle (CORE_ADDR addr, struct ui_file *stream,
- int do_demangle)
+print_address_demangle (struct gdbarch *gdbarch, CORE_ADDR addr,
+ struct ui_file *stream, int do_demangle)
{
struct value_print_options opts;
get_user_print_options (&opts);
}
else 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, "");
+ print_address_symbolic (gdbarch, addr, stream, do_demangle, "");
}
}
\f
-/* 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;
format = fmt.format;
size = fmt.size;
count = fmt.count;
+ next_gdbarch = gdbarch;
next_address = addr;
/* String or instruction format implies fetch single bytes
if (format == 's' || 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;
maxelts = 8;
if (size == 'w')
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;
fmt.count = 1;
fmt.format = 0;
fmt.size = 0;
+ fmt.raw = 0;
}
if (exp && *exp)
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");
struct value_print_options opts;
fmt.size = 0;
+ fmt.raw = 0;
if (exp && *exp == '/')
{
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 ();
&& sect_addr < obj_section_endaddr (osect)
&& (msymbol = lookup_minimal_symbol_by_pc_section (sect_addr, osect)))
{
+ const char *obj_name, *mapped, *sec_name, *msym_name;
+ char *loc_string;
+ struct cleanup *old_chain;
+
matches = 1;
offset = sect_addr - SYMBOL_VALUE_ADDRESS (msymbol);
+ mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
+ sec_name = osect->the_bfd_section->name;
+ msym_name = SYMBOL_PRINT_NAME (msymbol);
+
+ /* Don't print the offset if it is zero.
+ We assume there's no need to handle i18n of "sym + offset". */
if (offset)
- printf_filtered ("%s + %u in ",
- SYMBOL_PRINT_NAME (msymbol), offset);
+ loc_string = xstrprintf ("%s + %u", msym_name, offset);
else
- printf_filtered ("%s in ",
- SYMBOL_PRINT_NAME (msymbol));
- if (pc_in_unmapped_range (addr, osect))
- printf_filtered (_("load address range of "));
- if (section_is_overlay (osect))
- printf_filtered (_("%s overlay "),
- section_is_mapped (osect) ? "mapped" : "unmapped");
- printf_filtered (_("section %s"), osect->the_bfd_section->name);
- printf_filtered ("\n");
+ 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;
+
+ if (MULTI_OBJFILE_P ())
+ if (pc_in_unmapped_range (addr, osect))
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in load address range of "
+ "%s overlay section %s of %s\n"),
+ loc_string, mapped, sec_name, obj_name);
+ else
+ printf_filtered (_("%s in load address range of "
+ "section %s of %s\n"),
+ loc_string, sec_name, obj_name);
+ else
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in %s overlay section %s of %s\n"),
+ loc_string, mapped, sec_name, obj_name);
+ else
+ printf_filtered (_("%s in section %s of %s\n"),
+ loc_string, sec_name, obj_name);
+ else
+ if (pc_in_unmapped_range (addr, osect))
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in load address range of %s overlay "
+ "section %s\n"),
+ loc_string, mapped, sec_name);
+ else
+ printf_filtered (_("%s in load address range of section %s\n"),
+ loc_string, sec_name);
+ else
+ if (section_is_overlay (osect))
+ printf_filtered (_("%s in %s overlay section %s\n"),
+ loc_string, mapped, sec_name);
+ else
+ printf_filtered (_("%s in section %s\n"),
+ loc_string, sec_name);
+
+ do_cleanups (old_chain);
}
}
if (matches == 0)
static void
address_info (char *exp, int from_tty)
{
+ struct gdbarch *gdbarch;
+ int regno;
struct symbol *sym;
struct minimal_symbol *msymbol;
long val;
if (msymbol != NULL)
{
+ gdbarch = get_objfile_arch (msymbol_objfile (msymbol));
load_addr = SYMBOL_VALUE_ADDRESS (msymbol);
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);
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);
}
printf_filtered ("\" is ");
val = SYMBOL_VALUE (sym);
section = SYMBOL_OBJ_SECTION (sym);
+ gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile);
switch (SYMBOL_CLASS (sym))
{
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);
}
case LOC_COMPUTED:
/* FIXME: cagney/2004-01-26: It should be possible to
- unconditionally call the SYMBOL_OPS method when available.
+ 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_OPS (sym)->describe_location (sym, gdb_stdout);
+ SYMBOL_COMPUTED_OPS (sym)->describe_location (sym, gdb_stdout);
break;
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:
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);
}
else
{
section = SYMBOL_OBJ_SECTION (msym);
- printf_filtered (_("static storage at address "));
load_addr = SYMBOL_VALUE_ADDRESS (msym);
- fputs_filtered (paddress (load_addr), gdb_stdout);
- if (section_is_overlay (section))
+
+ 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);
+ else
{
- load_addr = overlay_unmapped_address (load_addr, section);
- printf_filtered (_(",\n -- loaded at "));
- fputs_filtered (paddress (load_addr), gdb_stdout);
- printf_filtered (_(" in overlay section %s"),
- section->the_bfd_section->name);
+ printf_filtered (_("static storage at address "));
+ 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 (gdbarch, load_addr), gdb_stdout);
+ printf_filtered (_(" in overlay section %s"),
+ section->the_bfd_section->name);
+ }
}
}
}
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 == '/')
{
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. */
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);
}
fmt.format = 0;
fmt.size = 0;
fmt.count = 0;
+ fmt.raw = 0;
}
- innermost_block = 0;
+ innermost_block = NULL;
expr = parse_expression (exp);
new = (struct display *) xmalloc (sizeof (struct display));
+ 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;
static void
free_display (struct display *d)
{
+ xfree (d->exp_string);
xfree (d->exp);
xfree (d);
}
while ((d = display_chain) != NULL)
{
- xfree (d->exp);
display_chain = d->next;
- xfree (d);
+ free_display (d);
}
}
if (args == 0)
{
- if (query ("Delete all auto-display expressions? "))
+ if (query (_("Delete all auto-display expressions? ")))
clear_displays ();
dont_repeat ();
return;
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;
+ d->exp = parse_expression (d->exp_string);
+ d->block = innermost_block;
+ }
+ if (ex.reason < 0)
+ {
+ /* Can't re-parse the expression. Disable this display item. */
+ d->enabled_p = 0;
+ warning (_("Unable to display \"%s\": %s"),
+ d->exp_string, ex.message);
+ return;
+ }
+ }
+
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)
annotate_display_expression ();
- print_expression (d->exp, gdb_stdout);
+ puts_filtered (d->exp_string);
annotate_display_expression_end ();
if (d->format.count != 1 || d->format.format == 'i')
val = evaluate_expression (d->exp);
addr = value_as_address (val);
if (d->format.format == 'i')
- addr = gdbarch_addr_bits_remove (current_gdbarch, addr);
+ addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr);
annotate_display_value ();
- do_examine (d->format, addr);
+ do_examine (d->format, d->exp->gdbarch, addr);
}
else
{
annotate_display_expression ();
- print_expression (d->exp, gdb_stdout);
+ puts_filtered (d->exp_string);
annotate_display_expression_end ();
printf_filtered (" = ");
annotate_display_expression ();
get_formatted_print_options (&opts, d->format.format);
+ opts.raw = d->format.raw;
print_formatted (evaluate_expression (d->exp),
d->format.size, &opts, gdb_stdout);
printf_filtered ("\n");
d->format.format);
else if (d->format.format)
printf_filtered ("/%c ", d->format.format);
- print_expression (d->exp, gdb_stdout);
+ puts_filtered (d->exp_string);
if (d->block && !contained_in (get_selected_block (0), d->block))
printf_filtered (_(" (cannot be evaluated in the current context)"));
printf_filtered ("\n");
p++;
}
}
+
+/* Return 1 if D uses SOLIB (and will become dangling when SOLIB
+ is unloaded), otherwise return 0. */
+
+static int
+display_uses_solib_p (const struct display *d,
+ const struct so_list *solib)
+{
+ int endpos;
+ struct expression *const exp = d->exp;
+ const union exp_element *const elts = exp->elts;
+
+ if (d->block != NULL
+ && d->pspace == solib->pspace
+ && 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;
+
+ if (section && section->objfile == solib->objfile)
+ return 1;
+ }
+ endpos -= oplen;
+ }
+
+ return 0;
+}
+
+/* display_chain items point to blocks and expressions. Some expressions in
+ turn may point to symbols.
+ Both symbols and blocks are obstack_alloc'd on objfile_stack, and are
+ obstack_free'd when a shared library is unloaded.
+ Clear pointers that are about to become dangling.
+ Both .exp and .block fields will be restored next time we need to display
+ an item by re-parsing .exp_string field in the new execution context. */
+
+static void
+clear_dangling_display_expressions (struct so_list *solib)
+{
+ struct display *d;
+ struct objfile *objfile = NULL;
+
+ for (d = display_chain; d; d = d->next)
+ {
+ if (d->exp && display_uses_solib_p (d, solib))
+ {
+ xfree (d->exp);
+ d->exp = NULL;
+ d->block = NULL;
+ }
+ }
+}
\f
/* Print the value in stack frame FRAME of a variable specified by a
- struct symbol. */
+ 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. */
void
-print_variable_value (struct symbol *var, struct frame_info *frame,
- struct ui_file *stream)
+print_variable_and_value (const char *name, struct symbol *var,
+ struct frame_info *frame,
+ struct ui_file *stream, int indent)
{
- struct value *val = read_var_value (var, frame);
+ struct value *val;
struct value_print_options opts;
+ if (!name)
+ name = SYMBOL_PRINT_NAME (var);
+
+ fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
+
+ val = read_var_value (var, frame);
get_user_print_options (&opts);
- value_print (val, stream, &opts);
+ common_val_print (val, stream, indent, &opts, current_language);
+ fprintf_filtered (stream, "\n");
}
static void
enum argclass
{
- int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
+ int_arg, long_arg, long_long_arg, ptr_arg,
+ string_arg, wide_string_arg, wide_char_arg,
double_arg, long_double_arg, decfloat_arg
};
enum argclass *argclass;
break;
case 'c':
- this_argclass = int_arg;
- if (lcount || seen_h || seen_big_l)
+ this_argclass = lcount == 0 ? int_arg : wide_char_arg;
+ if (lcount > 1 || seen_h || seen_big_l)
bad = 1;
if (seen_prec || seen_zero || seen_space || seen_plus)
bad = 1;
break;
case 's':
- this_argclass = string_arg;
- if (lcount || seen_h || seen_big_l)
+ this_argclass = lcount == 0 ? string_arg : wide_string_arg;
+ if (lcount > 1 || seen_h || seen_big_l)
bad = 1;
if (seen_zero || seen_space || seen_plus)
bad = 1;
last_arg[length_before_ll + lcount];
current_substring += length_before_ll + 4;
}
+ else if (this_argclass == wide_string_arg
+ || this_argclass == wide_char_arg)
+ {
+ /* Convert %ls or %lc to %s. */
+ int length_before_ls = f - last_arg - 2;
+ strncpy (current_substring, last_arg, length_before_ls);
+ strcpy (current_substring + length_before_ls, "s");
+ current_substring += length_before_ls + 2;
+ }
else
{
strncpy (current_substring, last_arg, f - last_arg);
printf_filtered (current_substring, (char *) str);
}
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 (byte_order),
+ host_charset (),
+ str, j, wcwidth,
+ &output, translit_char);
+ obstack_grow_str0 (&output, "");
+
+ printf_filtered (current_substring, obstack_base (&output));
+ do_cleanups (inner_cleanup);
+ }
+ break;
+ case wide_char_arg:
+ {
+ 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);
+ 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 (byte_order),
+ host_charset (),
+ bytes, TYPE_LENGTH (valtype),
+ TYPE_LENGTH (valtype),
+ &output, translit_char);
+ obstack_grow_str0 (&output, "");
+
+ printf_filtered (current_substring, obstack_base (&output));
+ do_cleanups (inner_cleanup);
+ }
+ break;
case double_arg:
{
struct type *type = value_type (val_args[i]);
/* 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."));
/* 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."));
/* 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;
if (*sos == 'H')
{
dfp_len = 4;
- dfp_type = builtin_type (current_gdbarch)->builtin_decfloat;
+ dfp_type = builtin_type (gdbarch)->builtin_decfloat;
}
else if (*sos == 'D' && *(sos - 1) == 'D')
{
dfp_len = 16;
- dfp_type = builtin_type (current_gdbarch)->builtin_declong;
+ dfp_type = builtin_type (gdbarch)->builtin_declong;
sos--;
}
else
{
dfp_len = 8;
- dfp_type = builtin_type (current_gdbarch)->builtin_decdouble;
+ dfp_type = builtin_type (gdbarch)->builtin_decdouble;
}
}
/* Conversion between different DFP types. */
if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT)
- decimal_convert (param_ptr, param_len, dec, dfp_len);
+ 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, "0");
+ 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, decstr);
+ decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
/* Print the DFP value. */
printf_filtered (current_substring, decstr);
current_display_number = -1;
+ observer_attach_solib_unloaded (clear_dangling_display_expressions);
+
add_info ("address", address_info,
_("Describe where symbol SYM is stored."));
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);
-
}