gdb-3.1
This commit is contained in:
parent
bb7592f010
commit
e91b87a368
150 changed files with 54576 additions and 10225 deletions
333
gdb/stack.c
333
gdb/stack.c
|
@ -1,5 +1,5 @@
|
|||
/* Print and select stack frames for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
|
@ -21,12 +21,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "initialize.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
START_FILE
|
||||
|
||||
/* Thie "selected" stack frame is used by default for local and arg access.
|
||||
May be zero, for no selected frame. */
|
||||
|
@ -39,6 +39,9 @@ FRAME selected_frame;
|
|||
|
||||
int selected_frame_level;
|
||||
|
||||
/* Error message when selected_frame is zero when it's needed */
|
||||
char no_sel_frame[] = "There is no current stack frame.";
|
||||
|
||||
/* Nonzero means print the full filename and linenumber
|
||||
when a frame is printed, and do so in a format programs can parse. */
|
||||
|
||||
|
@ -58,17 +61,23 @@ void print_frame_info ();
|
|||
If SOURCE is 1, print the source line as well.
|
||||
If SOURCE is -1, print ONLY the source line. */
|
||||
|
||||
/* FIXME, the argument "frame" is always "selected_frame". This is why
|
||||
we can say "No selected frame" if it == 0. Probably shouldn't be an
|
||||
argument anymore... */
|
||||
|
||||
static void
|
||||
print_stack_frame (frame, level, source)
|
||||
FRAME frame;
|
||||
int level;
|
||||
int source;
|
||||
{
|
||||
struct frame_info fi;
|
||||
struct frame_info *fi;
|
||||
|
||||
if (frame == 0)
|
||||
error (no_sel_frame);
|
||||
fi = get_frame_info (frame);
|
||||
|
||||
print_frame_info (&fi, level, source, 1);
|
||||
print_frame_info (fi, level, source, 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -78,14 +87,13 @@ print_frame_info (fi, level, source, args)
|
|||
int source;
|
||||
int args;
|
||||
{
|
||||
register FRAME frame = fi->frame;
|
||||
struct symtab_and_line sal;
|
||||
struct symbol *func;
|
||||
register char *funname = 0;
|
||||
int numargs;
|
||||
|
||||
sal = find_pc_line (fi->pc, fi->next_frame);
|
||||
func = get_frame_function (frame);
|
||||
func = find_pc_function (fi->pc);
|
||||
if (func)
|
||||
funname = SYMBOL_NAME (func);
|
||||
else
|
||||
|
@ -97,10 +105,6 @@ print_frame_info (fi, level, source, args)
|
|||
|
||||
if (source >= 0 || !sal.symtab)
|
||||
{
|
||||
/* This avoids a bug in cc on the sun. */
|
||||
struct frame_info tem;
|
||||
tem = *fi;
|
||||
|
||||
if (level >= 0)
|
||||
printf ("#%-2d ", level);
|
||||
if (fi->pc != sal.pc || !sal.symtab)
|
||||
|
@ -108,8 +112,8 @@ print_frame_info (fi, level, source, args)
|
|||
printf ("%s (", funname ? funname : "??");
|
||||
if (args)
|
||||
{
|
||||
FRAME_NUM_ARGS (numargs, tem);
|
||||
print_frame_args (func, FRAME_ARGS_ADDRESS (tem), numargs, stdout);
|
||||
FRAME_NUM_ARGS (numargs, fi);
|
||||
print_frame_args (func, fi, numargs, stdout);
|
||||
}
|
||||
printf (")");
|
||||
if (sal.symtab)
|
||||
|
@ -149,11 +153,112 @@ print_sel_frame (just_source)
|
|||
/* Print info on the selected frame, including level number
|
||||
but not source. */
|
||||
|
||||
void
|
||||
print_selected_frame ()
|
||||
{
|
||||
print_stack_frame (selected_frame, selected_frame_level, 0);
|
||||
}
|
||||
|
||||
void flush_cached_frames (); /* FIXME, never called! */
|
||||
|
||||
#ifdef FRAME_SPECIFICATION_DYADIC
|
||||
extern FRAME setup_arbitrary_frame ();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read a frame specification in whatever the appropriate format is.
|
||||
*/
|
||||
static FRAME
|
||||
parse_frame_specification (frame_exp)
|
||||
char *frame_exp;
|
||||
{
|
||||
int numargs = 0;
|
||||
int arg1, arg2;
|
||||
|
||||
if (frame_exp)
|
||||
{
|
||||
char *addr_string, *p;
|
||||
struct cleanup *tmp_cleanup;
|
||||
struct frame_info *fci;
|
||||
|
||||
while (*frame_exp == ' ') frame_exp++;
|
||||
for (p = frame_exp; *p && *p != ' '; p++)
|
||||
;
|
||||
|
||||
if (*frame_exp)
|
||||
{
|
||||
numargs = 1;
|
||||
addr_string = savestring(frame_exp, p - frame_exp);
|
||||
|
||||
{
|
||||
tmp_cleanup = make_cleanup (free, addr_string);
|
||||
arg1 = parse_and_eval_address (addr_string);
|
||||
do_cleanups (tmp_cleanup);
|
||||
}
|
||||
|
||||
while (*p == ' ') p++;
|
||||
|
||||
if (*p)
|
||||
{
|
||||
numargs = 2;
|
||||
arg2 = parse_and_eval_address (p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (numargs)
|
||||
{
|
||||
case 0:
|
||||
if (selected_frame == 0)
|
||||
error (no_sel_frame);
|
||||
return selected_frame;
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
{
|
||||
int level = arg1;
|
||||
FRAME fid = find_relative_frame (get_current_frame (), &level);
|
||||
FRAME tfid;
|
||||
|
||||
if (level == 0)
|
||||
/* find_relative_frame was successful */
|
||||
return fid;
|
||||
|
||||
/* If (s)he specifies the frame with an address, he deserves what
|
||||
(s)he gets. Still, give the highest one that matches. */
|
||||
|
||||
for (fid = get_current_frame ();
|
||||
fid && FRAME_FP (fid) != arg1;
|
||||
fid = get_prev_frame (fid))
|
||||
;
|
||||
|
||||
if (fid)
|
||||
while ((tfid = get_prev_frame (fid)) &&
|
||||
(FRAME_FP (tfid) == arg1))
|
||||
fid = tfid;
|
||||
|
||||
#ifdef FRAME_SPECIFICATION_DYADIC
|
||||
if (!fid)
|
||||
error ("Incorrect number of args in frame specification");
|
||||
|
||||
return fid;
|
||||
#else
|
||||
return create_new_frame (arg1, 0);
|
||||
#endif
|
||||
}
|
||||
/* NOTREACHED */
|
||||
case 2:
|
||||
/* Must be addresses */
|
||||
#ifndef FRAME_SPECIFICATION_DYADIC
|
||||
error ("Incorrect number of args in frame specification");
|
||||
#else
|
||||
return setup_arbitrary_frame (arg1, arg2);
|
||||
#endif
|
||||
/* NOTREACHED */
|
||||
}
|
||||
fatal ("Internal: Error in parsing in parse_frame_specification");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Print verbosely the selected frame or the frame at address ADDR.
|
||||
This means absolutely all information in the frame is printed. */
|
||||
|
||||
|
@ -161,8 +266,8 @@ static void
|
|||
frame_info (addr_exp)
|
||||
char *addr_exp;
|
||||
{
|
||||
FRAME frame = addr_exp ? parse_and_eval_address (addr_exp) : selected_frame;
|
||||
struct frame_info fi;
|
||||
FRAME frame;
|
||||
struct frame_info *fi;
|
||||
struct frame_saved_regs fsr;
|
||||
struct symtab_and_line sal;
|
||||
struct symbol *func;
|
||||
|
@ -171,15 +276,17 @@ frame_info (addr_exp)
|
|||
char *funname = 0;
|
||||
int numargs;
|
||||
|
||||
frame = parse_frame_specification (addr_exp);
|
||||
|
||||
fi = get_frame_info (frame);
|
||||
get_frame_saved_regs (&fi, &fsr);
|
||||
sal = find_pc_line (fi.pc, fi.next_frame);
|
||||
get_frame_saved_regs (fi, &fsr);
|
||||
sal = find_pc_line (fi->pc, fi->next_frame);
|
||||
func = get_frame_function (frame);
|
||||
if (func)
|
||||
funname = SYMBOL_NAME (func);
|
||||
else
|
||||
{
|
||||
register int misc_index = find_pc_misc_function (fi.pc);
|
||||
register int misc_index = find_pc_misc_function (fi->pc);
|
||||
if (misc_index >= 0)
|
||||
funname = misc_function_vector[misc_index].name;
|
||||
}
|
||||
|
@ -187,23 +294,23 @@ frame_info (addr_exp)
|
|||
|
||||
if (!addr_exp && selected_frame_level >= 0)
|
||||
printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x",
|
||||
selected_frame_level, frame, fi.pc);
|
||||
selected_frame_level, FRAME_FP(frame), fi->pc);
|
||||
else
|
||||
printf ("Stack frame at 0x%x:\n pc = 0x%x",
|
||||
frame, fi.pc);
|
||||
FRAME_FP(frame), fi->pc);
|
||||
|
||||
if (funname)
|
||||
printf (" in %s", funname);
|
||||
if (sal.symtab)
|
||||
printf (" (%s line %d)", sal.symtab->filename, sal.line);
|
||||
printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame, fi.next_frame));
|
||||
printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame));
|
||||
if (calling_frame)
|
||||
printf (" called by frame at 0x%x", calling_frame);
|
||||
if (fi.next_frame && calling_frame)
|
||||
printf (" called by frame at 0x%x", FRAME_FP (calling_frame));
|
||||
if (fi->next_frame && calling_frame)
|
||||
printf (",");
|
||||
if (fi.next_frame)
|
||||
printf (" caller of frame at 0x%x", fi.next_frame);
|
||||
if (fi.next_frame || calling_frame)
|
||||
if (fi->next_frame)
|
||||
printf (" caller of frame at 0x%x", fi->next_frame);
|
||||
if (fi->next_frame || calling_frame)
|
||||
printf ("\n");
|
||||
printf (" Arglist at 0x%x,", FRAME_ARGS_ADDRESS (fi));
|
||||
FRAME_NUM_ARGS (i, fi);
|
||||
|
@ -217,7 +324,7 @@ frame_info (addr_exp)
|
|||
printf (" %d args: ", i);
|
||||
|
||||
FRAME_NUM_ARGS (numargs, fi);
|
||||
print_frame_args (func, FRAME_ARGS_ADDRESS (fi), numargs, stdout);
|
||||
print_frame_args (func, fi, numargs, stdout);
|
||||
printf ("\n");
|
||||
count = 0;
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
|
@ -238,29 +345,103 @@ frame_info (addr_exp)
|
|||
printf ("\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Set a limit on the number of frames printed by default in a
|
||||
backtrace. */
|
||||
|
||||
static int backtrace_limit;
|
||||
|
||||
static void
|
||||
set_backtrace_limit_command (count_exp, from_tty)
|
||||
char *count_exp;
|
||||
int from_tty;
|
||||
{
|
||||
int count = parse_and_eval_address (count_exp);
|
||||
|
||||
if (count < 0)
|
||||
error ("Negative argument not meaningful as backtrace limit.");
|
||||
|
||||
backtrace_limit = count;
|
||||
}
|
||||
|
||||
static void
|
||||
backtrace_limit_info (arg, from_tty)
|
||||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
if (arg)
|
||||
error ("\"Info backtrace-limit\" takes no arguments.");
|
||||
|
||||
printf ("Backtrace limit: %d.\n", backtrace_limit);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print briefly all stack frames or just the innermost COUNT frames. */
|
||||
|
||||
static void
|
||||
backtrace_command (count_exp)
|
||||
char *count_exp;
|
||||
{
|
||||
struct frame_info fi;
|
||||
struct frame_info *fi;
|
||||
register int count;
|
||||
register FRAME frame;
|
||||
register int i;
|
||||
register FRAME trailing;
|
||||
register int trailing_level;
|
||||
|
||||
if (have_inferior_p () == 0 && corefile == 0)
|
||||
error ("There is no running program or core file.");
|
||||
|
||||
/* The following code must do two things. First, it must
|
||||
set the variable TRAILING to the frame from which we should start
|
||||
printing. Second, it must set the variable count to the number
|
||||
of frames which we should print, or -1 if all of them. */
|
||||
trailing = get_current_frame ();
|
||||
trailing_level = 0;
|
||||
if (count_exp)
|
||||
count = parse_and_eval_address (count_exp);
|
||||
else
|
||||
count = -1;
|
||||
{
|
||||
count = parse_and_eval_address (count_exp);
|
||||
if (count < 0)
|
||||
{
|
||||
FRAME current;
|
||||
|
||||
for (i = 0, frame = get_current_frame (), fi = get_frame_info (frame);
|
||||
count = -count;
|
||||
|
||||
current = trailing;
|
||||
while (current && count--)
|
||||
current = get_prev_frame (current);
|
||||
|
||||
/* Will stop when CURRENT reaches the top of the stack. TRAILING
|
||||
will be COUNT below it. */
|
||||
while (current)
|
||||
{
|
||||
trailing = get_prev_frame (trailing);
|
||||
current = get_prev_frame (current);
|
||||
trailing_level++;
|
||||
}
|
||||
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
#if 0
|
||||
count = backtrace_limit;
|
||||
#else
|
||||
count = -1;
|
||||
#endif
|
||||
|
||||
for (i = 0, frame = trailing;
|
||||
frame && count--;
|
||||
i++, fi = get_prev_frame_info (fi.frame), frame = fi.frame)
|
||||
i++, frame = get_prev_frame (frame))
|
||||
{
|
||||
QUIT;
|
||||
print_frame_info (&fi, i, 0, 1);
|
||||
fi = get_frame_info (frame);
|
||||
print_frame_info (fi, trailing_level + i, 0, 1);
|
||||
}
|
||||
|
||||
/* If we've stopped before the end, mention that. */
|
||||
if (frame)
|
||||
printf ("(More stack frames follow...)\n");
|
||||
}
|
||||
|
||||
/* Print the local variables of a block B active in FRAME. */
|
||||
|
@ -305,7 +486,9 @@ print_frame_local_vars (frame, stream)
|
|||
register FRAME frame;
|
||||
register FILE *stream;
|
||||
{
|
||||
register struct block *block = get_frame_block (frame);
|
||||
register struct block *block;
|
||||
|
||||
block = get_frame_block (frame);
|
||||
if (block == 0)
|
||||
return 0;
|
||||
while (block != 0)
|
||||
|
@ -324,6 +507,8 @@ print_frame_local_vars (frame, stream)
|
|||
static void
|
||||
locals_info ()
|
||||
{
|
||||
if (selected_frame == 0)
|
||||
error(no_sel_frame);
|
||||
print_frame_local_vars (selected_frame, stdout);
|
||||
}
|
||||
|
||||
|
@ -332,12 +517,13 @@ print_frame_arg_vars (frame, stream)
|
|||
register FRAME frame;
|
||||
register FILE *stream;
|
||||
{
|
||||
struct symbol *func = get_frame_function (frame);
|
||||
struct symbol *func;
|
||||
register struct block *b;
|
||||
int nsyms;
|
||||
register int i;
|
||||
register struct symbol *sym;
|
||||
|
||||
func = get_frame_function (frame);
|
||||
if (func == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -362,6 +548,8 @@ print_frame_arg_vars (frame, stream)
|
|||
static void
|
||||
args_info ()
|
||||
{
|
||||
if (selected_frame == 0)
|
||||
error(no_sel_frame);
|
||||
print_frame_arg_vars (selected_frame, stdout);
|
||||
}
|
||||
|
||||
|
@ -380,11 +568,11 @@ select_frame (frame, level)
|
|||
/* Store the selected frame and its level into *FRAMEP and *LEVELP. */
|
||||
|
||||
void
|
||||
record_selected_frame (framep, levelp)
|
||||
FRAME *framep;
|
||||
record_selected_frame (frameaddrp, levelp)
|
||||
FRAME_ADDR *frameaddrp;
|
||||
int *levelp;
|
||||
{
|
||||
*framep = selected_frame;
|
||||
*frameaddrp = FRAME_FP (selected_frame);
|
||||
*levelp = selected_frame_level;
|
||||
}
|
||||
|
||||
|
@ -417,9 +605,10 @@ find_relative_frame (frame, level_offset_ptr)
|
|||
register int* level_offset_ptr;
|
||||
{
|
||||
register FRAME prev;
|
||||
struct frame_info fi;
|
||||
register FRAME frame1, frame2;
|
||||
|
||||
if (frame == 0)
|
||||
error (no_sel_frame);
|
||||
/* Going up is simple: just do get_prev_frame enough times
|
||||
or until initial frame is reached. */
|
||||
while (*level_offset_ptr > 0)
|
||||
|
@ -459,37 +648,33 @@ find_relative_frame (frame, level_offset_ptr)
|
|||
}
|
||||
|
||||
/* The "frame" command. With no arg, print selected frame briefly.
|
||||
With arg LEVEL, select the frame at level LEVEL and print it.
|
||||
With arg larger than 100000, use it as address of frame to select.
|
||||
If from command file or user-defined command, don't print anything
|
||||
if we have an argument. */
|
||||
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
|
||||
frame expressions. */
|
||||
|
||||
static void
|
||||
frame_command (level_exp, from_tty)
|
||||
char *level_exp;
|
||||
int from_tty;
|
||||
{
|
||||
register int i;
|
||||
register FRAME frame;
|
||||
unsigned int level, level1;
|
||||
register FRAME frame, frame1;
|
||||
unsigned int level = 0;
|
||||
|
||||
if (level_exp)
|
||||
{
|
||||
level1 = level = parse_and_eval_address (level_exp);
|
||||
if (level > 100000)
|
||||
{
|
||||
select_frame (level, -1);
|
||||
frame_info (0);
|
||||
return;
|
||||
}
|
||||
frame = parse_frame_specification (level_exp);
|
||||
|
||||
frame = find_relative_frame (get_current_frame (), &level1);
|
||||
if (level1 != 0)
|
||||
error ("Stack level %d is out of range.", level);
|
||||
select_frame (frame, level);
|
||||
if (! from_tty)
|
||||
return;
|
||||
}
|
||||
for (frame1 = get_prev_frame (0);
|
||||
frame1 && frame1 != frame;
|
||||
frame1 = get_prev_frame (frame1))
|
||||
level++;
|
||||
|
||||
if (!frame1)
|
||||
level = 0;
|
||||
|
||||
select_frame (frame, level);
|
||||
|
||||
if (!from_tty)
|
||||
return;
|
||||
|
||||
print_stack_frame (selected_frame, selected_frame_level, 1);
|
||||
}
|
||||
|
@ -578,9 +763,15 @@ return_command (retval_exp, from_tty)
|
|||
frame_command ("0", 1);
|
||||
}
|
||||
|
||||
static
|
||||
initialize ()
|
||||
extern struct cmd_list_element *setlist;
|
||||
|
||||
void
|
||||
_initialize_stack ()
|
||||
{
|
||||
#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\
|
||||
|
@ -607,7 +798,8 @@ a command file or a user-defined command.");
|
|||
add_com_alias ("f", "frame", class_stack, 1);
|
||||
|
||||
add_com ("backtrace", class_stack, backtrace_command,
|
||||
"Print backtrace of all stack frames, or innermost COUNT frames.");
|
||||
"Print backtrace of all stack frames, or innermost COUNT frames.\n\
|
||||
With a negative argument, print outermost -COUNT frames.");
|
||||
add_com_alias ("bt", "backtrace", class_stack, 0);
|
||||
add_com_alias ("where", "backtrace", class_alias, 0);
|
||||
add_info ("stack", backtrace_command,
|
||||
|
@ -620,6 +812,13 @@ a command file or a user-defined command.");
|
|||
"Local variables of current stack frame.");
|
||||
add_info ("args", args_info,
|
||||
"Argument variables of current stack frame.");
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
END_FILE
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue