Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GDB.
#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
{"all", "scalars", "none", NULL};
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 *);
if (*SYMBOL_LINKAGE_NAME (sym))
{
struct symbol *nsym;
+
nsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
b, VAR_DOMAIN, NULL);
gdb_assert (nsym != NULL);
struct cmd_list_element *c,
const char *value)
{
- fprintf_filtered (file, _("\
-Debugger's willingness to use disassemble-next-line is %s.\n"),
+ fprintf_filtered (file,
+ _("Debugger's willingness to use "
+ "disassemble-next-line is %s.\n"),
value);
}
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);
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 (opts.addressprint && mid_statement)
{
/* 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,
- get_frame_pc (frame), sal.end);
+ do_gdb_disassembly (get_frame_arch (frame), -1, sal.pc, sal.end);
}
if (print_what != LOCATION)
gdb_flush (gdb_stdout);
}
-/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
- to FRAME. */
+/* 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)
+ enum language *funlang, struct symbol **funcp)
{
struct symbol *func;
*funname = NULL;
*funlang = language_unknown;
+ if (funcp)
+ *funcp = NULL;
func = get_frame_function (frame);
if (func)
{
*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,
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;
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);
+ find_frame_funname (frame, &funname, &funlang, &func);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
gdbarch, get_frame_pc (frame));
{
struct print_args_args args;
struct cleanup *args_list_chain;
+
args.frame = frame;
- args.func = find_pc_function (get_frame_address_in_block (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);
}
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[i]);
}
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;
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;
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);
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;
}
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_COMPUTED:
if (SYMBOL_IS_ARGUMENT (sym))
break;
- values_printed = 1;
- print_variable_and_value (NULL, sym, frame, stream, 4 * num_tabs);
+ (*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 gdbarch *gdbarch, struct block *b,
int *have_default, struct ui_file *stream)
{
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);
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. */
+
+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);
+ }
+}
- Returns 1 if the job was done, or 0 if nothing was printed because
- we have no info on the function running in FRAME. */
+/* 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.
- Also do not continue to the containing function of an inlined
- function. */
- 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"));
}
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)
{
/* Don't worry about things which aren't arguments. */
if (SYMBOL_IS_ARGUMENT (sym))
{
- values_printed = 1;
-
/* 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.
sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
b, VAR_DOMAIN, NULL);
- print_variable_and_value (SYMBOL_PRINT_NAME (sym), sym2,
- frame, stream, 0);
+ (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);
}
}
+}
+
+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;
- if (!values_printed)
+ 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"));
}
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);
&& 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);
}
/* 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"));
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."), _("\
+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\
show_disassemble_next_line,
&setlist, &showlist);
disassemble_next_line = AUTO_BOOLEAN_FALSE;
-
-#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
}