X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprintcmd.c;h=02d6e1c7b2f0fc21cf513a2cfb62f65131a8a272;hb=2f91880f3afb3cc521111dfcc99b214c77aa97a1;hp=7beb334c5e265762af913d8b47e584a64eb14b56;hpb=27833de78f4f6b7c96482732e3b09b5b9a370e0f;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 7beb334c5e..02d6e1c7b2 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1,6 +1,6 @@
/* Print values for GNU debugger GDB.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
@@ -18,7 +18,6 @@
along with this program. If not, see . */
#include "defs.h"
-#include "gdb_string.h"
#include "frame.h"
#include "symtab.h"
#include "gdbtypes.h"
@@ -37,18 +36,16 @@
#include "objfiles.h" /* ditto */
#include "completer.h" /* for completion functions */
#include "ui-out.h"
-#include "gdb_assert.h"
#include "block.h"
#include "disasm.h"
#include "dfp.h"
-#include "valprint.h"
-#include "exceptions.h"
#include "observer.h"
#include "solist.h"
#include "parser-defs.h"
#include "charset.h"
#include "arch-utils.h"
#include "cli/cli-utils.h"
+#include "cli/cli-script.h"
#include "format.h"
#include "source.h"
@@ -56,17 +53,6 @@
#include "tui/tui.h" /* For tui_active et al. */
#endif
-struct format_data
- {
- int count;
- char format;
- char size;
-
- /* True if the value should be printed raw -- that is, bypassing
- python-based formatters. */
- unsigned char raw;
- };
-
/* Last specified output format. */
static char last_format = 0;
@@ -134,7 +120,7 @@ struct display
char *exp_string;
/* Expression to be evaluated and displayed. */
- struct expression *exp;
+ expression_up exp;
/* Item number of this auto-display item. */
int number;
@@ -201,8 +187,13 @@ decode_format (const char **string_ptr, int oformat, int osize)
val.count = 1;
val.raw = 0;
+ if (*p == '-')
+ {
+ val.count = -1;
+ p++;
+ }
if (*p >= '0' && *p <= '9')
- val.count = atoi (p);
+ val.count *= atoi (p);
while (*p >= '0' && *p <= '9')
p++;
@@ -332,7 +323,6 @@ print_formatted (struct value *val, int size,
/* User specified format, so don't look to the type to tell us
what to do. */
val_print_scalar_formatted (type,
- value_contents_for_printing (val),
value_embedded_offset (val),
val,
options, size, stream);
@@ -361,7 +351,7 @@ float_type_from_length (struct type *type)
supported at this level. */
void
-print_scalar_formatted (const void *valaddr, struct type *type,
+print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
const struct value_print_options *options,
int size, struct ui_file *stream)
{
@@ -373,9 +363,9 @@ print_scalar_formatted (const void *valaddr, struct type *type,
/* 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))
+ if (len > sizeof(LONGEST)
+ && (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_ENUM))
{
switch (options->format)
{
@@ -533,6 +523,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);
}
@@ -566,7 +560,7 @@ 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;
@@ -628,7 +622,7 @@ build_address_symbolic (struct gdbarch *gdbarch,
int *line, /* OUT */
int *unmapped) /* OUT */
{
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
struct symbol *symbol;
CORE_ADDR name_location = 0;
struct obj_section *section = NULL;
@@ -658,7 +652,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).minsym;
+ msymbol = lookup_minimal_symbol_by_pc_section (addr, section);
symbol = find_pc_sect_function (addr, section);
if (symbol)
@@ -677,29 +671,40 @@ build_address_symbolic (struct gdbarch *gdbarch,
name_temp = SYMBOL_LINKAGE_NAME (symbol);
}
- if (msymbol != NULL
- && MSYMBOL_HAS_SIZE (msymbol)
- && MSYMBOL_SIZE (msymbol) == 0
- && MSYMBOL_TYPE (msymbol) != mst_text
- && MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc
- && MSYMBOL_TYPE (msymbol) != mst_file_text)
- msymbol = NULL;
+ if (msymbol.minsym != NULL
+ && MSYMBOL_HAS_SIZE (msymbol.minsym)
+ && MSYMBOL_SIZE (msymbol.minsym) == 0
+ && MSYMBOL_TYPE (msymbol.minsym) != mst_text
+ && MSYMBOL_TYPE (msymbol.minsym) != mst_text_gnu_ifunc
+ && MSYMBOL_TYPE (msymbol.minsym) != mst_file_text)
+ msymbol.minsym = NULL;
- if (msymbol != NULL)
+ if (msymbol.minsym != NULL)
{
- if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
+ if (BMSYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
{
+ /* If this is a function (i.e. a code address), strip out any
+ non-address bits. For instance, display a pointer to the
+ first instruction of a Thumb function as ; the
+ second instruction will be , even though the
+ pointer is . This matches the ISA behavior. */
+ if (MSYMBOL_TYPE (msymbol.minsym) == mst_text
+ || MSYMBOL_TYPE (msymbol.minsym) == mst_text_gnu_ifunc
+ || MSYMBOL_TYPE (msymbol.minsym) == mst_file_text
+ || MSYMBOL_TYPE (msymbol.minsym) == 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;
- name_location = SYMBOL_VALUE_ADDRESS (msymbol);
+ name_location = BMSYMBOL_VALUE_ADDRESS (msymbol);
if (do_demangle || asm_demangle)
- name_temp = SYMBOL_PRINT_NAME (msymbol);
+ name_temp = MSYMBOL_PRINT_NAME (msymbol.minsym);
else
- name_temp = SYMBOL_LINKAGE_NAME (msymbol);
+ name_temp = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
}
}
- if (symbol == NULL && msymbol == NULL)
+ if (symbol == NULL && msymbol.minsym == NULL)
return 1;
/* If the nearest symbol is too far away, don't print anything symbolic. */
@@ -785,6 +790,217 @@ print_address_demangle (const struct value_print_options *opts,
}
+/* Find the address of the instruction that is INST_COUNT instructions before
+ the instruction at ADDR.
+ Since some architectures have variable-length instructions, we can't just
+ simply subtract INST_COUNT * INSN_LEN from ADDR. Instead, we use line
+ number information to locate the nearest known instruction boundary,
+ and disassemble forward from there. If we go out of the symbol range
+ during disassembling, we return the lowest address we've got so far and
+ set the number of instructions read to INST_READ. */
+
+static CORE_ADDR
+find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr,
+ int inst_count, int *inst_read)
+{
+ /* The vector PCS is used to store instruction addresses within
+ a pc range. */
+ CORE_ADDR loop_start, loop_end, p;
+ std::vector pcs;
+ struct symtab_and_line sal;
+
+ *inst_read = 0;
+ loop_start = loop_end = addr;
+
+ /* In each iteration of the outer loop, we get a pc range that ends before
+ LOOP_START, then we count and store every instruction address of the range
+ iterated in the loop.
+ If the number of instructions counted reaches INST_COUNT, return the
+ stored address that is located INST_COUNT instructions back from ADDR.
+ If INST_COUNT is not reached, we subtract the number of counted
+ instructions from INST_COUNT, and go to the next iteration. */
+ do
+ {
+ pcs.clear ();
+ sal = find_pc_sect_line (loop_start, NULL, 1);
+ if (sal.line <= 0)
+ {
+ /* We reach here when line info is not available. In this case,
+ we print a message and just exit the loop. The return value
+ is calculated after the loop. */
+ printf_filtered (_("No line number information available "
+ "for address "));
+ wrap_here (" ");
+ print_address (gdbarch, loop_start - 1, gdb_stdout);
+ printf_filtered ("\n");
+ break;
+ }
+
+ loop_end = loop_start;
+ loop_start = sal.pc;
+
+ /* This loop pushes instruction addresses in the range from
+ LOOP_START to LOOP_END. */
+ for (p = loop_start; p < loop_end;)
+ {
+ pcs.push_back (p);
+ p += gdb_insn_length (gdbarch, p);
+ }
+
+ inst_count -= pcs.size ();
+ *inst_read += pcs.size ();
+ }
+ while (inst_count > 0);
+
+ /* After the loop, the vector PCS has instruction addresses of the last
+ source line we processed, and INST_COUNT has a negative value.
+ We return the address at the index of -INST_COUNT in the vector for
+ the reason below.
+ Let's assume the following instruction addresses and run 'x/-4i 0x400e'.
+ Line X of File
+ 0x4000
+ 0x4001
+ 0x4005
+ Line Y of File
+ 0x4009
+ 0x400c
+ => 0x400e
+ 0x4011
+ find_instruction_backward is called with INST_COUNT = 4 and expected to
+ return 0x4001. When we reach here, INST_COUNT is set to -1 because
+ it was subtracted by 2 (from Line Y) and 3 (from Line X). The value
+ 4001 is located at the index 1 of the last iterated line (= Line X),
+ which is simply calculated by -INST_COUNT.
+ 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 = 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
+ is, exclude {0x4000} in the example above. */
+ if (inst_count < 0)
+ *inst_read += inst_count;
+
+ return p;
+}
+
+/* Backward read LEN bytes of target memory from address MEMADDR + LEN,
+ placing the results in GDB's memory from MYADDR + LEN. Returns
+ a count of the bytes actually read. */
+
+static int
+read_memory_backward (struct gdbarch *gdbarch,
+ CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+ int errcode;
+ int nread; /* Number of bytes actually read. */
+
+ /* First try a complete read. */
+ errcode = target_read_memory (memaddr, myaddr, len);
+ if (errcode == 0)
+ {
+ /* Got it all. */
+ nread = len;
+ }
+ else
+ {
+ /* Loop, reading one byte at a time until we get as much as we can. */
+ memaddr += len;
+ myaddr += len;
+ for (nread = 0; nread < len; ++nread)
+ {
+ errcode = target_read_memory (--memaddr, --myaddr, 1);
+ if (errcode != 0)
+ {
+ /* The read was unsuccessful, so exit the loop. */
+ printf_filtered (_("Cannot access memory at address %s\n"),
+ paddress (gdbarch, memaddr));
+ break;
+ }
+ }
+ }
+ return nread;
+}
+
+/* Returns true if X (which is LEN bytes wide) is the number zero. */
+
+static int
+integer_is_zero (const gdb_byte *x, int len)
+{
+ int i = 0;
+
+ while (i < len && x[i] == 0)
+ ++i;
+ return (i == len);
+}
+
+/* Find the start address of a string in which ADDR is included.
+ Basically we search for '\0' and return the next address,
+ but if OPTIONS->PRINT_MAX is smaller than the length of a string,
+ we stop searching and return the address to print characters as many as
+ PRINT_MAX from the string. */
+
+static CORE_ADDR
+find_string_backward (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int count, int char_size,
+ const struct value_print_options *options,
+ 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;
+ int chars_counted = 0;
+ int count_original = count;
+ 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);
+ while (count > 0 && read_error == 0)
+ {
+ int i;
+
+ addr -= chars_to_read * char_size;
+ chars_read = read_memory_backward (gdbarch, addr, buffer,
+ chars_to_read * char_size);
+ chars_read /= char_size;
+ read_error = (chars_read == chars_to_read) ? 0 : 1;
+ /* Searching for '\0' from the end of buffer in backward direction. */
+ for (i = 0; i < chars_read && count > 0 ; ++i, ++chars_counted)
+ {
+ int offset = (chars_to_read - i - 1) * 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
+ '\0', we add CHAR_SIZE to return the start address of
+ a string. */
+ --count;
+ string_start_addr = addr + offset + char_size;
+ chars_counted = 0;
+ }
+ }
+ }
+
+ /* Update STRINGS_COUNTED with the actual number of loaded strings. */
+ *strings_counted = count_original - count;
+
+ if (read_error != 0)
+ {
+ /* In error case, STRING_START_ADDR is pointing to the string that
+ was last successfully loaded. Rewind the partially loaded string. */
+ string_start_addr -= chars_counted * char_size;
+ }
+
+ do_cleanups (cleanup);
+ return string_start_addr;
+}
+
/* Examine data at address ADDR in format FMT.
Fetch it from memory and print on gdb_stdout. */
@@ -798,6 +1014,8 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
int i;
int maxelts;
struct value_print_options opts;
+ int need_to_update_next_address = 0;
+ CORE_ADDR addr_rewound = 0;
format = fmt.format;
size = fmt.size;
@@ -868,6 +1086,38 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
get_formatted_print_options (&opts, format);
+ if (count < 0)
+ {
+ /* This is the negative repeat count case.
+ We rewind the address based on the given repeat count and format,
+ then examine memory from there in forward direction. */
+
+ count = -count;
+ if (format == 'i')
+ {
+ next_address = find_instruction_backward (gdbarch, addr, count,
+ &count);
+ }
+ else if (format == 's')
+ {
+ next_address = find_string_backward (gdbarch, addr, count,
+ TYPE_LENGTH (val_type),
+ &opts, &count);
+ }
+ else
+ {
+ next_address = addr - count * TYPE_LENGTH (val_type);
+ }
+
+ /* The following call to print_formatted updates next_address in every
+ iteration. In backward case, we store the start address here
+ and update next_address with it before exiting the function. */
+ addr_rewound = (format == 's'
+ ? next_address - TYPE_LENGTH (val_type)
+ : next_address);
+ need_to_update_next_address = 1;
+ }
+
/* Print as many objects as specified in COUNT, at most maxelts per line,
with the address of the next one at the start of each line. */
@@ -913,10 +1163,13 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
printf_filtered ("\n");
gdb_flush (gdb_stdout);
}
+
+ if (need_to_update_next_address)
+ next_address = addr_rewound;
}
static void
-validate_format (struct format_data fmt, char *cmdname)
+validate_format (struct format_data fmt, const char *cmdname)
{
if (fmt.size != 0)
error (_("Size letters are meaningless in \"%s\" command."), cmdname);
@@ -928,73 +1181,80 @@ validate_format (struct format_data fmt, char *cmdname)
fmt.format, cmdname);
}
-/* Evaluate string EXP as an expression in the current language and
- print the resulting value. EXP may contain a format specifier as the
- first argument ("/x myvar" for example, to print myvar in hex). */
+/* Parse print command format string into *FMTP and update *EXPP.
+ CMDNAME should name the current command. */
-static void
-print_command_1 (const char *exp, int voidprint)
+void
+print_command_parse_format (const char **expp, const char *cmdname,
+ struct format_data *fmtp)
{
- struct expression *expr;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- char format = 0;
- struct value *val;
- struct format_data fmt;
+ const char *exp = *expp;
if (exp && *exp == '/')
{
exp++;
- fmt = decode_format (&exp, last_format, 0);
- validate_format (fmt, "print");
- last_format = format = fmt.format;
+ *fmtp = decode_format (&exp, last_format, 0);
+ validate_format (*fmtp, cmdname);
+ last_format = fmtp->format;
}
else
{
- fmt.count = 1;
- fmt.format = 0;
- fmt.size = 0;
- fmt.raw = 0;
+ fmtp->count = 1;
+ fmtp->format = 0;
+ fmtp->size = 0;
+ fmtp->raw = 0;
}
- if (exp && *exp)
- {
- expr = parse_expression (exp);
- make_cleanup (free_current_contents, &expr);
- val = evaluate_expression (expr);
- }
- else
- val = access_value_history (0);
+ *expp = exp;
+}
- if (voidprint || (val && value_type (val) &&
- TYPE_CODE (value_type (val)) != TYPE_CODE_VOID))
- {
- struct value_print_options opts;
- int histindex = record_latest_value (val);
+/* Print VAL to console according to *FMTP, including recording it to
+ the history. */
- if (histindex >= 0)
- annotate_value_history_begin (histindex, value_type (val));
- else
- annotate_value_begin (value_type (val));
+void
+print_value (struct value *val, const struct format_data *fmtp)
+{
+ struct value_print_options opts;
+ int histindex = record_latest_value (val);
- if (histindex >= 0)
- printf_filtered ("$%d = ", histindex);
+ annotate_value_history_begin (histindex, value_type (val));
- if (histindex >= 0)
- annotate_value_history_value ();
+ printf_filtered ("$%d = ", histindex);
- get_formatted_print_options (&opts, format);
- opts.raw = fmt.raw;
+ annotate_value_history_value ();
- print_formatted (val, fmt.size, &opts, gdb_stdout);
- printf_filtered ("\n");
+ get_formatted_print_options (&opts, fmtp->format);
+ opts.raw = fmtp->raw;
- if (histindex >= 0)
- annotate_value_history_end ();
- else
- annotate_value_end ();
+ print_formatted (val, fmtp->size, &opts, gdb_stdout);
+ printf_filtered ("\n");
+
+ annotate_value_history_end ();
+}
+
+/* Evaluate string EXP as an expression in the current language and
+ print the resulting value. EXP may contain a format specifier as the
+ first argument ("/x myvar" for example, to print myvar in hex). */
+
+static void
+print_command_1 (const char *exp, int voidprint)
+{
+ struct value *val;
+ struct format_data fmt;
+
+ print_command_parse_format (&exp, "print", &fmt);
+
+ if (exp && *exp)
+ {
+ expression_up expr = parse_expression (exp);
+ val = evaluate_expression (expr.get ());
}
+ else
+ val = access_value_history (0);
- do_cleanups (old_chain);
+ if (voidprint || (val && value_type (val) &&
+ TYPE_CODE (value_type (val)) != TYPE_CODE_VOID))
+ print_value (val, &fmt);
}
static void
@@ -1023,8 +1283,6 @@ output_command (char *exp, int from_tty)
void
output_command_const (const char *exp, int from_tty)
{
- struct expression *expr;
- struct cleanup *old_chain;
char format = 0;
struct value *val;
struct format_data fmt;
@@ -1041,10 +1299,9 @@ output_command_const (const char *exp, int from_tty)
format = fmt.format;
}
- expr = parse_expression (exp);
- old_chain = make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_expression (exp);
- val = evaluate_expression (expr);
+ val = evaluate_expression (expr.get ());
annotate_value_begin (value_type (val));
@@ -1056,16 +1313,12 @@ output_command_const (const char *exp, int from_tty)
wrap_here ("");
gdb_flush (gdb_stdout);
-
- do_cleanups (old_chain);
}
static void
set_command (char *exp, int from_tty)
{
- struct expression *expr = parse_expression (exp);
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_expression (exp);
if (expr->nelts >= 1)
switch (expr->elts[0].opcode)
@@ -1083,8 +1336,7 @@ set_command (char *exp, int from_tty)
(_("Expression is not an assignment (and might have no effect)"));
}
- evaluate_expression (expr);
- do_cleanups (old_chain);
+ evaluate_expression (expr.get ());
}
static void
@@ -1120,10 +1372,10 @@ sym_info (char *arg, int from_tty)
struct cleanup *old_chain;
matches = 1;
- offset = sect_addr - SYMBOL_VALUE_ADDRESS (msymbol);
+ offset = sect_addr - MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
mapped = section_is_mapped (osect) ? _("mapped") : _("unmapped");
sec_name = osect->the_bfd_section->name;
- msym_name = SYMBOL_PRINT_NAME (msymbol);
+ msym_name = MSYMBOL_PRINT_NAME (msymbol);
/* Don't print the offset if it is zero.
We assume there's no need to handle i18n of "sym + offset". */
@@ -1136,8 +1388,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))
@@ -1186,7 +1438,7 @@ 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;
@@ -1196,7 +1448,7 @@ address_info (char *exp, int from_tty)
error (_("Argument required."));
sym = lookup_symbol (exp, get_selected_block (&context_pc), VAR_DOMAIN,
- &is_a_field_of_this);
+ &is_a_field_of_this).symbol;
if (sym == NULL)
{
if (is_a_field_of_this.type != NULL)
@@ -1212,14 +1464,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)
{
- struct objfile *objfile = msymbol_objfile (msymbol);
+ struct objfile *objfile = msymbol.objfile;
gdbarch = get_objfile_arch (objfile);
- load_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ load_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
printf_filtered ("Symbol \"");
fprintf_symbol_filtered (gdb_stdout, exp,
@@ -1227,7 +1479,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 (objfile, msymbol);
+ section = MSYMBOL_OBJ_SECTION (objfile, msymbol.minsym);
if (section_is_overlay (section))
{
load_addr = overlay_unmapped_address (load_addr, section);
@@ -1248,8 +1500,11 @@ address_info (char *exp, int from_tty)
current_language->la_language, DMGL_ANSI);
printf_filtered ("\" is ");
val = SYMBOL_VALUE (sym);
- section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
- gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile);
+ if (SYMBOL_OBJFILE_OWNED (sym))
+ section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
+ else
+ section = NULL;
+ gdbarch = symbol_arch (sym);
if (SYMBOL_COMPUTED_OPS (sym) != NULL)
{
@@ -1360,17 +1615,20 @@ address_info (char *exp, int from_tty)
printf_filtered ("unresolved");
else
{
- section = SYMBOL_OBJ_SECTION (msym.objfile, msym.minsym);
- load_addr = SYMBOL_VALUE_ADDRESS (msym.minsym);
+ section = MSYMBOL_OBJ_SECTION (msym.objfile, 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);
+ {
+ load_addr = MSYMBOL_VALUE_RAW_ADDRESS (msym.minsym);
+ printf_filtered (_("a thread-local variable at offset %s "
+ "in the thread-local storage for `%s'"),
+ paddress (gdbarch, load_addr),
+ objfile_name (section->objfile));
+ }
else
{
+ load_addr = BMSYMBOL_VALUE_ADDRESS (msym);
printf_filtered (_("static storage at address "));
fputs_filtered (paddress (gdbarch, load_addr), gdb_stdout);
if (section_is_overlay (section))
@@ -1401,7 +1659,6 @@ address_info (char *exp, int from_tty)
static void
x_command (char *exp, int from_tty)
{
- struct expression *expr;
struct format_data fmt;
struct cleanup *old_chain;
struct value *val;
@@ -1423,15 +1680,14 @@ x_command (char *exp, int from_tty)
if (exp != 0 && *exp != 0)
{
- expr = parse_expression (exp);
+ expression_up expr = parse_expression (exp);
/* Cause expression not to be there any more if this command is
repeated with Newline. But don't clobber a user-defined
command's definition. */
if (from_tty)
*exp = 0;
- old_chain = make_cleanup (free_current_contents, &expr);
- val = evaluate_expression (expr);
- if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
+ val = evaluate_expression (expr.get ());
+ 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. */
@@ -1443,7 +1699,6 @@ x_command (char *exp, int from_tty)
next_address = value_as_address (val);
next_gdbarch = expr->gdbarch;
- do_cleanups (old_chain);
}
if (!next_gdbarch)
@@ -1489,71 +1744,68 @@ static void
display_command (char *arg, int from_tty)
{
struct format_data fmt;
- struct expression *expr;
- struct display *new;
- int display_it = 1;
+ struct display *newobj;
const char *exp = arg;
-#if defined(TUI)
- /* NOTE: cagney/2003-02-13 The `tui_active' was previously
- `tui_version'. */
- if (tui_active && exp != NULL && *exp == '$')
- display_it = (tui_set_layout_for_display_command (exp) == TUI_FAILURE);
-#endif
-
- if (display_it)
+ if (exp == 0)
{
- if (exp == 0)
- {
- do_displays ();
- return;
- }
+ do_displays ();
+ return;
+ }
- if (*exp == '/')
- {
- exp++;
- fmt = decode_format (&exp, 0, 0);
- if (fmt.size && fmt.format == 0)
- fmt.format = 'x';
- if (fmt.format == 'i' || fmt.format == 's')
- fmt.size = 'b';
- }
- else
- {
- fmt.format = 0;
- fmt.size = 0;
- fmt.count = 0;
- fmt.raw = 0;
- }
+ if (*exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ if (fmt.size && fmt.format == 0)
+ fmt.format = 'x';
+ if (fmt.format == 'i' || fmt.format == 's')
+ fmt.size = 'b';
+ }
+ else
+ {
+ fmt.format = 0;
+ fmt.size = 0;
+ fmt.count = 0;
+ fmt.raw = 0;
+ }
- innermost_block = NULL;
- expr = parse_expression (exp);
+ innermost_block = NULL;
+ expression_up expr = parse_expression (exp);
- new = (struct display *) xmalloc (sizeof (struct display));
+ newobj = new 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;
- new->enabled_p = 1;
- display_chain = new;
+ newobj->exp_string = xstrdup (exp);
+ newobj->exp = std::move (expr);
+ newobj->block = innermost_block;
+ newobj->pspace = current_program_space;
+ newobj->number = ++display_number;
+ newobj->format = fmt;
+ newobj->enabled_p = 1;
+ newobj->next = NULL;
- if (from_tty && target_has_execution)
- do_one_display (new);
+ if (display_chain == NULL)
+ display_chain = newobj;
+ else
+ {
+ struct display *last;
- dont_repeat ();
+ for (last = display_chain; last->next != NULL; last = last->next)
+ ;
+ last->next = newobj;
}
+
+ if (from_tty)
+ do_one_display (newobj);
+
+ dont_repeat ();
}
static void
free_display (struct display *d)
{
xfree (d->exp_string);
- xfree (d->exp);
- xfree (d);
+ delete d;
}
/* Clear out the display_chain. Done when new symtabs are loaded,
@@ -1602,19 +1854,18 @@ map_display_numbers (char *args,
void *),
void *data)
{
- struct get_number_or_range_state state;
int num;
if (args == NULL)
error_no_arg (_("one or more display numbers"));
- init_number_or_range (&state, args);
+ number_or_range_parser parser (args);
- while (!state.finished)
+ while (!parser.finished ())
{
- char *p = state.string;
+ const char *p = parser.cur_tok ();
- num = get_number_or_range (&state);
+ num = parser.get_number ();
if (num == 0)
warning (_("bad display number at or near '%s'"), p);
else
@@ -1664,7 +1915,6 @@ undisplay_command (char *args, int from_tty)
static void
do_one_display (struct display *d)
{
- struct cleanup *old_chain;
int within_current_scope;
if (d->enabled_p == 0)
@@ -1679,22 +1929,20 @@ do_one_display (struct display *d)
expression if the current architecture has changed. */
if (d->exp != NULL && d->exp->gdbarch != get_current_arch ())
{
- xfree (d->exp);
- d->exp = NULL;
+ d->exp.reset ();
d->block = NULL;
}
if (d->exp == NULL)
{
- volatile struct gdb_exception ex;
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
innermost_block = NULL;
d->exp = parse_expression (d->exp_string);
d->block = innermost_block;
}
- if (ex.reason < 0)
+ CATCH (ex, RETURN_MASK_ALL)
{
/* Can't re-parse the expression. Disable this display item. */
d->enabled_p = 0;
@@ -1702,6 +1950,7 @@ do_one_display (struct display *d)
d->exp_string, ex.message);
return;
}
+ END_CATCH
}
if (d->block)
@@ -1716,8 +1965,8 @@ do_one_display (struct display *d)
if (!within_current_scope)
return;
- old_chain = make_cleanup_restore_integer (¤t_display_number);
- current_display_number = d->number;
+ scoped_restore save_display_number
+ = make_scoped_restore (¤t_display_number, d->number);
annotate_display_begin ();
printf_filtered ("%d", d->number);
@@ -1725,7 +1974,6 @@ do_one_display (struct display *d)
printf_filtered (": ");
if (d->format.size)
{
- volatile struct gdb_exception ex;
annotate_display_format ();
@@ -1749,24 +1997,26 @@ do_one_display (struct display *d)
annotate_display_value ();
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
struct value *val;
CORE_ADDR addr;
- val = evaluate_expression (d->exp);
+ val = evaluate_expression (d->exp.get ());
addr = value_as_address (val);
if (d->format.format == 'i')
addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr);
do_examine (d->format, d->exp->gdbarch, addr);
}
- if (ex.reason < 0)
- fprintf_filtered (gdb_stdout, _("\n"), ex.message);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ fprintf_filtered (gdb_stdout, _("\n"), ex.message);
+ }
+ END_CATCH
}
else
{
struct value_print_options opts;
- volatile struct gdb_exception ex;
annotate_display_format ();
@@ -1785,22 +2035,25 @@ do_one_display (struct display *d)
get_formatted_print_options (&opts, d->format.format);
opts.raw = d->format.raw;
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
struct value *val;
- val = evaluate_expression (d->exp);
+ val = evaluate_expression (d->exp.get ());
print_formatted (val, d->format.size, &opts, gdb_stdout);
}
- if (ex.reason < 0)
- fprintf_filtered (gdb_stdout, _(""), ex.message);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ fprintf_filtered (gdb_stdout, _(""), ex.message);
+ }
+ END_CATCH
+
printf_filtered ("\n");
}
annotate_display_end ();
gdb_flush (gdb_stdout);
- do_cleanups (old_chain);
}
/* Display all of the values on the auto-display chain which can be
@@ -1925,28 +2178,30 @@ 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
- || (d->exp && exp_uses_objfile (d->exp, objfile)))
+ || (d->exp != NULL && exp_uses_objfile (d->exp.get (), objfile)))
{
- xfree (d->exp);
- d->exp = NULL;
+ d->exp.reset ();
d->block = NULL;
}
}
@@ -1966,18 +2221,21 @@ print_variable_and_value (const char *name, struct symbol *var,
struct frame_info *frame,
struct ui_file *stream, int indent)
{
- volatile struct gdb_exception except;
if (!name)
name = SYMBOL_PRINT_NAME (var);
fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
struct value *val;
struct value_print_options opts;
- val = read_var_value (var, frame);
+ /* READ_VAR_VALUE needs a block in order to deal with non-local
+ references (i.e. to handle nested functions). In this context, we
+ print variables that are local to this frame, so we can avoid passing
+ a block to it. */
+ val = read_var_value (var, NULL, frame);
get_user_print_options (&opts);
opts.deref_ref = 1;
common_val_print (val, stream, indent, &opts, current_language);
@@ -1986,9 +2244,13 @@ print_variable_and_value (const char *name, struct symbol *var,
function. */
frame = NULL;
}
- if (except.reason < 0)
- fprintf_filtered(stream, "", name,
- except.message);
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ fprintf_filtered(stream, "", name,
+ except.message);
+ }
+ END_CATCH
+
fprintf_filtered (stream, "\n");
}
@@ -2042,7 +2304,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
struct type *wctype = lookup_typename (current_language, gdbarch,
"wchar_t", NULL, 0);
int wcwidth = TYPE_LENGTH (wctype);
- gdb_byte *buf = alloca (wcwidth);
+ gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
struct obstack output;
struct cleanup *inner_cleanup;
@@ -2181,7 +2443,7 @@ printf_pointer (struct ui_file *stream, const char *format,
long val = value_as_long (value);
#endif
- fmt = alloca (strlen (format) + 5);
+ fmt = (char *) alloca (strlen (format) + 5);
/* Copy up to the leading %. */
p = format;
@@ -2237,7 +2499,7 @@ ui_printf (const char *arg, struct ui_file *stream)
int allocated_args = 20;
struct cleanup *old_cleanups;
- val_args = xmalloc (allocated_args * sizeof (struct value *));
+ val_args = XNEWVEC (struct value *, allocated_args);
old_cleanups = make_cleanup (free_current_contents, &val_args);
if (s == 0)
@@ -2443,6 +2705,7 @@ static void
printf_command (char *arg, int from_tty)
{
ui_printf (arg, gdb_stdout);
+ gdb_flush (gdb_stdout);
}
/* Implement the "eval" command. */
@@ -2450,18 +2713,13 @@ printf_command (char *arg, int from_tty)
static void
eval_command (char *arg, int from_tty)
{
- struct ui_file *ui_out = mem_fileopen ();
- struct cleanup *cleanups = make_cleanup_ui_file_delete (ui_out);
- char *expanded;
-
- ui_printf (arg, ui_out);
+ string_file stb;
- expanded = ui_file_xstrdup (ui_out, NULL);
- make_cleanup (xfree, expanded);
+ ui_printf (arg, &stb);
- execute_command (expanded, from_tty);
+ std::string expanded = insert_user_defined_cmd_args (stb.c_str ());
- do_cleanups (cleanups);
+ execute_command (&expanded[0], from_tty);
}
void
@@ -2471,7 +2729,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."));
@@ -2485,10 +2743,12 @@ 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\
+according to the format. If a negative number is specified, memory is\n\
+examined backward from the address.\n\n\
Defaults for format and size letters are those previously used.\n\
Default count is 1. Default address is following last thing printed\n\
with this command or \"print\"."));