/* Print and select stack frames for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "block.h"
#include "stack.h"
#include "dictionary.h"
-#include "exceptions.h"
#include "reggroups.h"
#include "regcache.h"
#include "solib.h"
#include "valprint.h"
+#include "gdbthread.h"
+#include "cp-support.h"
+#include "disasm.h"
+#include "inline-frame.h"
+#include "linespec.h"
+#include "cli/cli-utils.h"
+#include "objfiles.h"
+
+#include "safe-ctype.h"
+#include "symfile.h"
+#include "extension.h"
+#include "observer.h"
+
+/* The possible choices of "set print frame-arguments", and the value
+ of this setting. */
-#include "gdb_assert.h"
-#include <ctype.h>
-#include "gdb_string.h"
+static const char *const print_frame_arguments_choices[] =
+ {"all", "scalars", "none", NULL};
+static const char *print_frame_arguments = "scalars";
-void (*deprecated_selected_frame_level_changed_hook) (int);
+/* If non-zero, don't invoke pretty-printers for frame arguments. */
+static int print_raw_frame_arguments;
-/* The possible choices of "set print frame-arguments, and the value
+/* The possible choices of "set print entry-values", and the value
of this setting. */
-static const char *print_frame_arguments_choices[] =
- {"all", "scalars", "none", NULL};
-static const char *print_frame_arguments = "all";
+const char print_entry_values_no[] = "no";
+const char print_entry_values_only[] = "only";
+const char print_entry_values_preferred[] = "preferred";
+const char print_entry_values_if_needed[] = "if-needed";
+const char print_entry_values_both[] = "both";
+const char print_entry_values_compact[] = "compact";
+const char print_entry_values_default[] = "default";
+static const char *const print_entry_values_choices[] =
+{
+ print_entry_values_no,
+ print_entry_values_only,
+ print_entry_values_preferred,
+ print_entry_values_if_needed,
+ print_entry_values_both,
+ print_entry_values_compact,
+ print_entry_values_default,
+ NULL
+};
+const char *print_entry_values = print_entry_values_default;
-/* Prototypes for local functions. */
+/* Prototypes for local functions. */
static void print_frame_local_vars (struct frame_info *, int,
struct ui_file *);
enum print_what print_what, int print_args,
struct symtab_and_line sal);
+static void set_last_displayed_sal (int valid,
+ struct program_space *pspace,
+ CORE_ADDR addr,
+ struct symtab *symtab,
+ int line);
+
/* Zero means do things normally; we are interacting directly with the
user. One means print the full filename and linenumber when a
frame is printed, and do so in a format emacs18/emacs19.22 can
cases and in a slightly different syntax. */
int annotation_level = 0;
+
+/* These variables hold the last symtab and line we displayed to the user.
+ * This is where we insert a breakpoint or a skiplist entry by default. */
+static int last_displayed_sal_valid = 0;
+static struct program_space *last_displayed_pspace = 0;
+static CORE_ADDR last_displayed_addr = 0;
+static struct symtab *last_displayed_symtab = 0;
+static int last_displayed_line = 0;
\f
-struct print_stack_frame_args
+/* Return 1 if we should display the address in addition to the location,
+ because we are in the middle of a statement. */
+
+static int
+frame_show_address (struct frame_info *frame,
+ struct symtab_and_line sal)
{
- struct frame_info *frame;
- int print_level;
- enum print_what print_what;
- int print_args;
-};
+ /* If there is a line number, but no PC, then there is no location
+ information associated with this sal. The only way that should
+ happen is for the call sites of inlined functions (SAL comes from
+ find_frame_sal). Otherwise, we would have some PC range if the
+ SAL came from a line table. */
+ if (sal.line != 0 && sal.pc == 0 && sal.end == 0)
+ {
+ if (get_next_frame (frame) == NULL)
+ gdb_assert (inline_skipped_frames (inferior_ptid) > 0);
+ else
+ gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME);
+ return 0;
+ }
-/* Show or print the frame arguments; stub for catch_errors. */
+ return get_frame_pc (frame) != sal.pc;
+}
-static int
-print_stack_frame_stub (void *args)
+/* See frame.h. */
+
+void
+print_stack_frame_to_uiout (struct ui_out *uiout, struct frame_info *frame,
+ int print_level, enum print_what print_what,
+ int set_current_sal)
{
- struct print_stack_frame_args *p = args;
- int center = (p->print_what == SRC_LINE || p->print_what == SRC_AND_LOC);
+ scoped_restore save_uiout = make_scoped_restore (¤t_uiout, uiout);
- print_frame_info (p->frame, p->print_level, p->print_what, p->print_args);
- set_current_sal_from_frame (p->frame, center);
- return 0;
+ print_stack_frame (frame, print_level, print_what, set_current_sal);
}
-/* Show or print a stack frame FRAME briefly. The output is format
+/* Show or print a stack frame FRAME briefly. The output is formatted
according to PRINT_LEVEL and PRINT_WHAT printing the frame's
relative level, function name, argument list, and file name and
line number. If the frame's PC is not at the beginning of the
void
print_stack_frame (struct frame_info *frame, int print_level,
- enum print_what print_what)
+ enum print_what print_what,
+ int set_current_sal)
{
- struct print_stack_frame_args args;
- args.frame = frame;
- args.print_level = print_level;
- args.print_what = print_what;
/* For mi, alway print location and address. */
- args.print_what = ui_out_is_mi_like_p (uiout) ? LOC_AND_ADDRESS : print_what;
- args.print_args = 1;
-
- catch_errors (print_stack_frame_stub, &args, "", RETURN_MASK_ERROR);
-}
+ if (current_uiout->is_mi_like_p ())
+ print_what = LOC_AND_ADDRESS;
-struct print_args_args
-{
- struct symbol *func;
- struct frame_info *frame;
- struct ui_file *stream;
-};
-
-static int print_args_stub (void *args);
+ TRY
+ {
+ print_frame_info (frame, print_level, print_what, 1 /* print_args */,
+ set_current_sal);
+ if (set_current_sal)
+ set_current_sal_from_frame (frame);
+ }
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
+}
/* Print nameless arguments of frame FRAME on STREAM, where START is
the offset of the first nameless argument, and NUM is the number of
print_frame_nameless_args (struct frame_info *frame, long start, int num,
int first, struct ui_file *stream)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int i;
CORE_ADDR argsaddr;
long arg_value;
argsaddr = get_frame_args_address (frame);
if (!argsaddr)
return;
- arg_value = read_memory_integer (argsaddr + start, sizeof (int));
+ arg_value = read_memory_integer (argsaddr + start,
+ sizeof (int), byte_order);
if (!first)
fprintf_filtered (stream, ", ");
fprintf_filtered (stream, "%ld", arg_value);
}
}
-/* Return non-zero if the debugger should print the value of the provided
- symbol parameter (SYM). */
+/* Print single argument of inferior function. ARG must be already
+ read in.
-static int
-print_this_frame_argument_p (struct symbol *sym)
+ Errors are printed as if they would be the parameter value. Use zeroed ARG
+ iff it should not be printed accoring to user settings. */
+
+static void
+print_frame_arg (const struct frame_arg *arg)
{
- struct type *type;
-
- /* If the user asked to print no argument at all, then obviously
- do not print this argument. */
+ struct ui_out *uiout = current_uiout;
+ const char *error_message = NULL;
+
+ string_file stb;
+
+ gdb_assert (!arg->val || !arg->error);
+ gdb_assert (arg->entry_kind == print_entry_values_no
+ || arg->entry_kind == print_entry_values_only
+ || (!uiout->is_mi_like_p ()
+ && arg->entry_kind == print_entry_values_compact));
+
+ annotate_arg_emitter arg_emitter;
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+ fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
+ SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI);
+ if (arg->entry_kind == print_entry_values_compact)
+ {
+ /* It is OK to provide invalid MI-like stream as with
+ PRINT_ENTRY_VALUE_COMPACT we never use MI. */
+ stb.puts ("=");
- if (strcmp (print_frame_arguments, "none") == 0)
- return 0;
+ fprintf_symbol_filtered (&stb, SYMBOL_PRINT_NAME (arg->sym),
+ SYMBOL_LANGUAGE (arg->sym),
+ DMGL_PARAMS | DMGL_ANSI);
+ }
+ if (arg->entry_kind == print_entry_values_only
+ || arg->entry_kind == print_entry_values_compact)
+ stb.puts ("@entry");
+ uiout->field_stream ("name", stb);
+ annotate_arg_name_end ();
+ uiout->text ("=");
+
+ if (!arg->val && !arg->error)
+ uiout->text ("...");
+ else
+ {
+ if (arg->error)
+ error_message = arg->error;
+ else
+ {
+ TRY
+ {
+ const struct language_defn *language;
+ struct value_print_options opts;
+
+ /* Avoid value_print because it will deref ref parameters. We
+ just want to print their addresses. Print ??? for args whose
+ address we do not know. We pass 2 as "recurse" to val_print
+ because our standard indentation here is 4 spaces, and
+ val_print indents 2 for each recurse. */
+
+ annotate_arg_value (value_type (arg->val));
+
+ /* Use the appropriate language to display our symbol, unless the
+ user forced the language to a specific language. */
+ if (language_mode == language_mode_auto)
+ language = language_def (SYMBOL_LANGUAGE (arg->sym));
+ else
+ language = current_language;
+
+ get_no_prettyformat_print_options (&opts);
+ opts.deref_ref = 1;
+ opts.raw = print_raw_frame_arguments;
+
+ /* True in "summary" mode, false otherwise. */
+ opts.summary = !strcmp (print_frame_arguments, "scalars");
+
+ common_val_print (arg->val, &stb, 2, &opts, language);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ error_message = except.message;
+ }
+ END_CATCH
+ }
+ if (error_message != NULL)
+ stb.printf (_("<error reading variable: %s>"), error_message);
+ }
- /* If the user asked to print all arguments, then we should print
- that one. */
+ uiout->field_stream ("value", stb);
+}
- if (strcmp (print_frame_arguments, "all") == 0)
- return 1;
+/* Read in inferior function local SYM at FRAME into ARGP. Caller is
+ responsible for xfree of ARGP->ERROR. This function never throws an
+ exception. */
- /* The user asked to print only the scalar arguments, so do not
- print the non-scalar ones. */
+void
+read_frame_local (struct symbol *sym, struct frame_info *frame,
+ struct frame_arg *argp)
+{
+ argp->sym = sym;
+ argp->val = NULL;
+ argp->error = NULL;
- type = CHECK_TYPEDEF (SYMBOL_TYPE (sym));
- while (TYPE_CODE (type) == TYPE_CODE_REF)
- type = CHECK_TYPEDEF (TYPE_TARGET_TYPE (type));
- switch (TYPE_CODE (type))
+ TRY
{
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- case TYPE_CODE_SET:
- case TYPE_CODE_STRING:
- case TYPE_CODE_BITSTRING:
- return 0;
- default:
- return 1;
+ argp->val = read_var_value (sym, NULL, frame);
}
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ argp->error = xstrdup (except.message);
+ }
+ END_CATCH
+}
+
+/* Read in inferior function parameter SYM at FRAME into ARGP. Caller is
+ responsible for xfree of ARGP->ERROR. This function never throws an
+ exception. */
+
+void
+read_frame_arg (struct symbol *sym, struct frame_info *frame,
+ struct frame_arg *argp, struct frame_arg *entryargp)
+{
+ struct value *val = NULL, *entryval = NULL;
+ char *val_error = NULL, *entryval_error = NULL;
+ int val_equal = 0;
+
+ if (print_entry_values != print_entry_values_only
+ && print_entry_values != print_entry_values_preferred)
+ {
+ TRY
+ {
+ val = read_var_value (sym, NULL, frame);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ val_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (val_error, except.message);
+ }
+ END_CATCH
+ }
+
+ if (SYMBOL_COMPUTED_OPS (sym) != NULL
+ && SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry != NULL
+ && print_entry_values != print_entry_values_no
+ && (print_entry_values != print_entry_values_if_needed
+ || !val || value_optimized_out (val)))
+ {
+ TRY
+ {
+ const struct symbol_computed_ops *ops;
+
+ ops = SYMBOL_COMPUTED_OPS (sym);
+ entryval = ops->read_variable_at_entry (sym, frame);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ if (except.error != NO_ENTRY_VALUE_ERROR)
+ {
+ entryval_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (entryval_error, except.message);
+ }
+ }
+ END_CATCH
+
+ if (entryval != NULL && value_optimized_out (entryval))
+ entryval = NULL;
+
+ if (print_entry_values == print_entry_values_compact
+ || print_entry_values == print_entry_values_default)
+ {
+ /* For MI do not try to use print_entry_values_compact for ARGP. */
+
+ if (val && entryval && !current_uiout->is_mi_like_p ())
+ {
+ struct type *type = value_type (val);
+
+ if (value_lazy (val))
+ value_fetch_lazy (val);
+ if (value_lazy (entryval))
+ value_fetch_lazy (entryval);
+
+ if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
+ {
+ /* Initialize it just to avoid a GCC false warning. */
+ struct value *val_deref = NULL, *entryval_deref;
+
+ /* DW_AT_call_value does match with the current
+ value. If it is a reference still try to verify if
+ dereferenced DW_AT_call_data_value does not differ. */
+
+ TRY
+ {
+ struct type *type_deref;
+
+ val_deref = coerce_ref (val);
+ if (value_lazy (val_deref))
+ value_fetch_lazy (val_deref);
+ type_deref = value_type (val_deref);
+
+ entryval_deref = coerce_ref (entryval);
+ if (value_lazy (entryval_deref))
+ value_fetch_lazy (entryval_deref);
+
+ /* If the reference addresses match but dereferenced
+ content does not match print them. */
+ if (val != val_deref
+ && value_contents_eq (val_deref, 0,
+ entryval_deref, 0,
+ TYPE_LENGTH (type_deref)))
+ val_equal = 1;
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ /* If the dereferenced content could not be
+ fetched do not display anything. */
+ if (except.error == NO_ENTRY_VALUE_ERROR)
+ val_equal = 1;
+ else if (except.message != NULL)
+ {
+ entryval_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (entryval_error, except.message);
+ }
+ }
+ END_CATCH
+
+ /* Value was not a reference; and its content matches. */
+ if (val == val_deref)
+ val_equal = 1;
+
+ if (val_equal)
+ entryval = NULL;
+ }
+ }
+
+ /* Try to remove possibly duplicate error message for ENTRYARGP even
+ in MI mode. */
+
+ if (val_error && entryval_error
+ && strcmp (val_error, entryval_error) == 0)
+ {
+ entryval_error = NULL;
+
+ /* Do not se VAL_EQUAL as the same error message may be shown for
+ the entry value even if no entry values are present in the
+ inferior. */
+ }
+ }
+ }
+
+ if (entryval == NULL)
+ {
+ if (print_entry_values == print_entry_values_preferred)
+ {
+ gdb_assert (val == NULL);
+
+ TRY
+ {
+ val = read_var_value (sym, NULL, frame);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ val_error = (char *) alloca (strlen (except.message) + 1);
+ strcpy (val_error, except.message);
+ }
+ END_CATCH
+ }
+ if (print_entry_values == print_entry_values_only
+ || print_entry_values == print_entry_values_both
+ || (print_entry_values == print_entry_values_preferred
+ && (!val || value_optimized_out (val))))
+ {
+ entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym));
+ entryval_error = NULL;
+ }
+ }
+ if ((print_entry_values == print_entry_values_compact
+ || print_entry_values == print_entry_values_if_needed
+ || print_entry_values == print_entry_values_preferred)
+ && (!val || value_optimized_out (val)) && entryval != NULL)
+ {
+ val = NULL;
+ val_error = NULL;
+ }
+
+ argp->sym = sym;
+ argp->val = val;
+ argp->error = val_error ? xstrdup (val_error) : NULL;
+ if (!val && !val_error)
+ argp->entry_kind = print_entry_values_only;
+ else if ((print_entry_values == print_entry_values_compact
+ || print_entry_values == print_entry_values_default) && val_equal)
+ {
+ argp->entry_kind = print_entry_values_compact;
+ gdb_assert (!current_uiout->is_mi_like_p ());
+ }
+ else
+ argp->entry_kind = print_entry_values_no;
+
+ entryargp->sym = sym;
+ entryargp->val = entryval;
+ entryargp->error = entryval_error ? xstrdup (entryval_error) : NULL;
+ if (!entryval && !entryval_error)
+ entryargp->entry_kind = print_entry_values_no;
+ else
+ entryargp->entry_kind = print_entry_values_only;
}
/* Print the arguments of frame FRAME on STREAM, given the function
of arguments according to the stack frame (or -1 if the number of
arguments is unknown). */
-/* Note that currently the "number of argumentss according to the
+/* Note that currently the "number of arguments according to the
stack frame" is only known on VAX where i refers to the "number of
- ints of argumentss according to the stack frame". */
+ ints of arguments according to the stack frame". */
static void
print_frame_args (struct symbol *func, struct frame_info *frame,
int num, struct ui_file *stream)
{
+ struct ui_out *uiout = current_uiout;
int first = 1;
/* Offset of next stack argument beyond the one we have seen that is
at the highest offset, or -1 if we haven't come to a stack
long highest_offset = -1;
/* Number of ints of arguments that we have printed so far. */
int args_printed = 0;
- struct cleanup *old_chain, *list_chain;
- struct ui_stream *stb;
-
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ /* True if we should print arguments, false otherwise. */
+ int print_args = strcmp (print_frame_arguments, "none");
if (func)
{
- struct block *b = SYMBOL_BLOCK_VALUE (func);
- struct dict_iterator iter;
+ const struct block *b = SYMBOL_BLOCK_VALUE (func);
+ struct block_iterator iter;
struct symbol *sym;
- struct value *val;
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
+ struct frame_arg arg, entryarg;
+
QUIT;
/* Keep track of the highest stack argument offset seen, and
parameter names occur on the RS/6000, for traceback
tables. FIXME, should we even print them? */
- if (*DEPRECATED_SYMBOL_NAME (sym))
+ if (*SYMBOL_LINKAGE_NAME (sym))
{
struct symbol *nsym;
- nsym = lookup_symbol (DEPRECATED_SYMBOL_NAME (sym),
- b, VAR_DOMAIN, NULL);
+
+ nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
+ b, VAR_DOMAIN, NULL).symbol;
gdb_assert (nsym != NULL);
if (SYMBOL_CLASS (nsym) == LOC_REGISTER
&& !SYMBOL_IS_ARGUMENT (nsym))
/* Print the current arg. */
if (!first)
- ui_out_text (uiout, ", ");
- ui_out_wrap_hint (uiout, " ");
-
- annotate_arg_begin ();
-
- list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
- fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (sym),
- SYMBOL_LANGUAGE (sym),
- DMGL_PARAMS | DMGL_ANSI);
- ui_out_field_stream (uiout, "name", stb);
- annotate_arg_name_end ();
- ui_out_text (uiout, "=");
-
- if (print_this_frame_argument_p (sym))
- {
- /* Avoid value_print because it will deref ref parameters.
- We just want to print their addresses. Print ??? for
- args whose address we do not know. We pass 2 as
- "recurse" to val_print because our standard indentation
- here is 4 spaces, and val_print indents 2 for each
- recurse. */
- val = read_var_value (sym, frame);
-
- annotate_arg_value (val == NULL ? NULL : value_type (val));
-
- if (val)
- {
- const struct language_defn *language;
-
- /* Use the appropriate language to display our symbol,
- unless the user forced the language to a specific
- language. */
- if (language_mode == language_mode_auto)
- language = language_def (SYMBOL_LANGUAGE (sym));
- else
- language = current_language;
-
- common_val_print (val, stb->stream, 0, 0, 2,
- Val_no_prettyprint, language);
- ui_out_field_stream (uiout, "value", stb);
- }
- else
- ui_out_text (uiout, "???");
- }
- else
- ui_out_text (uiout, "...");
+ uiout->text (", ");
+ uiout->wrap_hint (" ");
+
+ if (!print_args)
+ {
+ memset (&arg, 0, sizeof (arg));
+ arg.sym = sym;
+ arg.entry_kind = print_entry_values_no;
+ memset (&entryarg, 0, sizeof (entryarg));
+ entryarg.sym = sym;
+ entryarg.entry_kind = print_entry_values_no;
+ }
+ else
+ read_frame_arg (sym, frame, &arg, &entryarg);
+
+ if (arg.entry_kind != print_entry_values_only)
+ print_frame_arg (&arg);
+ if (entryarg.entry_kind != print_entry_values_no)
+ {
+ if (arg.entry_kind != print_entry_values_only)
+ {
+ uiout->text (", ");
+ uiout->wrap_hint (" ");
+ }
- /* Invoke ui_out_tuple_end. */
- do_cleanups (list_chain);
+ print_frame_arg (&entryarg);
+ }
- annotate_arg_end ();
+ xfree (arg.error);
+ xfree (entryarg.error);
first = 0;
}
print_frame_nameless_args (frame, start, num - args_printed,
first, stream);
}
-
- do_cleanups (old_chain);
-}
-
-/* Stub for catch_errors. */
-
-static int
-print_args_stub (void *args)
-{
- struct print_args_args *p = args;
- struct gdbarch *gdbarch = get_frame_arch (p->frame);
- int numargs;
-
- if (gdbarch_frame_num_args_p (gdbarch))
- {
- numargs = gdbarch_frame_num_args (gdbarch, p->frame);
- gdb_assert (numargs >= 0);
- }
- else
- numargs = -1;
- print_frame_args (p->func, p->frame, numargs, p->stream);
- return 0;
}
/* Set the current source and line to the location given by frame
line is in the center of the next 'list'. */
void
-set_current_sal_from_frame (struct frame_info *frame, int center)
+set_current_sal_from_frame (struct frame_info *frame)
{
struct symtab_and_line sal;
find_frame_sal (frame, &sal);
- if (sal.symtab)
+ if (sal.symtab != NULL)
+ set_current_source_symtab_and_line (&sal);
+}
+
+/* If ON, GDB will display disassembly of the next source line when
+ execution of the program being debugged stops.
+ If AUTO (which is the default), or there's no line info to determine
+ the source line of the next instruction, display disassembly of next
+ instruction instead. */
+
+static enum auto_boolean disassemble_next_line;
+
+static void
+show_disassemble_next_line (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file,
+ _("Debugger's willingness to use "
+ "disassemble-next-line is %s.\n"),
+ value);
+}
+
+/* Use TRY_CATCH to catch the exception from the gdb_disassembly
+ because it will be broken by filter sometime. */
+
+static void
+do_gdb_disassembly (struct gdbarch *gdbarch,
+ int how_many, CORE_ADDR low, CORE_ADDR high)
+{
+
+ TRY
+ {
+ gdb_disassembly (gdbarch, current_uiout,
+ DISASSEMBLY_RAW_INSN, how_many,
+ low, high);
+ }
+ CATCH (exception, RETURN_MASK_ERROR)
{
- if (center)
- sal.line = max (sal.line - get_lines_to_list () / 2, 1);
- set_current_source_symtab_and_line (&sal);
+ /* If an exception was thrown while doing the disassembly, print
+ the error message, to give the user a clue of what happened. */
+ exception_print (gdb_stderr, exception);
}
+ END_CATCH
}
/* Print information about frame FRAME. The output is format according
- to PRINT_LEVEL and PRINT_WHAT and PRINT ARGS. The meaning of
+ to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS. The meaning of
PRINT_WHAT is:
SRC_LINE: Print only source line.
void
print_frame_info (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args)
+ enum print_what print_what, int print_args,
+ int set_current_sal)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
struct symtab_and_line sal;
int source_print;
int location_print;
+ struct ui_out *uiout = current_uiout;
if (get_frame_type (frame) == DUMMY_FRAME
- || get_frame_type (frame) == SIGTRAMP_FRAME)
+ || get_frame_type (frame) == SIGTRAMP_FRAME
+ || get_frame_type (frame) == ARCH_FRAME)
{
- struct cleanup *uiout_cleanup
- = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
+ ui_out_emit_tuple tuple_emitter (uiout, "frame");
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- get_frame_pc (frame));
+ gdbarch, get_frame_pc (frame));
/* Do this regardless of SOURCE because we don't have any source
to list for this frame. */
if (print_level)
{
- ui_out_text (uiout, "#");
- ui_out_field_fmt_int (uiout, 2, ui_left, "level",
+ uiout->text ("#");
+ uiout->field_fmt_int (2, ui_left, "level",
frame_relative_level (frame));
}
- if (ui_out_is_mi_like_p (uiout))
+ if (uiout->is_mi_like_p ())
{
annotate_frame_address ();
- ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame));
+ uiout->field_core_addr ("addr",
+ gdbarch, get_frame_pc (frame));
annotate_frame_address_end ();
}
if (get_frame_type (frame) == DUMMY_FRAME)
{
annotate_function_call ();
- ui_out_field_string (uiout, "func", "<function called from gdb>");
+ uiout->field_string ("func", "<function called from gdb>");
}
else if (get_frame_type (frame) == SIGTRAMP_FRAME)
{
annotate_signal_handler_caller ();
- ui_out_field_string (uiout, "func", "<signal handler called>");
+ uiout->field_string ("func", "<signal handler called>");
}
- ui_out_text (uiout, "\n");
+ else if (get_frame_type (frame) == ARCH_FRAME)
+ {
+ uiout->field_string ("func", "<cross-architecture call>");
+ }
+ uiout->text ("\n");
annotate_frame_end ();
- do_cleanups (uiout_cleanup);
+ /* If disassemble-next-line is set to auto or on output the next
+ instruction. */
+ if (disassemble_next_line == AUTO_BOOLEAN_AUTO
+ || disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ do_gdb_disassembly (get_frame_arch (frame), 1,
+ get_frame_pc (frame), get_frame_pc (frame) + 1);
+
return;
}
source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
+ /* If disassemble-next-line is set to auto or on and doesn't have
+ the line debug messages for $pc, output the next instruction. */
+ if ((disassemble_next_line == AUTO_BOOLEAN_AUTO
+ || disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ && source_print && !sal.symtab)
+ do_gdb_disassembly (get_frame_arch (frame), 1,
+ get_frame_pc (frame), get_frame_pc (frame) + 1);
+
if (source_print && sal.symtab)
{
int done = 0;
int mid_statement = ((print_what == SRC_LINE)
- && (get_frame_pc (frame) != sal.pc));
+ && frame_show_address (frame, sal));
if (annotation_level)
done = identify_source_line (sal.symtab, sal.line, mid_statement,
sal.line + 1, 0);
else
{
+ struct value_print_options opts;
+
+ get_user_print_options (&opts);
/* We used to do this earlier, but that is clearly
- wrong. This function is used by many different
+ wrong. This function is used by many different
parts of gdb, including normal_stop in infrun.c,
which uses this to print out the current PC
when we stepi/nexti into the middle of a source
- line. Only the command line really wants this
- behavior. Other UIs probably would like the
+ line. Only the command line really wants this
+ behavior. Other UIs probably would like the
ability to decide for themselves if it is desired. */
- if (addressprint && mid_statement)
+ if (opts.addressprint && mid_statement)
{
- ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame));
- ui_out_text (uiout, "\t");
+ uiout->field_core_addr ("addr",
+ gdbarch, get_frame_pc (frame));
+ uiout->text ("\t");
}
print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
}
}
+
+ /* If disassemble-next-line is set to on and there is line debug
+ messages, output assembly codes for next line. */
+ if (disassemble_next_line == AUTO_BOOLEAN_TRUE)
+ do_gdb_disassembly (get_frame_arch (frame), -1, sal.pc, sal.end);
}
- if (print_what != LOCATION)
- set_default_breakpoint (1, get_frame_pc (frame), sal.symtab, sal.line);
+ if (set_current_sal)
+ {
+ CORE_ADDR pc;
+
+ if (get_frame_pc_if_available (frame, &pc))
+ set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line);
+ else
+ set_last_displayed_sal (0, 0, 0, 0, 0);
+ }
annotate_frame_end ();
gdb_flush (gdb_stdout);
}
+/* Remember the last symtab and line we displayed, which we use e.g.
+ * as the place to put a breakpoint when the `break' command is
+ * invoked with no arguments. */
+
static void
-print_frame (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
+set_last_displayed_sal (int valid, struct program_space *pspace,
+ CORE_ADDR addr, struct symtab *symtab,
+ int line)
+{
+ last_displayed_sal_valid = valid;
+ last_displayed_pspace = pspace;
+ last_displayed_addr = addr;
+ last_displayed_symtab = symtab;
+ last_displayed_line = line;
+ if (valid && pspace == NULL)
+ {
+ clear_last_displayed_sal ();
+ internal_error (__FILE__, __LINE__,
+ _("Trying to set NULL pspace."));
+ }
+}
+
+/* Forget the last sal we displayed. */
+
+void
+clear_last_displayed_sal (void)
+{
+ last_displayed_sal_valid = 0;
+ last_displayed_pspace = 0;
+ last_displayed_addr = 0;
+ last_displayed_symtab = 0;
+ last_displayed_line = 0;
+}
+
+/* Is our record of the last sal we displayed valid? If not,
+ * the get_last_displayed_* functions will return NULL or 0, as
+ * appropriate. */
+
+int
+last_displayed_sal_is_valid (void)
+{
+ return last_displayed_sal_valid;
+}
+
+/* Get the pspace of the last sal we displayed, if it's valid. */
+
+struct program_space *
+get_last_displayed_pspace (void)
+{
+ if (last_displayed_sal_valid)
+ return last_displayed_pspace;
+ return 0;
+}
+
+/* Get the address of the last sal we displayed, if it's valid. */
+
+CORE_ADDR
+get_last_displayed_addr (void)
+{
+ if (last_displayed_sal_valid)
+ return last_displayed_addr;
+ return 0;
+}
+
+/* Get the symtab of the last sal we displayed, if it's valid. */
+
+struct symtab*
+get_last_displayed_symtab (void)
+{
+ if (last_displayed_sal_valid)
+ return last_displayed_symtab;
+ return 0;
+}
+
+/* Get the line of the last sal we displayed, if it's valid. */
+
+int
+get_last_displayed_line (void)
+{
+ if (last_displayed_sal_valid)
+ return last_displayed_line;
+ return 0;
+}
+
+/* Get the last sal we displayed, if it's valid. */
+
+void
+get_last_displayed_sal (struct symtab_and_line *sal)
+{
+ if (last_displayed_sal_valid)
+ {
+ sal->pspace = last_displayed_pspace;
+ sal->pc = last_displayed_addr;
+ sal->symtab = last_displayed_symtab;
+ sal->line = last_displayed_line;
+ }
+ else
+ {
+ sal->pspace = 0;
+ sal->pc = 0;
+ sal->symtab = 0;
+ sal->line = 0;
+ }
+}
+
+
+/* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function
+ corresponding to FRAME. FUNNAME needs to be freed by the caller. */
+
+void
+find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang, struct symbol **funcp)
{
struct symbol *func;
- char *funname = NULL;
- enum language funlang = language_unknown;
- struct ui_stream *stb;
- struct cleanup *old_chain, *list_chain;
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ *funname = NULL;
+ *funlang = language_unknown;
+ if (funcp)
+ *funcp = NULL;
- func = find_pc_function (get_frame_address_in_block (frame));
+ func = get_frame_function (frame);
if (func)
{
/* In certain pathological cases, the symtabs give the wrong
changed (and we'll create a find_pc_minimal_function or some
such). */
- struct minimal_symbol *msymbol =
- lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
+ struct bound_minimal_symbol msymbol;
- if (msymbol != NULL
- && (SYMBOL_VALUE_ADDRESS (msymbol)
+ /* Don't attempt to do this for inlined functions, which do not
+ have a corresponding minimal symbol. */
+ if (!block_inlined_p (SYMBOL_BLOCK_VALUE (func)))
+ msymbol
+ = lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
+ else
+ memset (&msymbol, 0, sizeof (msymbol));
+
+ if (msymbol.minsym != NULL
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol)
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
{
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = xstrdup (MSYMBOL_PRINT_NAME (msymbol.minsym));
+ *funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
else
{
- funname = DEPRECATED_SYMBOL_NAME (func);
- funlang = SYMBOL_LANGUAGE (func);
- if (funlang == language_cplus)
+ const char *print_name = SYMBOL_PRINT_NAME (func);
+
+ *funlang = SYMBOL_LANGUAGE (func);
+ if (funcp)
+ *funcp = func;
+ if (*funlang == language_cplus)
{
/* It seems appropriate to use SYMBOL_PRINT_NAME() here,
to display the demangled name that we already have
stored in the symbol table, but we stored a version
with DMGL_PARAMS turned on, and here we don't want to
- display parameters. So call the demangler again, with
- DMGL_ANSI only.
-
- Yes, printf_symbol_filtered() will again try to
- demangle the name on the fly, but the issue is that
- if cplus_demangle() fails here, it will fail there
- too. So we want to catch the failure (where DEMANGLED
- is NULL below) here, while we still have our hands on
- the function symbol.) */
- char *demangled = cplus_demangle (funname, DMGL_ANSI);
- if (demangled == NULL)
- /* If the demangler fails, try the demangled name from
- the symbol table. That'll have parameters, but
- that's preferable to displaying a mangled name. */
- funname = SYMBOL_PRINT_NAME (func);
- else
- xfree (demangled);
+ display parameters. So remove the parameters. */
+ char *func_only = cp_remove_params (print_name);
+
+ if (func_only)
+ *funname = func_only;
}
+
+ /* If we didn't hit the C++ case above, set *funname here.
+ This approach is taken to avoid having to install a
+ cleanup in case cp_remove_params can throw. */
+ if (*funname == NULL)
+ *funname = xstrdup (print_name);
}
}
else
{
- struct minimal_symbol *msymbol =
- lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
+ struct bound_minimal_symbol msymbol;
+ CORE_ADDR pc;
+
+ if (!get_frame_address_in_block_if_available (frame, &pc))
+ return;
- if (msymbol != NULL)
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ if (msymbol.minsym != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = xstrdup (MSYMBOL_PRINT_NAME (msymbol.minsym));
+ *funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
}
+}
+
+static void
+print_frame (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct symtab_and_line sal)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct ui_out *uiout = current_uiout;
+ char *funname = NULL;
+ enum language funlang = language_unknown;
+ struct cleanup *old_chain, *list_chain;
+ struct value_print_options opts;
+ struct symbol *func;
+ CORE_ADDR pc = 0;
+ int pc_p;
+
+ pc_p = get_frame_pc_if_available (frame, &pc);
+
+
+ find_frame_funname (frame, &funname, &funlang, &func);
+ old_chain = make_cleanup (xfree, funname);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- get_frame_pc (frame));
+ gdbarch, pc);
list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
if (print_level)
{
- ui_out_text (uiout, "#");
- ui_out_field_fmt_int (uiout, 2, ui_left, "level",
+ uiout->text ("#");
+ uiout->field_fmt_int (2, ui_left, "level",
frame_relative_level (frame));
}
- if (addressprint)
- if (get_frame_pc (frame) != sal.pc || !sal.symtab
+ get_user_print_options (&opts);
+ if (opts.addressprint)
+ if (!sal.symtab
+ || frame_show_address (frame, sal)
|| print_what == LOC_AND_ADDRESS)
{
annotate_frame_address ();
- ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame));
+ if (pc_p)
+ uiout->field_core_addr ("addr", gdbarch, pc);
+ else
+ uiout->field_string ("addr", "<unavailable>");
annotate_frame_address_end ();
- ui_out_text (uiout, " in ");
+ uiout->text (" in ");
}
annotate_frame_function_name ();
- fprintf_symbol_filtered (stb->stream, funname ? funname : "??",
+
+ string_file stb;
+ fprintf_symbol_filtered (&stb, funname ? funname : "??",
funlang, DMGL_ANSI);
- ui_out_field_stream (uiout, "func", stb);
- ui_out_wrap_hint (uiout, " ");
+ uiout->field_stream ("func", stb);
+ uiout->wrap_hint (" ");
annotate_frame_args ();
- ui_out_text (uiout, " (");
+ uiout->text (" (");
if (print_args)
{
- struct print_args_args args;
- struct cleanup *args_list_chain;
- args.frame = frame;
- args.func = func;
- args.stream = gdb_stdout;
- args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
- catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR);
- /* FIXME: ARGS must be a list. If one argument is a string it
- will have " that will not be properly escaped. */
- /* Invoke ui_out_tuple_end. */
- do_cleanups (args_list_chain);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ int numargs;
+
+ if (gdbarch_frame_num_args_p (gdbarch))
+ {
+ numargs = gdbarch_frame_num_args (gdbarch, frame);
+ gdb_assert (numargs >= 0);
+ }
+ else
+ numargs = -1;
+
+ {
+ ui_out_emit_list list_emitter (uiout, "args");
+ TRY
+ {
+ print_frame_args (func, frame, numargs, gdb_stdout);
+ }
+ CATCH (e, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
+
+ /* FIXME: ARGS must be a list. If one argument is a string it
+ will have " that will not be properly escaped. */
+ }
QUIT;
}
- ui_out_text (uiout, ")");
- if (sal.symtab && sal.symtab->filename)
+ uiout->text (")");
+ if (sal.symtab)
{
+ const char *filename_display;
+
+ filename_display = symtab_to_filename_for_display (sal.symtab);
annotate_frame_source_begin ();
- ui_out_wrap_hint (uiout, " ");
- ui_out_text (uiout, " at ");
+ uiout->wrap_hint (" ");
+ uiout->text (" at ");
annotate_frame_source_file ();
- ui_out_field_string (uiout, "file", sal.symtab->filename);
- if (ui_out_is_mi_like_p (uiout))
+ uiout->field_string ("file", filename_display);
+ if (uiout->is_mi_like_p ())
{
const char *fullname = symtab_to_fullname (sal.symtab);
- if (fullname != NULL)
- ui_out_field_string (uiout, "fullname", fullname);
+
+ uiout->field_string ("fullname", fullname);
}
annotate_frame_source_file_end ();
- ui_out_text (uiout, ":");
+ uiout->text (":");
annotate_frame_source_line ();
- ui_out_field_int (uiout, "line", sal.line);
+ uiout->field_int ("line", sal.line);
annotate_frame_source_end ();
}
- if (!funname || (!sal.symtab || !sal.symtab->filename))
+ if (pc_p && (funname == NULL || sal.symtab == NULL))
{
-#ifdef PC_SOLIB
- char *lib = PC_SOLIB (get_frame_pc (frame));
-#else
- char *lib = solib_address (get_frame_pc (frame));
-#endif
+ char *lib = solib_name_from_address (get_frame_program_space (frame),
+ get_frame_pc (frame));
+
if (lib)
{
annotate_frame_where ();
- ui_out_wrap_hint (uiout, " ");
- ui_out_text (uiout, " from ");
- ui_out_field_string (uiout, "from", lib);
+ uiout->wrap_hint (" ");
+ uiout->text (" from ");
+ uiout->field_string ("from", lib);
}
}
/* do_cleanups will call ui_out_tuple_end() for us. */
do_cleanups (list_chain);
- ui_out_text (uiout, "\n");
+ uiout->text ("\n");
do_cleanups (old_chain);
}
\f
-/* Read a frame specification in whatever the appropriate format is
- from FRAME_EXP. Call error(), printing MESSAGE, if the
- specification is in any way invalid (so this function never returns
- NULL). When SEPECTED_P is non-NULL set its target to indicate that
- the default selected frame was used. */
+/* Read a frame specification in whatever the appropriate format is from
+ FRAME_EXP. Call error() if the specification is in any way invalid (so
+ this function never returns NULL). When SELECTED_FRAME_P is non-NULL
+ set its target to indicate that the default selected frame was used. */
static struct frame_info *
-parse_frame_specification_1 (const char *frame_exp, const char *message,
- int *selected_frame_p)
+parse_frame_specification (const char *frame_exp, int *selected_frame_p)
{
int numargs;
struct value *args[4];
numargs = 0;
else
{
- char *addr_string;
- struct cleanup *tmp_cleanup;
-
numargs = 0;
while (1)
{
const char *p;
/* Skip leading white space, bail of EOL. */
- while (isspace (*frame_exp))
- frame_exp++;
+ frame_exp = skip_spaces_const (frame_exp);
if (!*frame_exp)
break;
/* Parse the argument, extract it, save it. */
for (p = frame_exp;
- *p && !isspace (*p);
+ *p && !ISSPACE (*p);
p++);
addr_string = savestring (frame_exp, p - frame_exp);
frame_exp = p;
{
if (selected_frame_p != NULL)
(*selected_frame_p) = 1;
- return get_selected_frame (message);
+ return get_selected_frame (_("No stack."));
}
/* None of the remaining use the selected frame. */
{
struct frame_info *fid;
int level = value_as_long (args[0]);
+
fid = find_relative_frame (get_current_frame (), &level);
if (level == 0)
- /* find_relative_frame was successful */
+ /* find_relative_frame was successful. */
return fid;
}
/* Convert each value into a corresponding address. */
{
int i;
+
for (i = 0; i < numargs; i++)
- addrs[i] = value_as_address (args[0]);
+ addrs[i] = value_as_address (args[i]);
}
/* Assume that the single arg[0] is an address, use that to identify
{
if (frame_id_eq (id, get_frame_id (fid)))
{
- while (frame_id_eq (id, frame_unwind_id (fid)))
- fid = get_prev_frame (fid);
+ struct frame_info *prev_frame;
+
+ while (1)
+ {
+ prev_frame = get_prev_frame (fid);
+ if (!prev_frame
+ || !frame_id_eq (id, get_frame_id (prev_frame)))
+ break;
+ fid = prev_frame;
+ }
return fid;
}
}
error (_("Too many args in frame specification"));
}
-static struct frame_info *
-parse_frame_specification (char *frame_exp)
-{
- return parse_frame_specification_1 (frame_exp, NULL, NULL);
-}
-
/* Print verbosely the selected frame or the frame at address
ADDR_EXP. Absolutely all information in the frame is printed. */
struct symbol *func;
struct symtab *s;
struct frame_info *calling_frame_info;
- int i, count, numregs;
- char *funname = 0;
+ int numregs;
+ const char *funname = 0;
enum language funlang = language_unknown;
const char *pc_regname;
int selected_frame_p;
struct gdbarch *gdbarch;
-
- fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+ CORE_ADDR frame_pc;
+ int frame_pc_p;
+ /* Initialize it to avoid "may be used uninitialized" warning. */
+ CORE_ADDR caller_pc = 0;
+ int caller_pc_p = 0;
+
+ fi = parse_frame_specification (addr_exp, &selected_frame_p);
gdbarch = get_frame_arch (fi);
/* Name of the value returned by get_frame_pc(). Per comments, "pc"
get_frame_pc(). */
pc_regname = "pc";
+ frame_pc_p = get_frame_pc_if_available (fi, &frame_pc);
find_frame_sal (fi, &sal);
func = get_frame_function (fi);
- /* FIXME: cagney/2002-11-28: Why bother? Won't sal.symtab contain
- the same value? */
- s = find_pc_symtab (get_frame_pc (fi));
+ s = sal.symtab;
if (func)
{
- /* It seems appropriate to use SYMBOL_PRINT_NAME() here, to
- display the demangled name that we already have stored in the
- symbol table, but we stored a version with DMGL_PARAMS turned
- on, and here we don't want to display parameters. So call the
- demangler again, with DMGL_ANSI only.
-
- Yes, printf_symbol_filtered() will again try to demangle the
- name on the fly, but the issue is that if cplus_demangle()
- fails here, it will fail there too. So we want to catch the
- failure (where DEMANGLED is NULL below) here, while we still
- have our hands on the function symbol.) */
- funname = DEPRECATED_SYMBOL_NAME (func);
+ funname = SYMBOL_PRINT_NAME (func);
funlang = SYMBOL_LANGUAGE (func);
if (funlang == language_cplus)
{
- char *demangled = cplus_demangle (funname, DMGL_ANSI);
- /* If the demangler fails, try the demangled name from the
- symbol table. That'll have parameters, but that's
- preferable to displaying a mangled name. */
- if (demangled == NULL)
- funname = SYMBOL_PRINT_NAME (func);
- else
- xfree (demangled);
+ /* It seems appropriate to use SYMBOL_PRINT_NAME() here,
+ to display the demangled name that we already have
+ stored in the symbol table, but we stored a version
+ with DMGL_PARAMS turned on, and here we don't want to
+ display parameters. So remove the parameters. */
+ char *func_only = cp_remove_params (funname);
+
+ if (func_only)
+ {
+ funname = func_only;
+ make_cleanup (xfree, func_only);
+ }
}
}
- else
+ else if (frame_pc_p)
{
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
- msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
- if (msymbol != NULL)
+ msymbol = lookup_minimal_symbol_by_pc (frame_pc);
+ if (msymbol.minsym != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ funname = MSYMBOL_PRINT_NAME (msymbol.minsym);
+ funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
}
}
calling_frame_info = get_prev_frame (fi);
{
printf_filtered (_("Stack frame at "));
}
- fputs_filtered (paddress (get_frame_base (fi)), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, get_frame_base (fi)), gdb_stdout);
printf_filtered (":\n");
printf_filtered (" %s = ", pc_regname);
- fputs_filtered (paddress (get_frame_pc (fi)), gdb_stdout);
+ if (frame_pc_p)
+ fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout);
+ else
+ fputs_filtered ("<unavailable>", gdb_stdout);
wrap_here (" ");
if (funname)
}
wrap_here (" ");
if (sal.symtab)
- printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
+ printf_filtered (" (%s:%d)", symtab_to_filename_for_display (sal.symtab),
+ sal.line);
puts_filtered ("; ");
wrap_here (" ");
- printf_filtered ("saved %s ", pc_regname);
- fputs_filtered (paddress (frame_pc_unwind (fi)), gdb_stdout);
+ printf_filtered ("saved %s = ", pc_regname);
+
+ if (!frame_id_p (frame_unwind_caller_id (fi)))
+ val_print_not_saved (gdb_stdout);
+ else
+ {
+ TRY
+ {
+ caller_pc = frame_unwind_caller_pc (fi);
+ caller_pc_p = 1;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ switch (ex.error)
+ {
+ case NOT_AVAILABLE_ERROR:
+ val_print_unavailable (gdb_stdout);
+ break;
+ case OPTIMIZED_OUT_ERROR:
+ val_print_not_saved (gdb_stdout);
+ break;
+ default:
+ fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+ break;
+ }
+ }
+ END_CATCH
+ }
+
+ if (caller_pc_p)
+ fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout);
printf_filtered ("\n");
if (calling_frame_info == NULL)
reason = get_frame_unwind_stop_reason (fi);
if (reason != UNWIND_NO_REASON)
printf_filtered (_(" Outermost frame: %s\n"),
- frame_stop_reason_string (reason));
+ frame_stop_reason_string (fi));
}
-
- if (calling_frame_info)
+ else if (get_frame_type (fi) == TAILCALL_FRAME)
+ puts_filtered (" tail call frame");
+ else if (get_frame_type (fi) == INLINE_FRAME)
+ printf_filtered (" inlined into frame %d",
+ frame_relative_level (get_prev_frame (fi)));
+ else
{
printf_filtered (" called by frame at ");
- fputs_filtered (paddress (get_frame_base (calling_frame_info)),
+ fputs_filtered (paddress (gdbarch, get_frame_base (calling_frame_info)),
gdb_stdout);
}
if (get_next_frame (fi) && calling_frame_info)
if (get_next_frame (fi))
{
printf_filtered (" caller of frame at ");
- fputs_filtered (paddress (get_frame_base (get_next_frame (fi))),
+ fputs_filtered (paddress (gdbarch, get_frame_base (get_next_frame (fi))),
gdb_stdout);
}
if (get_next_frame (fi) || calling_frame_info)
else
{
printf_filtered (" Arglist at ");
- fputs_filtered (paddress (arg_list), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, arg_list), gdb_stdout);
printf_filtered (",");
if (!gdbarch_frame_num_args_p (gdbarch))
else
{
printf_filtered (" Locals at ");
- fputs_filtered (paddress (arg_list), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, arg_list), gdb_stdout);
printf_filtered (",");
}
}
/* Print as much information as possible on the location of all the
registers. */
{
- enum lval_type lval;
- int optimized;
- CORE_ADDR addr;
- int realnum;
int count;
int i;
int need_nl = 1;
+ int sp_regnum = gdbarch_sp_regnum (gdbarch);
/* The sp is special; what's displayed isn't the save address, but
the value of the previous frame's sp. This is a legacy thing,
at one stage the frame cached the previous frame's SP instead
of its address, hence it was easiest to just display the cached
value. */
- if (gdbarch_sp_regnum (gdbarch) >= 0)
+ if (sp_regnum >= 0)
{
- /* Find out the location of the saved stack pointer with out
- actually evaluating it. */
- frame_register_unwind (fi, gdbarch_sp_regnum (gdbarch),
- &optimized, &lval, &addr,
- &realnum, NULL);
- if (!optimized && lval == not_lval)
- {
- gdb_byte value[MAX_REGISTER_SIZE];
- CORE_ADDR sp;
- frame_register_unwind (fi, gdbarch_sp_regnum (gdbarch),
- &optimized, &lval, &addr,
- &realnum, value);
- /* NOTE: cagney/2003-05-22: This is assuming that the
- stack pointer was packed as an unsigned integer. That
- may or may not be valid. */
- sp = extract_unsigned_integer (value,
- register_size (gdbarch,
- gdbarch_sp_regnum (gdbarch)));
- printf_filtered (" Previous frame's sp is ");
- fputs_filtered (paddress (sp), gdb_stdout);
- printf_filtered ("\n");
- need_nl = 0;
- }
- else if (!optimized && lval == lval_memory)
- {
- printf_filtered (" Previous frame's sp at ");
- fputs_filtered (paddress (addr), gdb_stdout);
- printf_filtered ("\n");
- need_nl = 0;
- }
- else if (!optimized && lval == lval_register)
+ struct value *value = frame_unwind_register_value (fi, sp_regnum);
+ gdb_assert (value != NULL);
+
+ if (!value_optimized_out (value) && value_entirely_available (value))
{
- printf_filtered (" Previous frame's sp in %s\n",
- gdbarch_register_name (gdbarch, realnum));
+ if (VALUE_LVAL (value) == not_lval)
+ {
+ CORE_ADDR sp;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int sp_size = register_size (gdbarch, sp_regnum);
+
+ sp = extract_unsigned_integer (value_contents_all (value),
+ sp_size, byte_order);
+
+ printf_filtered (" Previous frame's sp is ");
+ fputs_filtered (paddress (gdbarch, sp), gdb_stdout);
+ printf_filtered ("\n");
+ }
+ else if (VALUE_LVAL (value) == lval_memory)
+ {
+ printf_filtered (" Previous frame's sp at ");
+ fputs_filtered (paddress (gdbarch, value_address (value)),
+ gdb_stdout);
+ printf_filtered ("\n");
+ }
+ else if (VALUE_LVAL (value) == lval_register)
+ {
+ printf_filtered (" Previous frame's sp in %s\n",
+ gdbarch_register_name (gdbarch,
+ VALUE_REGNUM (value)));
+ }
+
+ release_value (value);
+ value_free (value);
need_nl = 0;
}
/* else keep quiet. */
numregs = gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch);
for (i = 0; i < numregs; i++)
- if (i != gdbarch_sp_regnum (gdbarch)
+ if (i != sp_regnum
&& gdbarch_register_reggroup_p (gdbarch, i, all_reggroup))
{
+ enum lval_type lval;
+ int optimized;
+ int unavailable;
+ CORE_ADDR addr;
+ int realnum;
+
/* Find out the location of the saved register without
fetching the corresponding value. */
- frame_register_unwind (fi, i, &optimized, &lval, &addr, &realnum,
- NULL);
+ frame_register_unwind (fi, i, &optimized, &unavailable,
+ &lval, &addr, &realnum, NULL);
/* For moment, only display registers that were saved on the
stack. */
- if (!optimized && lval == lval_memory)
+ if (!optimized && !unavailable && lval == lval_memory)
{
if (count == 0)
puts_filtered (" Saved registers:\n ");
wrap_here (" ");
printf_filtered (" %s at ",
gdbarch_register_name (gdbarch, i));
- fputs_filtered (paddress (addr), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, addr), gdb_stdout);
count++;
}
}
if (count || need_nl)
puts_filtered ("\n");
}
+
+ do_cleanups (back_to);
}
/* Print briefly all stack frames or just the innermost COUNT_EXP
frames. */
static void
-backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
+backtrace_command_1 (char *count_exp, int show_locals, int no_filters,
+ int from_tty)
{
struct frame_info *fi;
int count;
int i;
struct frame_info *trailing;
- int trailing_level;
+ int trailing_level, py_start = 0, py_end = 0;
+ enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
if (!target_has_stack)
error (_("No stack."));
of frames which we should print, or -1 if all of them. */
trailing = get_current_frame ();
- /* The target can be in a state where there is no valid frames
- (e.g., just connected). */
- if (trailing == NULL)
- error (_("No stack."));
-
trailing_level = 0;
if (count_exp)
{
{
struct frame_info *current;
+ py_start = count;
count = -count;
current = trailing;
count = -1;
}
+ else
+ {
+ py_start = 0;
+ py_end = count;
+ }
}
else
- count = -1;
+ {
+ py_end = -1;
+ count = -1;
+ }
if (info_verbose)
{
- struct partial_symtab *ps;
-
/* Read in symbols for all of the frames. Need to do this in a
separate pass so that "Reading in symbols for xxx" messages
don't screw up the appearance of the backtrace. Also if
i = count;
for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi))
{
+ CORE_ADDR pc;
+
QUIT;
- ps = find_pc_psymtab (get_frame_address_in_block (fi));
- if (ps)
- PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in. */
+ pc = get_frame_address_in_block (fi);
+ expand_symtab_containing_pc (pc, find_pc_mapped_section (pc));
}
}
- for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
+ if (! no_filters)
{
- QUIT;
+ int flags = PRINT_LEVEL | PRINT_FRAME_INFO | PRINT_ARGS;
+ enum ext_lang_frame_args arg_type;
- /* Don't use print_stack_frame; if an error() occurs it probably
- means further attempts to backtrace would fail (on the other
- hand, perhaps the code does or could be fixed to make sure
- the frame->prev field gets set to NULL in that case). */
- print_frame_info (fi, 1, LOCATION, 1);
if (show_locals)
- print_frame_local_vars (fi, 1, gdb_stdout);
+ flags |= PRINT_LOCALS;
- /* Save the last frame to check for error conditions. */
- trailing = fi;
- }
+ if (!strcmp (print_frame_arguments, "scalars"))
+ arg_type = CLI_SCALAR_VALUES;
+ else if (!strcmp (print_frame_arguments, "all"))
+ arg_type = CLI_ALL_VALUES;
+ else
+ arg_type = NO_VALUES;
- /* If we've stopped before the end, mention that. */
- if (fi && from_tty)
- printf_filtered (_("(More stack frames follow...)\n"));
+ result = apply_ext_lang_frame_filter (get_current_frame (), flags,
+ arg_type, current_uiout,
+ py_start, py_end);
+ }
- /* If we've run out of frames, and the reason appears to be an error
- condition, print it. */
- if (fi == NULL && trailing != NULL)
+ /* Run the inbuilt backtrace if there are no filters registered, or
+ "no-filters" has been specified from the command. */
+ if (no_filters || result == EXT_LANG_BT_NO_FILTERS)
{
- enum unwind_stop_reason reason;
+ for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
+ {
+ QUIT;
- reason = get_frame_unwind_stop_reason (trailing);
- if (reason > UNWIND_FIRST_ERROR)
- printf_filtered (_("Backtrace stopped: %s\n"),
- frame_stop_reason_string (reason));
- }
-}
+ /* Don't use print_stack_frame; if an error() occurs it probably
+ means further attempts to backtrace would fail (on the other
+ hand, perhaps the code does or could be fixed to make sure
+ the frame->prev field gets set to NULL in that case). */
-struct backtrace_command_args
-{
- char *count_exp;
- int show_locals;
- int from_tty;
-};
+ print_frame_info (fi, 1, LOCATION, 1, 0);
+ if (show_locals)
+ {
+ struct frame_id frame_id = get_frame_id (fi);
-/* Stub for catch_errors. */
+ print_frame_local_vars (fi, 1, gdb_stdout);
-static int
-backtrace_command_stub (void *data)
-{
- struct backtrace_command_args *args = data;
- backtrace_command_1 (args->count_exp, args->show_locals, args->from_tty);
- return 0;
+ /* print_frame_local_vars invalidates FI. */
+ fi = frame_find_by_id (frame_id);
+ if (fi == NULL)
+ {
+ trailing = NULL;
+ warning (_("Unable to restore previously selected frame."));
+ break;
+ }
+ }
+
+ /* Save the last frame to check for error conditions. */
+ trailing = fi;
+ }
+
+ /* If we've stopped before the end, mention that. */
+ if (fi && from_tty)
+ printf_filtered (_("(More stack frames follow...)\n"));
+
+ /* If we've run out of frames, and the reason appears to be an error
+ condition, print it. */
+ if (fi == NULL && trailing != NULL)
+ {
+ enum unwind_stop_reason reason;
+
+ reason = get_frame_unwind_stop_reason (trailing);
+ if (reason >= UNWIND_FIRST_ERROR)
+ printf_filtered (_("Backtrace stopped: %s\n"),
+ frame_stop_reason_string (trailing));
+ }
+ }
}
static void
backtrace_command (char *arg, int from_tty)
{
- struct cleanup *old_chain = NULL;
- int fulltrace_arg = -1, arglen = 0, argc = 0;
- struct backtrace_command_args btargs;
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+ int fulltrace_arg = -1, arglen = 0, argc = 0, no_filters = -1;
+ int user_arg = 0;
if (arg)
{
char **argv;
int i;
- argv = buildargv (arg);
- old_chain = make_cleanup_freeargv (argv);
+ argv = gdb_buildargv (arg);
+ make_cleanup_freeargv (argv);
argc = 0;
for (i = 0; argv[i]; i++)
{
unsigned int j;
for (j = 0; j < strlen (argv[i]); j++)
- argv[i][j] = tolower (argv[i][j]);
+ argv[i][j] = TOLOWER (argv[i][j]);
- if (fulltrace_arg < 0 && subset_compare (argv[i], "full"))
- fulltrace_arg = argc;
+ if (no_filters < 0 && subset_compare (argv[i], "no-filters"))
+ no_filters = argc;
else
{
- arglen += strlen (argv[i]);
- argc++;
+ if (fulltrace_arg < 0 && subset_compare (argv[i], "full"))
+ fulltrace_arg = argc;
+ else
+ {
+ user_arg++;
+ arglen += strlen (argv[i]);
+ }
}
+ argc++;
}
- arglen += argc;
- if (fulltrace_arg >= 0)
+ arglen += user_arg;
+ if (fulltrace_arg >= 0 || no_filters >= 0)
{
if (arglen > 0)
{
- arg = xmalloc (arglen + 1);
- memset (arg, 0, arglen + 1);
- for (i = 0; i < (argc + 1); i++)
+ arg = (char *) xmalloc (arglen + 1);
+ make_cleanup (xfree, arg);
+ arg[0] = 0;
+ for (i = 0; i < argc; i++)
{
- if (i != fulltrace_arg)
+ if (i != fulltrace_arg && i != no_filters)
{
strcat (arg, argv[i]);
strcat (arg, " ");
}
}
- btargs.count_exp = arg;
- btargs.show_locals = (fulltrace_arg >= 0);
- btargs.from_tty = from_tty;
- catch_errors (backtrace_command_stub, &btargs, "", RETURN_MASK_ERROR);
-
- if (fulltrace_arg >= 0 && arglen > 0)
- xfree (arg);
-
- if (old_chain)
- do_cleanups (old_chain);
-}
+ backtrace_command_1 (arg, fulltrace_arg >= 0 /* show_locals */,
+ no_filters >= 0 /* no frame-filters */, from_tty);
-static void
-backtrace_full_command (char *arg, int from_tty)
-{
- struct backtrace_command_args btargs;
- btargs.count_exp = arg;
- btargs.show_locals = 1;
- btargs.from_tty = from_tty;
- catch_errors (backtrace_command_stub, &btargs, "", RETURN_MASK_ERROR);
+ do_cleanups (old_chain);
}
-\f
-/* Print the local variables of a block B active in FRAME on STREAM.
- Return 1 if any variables were printed; 0 otherwise. */
+/* Iterate over the local variables of a block B, calling CB with
+ CB_DATA. */
-static int
-print_block_frame_locals (struct block *b, struct frame_info *frame,
- int num_tabs, struct ui_file *stream)
+static void
+iterate_over_block_locals (const struct block *b,
+ iterate_over_block_arg_local_vars_cb cb,
+ void *cb_data)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym;
- int values_printed = 0;
- int j;
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
case LOC_COMPUTED:
if (SYMBOL_IS_ARGUMENT (sym))
break;
- values_printed = 1;
- for (j = 0; j < num_tabs; j++)
- fputs_filtered ("\t", stream);
- fputs_filtered (SYMBOL_PRINT_NAME (sym), stream);
- fputs_filtered (" = ", stream);
- print_variable_value (sym, frame, stream);
- fprintf_filtered (stream, "\n");
+ if (SYMBOL_DOMAIN (sym) == COMMON_BLOCK_DOMAIN)
+ break;
+ (*cb) (SYMBOL_PRINT_NAME (sym), sym, cb_data);
break;
default:
break;
}
}
-
- return values_printed;
}
+
/* Same, but print labels. */
+#if 0
+/* Commented out, as the code using this function has also been
+ commented out. FIXME:brobecker/2009-01-13: Find out why the code
+ was commented out in the first place. The discussion introducing
+ this change (2007-12-04: Support lexical blocks and function bodies
+ that occupy non-contiguous address ranges) did not explain why
+ this change was made. */
static int
-print_block_frame_labels (struct block *b, int *have_default,
- struct ui_file *stream)
+print_block_frame_labels (struct gdbarch *gdbarch, struct block *b,
+ int *have_default, struct ui_file *stream)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym;
int values_printed = 0;
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- if (strcmp (DEPRECATED_SYMBOL_NAME (sym), "default") == 0)
+ if (strcmp (SYMBOL_LINKAGE_NAME (sym), "default") == 0)
{
if (*have_default)
continue;
if (SYMBOL_CLASS (sym) == LOC_LABEL)
{
struct symtab_and_line sal;
+ struct value_print_options opts;
+
sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
values_printed = 1;
fputs_filtered (SYMBOL_PRINT_NAME (sym), stream);
- if (addressprint)
+ get_user_print_options (&opts);
+ if (opts.addressprint)
{
fprintf_filtered (stream, " ");
- fputs_filtered (paddress (SYMBOL_VALUE_ADDRESS (sym)), stream);
+ fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (sym)),
+ stream);
}
fprintf_filtered (stream, " in file %s, line %d\n",
sal.symtab->filename, sal.line);
return values_printed;
}
+#endif
-/* Print on STREAM all the local variables in frame FRAME, including
- all the blocks active in that frame at its current PC.
-
- Returns 1 if the job was done, or 0 if nothing was printed because
- we have no info on the function running in FRAME. */
+/* Iterate over all the local variables in block B, including all its
+ superblocks, stopping when the top-level block is reached. */
-static void
-print_frame_local_vars (struct frame_info *frame, int num_tabs,
- struct ui_file *stream)
+void
+iterate_over_block_local_vars (const struct block *block,
+ iterate_over_block_arg_local_vars_cb cb,
+ void *cb_data)
{
- struct block *block = get_frame_block (frame, 0);
- int values_printed = 0;
-
- if (block == 0)
- {
- fprintf_filtered (stream, "No symbol table info available.\n");
- return;
- }
-
while (block)
{
- if (print_block_frame_locals (block, frame, num_tabs, stream))
- values_printed = 1;
+ iterate_over_block_locals (block, cb, cb_data);
/* After handling the function's top-level block, stop. Don't
- continue to its superblock, the block of per-file symbols. */
+ continue to its superblock, the block of per-file
+ symbols. */
if (BLOCK_FUNCTION (block))
break;
block = BLOCK_SUPERBLOCK (block);
}
+}
- if (!values_printed)
- fprintf_filtered (stream, _("No locals.\n"));
+/* Data to be passed around in the calls to the locals and args
+ iterators. */
+
+struct print_variable_and_value_data
+{
+ struct frame_id frame_id;
+ int num_tabs;
+ struct ui_file *stream;
+ int values_printed;
+};
+
+/* The callback for the locals and args iterators. */
+
+static void
+do_print_variable_and_value (const char *print_name,
+ struct symbol *sym,
+ void *cb_data)
+{
+ struct print_variable_and_value_data *p
+ = (struct print_variable_and_value_data *) cb_data;
+ struct frame_info *frame;
+
+ frame = frame_find_by_id (p->frame_id);
+ if (frame == NULL)
+ {
+ warning (_("Unable to restore previously selected frame."));
+ return;
+ }
+
+ print_variable_and_value (print_name, sym, frame, p->stream, p->num_tabs);
+
+ /* print_variable_and_value invalidates FRAME. */
+ frame = NULL;
+
+ p->values_printed = 1;
}
-/* Same, but print labels. */
+/* Print all variables from the innermost up to the function block of FRAME.
+ Print them with values to STREAM indented by NUM_TABS.
+
+ This function will invalidate FRAME. */
static void
-print_frame_label_vars (struct frame_info *frame, int this_level_only,
+print_frame_local_vars (struct frame_info *frame, int num_tabs,
struct ui_file *stream)
{
-#if 1
- fprintf_filtered (stream, "print_frame_label_vars disabled.\n");
-#else
- struct blockvector *bl;
- struct block *block = get_frame_block (frame, 0);
- int values_printed = 0;
- int index, have_default = 0;
- char *blocks_printed;
- CORE_ADDR pc = get_frame_pc (frame);
+ struct print_variable_and_value_data cb_data;
+ const struct block *block;
+ CORE_ADDR pc;
+ struct gdb_exception except = exception_none;
+
+ if (!get_frame_pc_if_available (frame, &pc))
+ {
+ fprintf_filtered (stream,
+ _("PC unavailable, cannot determine locals.\n"));
+ return;
+ }
+ block = get_frame_block (frame, 0);
if (block == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
return;
}
- bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
- blocks_printed = alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
- memset (blocks_printed, 0, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ cb_data.frame_id = get_frame_id (frame);
+ cb_data.num_tabs = 4 * num_tabs;
+ cb_data.stream = stream;
+ cb_data.values_printed = 0;
- while (block != 0)
- {
- CORE_ADDR end = BLOCK_END (block) - 4;
- int last_index;
-
- if (bl != blockvector_for_pc (end, &index))
- error (_("blockvector blotch"));
- if (BLOCKVECTOR_BLOCK (bl, index) != block)
- error (_("blockvector botch"));
- last_index = BLOCKVECTOR_NBLOCKS (bl);
- index += 1;
+ /* Temporarily change the selected frame to the given FRAME.
+ This allows routines that rely on the selected frame instead
+ of being given a frame as parameter to use the correct frame. */
+ select_frame (frame);
- /* Don't print out blocks that have gone by. */
- while (index < last_index
- && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < pc)
- index++;
+ TRY
+ {
+ iterate_over_block_local_vars (block,
+ do_print_variable_and_value,
+ &cb_data);
+ }
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ except = ex;
+ }
+ END_CATCH
- while (index < last_index
- && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < end)
- {
- if (blocks_printed[index] == 0)
- {
- if (print_block_frame_labels (BLOCKVECTOR_BLOCK (bl, index),
- &have_default, stream))
- values_printed = 1;
- blocks_printed[index] = 1;
- }
- index++;
- }
- if (have_default)
- return;
- if (values_printed && this_level_only)
- return;
+ /* Restore the selected frame, and then rethrow if there was a problem. */
+ select_frame (frame_find_by_id (cb_data.frame_id));
+ if (except.reason < 0)
+ throw_exception (except);
- /* After handling the function's top-level block, stop. Don't
- continue to its superblock, the block of per-file symbols. */
- if (BLOCK_FUNCTION (block))
- break;
- block = BLOCK_SUPERBLOCK (block);
- }
+ /* do_print_variable_and_value invalidates FRAME. */
+ frame = NULL;
- if (!values_printed && !this_level_only)
- fprintf_filtered (stream, _("No catches.\n"));
-#endif
+ if (!cb_data.values_printed)
+ fprintf_filtered (stream, _("No locals.\n"));
}
void
0, gdb_stdout);
}
-static void
-catch_info (char *ignore, int from_tty)
-{
- struct symtab_and_line *sal;
+/* Iterate over all the argument variables in block B.
- /* Assume g++ compiled code; old GDB 4.16 behaviour. */
- print_frame_label_vars (get_selected_frame (_("No frame selected.")),
- 0, gdb_stdout);
-}
+ Returns 1 if any argument was walked; 0 otherwise. */
-static void
-print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
+void
+iterate_over_block_arg_vars (const struct block *b,
+ iterate_over_block_arg_local_vars_cb cb,
+ void *cb_data)
{
- struct symbol *func = get_frame_function (frame);
- struct block *b;
- struct dict_iterator iter;
+ struct block_iterator iter;
struct symbol *sym, *sym2;
- int values_printed = 0;
-
- if (func == 0)
- {
- fprintf_filtered (stream, _("No symbol table info available.\n"));
- return;
- }
- b = SYMBOL_BLOCK_VALUE (func);
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
/* Don't worry about things which aren't arguments. */
if (SYMBOL_IS_ARGUMENT (sym))
{
- values_printed = 1;
- fputs_filtered (SYMBOL_PRINT_NAME (sym), stream);
- fputs_filtered (" = ", stream);
-
/* We have to look up the symbol because arguments can have
two entries (one a parameter, one a local) and the one we
want is the local, which lookup_symbol will find for us.
float). There are also LOC_ARG/LOC_REGISTER pairs which
are not combined in symbol-reading. */
- sym2 = lookup_symbol (DEPRECATED_SYMBOL_NAME (sym),
- b, VAR_DOMAIN, NULL);
- print_variable_value (sym2, frame, stream);
- fprintf_filtered (stream, "\n");
+ sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
+ b, VAR_DOMAIN, NULL).symbol;
+ (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);
}
}
+}
+
+/* Print all argument variables of the function of FRAME.
+ Print them with values to STREAM.
+
+ This function will invalidate FRAME. */
+
+static void
+print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
+{
+ struct print_variable_and_value_data cb_data;
+ struct symbol *func;
+ CORE_ADDR pc;
+
+ if (!get_frame_pc_if_available (frame, &pc))
+ {
+ fprintf_filtered (stream, _("PC unavailable, cannot determine args.\n"));
+ return;
+ }
+
+ func = get_frame_function (frame);
+ if (func == NULL)
+ {
+ fprintf_filtered (stream, _("No symbol table info available.\n"));
+ return;
+ }
- if (!values_printed)
+ cb_data.frame_id = get_frame_id (frame);
+ cb_data.num_tabs = 0;
+ cb_data.stream = gdb_stdout;
+ cb_data.values_printed = 0;
+
+ iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func),
+ do_print_variable_and_value, &cb_data);
+
+ /* do_print_variable_and_value invalidates FRAME. */
+ frame = NULL;
+
+ if (!cb_data.values_printed)
fprintf_filtered (stream, _("No arguments.\n"));
}
gdb_stdout);
}
-
-static void
-args_plus_locals_info (char *ignore, int from_tty)
-{
- args_info (ignore, from_tty);
- locals_info (ignore, from_tty);
-}
-\f
-
/* Select frame FRAME. Also print the stack frame and show the source
if this is the tui version. */
static void
{
select_frame (frame);
if (frame)
- print_stack_frame (frame, 1, SRC_AND_LOC);
+ print_stack_frame (frame, 1, SRC_AND_LOC, 1);
}
\f
/* Return the symbol-block in which the selected frame is executing.
code address within the block returned. We use this to decide
which macros are in scope. */
-struct block *
+const struct block *
get_selected_block (CORE_ADDR *addr_in_block)
{
- if (!target_has_stack)
+ if (!has_stack_frames ())
return 0;
return get_frame_block (get_selected_frame (NULL), addr_in_block);
while (*level_offset_ptr > 0)
{
struct frame_info *prev = get_prev_frame (frame);
+
if (!prev)
break;
(*level_offset_ptr)--;
while (*level_offset_ptr < 0)
{
struct frame_info *next = get_next_frame (frame);
+
if (!next)
break;
(*level_offset_ptr)++;
void
select_frame_command (char *level_exp, int from_tty)
{
- select_frame (parse_frame_specification_1 (level_exp, "No stack.", NULL));
+ struct frame_info *prev_frame = get_selected_frame_if_set ();
+
+ select_frame (parse_frame_specification (level_exp, NULL));
+ if (get_selected_frame_if_set () != prev_frame)
+ observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
}
/* The "frame" command. With no argument, print the selected frame
static void
frame_command (char *level_exp, int from_tty)
{
- select_frame_command (level_exp, from_tty);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
-}
+ struct frame_info *prev_frame = get_selected_frame_if_set ();
-/* The XDB Compatibility command to print the current frame. */
-
-static void
-current_frame_command (char *level_exp, int from_tty)
-{
- print_stack_frame (get_selected_frame (_("No stack.")), 1, SRC_AND_LOC);
+ select_frame (parse_frame_specification (level_exp, NULL));
+ if (get_selected_frame_if_set () != prev_frame)
+ observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
+ else
+ print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
}
/* Select the frame up one or COUNT_EXP stack levels from the
previously selected frame, and print it briefly. */
static void
-up_silently_base (char *count_exp)
+up_silently_base (const char *count_exp)
{
struct frame_info *frame;
int count = 1;
up_command (char *count_exp, int from_tty)
{
up_silently_base (count_exp);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
}
/* Select the frame down one or COUNT_EXP stack levels from the previously
selected frame, and print it briefly. */
static void
-down_silently_base (char *count_exp)
+down_silently_base (const char *count_exp)
{
struct frame_info *frame;
int count = -1;
+
if (count_exp)
count = -parse_and_eval_long (count_exp);
down_command (char *count_exp, int from_tty)
{
down_silently_base (count_exp);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ observer_notify_user_selected_context_changed (USER_SELECTED_FRAME);
}
-\f
void
return_command (char *retval_exp, int from_tty)
{
+ /* Initialize it just to avoid a GCC false warning. */
+ enum return_value_convention rv_conv = RETURN_VALUE_STRUCT_CONVENTION;
+ struct frame_info *thisframe;
+ struct gdbarch *gdbarch;
struct symbol *thisfun;
struct value *return_value = NULL;
+ struct value *function = NULL;
const char *query_prefix = "";
- thisfun = get_frame_function (get_selected_frame ("No selected frame."));
+ thisframe = get_selected_frame ("No selected frame.");
+ thisfun = get_frame_function (thisframe);
+ gdbarch = get_frame_arch (thisframe);
+
+ if (get_frame_type (get_current_frame ()) == INLINE_FRAME)
+ error (_("Can not force return from an inlined function."));
/* Compute the return value. If the computation triggers an error,
let it bail. If the return type can't be handled, set
message. */
if (retval_exp)
{
+ expression_up retval_expr = parse_expression (retval_exp);
struct type *return_type = NULL;
/* Compute the return value. Should the computation fail, this
call throws an error. */
- return_value = parse_and_eval (retval_exp);
+ return_value = evaluate_expression (retval_expr.get ());
/* Cast return value to the return type of the function. Should
the cast fail, this call throws an error. */
if (thisfun != NULL)
return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
if (return_type == NULL)
- return_type = builtin_type_int;
- CHECK_TYPEDEF (return_type);
+ {
+ if (retval_expr->elts[0].opcode != UNOP_CAST
+ && retval_expr->elts[0].opcode != UNOP_CAST_TYPE)
+ error (_("Return value type not available for selected "
+ "stack frame.\n"
+ "Please use an explicit cast of the value to return."));
+ return_type = value_type (return_value);
+ }
+ return_type = check_typedef (return_type);
return_value = value_cast (return_type, return_value);
/* Make sure the value is fully evaluated. It may live in the
if (value_lazy (return_value))
value_fetch_lazy (return_value);
+ if (thisfun != NULL)
+ function = read_var_value (thisfun, NULL, thisframe);
+
+ rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
/* If the return-type is "void", don't try to find the
return-value's location. However, do still evaluate the
is discarded, side effects such as "return i++" still
occur. */
return_value = NULL;
- else if (using_struct_return (SYMBOL_TYPE (thisfun), return_type))
+ else if (thisfun != NULL)
{
- query_prefix = "\
-The location at which to store the function's return value is unknown.\n\
-If you continue, the return value that you specified will be ignored.\n";
- return_value = NULL;
+ rv_conv = struct_return_convention (gdbarch, function, return_type);
+ if (rv_conv == RETURN_VALUE_STRUCT_CONVENTION
+ || rv_conv == RETURN_VALUE_ABI_RETURNS_ADDRESS)
+ {
+ query_prefix = "The location at which to store the "
+ "function's return value is unknown.\n"
+ "If you continue, the return value "
+ "that you specified will be ignored.\n";
+ return_value = NULL;
+ }
}
}
if (from_tty)
{
int confirmed;
+
if (thisfun == NULL)
confirmed = query (_("%sMake selected stack frame return now? "),
query_prefix);
else
- confirmed = query (_("%sMake %s return now? "), query_prefix,
- SYMBOL_PRINT_NAME (thisfun));
+ {
+ if (TYPE_NO_RETURN (thisfun->type))
+ warning (_("Function does not return normally to caller."));
+ confirmed = query (_("%sMake %s return now? "), query_prefix,
+ SYMBOL_PRINT_NAME (thisfun));
+ }
if (!confirmed)
error (_("Not confirmed"));
}
- /* NOTE: cagney/2003-01-18: Is this silly? Rather than pop each
- frame in turn, should this code just go straight to the relevant
- frame and pop that? */
-
- /* First discard all frames inner-to the selected frame (making the
- selected frame current). */
- {
- struct frame_id selected_id = get_frame_id (get_selected_frame (NULL));
- while (!frame_id_eq (selected_id, get_frame_id (get_current_frame ())))
- {
- struct frame_info *frame = get_current_frame ();
- if (frame_id_inner (get_frame_arch (frame), selected_id,
- get_frame_id (frame)))
- /* Caught in the safety net, oops! We've gone way past the
- selected frame. */
- error (_("Problem while popping stack frames (corrupt stack?)"));
- frame_pop (get_current_frame ());
- }
- }
-
- /* Second discard the selected frame (which is now also the current
- frame). */
- frame_pop (get_current_frame ());
+ /* Discard the selected frame and all frames inner-to it. */
+ frame_pop (get_selected_frame (NULL));
/* Store RETURN_VALUE in the just-returned register set. */
if (return_value != NULL)
{
struct type *return_type = value_type (return_value);
struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
- gdb_assert (gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun),
- return_type, NULL, NULL, NULL)
- == RETURN_VALUE_REGISTER_CONVENTION);
- gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun), return_type,
+
+ gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION
+ && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS);
+ gdbarch_return_value (gdbarch, function, return_type,
get_current_regcache (), NULL /*read*/,
value_contents (return_value) /*write*/);
}
if (get_frame_type (get_current_frame ()) == DUMMY_FRAME)
frame_pop (get_current_frame ());
+ select_frame (get_current_frame ());
/* If interactive, print the frame that is now current. */
if (from_tty)
- frame_command ("0", 1);
- else
- select_frame_command ("0", 0);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
/* Sets the scope to input function name, provided that the function
- is within the current stack frame */
+ is within the current stack frame. */
struct function_bounds
{
int i;
int level = 1;
struct function_bounds *func_bounds = NULL;
+ struct cleanup *cleanups;
- if (arg != NULL)
+ if (arg == NULL)
return;
- frame = parse_frame_specification ("0");
- sals = decode_line_spec (arg, 1);
- func_bounds = (struct function_bounds *) xmalloc (
- sizeof (struct function_bounds) * sals.nelts);
+ frame = get_current_frame ();
+ sals = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
+ cleanups = make_cleanup (xfree, sals.sals);
+ func_bounds = XNEWVEC (struct function_bounds, sals.nelts);
+ make_cleanup (xfree, func_bounds);
for (i = 0; (i < sals.nelts && !found); i++)
{
- if (sals.sals[i].pc == 0
- || find_pc_partial_function (sals.sals[i].pc, NULL,
- &func_bounds[i].low,
- &func_bounds[i].high) == 0)
+ if (sals.sals[i].pspace != current_program_space)
+ func_bounds[i].low = func_bounds[i].high = 0;
+ else if (sals.sals[i].pc == 0
+ || find_pc_partial_function (sals.sals[i].pc, NULL,
+ &func_bounds[i].low,
+ &func_bounds[i].high) == 0)
{
func_bounds[i].low = func_bounds[i].high = 0;
}
}
while (!found && level == 0);
- if (func_bounds)
- xfree (func_bounds);
+ do_cleanups (cleanups);
if (!found)
printf_filtered (_("'%s' not within current stack frame.\n"), arg);
else if (frame != get_selected_frame (NULL))
select_and_print_frame (frame);
}
-
-/* Gets the language of the current frame. */
-
-enum language
-get_frame_language (void)
-{
- struct frame_info *frame = deprecated_safe_get_selected_frame ();
-
- if (frame)
- {
- /* We determine the current frame language by looking up its
- associated symtab. To retrieve this symtab, we use the frame
- PC. However we cannot use the frame PC as is, because it
- usually points to the instruction following the "call", which
- is sometimes the first instruction of another function. So
- we rely on get_frame_address_in_block(), it provides us with
- a PC that is guaranteed to be inside the frame's code
- block. */
- CORE_ADDR pc = get_frame_address_in_block (frame);
- struct symtab *s = find_pc_symtab (pc);
-
- if (s)
- return s->language;
- }
-
- return language_unknown;
-}
\f
/* Provide a prototype to silence -Wmissing-prototypes. */
void
_initialize_stack (void)
{
-#if 0
- backtrace_limit = 30;
-#endif
-
add_com ("return", class_stack, return_command, _("\
Make selected stack frame return to its caller.\n\
Control remains in the debugger, but when you continue\n\
This is useful in command scripts."));
add_com ("frame", class_stack, frame_command, _("\
-Select and print a stack frame.\n\
-With no argument, print the selected stack frame. (See also \"info frame\").\n\
+Select and print a stack frame.\nWith no argument, \
+print the selected stack frame. (See also \"info frame\").\n\
An argument specifies the frame to select.\n\
-It can be a stack frame number or the address of the frame.\n\
-With argument, nothing is printed if input is coming from\n\
-a command file or a user-defined command."));
+It can be a stack frame number or the address of the frame.\n"));
add_com_alias ("f", "frame", class_stack, 1);
- if (xdb_commands)
- {
- add_com ("L", class_stack, current_frame_command,
- _("Print the current stack frame.\n"));
- add_com_alias ("V", "frame", class_stack, 1);
- }
- add_com ("select-frame", class_stack, select_frame_command, _("\
+ add_com_suppress_notification ("select-frame", class_stack, select_frame_command, _("\
Select a stack frame without printing anything.\n\
An argument specifies the frame to select.\n\
-It can be a stack frame number or the address of the frame.\n"));
+It can be a stack frame number or the address of the frame.\n"),
+ &cli_suppress_notification.user_selected_context);
add_com ("backtrace", class_stack, backtrace_command, _("\
Print backtrace of all stack frames, or innermost COUNT frames.\n\
-With a negative argument, print outermost -COUNT frames.\n\
-Use of the 'full' qualifier also prints the values of the local variables.\n"));
+With a negative argument, print outermost -COUNT frames.\nUse of the \
+'full' qualifier also prints the values of the local variables.\n\
+Use of the 'no-filters' qualifier prohibits frame filters from executing\n\
+on this backtrace.\n"));
add_com_alias ("bt", "backtrace", class_stack, 0);
- if (xdb_commands)
- {
- add_com_alias ("t", "backtrace", class_stack, 0);
- add_com ("T", class_stack, backtrace_full_command, _("\
-Print backtrace of all stack frames, or innermost COUNT frames \n\
-and the values of the local variables.\n\
-With a negative argument, print outermost -COUNT frames.\n\
-Usage: T <count>\n"));
- }
add_com_alias ("where", "backtrace", class_alias, 0);
add_info ("stack", backtrace_command,
_("Local variables of current stack frame."));
add_info ("args", args_info,
_("Argument variables of current stack frame."));
- if (xdb_commands)
- add_com ("l", class_info, args_plus_locals_info,
- _("Argument and local variables of current stack frame."));
if (dbx_commands)
add_com ("func", class_stack, func_command, _("\
Select the stack frame that contains <func>.\n\
Usage: func <name>\n"));
- add_info ("catch", catch_info,
- _("Exceptions that can be caught in the current stack frame."));
-
add_setshow_enum_cmd ("frame-arguments", class_stack,
print_frame_arguments_choices, &print_frame_arguments,
_("Set printing of non-scalar frame arguments"),
_("Show printing of non-scalar frame arguments"),
NULL, NULL, NULL, &setprintlist, &showprintlist);
-#if 0
- add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, _(\
-"Specify maximum number of frames for \"backtrace\" to print by default."),
- &setlist);
- add_info ("backtrace-limit", backtrace_limit_info, _("\
-The maximum number of frames for \"backtrace\" to print by default."));
-#endif
+ add_setshow_boolean_cmd ("frame-arguments", no_class,
+ &print_raw_frame_arguments, _("\
+Set whether to print frame arguments in raw form."), _("\
+Show whether to print frame arguments in raw form."), _("\
+If set, frame arguments are printed in raw form, bypassing any\n\
+pretty-printers for that value."),
+ NULL, NULL,
+ &setprintrawlist, &showprintrawlist);
+
+ add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack,
+ &disassemble_next_line, _("\
+Set whether to disassemble next source line or insn when execution stops."),
+ _("\
+Show whether to disassemble next source line or insn when execution stops."),
+ _("\
+If ON, GDB will display disassembly of the next source line, in addition\n\
+to displaying the source line itself. If the next source line cannot\n\
+be displayed (e.g., source is unavailable or there's no line info), GDB\n\
+will display disassembly of next instruction instead of showing the\n\
+source line.\n\
+If AUTO, display disassembly of next instruction only if the source line\n\
+cannot be displayed.\n\
+If OFF (which is the default), never display the disassembly of the next\n\
+source line."),
+ NULL,
+ show_disassemble_next_line,
+ &setlist, &showlist);
+ disassemble_next_line = AUTO_BOOLEAN_FALSE;
+
+ add_setshow_enum_cmd ("entry-values", class_stack,
+ print_entry_values_choices, &print_entry_values,
+ _("Set printing of function arguments at function "
+ "entry"),
+ _("Show printing of function arguments at function "
+ "entry"),
+ _("\
+GDB can sometimes determine the values of function arguments at entry,\n\
+in addition to their current values. This option tells GDB whether\n\
+to print the current value, the value at entry (marked as val@entry),\n\
+or both. Note that one or both of these values may be <optimized out>."),
+ NULL, NULL, &setprintlist, &showprintlist);
}