/* Cache and manage frames for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
- 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
+ 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 "frame.h"
}
int
-frame_id_inner (struct frame_id l, struct frame_id r)
+frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r)
{
int inner;
if (!l.stack_addr_p || !r.stack_addr_p)
comment in "frame.h", there is some fuzz here. Frameless
functions are not strictly inner than (same .stack but
different .code and/or .special address). */
- inner = INNER_THAN (l.stack_addr, r.stack_addr);
+ inner = gdbarch_inner_than (gdbarch, l.stack_addr, r.stack_addr);
if (frame_debug)
{
fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l=");
if (frame_id_eq (id, this))
/* An exact match. */
return frame;
- if (frame_id_inner (id, this))
+ if (frame_id_inner (get_frame_arch (frame), id, this))
/* Gone to far. */
return NULL;
/* Either we're not yet gone far enough out along the frame
/* A per-frame unwinder, prefer it. */
pc = this_frame->unwind->prev_pc (this_frame->next,
&this_frame->prologue_cache);
- else if (gdbarch_unwind_pc_p (current_gdbarch))
+ else if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
{
/* The right way. The `pure' way. The one true way. This
method depends solely on the register-unwind code to
frame. This is all in stark contrast to the old
FRAME_SAVED_PC which would try to directly handle all the
different ways that a PC could be unwound. */
- pc = gdbarch_unwind_pc (current_gdbarch, this_frame);
+ pc = gdbarch_unwind_pc (get_frame_arch (this_frame), this_frame);
}
else
internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
struct regcache *
frame_save_as_regcache (struct frame_info *this_frame)
{
- struct regcache *regcache = regcache_xmalloc (current_gdbarch);
+ struct regcache *regcache = regcache_xmalloc (get_frame_arch (this_frame));
struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
regcache_save (regcache, do_frame_register_read, this_frame);
discard_cleanups (cleanups);
void
frame_pop (struct frame_info *this_frame)
{
+ struct frame_info *prev_frame;
+ struct regcache *scratch;
+ struct cleanup *cleanups;
+
+ /* Ensure that we have a frame to pop to. */
+ prev_frame = get_prev_frame_1 (this_frame);
+
+ if (!prev_frame)
+ error (_("Cannot pop the initial frame."));
+
/* Make a copy of all the register values unwound from this frame.
Save them in a scratch buffer so that there isn't a race between
- trying to extract the old values from the current_regcache while
+ trying to extract the old values from the current regcache while
at the same time writing new values into that same cache. */
- struct regcache *scratch
- = frame_save_as_regcache (get_prev_frame_1 (this_frame));
- struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch);
+ scratch = frame_save_as_regcache (prev_frame);
+ cleanups = make_cleanup_regcache_xfree (scratch);
/* FIXME: cagney/2003-03-16: It should be possible to tell the
target's register cache that it is about to be hit with a burst
(arguably a bug in the target code mind). */
/* Now copy those saved registers into the current regcache.
Here, regcache_cpy() calls regcache_restore(). */
- regcache_cpy (current_regcache, scratch);
+ regcache_cpy (get_current_regcache (), scratch);
do_cleanups (cleanups);
/* We've made right mess of GDB's local state, just discard
everything. */
- flush_cached_frames ();
+ reinit_frame_cache ();
}
void
int i;
const unsigned char *buf = bufferp;
fprintf_unfiltered (gdb_stdlog, "[");
- for (i = 0; i < register_size (current_gdbarch, regnum); i++)
+ for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
fprintf_unfiltered (gdb_stdlog, "]");
}
return frame_unwind_register_unsigned (frame->next, regnum);
}
-void
-frame_unwind_unsigned_register (struct frame_info *frame, int regnum,
- ULONGEST *val)
-{
- gdb_byte buf[MAX_REGISTER_SIZE];
- frame_unwind_register (frame, regnum, buf);
- (*val) = extract_unsigned_integer (buf,
- register_size (get_frame_arch (frame),
- regnum));
-}
-
void
put_frame_register (struct frame_info *frame, int regnum,
const gdb_byte *buf)
break;
}
case lval_register:
- regcache_cooked_write (current_regcache, realnum, buf);
+ regcache_cooked_write (get_current_regcache (), realnum, buf);
break;
default:
error (_("Attempt to assign to an unmodifiable value."));
int realnum;
frame_register (frame, regnum, &optimized, &lval, &addr, &realnum, myaddr);
- /* FIXME: cagney/2002-05-15: This test is just bogus.
-
- It indicates that the target failed to supply a value for a
- register because it was "not available" at this time. Problem
- is, the target still has the register and so get saved_register()
- may be returning a value saved on the stack. */
-
- if (register_cached (regnum) < 0)
- return 0; /* register value not available */
-
return !optimized;
}
if (current_frame == NULL)
{
struct frame_info *sentinel_frame =
- create_sentinel_frame (current_regcache);
+ create_sentinel_frame (get_current_regcache ());
if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
RETURN_MASK_ERROR) != 0)
{
fi = FRAME_OBSTACK_ZALLOC (struct frame_info);
- fi->next = create_sentinel_frame (current_regcache);
+ fi->next = create_sentinel_frame (get_current_regcache ());
/* Select/initialize both the unwind function and the frame's type
based on the PC. */
void
frame_observer_target_changed (struct target_ops *target)
{
- flush_cached_frames ();
+ reinit_frame_cache ();
}
/* Flush the entire frame cache. */
void
-flush_cached_frames (void)
+reinit_frame_cache (void)
{
+ struct frame_info *fi;
+
+ /* Tear down all frame caches. */
+ for (fi = current_frame; fi != NULL; fi = fi->prev)
+ {
+ if (fi->prologue_cache && fi->unwind->dealloc_cache)
+ fi->unwind->dealloc_cache (fi, fi->prologue_cache);
+ if (fi->base_cache && fi->base->unwind->dealloc_cache)
+ fi->base->unwind->dealloc_cache (fi, fi->base_cache);
+ }
+
/* Since we can't really be sure what the first object allocated was */
obstack_free (&frame_cache_obstack, 0);
obstack_init (&frame_cache_obstack);
select_frame (NULL);
annotate_frames_invalid ();
if (frame_debug)
- fprintf_unfiltered (gdb_stdlog, "{ flush_cached_frames () }\n");
-}
-
-/* Flush the frame cache, and start a new one if necessary. */
-
-void
-reinit_frame_cache (void)
-{
- flush_cached_frames ();
-
- /* FIXME: The inferior_ptid test is wrong if there is a corefile. */
- if (PIDGET (inferior_ptid) != 0)
- {
- select_frame (get_current_frame ());
- }
+ fprintf_unfiltered (gdb_stdlog, "{ reinit_frame_cache () }\n");
}
/* Find where a register is saved (in memory or another register).
{
struct frame_info *prev_frame;
struct frame_id this_id;
+ struct gdbarch *gdbarch;
gdb_assert (this_frame != NULL);
+ gdbarch = get_frame_arch (this_frame);
if (frame_debug)
{
go backwards) and sentinel frames (the test is meaningless). */
if (this_frame->next->level >= 0
&& this_frame->next->unwind->type != SIGTRAMP_FRAME
- && frame_id_inner (this_id, get_frame_id (this_frame->next)))
+ && frame_id_inner (get_frame_arch (this_frame), this_id,
+ get_frame_id (this_frame->next)))
{
if (frame_debug)
{
method set the same lval and location information as
frame_register_unwind. */
if (this_frame->level > 0
- && PC_REGNUM >= 0
+ && gdbarch_pc_regnum (gdbarch) >= 0
&& get_frame_type (this_frame) == NORMAL_FRAME
&& get_frame_type (this_frame->next) == NORMAL_FRAME)
{
- int optimized, realnum;
+ int optimized, realnum, nrealnum;
enum lval_type lval, nlval;
CORE_ADDR addr, naddr;
- frame_register_unwind_location (this_frame, PC_REGNUM, &optimized,
- &lval, &addr, &realnum);
- frame_register_unwind_location (get_next_frame (this_frame), PC_REGNUM,
- &optimized, &nlval, &naddr, &realnum);
+ frame_register_unwind_location (this_frame,
+ gdbarch_pc_regnum (gdbarch),
+ &optimized, &lval, &addr, &realnum);
+ frame_register_unwind_location (get_next_frame (this_frame),
+ gdbarch_pc_regnum (gdbarch),
+ &optimized, &nlval, &naddr, &nrealnum);
- if (lval == lval_memory && lval == nlval && addr == naddr)
+ if ((lval == lval_memory && lval == nlval && addr == naddr)
+ || (lval == lval_register && lval == nlval && realnum == nrealnum))
{
if (frame_debug)
{
return 0;
/* Make certain that the code, and not descriptor, address is
returned. */
- maddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ maddr = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame),
SYMBOL_VALUE_ADDRESS (msymbol),
¤t_target);
return maddr == get_frame_func (this_frame);
CORE_ADDR
frame_sp_unwind (struct frame_info *next_frame)
{
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
/* Normality - an architecture that provides a way of obtaining any
frame inner-most address. */
- if (gdbarch_unwind_sp_p (current_gdbarch))
- return gdbarch_unwind_sp (current_gdbarch, next_frame);
- /* Things are looking grim. If it's the inner-most frame and there
- is a TARGET_READ_SP, then that can be used. */
- if (next_frame->level < 0 && TARGET_READ_SP_P ())
- return TARGET_READ_SP ();
+ if (gdbarch_unwind_sp_p (gdbarch))
+ return gdbarch_unwind_sp (gdbarch, next_frame);
/* Now things are really are grim. Hope that the value returned by
- the SP_REGNUM register is meaningful. */
- if (SP_REGNUM >= 0)
- {
- ULONGEST sp;
- frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
- return sp;
- }
+ the gdbarch_sp_regnum register is meaningful. */
+ if (gdbarch_sp_regnum (gdbarch) >= 0)
+ return frame_unwind_register_unsigned (next_frame,
+ gdbarch_sp_regnum (gdbarch));
internal_error (__FILE__, __LINE__, _("Missing unwind SP method"));
}