/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free
- Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "command.h"
#include "gdbcmd.h"
#include "gdb_string.h"
+#include "observer.h"
/* Dummy frame. This saves the processor state just prior to setting
up the inferior function call. Older targets save the registers
{
struct dummy_frame *next;
/* This frame's ID. Must match the value returned by
- gdbarch_unwind_dummy_id. */
+ gdbarch_dummy_id. */
struct frame_id id;
/* The caller's regcache. */
struct regcache *regcache;
/* Function: deprecated_pc_in_call_dummy (pc)
Return non-zero if the PC falls in a dummy frame created by gdb for
- an inferior call. The code below which allows DECR_PC_AFTER_BREAK
+ an inferior call. The code below which allows gdbarch_decr_pc_after_break
is for infrun.c, which may give the function a PC without that
subtracted out.
dummyframe = dummyframe->next)
{
if ((pc >= dummyframe->id.code_addr)
- && (pc <= dummyframe->id.code_addr + DECR_PC_AFTER_BREAK))
+ && (pc <= dummyframe->id.code_addr
+ + gdbarch_decr_pc_after_break (current_gdbarch)))
return 1;
}
return 0;
{
struct dummy_frame *dummy_frame;
- /* Check to see if there are stale dummy frames, perhaps left over
- from when a longjump took us out of a function that was called by
- the debugger. */
- dummy_frame = dummy_frame_stack;
- while (dummy_frame)
- /* FIXME: cagney/2004-08-02: Should just test IDs. */
- if (frame_id_inner (dummy_frame->id, (*dummy_id)))
- /* Stale -- destroy! */
- {
- dummy_frame_stack = dummy_frame->next;
- regcache_xfree (dummy_frame->regcache);
- xfree (dummy_frame);
- dummy_frame = dummy_frame_stack;
- }
- else
- dummy_frame = dummy_frame->next;
-
dummy_frame = XZALLOC (struct dummy_frame);
dummy_frame->regcache = caller_regcache;
dummy_frame->id = (*dummy_id);
dummy_frame_stack = dummy_frame;
}
+/* Pop the dummy frame with ID dummy_id from the dummy-frame stack. */
+
+void
+dummy_frame_pop (struct frame_id dummy_id)
+{
+ struct dummy_frame **dummy_ptr;
+
+ for (dummy_ptr = &dummy_frame_stack;
+ (*dummy_ptr) != NULL;
+ dummy_ptr = &(*dummy_ptr)->next)
+ {
+ struct dummy_frame *dummy = *dummy_ptr;
+ if (frame_id_eq (dummy->id, dummy_id))
+ {
+ *dummy_ptr = dummy->next;
+ regcache_xfree (dummy->regcache);
+ xfree (dummy);
+ break;
+ }
+ }
+}
+
+/* There may be stale dummy frames, perhaps left over from when a longjump took us
+ out of a function that was called by the debugger. Clean them up at least once
+ whenever we start a new inferior. */
+
+static void
+cleanup_dummy_frames (struct target_ops *target, int from_tty)
+{
+ struct dummy_frame *dummy, *next;
+
+ for (dummy = dummy_frame_stack; dummy; dummy = next)
+ {
+ next = dummy->next;
+ regcache_xfree (dummy->regcache);
+ xfree (dummy);
+ }
+
+ dummy_frame_stack = NULL;
+}
+
/* Return the dummy frame cache, it contains both the ID, and a
pointer to the regcache. */
struct dummy_frame_cache
int
dummy_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *next_frame,
+ struct frame_info *this_frame,
void **this_prologue_cache)
{
struct dummy_frame *dummyframe;
/* Don't bother unles there is at least one dummy frame. */
if (dummy_frame_stack != NULL)
{
- /* Use an architecture specific method to extract the prev's
- dummy ID from the next frame. Note that this method uses
- frame_register_unwind to obtain the register values needed to
- determine the dummy frame's ID. */
- this_id = gdbarch_unwind_dummy_id (get_frame_arch (next_frame),
- next_frame);
+ /* Use an architecture specific method to extract this frame's
+ dummy ID, assuming it is a dummy frame. */
+ this_id = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
/* Use that ID to find the corresponding cache entry. */
for (dummyframe = dummy_frame_stack;
/* Given a call-dummy dummy-frame, return the registers. Here the
register value is taken from the local copy of the register buffer. */
-static void
-dummy_frame_prev_register (struct frame_info *next_frame,
+static struct value *
+dummy_frame_prev_register (struct frame_info *this_frame,
void **this_prologue_cache,
- int regnum, int *optimized,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnum, gdb_byte *bufferp)
+ int regnum)
{
- /* The dummy-frame sniffer always fills in the cache. */
struct dummy_frame_cache *cache = (*this_prologue_cache);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct value *reg_val;
+
+ /* The dummy-frame sniffer always fills in the cache. */
gdb_assert (cache != NULL);
/* Describe the register's location. Generic dummy frames always
have the register value in an ``expression''. */
- *optimized = 0;
- *lvalp = not_lval;
- *addrp = 0;
- *realnum = -1;
-
- /* If needed, find and return the value of the register. */
- if (bufferp != NULL)
- {
- /* Return the actual value. */
- /* Use the regcache_cooked_read() method so that it, on the fly,
- constructs either a raw or pseudo register from the raw
- register cache. */
- regcache_cooked_read (cache->prev_regcache, regnum, bufferp);
- }
+ reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
+
+ /* Use the regcache_cooked_read() method so that it, on the fly,
+ constructs either a raw or pseudo register from the raw
+ register cache. */
+ regcache_cooked_read (cache->prev_regcache, regnum,
+ value_contents_writeable (reg_val));
+ return reg_val;
}
-/* Assuming that THIS frame is a dummy (remember, the NEXT and not
- THIS frame is passed in), return the ID of THIS frame. That ID is
+/* Assuming that THIS frame is a dummy, return the ID of THIS frame. That ID is
determined by examining the NEXT frame's unwound registers using
- the method unwind_dummy_id(). As a side effect, THIS dummy frame's
+ the method dummy_id(). As a side effect, THIS dummy frame's
dummy cache is located and and saved in THIS_PROLOGUE_CACHE. */
static void
-dummy_frame_this_id (struct frame_info *next_frame,
+dummy_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache,
struct frame_id *this_id)
{
_("Print the contents of the internal dummy-frame stack."),
&maintenanceprintlist);
+ observer_attach_inferior_created (cleanup_dummy_frames);
}