2003-01-19 Andrew Cagney <ac131313@redhat.com>
* frame-unwind.h (frame_unwind_pop_ftype): Declare. (struct frame_unwind): Add field pop. * frame.h (frame_pop): Declare. * frame.c (frame_saved_regs_pop): New function. (trad_frame_unwinder): Add frame_saved_regs_pop. (frame_pop): New function. * dummy-frame.c (dummy_frame_pop): New function. (discard_innermost_dummy): New function. (generic_pop_dummy_frame): Use discard_innermost_dummy. (dummy_frame_unwind): Add dummy_frame_pop. * infrun.c (normal_stop): Call frame_pop instead of POP_FRAME. * valops.c (hand_function_call): Ditto. * stack.c (return_command): Ditto.
This commit is contained in:
parent
b4fc4eff63
commit
dbe9fe588f
8 changed files with 118 additions and 14 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
2003-01-19 Andrew Cagney <ac131313@redhat.com>
|
||||||
|
|
||||||
|
* frame-unwind.h (frame_unwind_pop_ftype): Declare.
|
||||||
|
(struct frame_unwind): Add field pop.
|
||||||
|
* frame.h (frame_pop): Declare.
|
||||||
|
* frame.c (frame_saved_regs_pop): New function.
|
||||||
|
(trad_frame_unwinder): Add frame_saved_regs_pop.
|
||||||
|
(frame_pop): New function.
|
||||||
|
* dummy-frame.c (dummy_frame_pop): New function.
|
||||||
|
(discard_innermost_dummy): New function.
|
||||||
|
(generic_pop_dummy_frame): Use discard_innermost_dummy.
|
||||||
|
(dummy_frame_unwind): Add dummy_frame_pop.
|
||||||
|
* infrun.c (normal_stop): Call frame_pop instead of POP_FRAME.
|
||||||
|
* valops.c (hand_function_call): Ditto.
|
||||||
|
* stack.c (return_command): Ditto.
|
||||||
|
|
||||||
2003-01-18 Andrew Cagney <ac131313@redhat.com>
|
2003-01-18 Andrew Cagney <ac131313@redhat.com>
|
||||||
|
|
||||||
* cris-tdep.c: Fix function declaration indentation.
|
* cris-tdep.c: Fix function declaration indentation.
|
||||||
|
|
|
@ -270,8 +270,48 @@ generic_pop_current_frame (void (*popper) (struct frame_info * frame))
|
||||||
(*popper) (frame);
|
(*popper) (frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function: pop_dummy_frame
|
/* Discard the innermost dummy frame from the dummy frame stack
|
||||||
Restore the machine state from a saved dummy stack frame. */
|
(passed in as a parameter). */
|
||||||
|
|
||||||
|
static void
|
||||||
|
discard_innermost_dummy (struct dummy_frame **stack)
|
||||||
|
{
|
||||||
|
struct dummy_frame *tbd = (*stack);
|
||||||
|
(*stack) = (*stack)->next;
|
||||||
|
regcache_xfree (tbd->regcache);
|
||||||
|
xfree (tbd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function: dummy_frame_pop. Restore the machine state from a saved
|
||||||
|
dummy stack frame. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
dummy_frame_pop (struct frame_info *fi, void **cache,
|
||||||
|
struct regcache *regcache)
|
||||||
|
{
|
||||||
|
struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache);
|
||||||
|
|
||||||
|
/* If it isn't, what are we even doing here? */
|
||||||
|
gdb_assert (get_frame_type (fi) == DUMMY_FRAME);
|
||||||
|
|
||||||
|
if (dummy == NULL)
|
||||||
|
error ("Can't pop dummy frame!");
|
||||||
|
|
||||||
|
/* Discard all dummy frames up-to but not including this one. */
|
||||||
|
while (dummy_frame_stack != dummy)
|
||||||
|
discard_innermost_dummy (&dummy_frame_stack);
|
||||||
|
|
||||||
|
/* Restore this one. */
|
||||||
|
regcache_cpy (regcache, dummy->regcache);
|
||||||
|
flush_cached_frames ();
|
||||||
|
|
||||||
|
/* Now discard it. */
|
||||||
|
discard_innermost_dummy (&dummy_frame_stack);
|
||||||
|
|
||||||
|
/* Note: target changed would be better. Registers, memory and
|
||||||
|
frame are all invalid. */
|
||||||
|
flush_cached_frames ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
generic_pop_dummy_frame (void)
|
generic_pop_dummy_frame (void)
|
||||||
|
@ -283,12 +323,10 @@ generic_pop_dummy_frame (void)
|
||||||
|
|
||||||
if (!dummy_frame)
|
if (!dummy_frame)
|
||||||
error ("Can't pop dummy frame!");
|
error ("Can't pop dummy frame!");
|
||||||
dummy_frame_stack = dummy_frame->next;
|
|
||||||
regcache_cpy (current_regcache, dummy_frame->regcache);
|
regcache_cpy (current_regcache, dummy_frame->regcache);
|
||||||
flush_cached_frames ();
|
flush_cached_frames ();
|
||||||
|
|
||||||
regcache_xfree (dummy_frame->regcache);
|
discard_innermost_dummy (&dummy_frame_stack);
|
||||||
xfree (dummy_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function: fix_call_dummy
|
/* Function: fix_call_dummy
|
||||||
|
@ -369,6 +407,7 @@ dummy_frame_id_unwind (struct frame_info *frame,
|
||||||
|
|
||||||
static struct frame_unwind dummy_frame_unwind =
|
static struct frame_unwind dummy_frame_unwind =
|
||||||
{
|
{
|
||||||
|
dummy_frame_pop,
|
||||||
dummy_frame_pc_unwind,
|
dummy_frame_pc_unwind,
|
||||||
dummy_frame_id_unwind,
|
dummy_frame_id_unwind,
|
||||||
dummy_frame_register_unwind
|
dummy_frame_register_unwind
|
||||||
|
|
|
@ -82,12 +82,27 @@ typedef void (frame_unwind_id_ftype) (struct frame_info * frame,
|
||||||
void **unwind_cache,
|
void **unwind_cache,
|
||||||
struct frame_id * id);
|
struct frame_id * id);
|
||||||
|
|
||||||
|
/* Discard the frame by restoring the registers (in regcache) back to
|
||||||
|
that of the caller. */
|
||||||
|
/* NOTE: cagney/2003-01-19: While at present the callers all pop each
|
||||||
|
frame in turn, the implementor should try to code things so that
|
||||||
|
any frame can be popped directly. */
|
||||||
|
/* FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a
|
||||||
|
common register cache, care must be taken when restoring the
|
||||||
|
registers. The `correct fix' is to first first save the registers
|
||||||
|
in a scratch cache, and second write that scratch cache back to to
|
||||||
|
the real register cache. */
|
||||||
|
|
||||||
|
typedef void (frame_unwind_pop_ftype) (struct frame_info *frame,
|
||||||
|
void **unwind_cache,
|
||||||
|
struct regcache *regcache);
|
||||||
|
|
||||||
struct frame_unwind
|
struct frame_unwind
|
||||||
{
|
{
|
||||||
/* Should the frame's type go here? */
|
/* Should the frame's type go here? */
|
||||||
/* Should an attribute indicating the frame's address-in-block go
|
/* Should an attribute indicating the frame's address-in-block go
|
||||||
here? */
|
here? */
|
||||||
|
frame_unwind_pop_ftype *pop;
|
||||||
frame_unwind_pc_ftype *pc;
|
frame_unwind_pc_ftype *pc;
|
||||||
frame_unwind_id_ftype *id;
|
frame_unwind_id_ftype *id;
|
||||||
frame_unwind_reg_ftype *reg;
|
frame_unwind_reg_ftype *reg;
|
||||||
|
|
20
gdb/frame.c
20
gdb/frame.c
|
@ -145,6 +145,18 @@ frame_id_unwind (struct frame_info *frame)
|
||||||
return frame->id_unwind_cache;
|
return frame->id_unwind_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
frame_pop (struct frame_info *frame)
|
||||||
|
{
|
||||||
|
/* FIXME: cagney/2003-01-18: There is probably a chicken-egg problem
|
||||||
|
with passing in current_regcache. The pop function needs to be
|
||||||
|
written carefully so as to not overwrite registers whose [old]
|
||||||
|
values are needed to restore other registers. Instead, this code
|
||||||
|
should pass in a scratch cache and, as a second step, restore the
|
||||||
|
registers using that. */
|
||||||
|
frame->unwind->pop (frame, &frame->unwind_cache, current_regcache);
|
||||||
|
flush_cached_frames ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
frame_register_unwind (struct frame_info *frame, int regnum,
|
frame_register_unwind (struct frame_info *frame, int regnum,
|
||||||
|
@ -715,7 +727,15 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
|
||||||
id->base = base;
|
id->base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_saved_regs_pop (struct frame_info *fi, void **cache,
|
||||||
|
struct regcache *regcache)
|
||||||
|
{
|
||||||
|
POP_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
const struct frame_unwind trad_frame_unwinder = {
|
const struct frame_unwind trad_frame_unwinder = {
|
||||||
|
frame_saved_regs_pop,
|
||||||
frame_saved_regs_pc_unwind,
|
frame_saved_regs_pc_unwind,
|
||||||
frame_saved_regs_id_unwind,
|
frame_saved_regs_id_unwind,
|
||||||
frame_saved_regs_register_unwind
|
frame_saved_regs_register_unwind
|
||||||
|
|
|
@ -306,6 +306,10 @@ extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
|
||||||
caller's frame. */
|
caller's frame. */
|
||||||
extern struct frame_id frame_id_unwind (struct frame_info *frame);
|
extern struct frame_id frame_id_unwind (struct frame_info *frame);
|
||||||
|
|
||||||
|
/* Discard the specified frame. Restoring the registers to the state
|
||||||
|
of the caller. */
|
||||||
|
extern void frame_pop (struct frame_info *frame);
|
||||||
|
|
||||||
/* Describe the saved registers of a frame. */
|
/* Describe the saved registers of a frame. */
|
||||||
|
|
||||||
#if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)
|
#if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)
|
||||||
|
|
|
@ -3109,10 +3109,10 @@ normal_stop (void)
|
||||||
|
|
||||||
if (stop_stack_dummy)
|
if (stop_stack_dummy)
|
||||||
{
|
{
|
||||||
/* Pop the empty frame that contains the stack dummy.
|
/* Pop the empty frame that contains the stack dummy. POP_FRAME
|
||||||
POP_FRAME ends with a setting of the current frame, so we
|
ends with a setting of the current frame, so we can use that
|
||||||
can use that next. */
|
next. */
|
||||||
POP_FRAME;
|
frame_pop (get_current_frame ());
|
||||||
/* Set stop_pc to what it was before we called the function.
|
/* Set stop_pc to what it was before we called the function.
|
||||||
Can't rely on restore_inferior_status because that only gets
|
Can't rely on restore_inferior_status because that only gets
|
||||||
called if we don't stop in the called function. */
|
called if we don't stop in the called function. */
|
||||||
|
|
15
gdb/stack.c
15
gdb/stack.c
|
@ -1625,6 +1625,10 @@ return_command (char *retval_exp, int from_tty)
|
||||||
error ("Not confirmed.");
|
error ("Not confirmed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: cagney/2003-01-18: Rather than pop each frame in turn,
|
||||||
|
this code should just go straight to the relevant frame and pop
|
||||||
|
that. */
|
||||||
|
|
||||||
/* Do the real work. Pop until the specified frame is current. We
|
/* Do the real work. Pop until the specified frame is current. We
|
||||||
use this method because the deprecated_selected_frame is not valid after
|
use this method because the deprecated_selected_frame is not valid after
|
||||||
a POP_FRAME. The pc comparison makes this work even if the
|
a POP_FRAME. The pc comparison makes this work even if the
|
||||||
|
@ -1632,11 +1636,11 @@ return_command (char *retval_exp, int from_tty)
|
||||||
|
|
||||||
while (selected_frame_addr != get_frame_base (frame = get_current_frame ())
|
while (selected_frame_addr != get_frame_base (frame = get_current_frame ())
|
||||||
|| selected_frame_pc != get_frame_pc (frame))
|
|| selected_frame_pc != get_frame_pc (frame))
|
||||||
POP_FRAME;
|
frame_pop (get_current_frame ());
|
||||||
|
|
||||||
/* Then pop that frame. */
|
/* Then pop that frame. */
|
||||||
|
|
||||||
POP_FRAME;
|
frame_pop (get_current_frame ());
|
||||||
|
|
||||||
/* Compute the return value (if any) and store in the place
|
/* Compute the return value (if any) and store in the place
|
||||||
for return values. */
|
for return values. */
|
||||||
|
@ -1646,9 +1650,14 @@ return_command (char *retval_exp, int from_tty)
|
||||||
|
|
||||||
/* If we are at the end of a call dummy now, pop the dummy frame too. */
|
/* If we are at the end of a call dummy now, pop the dummy frame too. */
|
||||||
|
|
||||||
|
/* FIXME: cagney/2003-01-18: This is silly. Instead of popping all
|
||||||
|
the frames except the dummy, and then, as an afterthought,
|
||||||
|
popping the dummy frame, this code should just pop through to the
|
||||||
|
dummy frame. */
|
||||||
|
|
||||||
if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (),
|
if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (),
|
||||||
get_frame_base (get_current_frame ())))
|
get_frame_base (get_current_frame ())))
|
||||||
POP_FRAME;
|
frame_pop (get_current_frame ());
|
||||||
|
|
||||||
/* If interactive, print the frame that is now current. */
|
/* If interactive, print the frame that is now current. */
|
||||||
|
|
||||||
|
|
|
@ -1711,8 +1711,9 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
|
||||||
{
|
{
|
||||||
/* The user wants the context restored. */
|
/* The user wants the context restored. */
|
||||||
|
|
||||||
/* We must get back to the frame we were before the dummy call. */
|
/* We must get back to the frame we were before the dummy
|
||||||
POP_FRAME;
|
call. */
|
||||||
|
frame_pop (get_current_frame ());
|
||||||
|
|
||||||
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
|
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's
|
||||||
a C++ name with arguments and stuff. */
|
a C++ name with arguments and stuff. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue