/* 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.
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
+ 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GDB.
#include "regcache.h"
#include "solib.h"
#include "valprint.h"
+#include "gdbthread.h"
+#include "cp-support.h"
+#include "disasm.h"
+#include "inline-frame.h"
#include "gdb_assert.h"
#include <ctype.h>
#include "gdb_string.h"
+#include "psymtab.h"
+#include "symfile.h"
+
void (*deprecated_selected_frame_level_changed_hook) (int);
/* The possible choices of "set print frame-arguments, and the value
static const char *print_frame_arguments_choices[] =
{"all", "scalars", "none", NULL};
-static const char *print_frame_arguments = "all";
+static const char *print_frame_arguments = "scalars";
-/* Prototypes for local functions. */
+/* Prototypes for local functions. */
static void print_frame_local_vars (struct frame_info *, int,
struct ui_file *);
return 0;
}
+/* 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)
+{
+ /* 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;
+ }
+
+ return get_frame_pc (frame) != sal.pc;
+}
+
/* Show or print a stack frame FRAME briefly. The output is format
according to PRINT_LEVEL and PRINT_WHAT printing the frame's
relative level, function name, argument list, and file name and
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). */
-
-static int
-print_this_frame_argument_p (struct symbol *sym)
-{
- struct type *type;
-
- /* If the user asked to print no argument at all, then obviously
- do not print this argument. */
-
- if (strcmp (print_frame_arguments, "none") == 0)
- return 0;
-
- /* If the user asked to print all arguments, then we should print
- that one. */
-
- if (strcmp (print_frame_arguments, "all") == 0)
- return 1;
-
- /* The user asked to print only the scalar arguments, so do not
- print the non-scalar ones. */
-
- type = CHECK_TYPEDEF (SYMBOL_TYPE (sym));
- while (TYPE_CODE (type) == TYPE_CODE_REF)
- type = CHECK_TYPEDEF (TYPE_TARGET_TYPE (type));
- switch (TYPE_CODE (type))
- {
- 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;
- }
-}
-
/* Print the arguments of frame FRAME on STREAM, given the function
FUNC running in that frame (as a symbol), where NUM is the number
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 args_printed = 0;
struct cleanup *old_chain, *list_chain;
struct ui_stream *stb;
+ /* True if we should print arguments, false otherwise. */
+ int print_args = strcmp (print_frame_arguments, "none");
+ /* True in "summary" mode, false otherwise. */
+ int summary = !strcmp (print_frame_arguments, "scalars");
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
/* Keep track of the highest stack argument offset seen, and
skip over any kinds of symbols we don't care about. */
+ if (!SYMBOL_IS_ARGUMENT (sym))
+ continue;
+
switch (SYMBOL_CLASS (sym))
{
case LOC_ARG:
/* We care about types of symbols, but don't need to
keep track of stack offsets in them. */
- case LOC_REGPARM:
+ case LOC_REGISTER:
case LOC_REGPARM_ADDR:
- case LOC_LOCAL_ARG:
- case LOC_BASEREG_ARG:
- case LOC_COMPUTED_ARG:
- break;
-
- /* Other types of symbols we just skip over. */
+ case LOC_COMPUTED:
+ case LOC_OPTIMIZED_OUT:
default:
- continue;
+ break;
}
/* We have to look up the symbol because arguments can have
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),
+
+ nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
b, VAR_DOMAIN, NULL);
gdb_assert (nsym != NULL);
- if (SYMBOL_CLASS (nsym) == LOC_REGISTER)
+ if (SYMBOL_CLASS (nsym) == LOC_REGISTER
+ && !SYMBOL_IS_ARGUMENT (nsym))
{
/* There is a LOC_ARG/LOC_REGISTER pair. This means
that it was passed on the stack and loaded into a
annotate_arg_name_end ();
ui_out_text (uiout, "=");
- if (print_this_frame_argument_p (sym))
+ if (print_args)
{
/* Avoid value_print because it will deref ref parameters.
We just want to print their addresses. Print ??? for
if (val)
{
const struct language_defn *language;
+ struct value_print_options opts;
/* Use the appropriate language to display our symbol,
unless the user forced the language to a specific
else
language = current_language;
- common_val_print (val, stb->stream, 0, 0, 2,
- Val_no_prettyprint, language);
+ get_raw_print_options (&opts);
+ opts.deref_ref = 0;
+ opts.summary = summary;
+ common_val_print (val, stb->stream, 2, &opts, language);
ui_out_field_stream (uiout, "value", stb);
}
else
}
}
+/* 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);
+}
+
+/* Show assembly codes; stub for catch_errors. */
+
+struct gdb_disassembly_stub_args
+{
+ struct gdbarch *gdbarch;
+ int how_many;
+ CORE_ADDR low;
+ CORE_ADDR high;
+};
+
+static void
+gdb_disassembly_stub (void *args)
+{
+ struct gdb_disassembly_stub_args *p = args;
+
+ gdb_disassembly (p->gdbarch, uiout, 0,
+ DISASSEMBLY_RAW_INSN, p->how_many,
+ p->low, p->high);
+}
+
+/* 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)
+{
+ volatile struct gdb_exception exception;
+ struct gdb_disassembly_stub_args args;
+
+ args.gdbarch = gdbarch;
+ args.how_many = how_many;
+ args.low = low;
+ args.high = high;
+ TRY_CATCH (exception, RETURN_MASK_ALL)
+ {
+ gdb_disassembly_stub (&args);
+ }
+ /* If an exception was thrown while doing the disassembly, print
+ the error message, to give the user a clue of what happened. */
+ if (exception.reason == RETURN_ERROR)
+ exception_print (gdb_stderr, exception);
+}
+
/* Print information about frame FRAME. The output is format according
to PRINT_LEVEL and PRINT_WHAT and PRINT ARGS. The meaning of
PRINT_WHAT is:
print_frame_info (struct frame_info *frame, int print_level,
enum print_what print_what, int print_args)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
struct symtab_and_line sal;
int source_print;
int location_print;
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");
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 (ui_out_is_mi_like_p (uiout))
{
annotate_frame_address ();
- ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame));
+ ui_out_field_core_addr (uiout, "addr",
+ gdbarch, get_frame_pc (frame));
annotate_frame_address_end ();
}
annotate_signal_handler_caller ();
ui_out_field_string (uiout, "func", "<signal handler called>");
}
+ else if (get_frame_type (frame) == ARCH_FRAME)
+ {
+ ui_out_field_string (uiout, "func", "<cross-architecture call>");
+ }
ui_out_text (uiout, "\n");
annotate_frame_end ();
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_field_core_addr (uiout, "addr",
+ gdbarch, get_frame_pc (frame));
ui_out_text (uiout, "\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);
+ set_default_breakpoint (1, sal.pspace,
+ get_frame_pc (frame), sal.symtab, sal.line);
annotate_frame_end ();
gdb_flush (gdb_stdout);
}
-static void
-print_frame (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
+/* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function
+ corresponding to FRAME. */
+
+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 minimal_symbol *msymbol = NULL;
+
+ /* 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));
if (msymbol != NULL
&& (SYMBOL_VALUE_ADDRESS (msymbol)
/* 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 = SYMBOL_PRINT_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
else
{
- funname = DEPRECATED_SYMBOL_NAME (func);
- funlang = SYMBOL_LANGUAGE (func);
- if (funlang == language_cplus)
+ *funname = 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 (*funname);
+
+ if (func_only)
+ {
+ *funname = func_only;
+ make_cleanup (xfree, func_only);
+ }
}
}
}
if (msymbol != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = SYMBOL_PRINT_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
}
+}
+
+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);
+ char *funname = NULL;
+ enum language funlang = language_unknown;
+ struct ui_stream *stb;
+ struct cleanup *old_chain, *list_chain;
+ struct value_print_options opts;
+ struct symbol *func;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+ find_frame_funname (frame, &funname, &funlang, &func);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
- get_frame_pc (frame));
+ gdbarch, get_frame_pc (frame));
list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
ui_out_field_fmt_int (uiout, 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 (frame_show_address (frame, sal) || !sal.symtab
|| print_what == LOC_AND_ADDRESS)
{
annotate_frame_address ();
- ui_out_field_core_addr (uiout, "addr", get_frame_pc (frame));
+ ui_out_field_core_addr (uiout, "addr", gdbarch, get_frame_pc (frame));
annotate_frame_address_end ();
ui_out_text (uiout, " in ");
}
{
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
+ /* 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);
if (ui_out_is_mi_like_p (uiout))
{
const char *fullname = symtab_to_fullname (sal.symtab);
+
if (fullname != NULL)
ui_out_field_string (uiout, "fullname", fullname);
}
#ifdef PC_SOLIB
char *lib = PC_SOLIB (get_frame_pc (frame));
#else
- char *lib = solib_address (get_frame_pc (frame));
+ char *lib = solib_name_from_address (get_frame_program_space (frame),
+ get_frame_pc (frame));
#endif
if (lib)
{
numargs = 0;
else
{
- char *addr_string;
- struct cleanup *tmp_cleanup;
-
numargs = 0;
while (1)
{
{
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;
}
}
struct symbol *func;
struct symtab *s;
struct frame_info *calling_frame_info;
- int i, count, numregs;
+ int numregs;
char *funname = 0;
enum language funlang = language_unknown;
const char *pc_regname;
int selected_frame_p;
struct gdbarch *gdbarch;
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
gdbarch = get_frame_arch (fi);
s = find_pc_symtab (get_frame_pc (fi));
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
msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
if (msymbol != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ funname = SYMBOL_PRINT_NAME (msymbol);
funlang = SYMBOL_LANGUAGE (msymbol);
}
}
{
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);
+ fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout);
wrap_here (" ");
if (funname)
puts_filtered ("; ");
wrap_here (" ");
printf_filtered ("saved %s ", pc_regname);
- fputs_filtered (paddress (frame_pc_unwind (fi)), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, frame_unwind_caller_pc (fi)), gdb_stdout);
printf_filtered ("\n");
if (calling_frame_info == NULL)
printf_filtered (_(" Outermost frame: %s\n"),
frame_stop_reason_string (reason));
}
-
- if (calling_frame_info)
+ 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 (",");
}
}
&realnum, NULL);
if (!optimized && lval == not_lval)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int sp_size = register_size (gdbarch, gdbarch_sp_regnum (gdbarch));
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)));
+ sp = extract_unsigned_integer (value, sp_size, byte_order);
printf_filtered (" Previous frame's sp is ");
- fputs_filtered (paddress (sp), gdb_stdout);
+ fputs_filtered (paddress (gdbarch, 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);
+ fputs_filtered (paddress (gdbarch, addr), gdb_stdout);
printf_filtered ("\n");
need_nl = 0;
}
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
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)
{
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);
+ find_pc_sect_symtab_via_partial (pc, find_pc_mapped_section (pc));
}
}
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;
}
char **argv;
int i;
- argv = buildargv (arg);
+ argv = gdb_buildargv (arg);
old_chain = make_cleanup_freeargv (argv);
argc = 0;
for (i = 0; argv[i]; i++)
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;
}
\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 (struct block *b,
+ iterate_over_block_arg_local_vars_cb cb,
+ void *cb_data)
{
struct dict_iterator iter;
struct symbol *sym;
- int values_printed = 0;
- int j;
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
case LOC_LOCAL:
case LOC_REGISTER:
case LOC_STATIC:
- case LOC_BASEREG:
case LOC_COMPUTED:
- 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_IS_ARGUMENT (sym))
+ 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 symbol *sym;
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.
+/* Iterate over all the local variables in block B, including all its
+ superblocks, stopping when the top-level block is reached. */
- Returns 1 if the job was done, or 0 if nothing was printed because
- we have no info on the function running in FRAME. */
+void
+iterate_over_block_local_vars (struct block *block,
+ iterate_over_block_arg_local_vars_cb cb,
+ void *cb_data)
+{
+ while (block)
+ {
+ 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. */
+ if (BLOCK_FUNCTION (block))
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+}
+
+/* Data to be passed around in the calls to the locals and args
+ iterators. */
+
+struct print_variable_and_value_data
+{
+ struct frame_info *frame;
+ 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 = cb_data;
+
+ print_variable_and_value (print_name, sym,
+ p->frame, p->stream, p->num_tabs);
+ p->values_printed = 1;
+}
static void
print_frame_local_vars (struct frame_info *frame, int num_tabs,
struct ui_file *stream)
{
- struct block *block = get_frame_block (frame, 0);
- int values_printed = 0;
+ struct print_variable_and_value_data cb_data;
+ struct block *block;
+ block = get_frame_block (frame, 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;
- /* 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);
- }
+ cb_data.frame = frame;
+ cb_data.num_tabs = 4 * num_tabs;
+ cb_data.stream = stream;
+ cb_data.values_printed = 0;
+
+ iterate_over_block_local_vars (block,
+ do_print_variable_and_value,
+ &cb_data);
- if (!values_printed)
+ if (!cb_data.values_printed)
fprintf_filtered (stream, _("No locals.\n"));
}
#else
struct blockvector *bl;
struct block *block = get_frame_block (frame, 0);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
int values_printed = 0;
int index, have_default = 0;
char *blocks_printed;
{
if (blocks_printed[index] == 0)
{
- if (print_block_frame_labels (BLOCKVECTOR_BLOCK (bl, index),
+ if (print_block_frame_labels (gdbarch,
+ BLOCKVECTOR_BLOCK (bl, index),
&have_default, stream))
values_printed = 1;
blocks_printed[index] = 1;
return;
/* 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.
+ Also do not continue to the containing function of an inlined
+ function. */
if (BLOCK_FUNCTION (block))
break;
block = BLOCK_SUPERBLOCK (block);
static void
catch_info (char *ignore, int from_tty)
{
- struct symtab_and_line *sal;
-
/* Assume g++ compiled code; old GDB 4.16 behaviour. */
print_frame_label_vars (get_selected_frame (_("No frame selected.")),
0, gdb_stdout);
}
-static void
-print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
+/* Iterate over all the argument variables in block B.
+
+ Returns 1 if any argument was walked; 0 otherwise. */
+
+void
+iterate_over_block_arg_vars (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 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)
{
- switch (SYMBOL_CLASS (sym))
+ /* Don't worry about things which aren't arguments. */
+ if (SYMBOL_IS_ARGUMENT (sym))
{
- case LOC_ARG:
- case LOC_LOCAL_ARG:
- case LOC_REF_ARG:
- case LOC_REGPARM:
- case LOC_REGPARM_ADDR:
- case LOC_BASEREG_ARG:
- case LOC_COMPUTED_ARG:
- 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),
+ sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
b, VAR_DOMAIN, NULL);
- print_variable_value (sym2, frame, stream);
- fprintf_filtered (stream, "\n");
- break;
-
- default:
- /* Don't worry about things which aren't arguments. */
- break;
+ (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);
}
}
+}
- if (!values_printed)
+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;
+
+ func = get_frame_function (frame);
+ if (func == NULL)
+ {
+ fprintf_filtered (stream, _("No symbol table info available.\n"));
+ return;
+ }
+
+ cb_data.frame = 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);
+
+ if (!cb_data.values_printed)
fprintf_filtered (stream, _("No arguments.\n"));
}
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)++;
{
struct frame_info *frame;
int count = -1;
+
if (count_exp)
count = -parse_and_eval_long (count_exp);
void
return_command (char *retval_exp, int from_tty)
{
+ struct frame_info *thisframe;
+ struct gdbarch *gdbarch;
struct symbol *thisfun;
struct value *return_value = 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)
{
+ struct expression *retval_expr = parse_expression (retval_exp);
+ struct cleanup *old_chain = make_cleanup (xfree, retval_expr);
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);
/* 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;
+ {
+ if (retval_expr->elts[0].opcode != UNOP_CAST)
+ 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);
+ }
+ do_cleanups (old_chain);
CHECK_TYPEDEF (return_type);
return_value = value_cast (return_type, return_value);
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
+ && using_struct_return (gdbarch,
+ SYMBOL_TYPE (thisfun), return_type))
{
- 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";
+ 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);
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)
+ struct type *func_type = thisfun == NULL ? NULL : SYMBOL_TYPE (thisfun);
+
+ gdb_assert (gdbarch_return_value (gdbarch, func_type, return_type, NULL,
+ NULL, NULL)
== RETURN_VALUE_REGISTER_CONVENTION);
- gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun), return_type,
+ gdbarch_return_value (gdbarch, func_type, return_type,
get_current_regcache (), NULL /*read*/,
value_contents (return_value) /*write*/);
}
}
/* 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
{
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\
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"));
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\
+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"));
_("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_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;
}