along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
-
#include "defs.h"
-#include "param.h"
-#include "language.h"
+#include "value.h"
#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
#include "frame.h"
#include "gdbcmd.h"
-#include "value.h"
#include "gdbcore.h"
#include "target.h"
#include "breakpoint.h"
+#include "demangle.h"
+
+static void
+return_command PARAMS ((char *, int));
+
+static void
+down_command PARAMS ((char *, int));
+
+static void
+down_silently_command PARAMS ((char *, int));
+
+static void
+up_command PARAMS ((char *, int));
+
+static void
+up_silently_command PARAMS ((char *, int));
+
+static void
+frame_command PARAMS ((char *, int));
+
+static void
+select_frame_command PARAMS ((char *, int));
+
+static void
+args_info PARAMS ((char *, int));
+
+static void
+print_frame_arg_vars PARAMS ((FRAME, FILE *));
+
+static void
+catch_info PARAMS ((char *, int));
+
+static void
+locals_info PARAMS ((char *, int));
+
+static void
+print_frame_label_vars PARAMS ((FRAME, int, FILE *));
+
+static void
+print_frame_local_vars PARAMS ((FRAME, FILE *));
+
+static int
+print_block_frame_labels PARAMS ((struct block *, int *, FILE *));
+
+static int
+print_block_frame_locals PARAMS ((struct block *, FRAME, FILE *));
+
+static void
+backtrace_command PARAMS ((char *, int));
+
+static FRAME
+parse_frame_specification PARAMS ((char *));
+
+static void
+frame_info PARAMS ((char *, int));
+
extern int addressprint; /* Print addresses, or stay symbolic only? */
extern int info_verbose; /* Verbosity of symbol reading msgs */
-extern unsigned lines_to_list; /* # of lines "list" command shows by default */
-extern char *reg_names[]; /* Names of registers */
+extern int lines_to_list; /* # of lines "list" command shows by default */
-/* Thie "selected" stack frame is used by default for local and arg access.
+/* The "selected" stack frame is used by default for local and arg access.
May be zero, for no selected frame. */
FRAME selected_frame;
int frame_file_full_name = 0;
-void print_frame_info ();
\f
/* Print a stack frame briefly. FRAME should be the frame id
and LEVEL should be its level in the stack (or -1 for level not defined).
if (addressprint)
printf_filtered ("%s in ", local_hex_string(fi->pc));
- fputs_demangled (fname, stdout, -1);
+ fputs_demangled (fname, stdout, 0);
fputs_filtered (" (...)\n", stdout);
return;
}
#endif
+#ifdef CORE_NEEDS_RELOCATION
+ CORE_NEEDS_RELOCATION(fi->pc);
+#endif
+
sal = find_pc_line (fi->pc, fi->next_frame);
func = find_pc_function (fi->pc);
if (func)
ends has been truncated by ar because it is longer than 15
characters).
- So look in the misc_function_vector as well, and if it comes
+ So look in the minimal symbol tables as well, and if it comes
up with a larger address for the function use that instead.
- I don't think this can ever cause any problems;
- there shouldn't be any
- misc_function_vector symbols in the middle of a function. */
- int misc_index = find_pc_misc_function (fi->pc);
- if (misc_index >= 0
- && (misc_function_vector[misc_index].address
+ I don't think this can ever cause any problems; there shouldn't
+ be any minimal symbols in the middle of a function.
+ FIXME: (Not necessarily true. What about text labels) */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL
+ && (msymbol -> address
> BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
{
/* In this case we have no way of knowing the source file
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- funname = misc_function_vector[misc_index].name;
+ funname = msymbol -> name;
}
else
funname = SYMBOL_NAME (func);
}
else
{
- register int misc_index = find_pc_misc_function (fi->pc);
- if (misc_index >= 0)
- funname = misc_function_vector[misc_index].name;
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ funname = msymbol -> name;
}
if (source >= 0 || !sal.symtab)
if (addressprint)
if (fi->pc != sal.pc || !sal.symtab)
printf_filtered ("%s in ", local_hex_string(fi->pc));
- fputs_demangled (funname ? funname : "??", stdout, -1);
+ fputs_demangled (funname ? funname : "??", stdout, 0);
wrap_here (" ");
fputs_filtered (" (", stdout);
if (args)
wrap_here (" ");
printf_filtered (" at %s:%d", sal.symtab->filename, sal.line);
}
+
+#ifdef PC_LOAD_SEGMENT
+ /* If we couldn't print out function name but if can figure out what
+ load segment this pc value is from, at least print out some info
+ about its load segment. */
+ if (!funname) {
+ wrap_here (" ");
+ printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc));
+ }
+#endif
printf_filtered ("\n");
}
fflush (stdout);
}
-void flush_cached_frames ();
-
#ifdef FRAME_SPECIFICATION_DYADIC
extern FRAME setup_arbitrary_frame ();
#endif
This means absolutely all information in the frame is printed. */
static void
-frame_info (addr_exp)
+frame_info (addr_exp, from_tty)
char *addr_exp;
+ int from_tty;
{
FRAME frame;
struct frame_info *fi;
funname = SYMBOL_NAME (func);
else
{
- register int misc_index = find_pc_misc_function (fi->pc);
- if (misc_index >= 0)
- funname = misc_function_vector[misc_index].name;
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ funname = msymbol -> name;
}
calling_frame = get_prev_frame (frame);
wrap_here (" ");
if (funname)
- printf_filtered (" in %s", funname);
+ {
+ printf_filtered (" in ");
+ fputs_demangled (funname, stdout, DMGL_ANSI | DMGL_PARAMS);
+ }
wrap_here (" ");
if (sal.symtab)
printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
wrap_here (" ");
printf_filtered ("saved %s %s\n", reg_names[PC_REGNUM],
local_hex_string(FRAME_SAVED_PC (frame)));
+
+ {
+ int frameless = 0;
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+#endif
+ if (frameless)
+ printf_filtered (" (FRAMELESS),");
+ }
+
if (calling_frame)
printf_filtered (" called by frame at %s",
local_hex_string(FRAME_FP (calling_frame)));
puts_filtered ("\n");
}
}
+ {
+ /* Address of the local variables for this frame, or 0. */
+ CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi);
+
+ if (arg_list == 0)
+ printf_filtered (" Locals at unknown address,");
+ else
+ printf_filtered (" Locals at %s,", local_hex_string(arg_list));
+ }
#if defined (FRAME_FIND_SAVED_REGS)
get_frame_saved_regs (fi, &fsr);
fi = get_frame_info (frame);
ps = find_pc_psymtab (fi->pc);
if (ps)
- (void) PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in */
+ PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in */
}
}
fputs_filtered (" = ", stream);
print_variable_value (sym, frame, stream);
fprintf_filtered (stream, "\n");
- fflush (stream);
}
}
return values_printed;
struct symtab_and_line sal;
sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
values_printed = 1;
- fputs_demangled (SYMBOL_NAME (sym), stream, 1);
+ fputs_demangled (SYMBOL_NAME (sym), stream, DMGL_ANSI | DMGL_PARAMS);
if (addressprint)
fprintf_filtered (stream, " %s",
local_hex_string(SYMBOL_VALUE_ADDRESS (sym)));
fprintf_filtered (stream, " in file %s, line %d\n",
sal.symtab->filename, sal.line);
- fflush (stream);
}
}
return values_printed;
or 0 if nothing was printed because we have no info
on the function running in FRAME. */
-static int
+static void
print_frame_local_vars (frame, stream)
register FRAME frame;
register FILE *stream;
if (block == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
- fflush (stream);
- return 0;
+ return;
}
while (block != 0)
if (!values_printed)
{
fprintf_filtered (stream, "No locals.\n");
- fflush (stream);
}
-
- return 1;
}
/* Same, but print labels. */
-static int
+static void
print_frame_label_vars (frame, this_level_only, stream)
register FRAME frame;
int this_level_only;
register FILE *stream;
{
- extern struct blockvector *blockvector_for_pc ();
register struct blockvector *bl;
register struct block *block = get_frame_block (frame);
register int values_printed = 0;
if (block == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
- fflush (stream);
- return 0;
+ return;
}
bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
blocks_printed = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
- bzero (blocks_printed, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ memset (blocks_printed, 0, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
while (block != 0)
{
index++;
}
if (have_default)
- return 1;
+ return;
if (values_printed && this_level_only)
- return 1;
+ return;
/* After handling the function's top-level block, stop.
Don't continue to its superblock, the block of
if (!values_printed && !this_level_only)
{
fprintf_filtered (stream, "No catches.\n");
- fflush (stream);
}
-
- return values_printed;
}
/* ARGSUSED */
}
static void
-catch_info ()
+catch_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
{
if (!selected_frame)
error ("No frame selected.");
print_frame_label_vars (selected_frame, 0, stdout);
}
-static int
+static void
print_frame_arg_vars (frame, stream)
register FRAME frame;
register FILE *stream;
if (func == 0)
{
fprintf_filtered (stream, "No symbol table info available.\n");
- fflush (stream);
- return 0;
+ return;
}
b = SYMBOL_BLOCK_VALUE (func);
b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
print_variable_value (sym2, frame, stream);
fprintf_filtered (stream, "\n");
- fflush (stream);
}
}
if (!values_printed)
{
fprintf_filtered (stream, "No arguments.\n");
- fflush (stream);
}
-
- return 1;
}
static void
-args_info ()
+args_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
{
if (!selected_frame)
error ("No frame selected.");
{
s = find_pc_symtab (get_frame_info (frame)->pc);
if (s
- && working_lang != s->language
+ && s->language != current_language->la_language
&& s->language != language_unknown
&& language_mode == language_mode_auto) {
set_language(s->language);
FRAME_ADDR *frameaddrp;
int *levelp;
{
- *frameaddrp = selected_frame ? FRAME_FP (selected_frame) : NULL;
+ *frameaddrp = selected_frame ? FRAME_FP (selected_frame) : 0;
*levelp = selected_frame_level;
}
register int* level_offset_ptr;
{
register FRAME prev;
- register FRAME frame1, frame2;
+ register FRAME frame1;
/* Going up is simple: just do get_prev_frame enough times
or until initial frame is reached. */
(*level_offset_ptr)--;
frame = prev;
}
- /* Going down could be done by iterating get_frame_info to
- find the next frame, but that would be quadratic
- since get_frame_info must scan all the way from the current frame.
- The following algorithm is linear. */
+ /* Going down is just as simple. */
if (*level_offset_ptr < 0)
{
-#if 0
-/* This is ancient and unnecessary? -- gnu@cygnus.com
- It also loops forever if frame #0 is not current_frame (e.g. when we have
- used the "frame" command after the stack was invalid). */
-
- /* First put frame1 at innermost frame
- and frame2 N levels up from there. */
- frame1 = get_current_frame ();
- frame2 = frame1;
- while (*level_offset_ptr < 0 && frame2 != frame)
- {
- frame2 = get_prev_frame (frame2);
- (*level_offset_ptr) ++;
- }
- /* Then slide frame1 and frame2 up in synchrony
- and when frame2 reaches our starting point
- frame1 must be N levels down from there. */
- while (frame2 != frame)
- {
- frame1 = get_prev_frame (frame1);
- frame2 = get_prev_frame (frame2);
- }
- return frame1;
-#else
while (*level_offset_ptr < 0) {
frame1 = get_next_frame (frame);
if (!frame1)
frame = frame1;
(*level_offset_ptr)++;
}
-#endif
}
return frame;
}
-/* The "frame" command. With no arg, print selected frame briefly.
+/* The "select_frame" command. With no arg, NOP.
With arg LEVEL_EXP, select the frame at level LEVEL if it is a
valid level. Otherwise, treat level_exp as an address expression
- and print it. See parse_frame_specification for more info on proper
+ and select it. See parse_frame_specification for more info on proper
frame expressions. */
+/* ARGSUSED */
static void
-frame_command (level_exp, from_tty)
+select_frame_command (level_exp, from_tty)
char *level_exp;
int from_tty;
{
level = 0;
select_frame (frame, level);
+}
- if (!from_tty)
- return;
+/* The "frame" command. With no arg, print selected frame briefly.
+ With arg, behaves like select_frame and then prints the selected
+ frame. */
+static void
+frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ select_frame_command (level_exp, from_tty);
print_stack_frame (selected_frame, selected_frame_level, 1);
}
count = parse_and_eval_address (count_exp);
count1 = count;
- if (!target_has_stack)
+ if (target_has_stack == 0 || selected_frame == 0)
error ("No stack.");
frame = find_relative_frame (selected_frame, &count1);
count = - parse_and_eval_address (count_exp);
count1 = count;
- if (!target_has_stack)
+ if (target_has_stack == 0 || selected_frame == 0)
error ("No stack.");
frame = find_relative_frame (selected_frame, &count1);
FRAME_ADDR selected_frame_addr;
CORE_ADDR selected_frame_pc;
FRAME frame;
+ char *funcname;
+ struct cleanup *back_to;
+ value return_value;
if (selected_frame == NULL)
error ("No selected frame.");
selected_frame_addr = FRAME_FP (selected_frame);
selected_frame_pc = (get_frame_info (selected_frame))->pc;
+ /* Compute the return value (if any -- possibly getting errors here).
+ Call VALUE_CONTENTS to make sure we have fully evaluated it, since
+ it might live in the stack frame we're about to pop. */
+
+ if (retval_exp)
+ {
+ return_value = parse_and_eval (retval_exp);
+ VALUE_CONTENTS (return_value);
+ }
+
/* If interactive, require confirmation. */
if (from_tty)
{
if (thisfun != 0)
{
- if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun)))
- error ("Not confirmed.");
+ funcname = strdup_demangled (SYMBOL_NAME (thisfun));
+ back_to = make_cleanup (free, funcname);
+ if (!query ("Make %s return now? ", funcname))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ do_cleanups (back_to);
}
else
if (!query ("Make selected stack frame return now? "))
for return values. */
if (retval_exp)
- set_return_value (parse_and_eval (retval_exp));
+ set_return_value (return_value);
/* If interactive, print the frame that is now current. */
"Select and print stack frame called by this one.\n\
An argument says how many frames down to go.");
add_com_alias ("do", "down", class_stack, 1);
+ add_com_alias ("dow", "down", class_stack, 1);
add_com ("down-silently", class_support, down_silently_command,
"Same as the `down' command, but does not print anything.\n\
This is useful in command scripts.");
add_com_alias ("f", "frame", class_stack, 1);
+ add_com ("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");
+
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.");