#include "ui-out.h"
#include "block.h"
#include "stack.h"
+#include "gdb_assert.h"
+#include "dictionary.h"
+#include "reggroups.h"
/* Prototypes for exported functions. */
static int print_args_stub (void *);
+/* Print nameless args on STREAM.
+ FI is the frameinfo for this frame, START is the offset
+ of the first nameless arg, and NUM is the number of nameless args to
+ print. FIRST is nonzero if this is the first argument (not just
+ the first nameless arg). */
+
+static void
+print_frame_nameless_args (struct frame_info *fi, long start, int num,
+ int first, struct ui_file *stream)
+{
+ int i;
+ CORE_ADDR argsaddr;
+ long arg_value;
+
+ for (i = 0; i < num; i++)
+ {
+ QUIT;
+ argsaddr = get_frame_args_address (fi);
+ if (!argsaddr)
+ return;
+ arg_value = read_memory_integer (argsaddr + start, sizeof (int));
+ if (!first)
+ fprintf_filtered (stream, ", ");
+ fprintf_filtered (stream, "%ld", arg_value);
+ first = 0;
+ start += sizeof (int);
+ }
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+ running in that frame (as a symbol), the info on the frame,
+ and the number of args according to the stack frame (or -1 if unknown). */
+
+/* References here and elsewhere to "number of args according to the
+ stack frame" appear in all cases to refer to "number of ints of args
+ according to the stack frame". At least for VAX, i386, isi. */
+
+static void
+print_frame_args (struct symbol *func, struct frame_info *fi, int num,
+ struct ui_file *stream)
+{
+ struct block *b = NULL;
+ int first = 1;
+ struct dict_iterator iter;
+ struct symbol *sym;
+ struct value *val;
+ /* Offset of next stack argument beyond the one we have seen that is
+ at the highest offset.
+ -1 if we haven't come to a stack argument yet. */
+ long highest_offset = -1;
+ int arg_size;
+ /* 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);
+
+ if (func)
+ {
+ b = SYMBOL_BLOCK_VALUE (func);
+
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ QUIT;
+
+ /* Keep track of the highest stack argument offset seen, and
+ skip over any kinds of symbols we don't care about. */
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ {
+ long current_offset = SYMBOL_VALUE (sym);
+ arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+
+ /* Compute address of next argument by adding the size of
+ this argument and rounding to an int boundary. */
+ current_offset =
+ ((current_offset + arg_size + sizeof (int) - 1)
+ & ~(sizeof (int) - 1));
+
+ /* If this is the highest offset seen yet, set highest_offset. */
+ if (highest_offset == -1
+ || (current_offset > highest_offset))
+ highest_offset = current_offset;
+
+ /* Add the number of ints we're about to print to args_printed. */
+ args_printed += (arg_size + sizeof (int) - 1) / sizeof (int);
+ }
+
+ /* We care about types of symbols, but don't need to keep track of
+ stack offsets in them. */
+ case LOC_REGPARM:
+ 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. */
+ default:
+ continue;
+ }
+
+ /* 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.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ and it is passed as a double and converted to float by
+ the prologue (in the latter case the type of the LOC_ARG
+ symbol is double and the type of the LOC_LOCAL symbol is
+ float). */
+ /* But if the parameter name is null, don't try it.
+ Null parameter names occur on the RS/6000, for traceback tables.
+ FIXME, should we even print them? */
+
+ if (*DEPRECATED_SYMBOL_NAME (sym))
+ {
+ struct symbol *nsym;
+ nsym = lookup_symbol
+ (DEPRECATED_SYMBOL_NAME (sym),
+ b, VAR_DOMAIN, (int *) NULL, (struct symtab **) NULL);
+ if (SYMBOL_CLASS (nsym) == LOC_REGISTER)
+ {
+ /* There is a LOC_ARG/LOC_REGISTER pair. This means that
+ it was passed on the stack and loaded into a register,
+ or passed in a register and stored in a stack slot.
+ GDB 3.x used the LOC_ARG; GDB 4.0-4.11 used the LOC_REGISTER.
+
+ Reasons for using the LOC_ARG:
+ (1) because find_saved_registers may be slow for remote
+ debugging,
+ (2) because registers are often re-used and stack slots
+ rarely (never?) are. Therefore using the stack slot is
+ much less likely to print garbage.
+
+ Reasons why we might want to use the LOC_REGISTER:
+ (1) So that the backtrace prints the same value as
+ "print foo". I see no compelling reason why this needs
+ to be the case; having the backtrace print the value which
+ was passed in, and "print foo" print the value as modified
+ within the called function, makes perfect sense to me.
+
+ Additional note: It might be nice if "info args" displayed
+ both values.
+ One more note: There is a case with sparc structure passing
+ where we need to use the LOC_REGISTER, but this is dealt with
+ by creating a single LOC_REGPARM in symbol reading. */
+
+ /* Leave sym (the LOC_ARG) alone. */
+ ;
+ }
+ else
+ sym = 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, "=");
+
+ /* 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, fi);
+
+ annotate_arg_value (val == NULL ? NULL : VALUE_TYPE (val));
+
+ if (val)
+ {
+ val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
+ VALUE_ADDRESS (val),
+ stb->stream, 0, 0, 2, Val_no_prettyprint);
+ ui_out_field_stream (uiout, "value", stb);
+ }
+ else
+ ui_out_text (uiout, "???");
+
+ /* Invoke ui_out_tuple_end. */
+ do_cleanups (list_chain);
+
+ annotate_arg_end ();
+
+ first = 0;
+ }
+ }
+
+ /* Don't print nameless args in situations where we don't know
+ enough about the stack to find them. */
+ if (num != -1)
+ {
+ long start;
+
+ if (highest_offset == -1)
+ start = FRAME_ARGS_SKIP;
+ else
+ start = highest_offset;
+
+ print_frame_nameless_args (fi, start, num - args_printed,
+ first, stream);
+ }
+ do_cleanups (old_chain);
+}
+
/* Pass the args the way catch_errors wants them. */
static int
int numargs;
struct print_args_args *p = (struct print_args_args *) args;
- numargs = FRAME_NUM_ARGS (p->fi);
+ if (FRAME_NUM_ARGS_P ())
+ {
+ numargs = FRAME_NUM_ARGS (p->fi);
+ gdb_assert (numargs >= 0);
+ }
+ else
+ numargs = -1;
print_frame_args (p->func, p->fi, numargs, p->stream);
return 0;
}
struct symtab_and_line sal)
{
struct symbol *func;
- register char *funname = 0;
+ char *funname = 0;
enum language funlang = language_unknown;
struct ui_stream *stb;
struct cleanup *old_chain;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
- func = find_pc_function (frame_address_in_block (fi));
+ func = find_pc_function (get_frame_address_in_block (fi));
if (func)
{
/* In certain pathological cases, the symtabs give the wrong
ever changed many parts of GDB will need to be changed (and we'll
create a find_pc_minimal_function or some such). */
- struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (frame_address_in_block (fi));
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_address_in_block (fi));
if (msymbol != NULL
&& (SYMBOL_VALUE_ADDRESS (msymbol)
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
}
else
{
- struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (frame_address_in_block (fi));
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_address_in_block (fi));
if (msymbol != NULL)
{
funname = DEPRECATED_SYMBOL_NAME (msymbol);
}
else
{
- register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (get_frame_pc (fi));
if (msymbol != NULL)
{
funname = DEPRECATED_SYMBOL_NAME (msymbol);
print_address_numeric (arg_list, 1, gdb_stdout);
printf_filtered (",");
- numargs = FRAME_NUM_ARGS (fi);
- if (numargs < 0)
- puts_filtered (" args: ");
- else if (numargs == 0)
- puts_filtered (" no args.");
- else if (numargs == 1)
- puts_filtered (" 1 arg: ");
+ if (!FRAME_NUM_ARGS_P ())
+ {
+ numargs = -1;
+ puts_filtered (" args: ");
+ }
else
- printf_filtered (" %d args: ", numargs);
+ {
+ numargs = FRAME_NUM_ARGS (fi);
+ gdb_assert (numargs >= 0);
+ if (numargs == 0)
+ puts_filtered (" no args.");
+ else if (numargs == 1)
+ puts_filtered (" 1 arg: ");
+ else
+ printf_filtered (" %d args: ", numargs);
+ }
print_frame_args (func, fi, numargs, gdb_stdout);
puts_filtered ("\n");
}
}
if (DEPRECATED_FRAME_INIT_SAVED_REGS_P ()
- && get_frame_saved_regs (fi) == NULL)
+ && deprecated_get_frame_saved_regs (fi) == NULL)
DEPRECATED_FRAME_INIT_SAVED_REGS (fi);
/* Print as much information as possible on the location of all the
registers. */
count = 0;
numregs = NUM_REGS + NUM_PSEUDO_REGS;
for (i = 0; i < numregs; i++)
- if (i != SP_REGNUM)
+ if (i != SP_REGNUM
+ && gdbarch_register_reggroup_p (current_gdbarch, i, all_reggroup))
{
/* Find out the location of the saved register without
fetching the corresponding value. */
backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
{
struct frame_info *fi;
- register int count;
- register int i;
- register struct frame_info *trailing;
- register int trailing_level;
+ int count;
+ int i;
+ struct frame_info *trailing;
+ int trailing_level;
if (!target_has_stack)
error ("No stack.");
fi = get_prev_frame (fi))
{
QUIT;
- ps = find_pc_psymtab (frame_address_in_block (fi));
+ ps = find_pc_psymtab (get_frame_address_in_block (fi));
if (ps)
PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in */
}
Return 1 if any variables were printed; 0 otherwise. */
static int
-print_block_frame_locals (struct block *b, register struct frame_info *fi,
- int num_tabs, register struct ui_file *stream)
+print_block_frame_locals (struct block *b, struct frame_info *fi,
+ int num_tabs, struct ui_file *stream)
{
- register int i, j;
- register struct symbol *sym;
- register int values_printed = 0;
+ struct dict_iterator iter;
+ int j;
+ struct symbol *sym;
+ int values_printed = 0;
- ALL_BLOCK_SYMBOLS (b, i, sym)
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
{
switch (SYMBOL_CLASS (sym))
{
static int
print_block_frame_labels (struct block *b, int *have_default,
- register struct ui_file *stream)
+ struct ui_file *stream)
{
- register int i;
- register struct symbol *sym;
- register int values_printed = 0;
+ struct dict_iterator iter;
+ struct symbol *sym;
+ int values_printed = 0;
- ALL_BLOCK_SYMBOLS (b, i, sym)
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
{
if (STREQ (DEPRECATED_SYMBOL_NAME (sym), "default"))
{
on the function running in FRAME. */
static void
-print_frame_local_vars (register struct frame_info *fi, register int num_tabs,
- register struct ui_file *stream)
+print_frame_local_vars (struct frame_info *fi, int num_tabs,
+ struct ui_file *stream)
{
- register struct block *block = get_frame_block (fi, 0);
- register int values_printed = 0;
+ struct block *block = get_frame_block (fi, 0);
+ int values_printed = 0;
if (block == 0)
{
/* Same, but print labels. */
static void
-print_frame_label_vars (register struct frame_info *fi, int this_level_only,
- register struct ui_file *stream)
+print_frame_label_vars (struct frame_info *fi, int this_level_only,
+ struct ui_file *stream)
{
- register struct blockvector *bl;
- register struct block *block = get_frame_block (fi, 0);
- register int values_printed = 0;
+ struct blockvector *bl;
+ struct block *block = get_frame_block (fi, 0);
+ int values_printed = 0;
int index, have_default = 0;
char *blocks_printed;
CORE_ADDR pc = get_frame_pc (fi);
}
}
-/* ARGSUSED */
void
locals_info (char *args, int from_tty)
{
}
static void
-print_frame_arg_vars (register struct frame_info *fi,
- register struct ui_file *stream)
+print_frame_arg_vars (struct frame_info *fi,
+ struct ui_file *stream)
{
struct symbol *func = get_frame_function (fi);
- register struct block *b;
- register int i;
- register struct symbol *sym, *sym2;
- register int values_printed = 0;
+ struct block *b;
+ struct dict_iterator iter;
+ struct symbol *sym, *sym2;
+ int values_printed = 0;
if (func == 0)
{
}
b = SYMBOL_BLOCK_VALUE (func);
- ALL_BLOCK_SYMBOLS (b, i, sym)
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
{
switch (SYMBOL_CLASS (sym))
{
how much farther the original request asked to go. */
struct frame_info *
-find_relative_frame (register struct frame_info *frame,
- register int *level_offset_ptr)
+find_relative_frame (struct frame_info *frame,
+ int *level_offset_ptr)
{
- register struct frame_info *prev;
- register struct frame_info *frame1;
+ struct frame_info *prev;
+ struct frame_info *frame1;
/* Going up is simple: just do get_prev_frame enough times
or until initial frame is reached. */
/* Select the frame up one or COUNT stack levels
from the previously selected frame, and print it briefly. */
-/* ARGSUSED */
static void
up_silently_base (char *count_exp)
{
- register struct frame_info *fi;
+ struct frame_info *fi;
int count = 1, count1;
if (count_exp)
count = parse_and_eval_long (count_exp);
/* Select the frame down one or COUNT stack levels
from the previously selected frame, and print it briefly. */
-/* ARGSUSED */
static void
down_silently_base (char *count_exp)
{
- register struct frame_info *frame;
+ struct frame_info *frame;
int count = -1, count1;
if (count_exp)
count = -parse_and_eval_long (count_exp);
selected_frame_level_changed_event (frame_relative_level (deprecated_selected_frame));
}
-/* ARGSUSED */
static void
down_silently_command (char *count_exp, int from_tty)
{
enum language
get_frame_language (void)
{
- register struct symtab *s;
+ struct symtab *s;
enum language flang; /* The language of the current frame */
if (deprecated_selected_frame)