2003-01-18 Andrew Cagney <ac131313@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Sat, 18 Jan 2003 17:25:23 +0000 (17:25 +0000)
committerAndrew Cagney <cagney@redhat.com>
Sat, 18 Jan 2003 17:25:23 +0000 (17:25 +0000)
* dummy-frame.h (dummy_frame_id_unwind): Delete declaration.
(dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
(struct frame_unwind): Declare opaque.
(dummy_frame_p): Declare function.
* dummy-frame.c (dummy_frame_id_unwind): Make static.
(dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
* dummy-frame.c: Include "frame-unwind.h".
(dummy_frame_p): New function.
(dummy_frame_unwind): New variable.
* frame.c: Include "frame-unwind.h".
(frame_pc_unwind, frame_id_unwind, frame_register_unwind): Update
to use the new unwind field.
(set_unwind_by_pc): Delete function.
(create_new_frame, get_prev_frame): Set unwind field using
frame_unwind_find_by_pc.
(trad_frame_unwind, trad_frame_unwinder): New variables.
* frame.h (trad_frame_unwind): Declare variable.
(frame_id_unwind_ftype): Delete declaration.
(frame_pc_unwind_ftype, frame_register_unwind_ftype): Ditto.
(struct frame_unwind): Declare opaque.
(struct frame_info): Replace the fields id_unwind, pc_unwind and
register_unwind with a single unwind pointer.
* frame-unwind.h, frame-unwind.c: New files.
* Makefile.in (SFILES): Add frame-unwind.c.
(frame_unwind_h): Define.
(COMMON_OBS): Add frame-unwind.o.
(frame-unwind.o): Specify dependencies.
(frame.o, dummy-frame.o): Update dependencies.

gdb/ChangeLog
gdb/Makefile.in
gdb/dummy-frame.c
gdb/dummy-frame.h
gdb/frame-unwind.c [new file with mode: 0644]
gdb/frame-unwind.h [new file with mode: 0644]
gdb/frame.c
gdb/frame.h

index c73c06d..e0f1231 100644 (file)
@@ -1,5 +1,36 @@
 2003-01-18  Andrew Cagney  <ac131313@redhat.com>
 
+       * dummy-frame.h (dummy_frame_id_unwind): Delete declaration.
+       (dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
+       (struct frame_unwind): Declare opaque.
+       (dummy_frame_p): Declare function.
+       * dummy-frame.c (dummy_frame_id_unwind): Make static.
+       (dummy_frame_pc_unwind, dummy_frame_register_unwind): Ditto.
+       * dummy-frame.c: Include "frame-unwind.h".
+       (dummy_frame_p): New function.
+       (dummy_frame_unwind): New variable.
+       * frame.c: Include "frame-unwind.h".
+       (frame_pc_unwind, frame_id_unwind, frame_register_unwind): Update
+       to use the new unwind field.
+       (set_unwind_by_pc): Delete function.
+       (create_new_frame, get_prev_frame): Set unwind field using
+       frame_unwind_find_by_pc.
+       (trad_frame_unwind, trad_frame_unwinder): New variables.
+       * frame.h (trad_frame_unwind): Declare variable.
+       (frame_id_unwind_ftype): Delete declaration.
+       (frame_pc_unwind_ftype, frame_register_unwind_ftype): Ditto.
+       (struct frame_unwind): Declare opaque.
+       (struct frame_info): Replace the fields id_unwind, pc_unwind and
+       register_unwind with a single unwind pointer.
+       * frame-unwind.h, frame-unwind.c: New files.
+       * Makefile.in (SFILES): Add frame-unwind.c.
+       (frame_unwind_h): Define.
+       (COMMON_OBS): Add frame-unwind.o.
+       (frame-unwind.o): Specify dependencies.
+       (frame.o, dummy-frame.o): Update dependencies.
+       
+2003-01-18  Andrew Cagney  <ac131313@redhat.com>
+
        * ada-valprint.c: Eliminate PTR.
        * breakpoint.c, corelow.c, cris-tdep.c, dbxread.c: Ditto.
        * defs.h, dve3900-rom.c, dwarf2read.c, dwarfread.c: Ditto.
index c0847dd..d23d48c 100644 (file)
@@ -511,6 +511,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
        dummy-frame.c dwarfread.c dwarf2read.c \
        elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
        f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
+       frame-unwind.c \
        gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
        hpacc-abi.c \
        inf-loop.c infcmd.c inflow.c infrun.c \
@@ -623,6 +624,7 @@ event_top_h = event-top.h
 expression_h = expression.h $(symtab_h) $(doublest_h)
 f_lang_h = f-lang.h
 frame_h = frame.h
+frame_unwind_h = frame-unwind.h
 gdb_events_h = gdb-events.h
 gdb_stabs_h = gdb-stabs.h
 gdb_h = gdb.h
@@ -833,7 +835,7 @@ COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
        c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
        nlmread.o serial.o mdebugread.o top.o utils.o \
        ui-file.o \
-       frame.o doublest.o \
+       frame.o frame-unwind.o doublest.o \
        gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
        reggroups.o
 
@@ -1636,7 +1638,7 @@ doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \
 dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h)
 dsrec.o: dsrec.c $(defs_h) $(serial_h) $(srec_h)
 dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
-       $(frame_h) $(inferior_h) $(gdb_assert_h)
+       $(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h)
 dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
        $(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h)
 dwarf2cfi.o: dwarf2cfi.c $(defs_h) $(gdbcore_h) $(symtab_h) $(symfile_h) \
@@ -1688,7 +1690,9 @@ fork-child.o: fork-child.c $(defs_h) $(gdb_string_h) $(frame_h) \
 frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
        $(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
        $(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \
-       $(language_h)
+       $(language_h) $(frame_unwind_h)
+frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \
+       $(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h)
 frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
        $(arch_utils_h) $(regcache_h)
 gcore.o: gcore.c $(defs_h) $(cli_decode_h) $(inferior_h) $(gdbcore_h) \
index 99d388d..0a3e35e 100644 (file)
@@ -28,6 +28,7 @@
 #include "frame.h"
 #include "inferior.h"
 #include "gdb_assert.h"
+#include "frame-unwind.h"
 
 /* Dummy frame.  This saves the processor state just prior to setting
    up the inferior function call.  Older targets save the registers
@@ -304,7 +305,7 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
 /* Given a call-dummy dummy-frame, return the registers.  Here the
    register value is taken from the local copy of the register buffer.  */
 
-void
+static void
 dummy_frame_register_unwind (struct frame_info *frame, void **cache,
                             int regnum, int *optimized,
                             enum lval_type *lvalp, CORE_ADDR *addrp,
@@ -331,7 +332,10 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache,
     }
 }
 
-CORE_ADDR
+/* Assuming that FRAME is a dummy, return the resume address for the
+   previous frame.  */
+
+static CORE_ADDR
 dummy_frame_pc_unwind (struct frame_info *frame,
                       void **cache)
 {
@@ -345,8 +349,12 @@ dummy_frame_pc_unwind (struct frame_info *frame,
 }
 
 
-void
-dummy_frame_id_unwind (struct frame_info *frame, void **cache,
+/* Assuming that FRAME is a dummy, return the ID of the calling frame
+   (the frame that the dummy has the saved state of).  */
+
+static void
+dummy_frame_id_unwind (struct frame_info *frame,
+                      void **cache,
                       struct frame_id *id)
 {
   struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
@@ -359,3 +367,20 @@ dummy_frame_id_unwind (struct frame_info *frame, void **cache,
     (*id) = dummy->id;
 }
 
+static struct frame_unwind dummy_frame_unwind =
+{
+  dummy_frame_pc_unwind,
+  dummy_frame_id_unwind,
+  dummy_frame_register_unwind
+};
+
+const struct frame_unwind *
+dummy_frame_p (CORE_ADDR pc)
+{
+  if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
+      ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
+      : pc_in_dummy_frame (pc))
+    return &dummy_frame_unwind;
+  else
+    return NULL;
+}
index 746e663..2d03421 100644 (file)
@@ -24,6 +24,7 @@
 
 struct frame_info;
 struct regcache;
+struct frame_unwind;
 struct frame_id;
 
 /* GENERIC DUMMY FRAMES
@@ -43,30 +44,10 @@ struct frame_id;
    generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as
    generic_fix_call_dummy.  */
 
-/* Assuming that FRAME is a dummy, return a register value for the
-   previous frame.  */
+/* If the PC falls in a dummy frame, return a dummy frame
+   unwinder.  */
 
-extern void dummy_frame_register_unwind (struct frame_info *frame,
-                                        void **unwind_cache,
-                                        int regnum,
-                                        int *optimized,
-                                        enum lval_type *lvalp,
-                                        CORE_ADDR *addrp,
-                                        int *realnump,
-                                        void *valuep);
-
-/* Assuming that FRAME is a dummy, return the resume address for the
-   previous frame.  */
-
-extern CORE_ADDR dummy_frame_pc_unwind (struct frame_info *frame,
-                                       void **unwind_cache);
-
-/* Assuming that FRAME is a dummy, return the ID of the calling frame
-   (the frame that the dummy has the saved state of).  */
-
-extern void dummy_frame_id_unwind (struct frame_info *frame,
-                                  void **unwind_cache,
-                                  struct frame_id *id);
+extern const struct frame_unwind *dummy_frame_p (CORE_ADDR pc);
 
 /* Does the PC fall in a dummy frame?
 
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
new file mode 100644 (file)
index 0000000..a889f95
--- /dev/null
@@ -0,0 +1,103 @@
+/* Definitions for frame unwinder, for GDB, the GNU debugger.
+
+   Copyright 2003 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
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "gdb_assert.h"
+#include "dummy-frame.h"
+
+static struct gdbarch_data *frame_unwind_data;
+
+struct frame_unwind_table
+{
+  frame_unwind_p_ftype **p;
+  int middle;
+  int nr;
+};
+
+/* Append a predicate to the end of the table.  */
+static void
+append_predicate (struct frame_unwind_table *table, frame_unwind_p_ftype *p)
+{
+  table->p = xrealloc (table->p, ((table->nr + 1)
+                                 * sizeof (frame_unwind_p_ftype *)));
+  table->p[table->nr] = p;
+  table->nr++;
+}
+
+static void *
+frame_unwind_init (struct gdbarch *gdbarch)
+{
+  struct frame_unwind_table *table = XCALLOC (1, struct frame_unwind_table);
+  append_predicate (table, dummy_frame_p);
+  return table;
+}
+
+static void
+frame_unwind_free (struct gdbarch *gdbarch, void *data)
+{
+  struct frame_unwind_table *table =
+    gdbarch_data (gdbarch, frame_unwind_data);
+  xfree (table->p);
+  xfree (table);
+}
+
+void
+frame_unwind_append_predicate (struct gdbarch *gdbarch,
+                              frame_unwind_p_ftype *p)
+{
+  struct frame_unwind_table *table =
+    gdbarch_data (gdbarch, frame_unwind_data);
+  if (table == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      table = frame_unwind_init (gdbarch);
+      set_gdbarch_data (gdbarch, frame_unwind_data, table);
+    }
+  append_predicate (table, p);
+}
+
+const struct frame_unwind *
+frame_unwind_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  int i;
+  struct frame_unwind_table *table =
+    gdbarch_data (gdbarch, frame_unwind_data);
+  /* Seriously old code.  Don't even try to use this new mechanism.  */
+  if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
+    return trad_frame_unwind;
+  for (i = 0; i < table->nr; i++)
+    {
+      const struct frame_unwind *desc = table->p[i] (pc);
+      if (desc != NULL)
+       return desc;
+    }
+  return trad_frame_unwind;
+}
+
+void
+_initialize_frame_unwind (void)
+{
+  frame_unwind_data = register_gdbarch_data (frame_unwind_init,
+                                            frame_unwind_free);
+}
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
new file mode 100644 (file)
index 0000000..863f259
--- /dev/null
@@ -0,0 +1,96 @@
+/* Definitions for a frame unwinder, for GDB, the GNU debugger.
+
+   Copyright 2003 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
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#if !defined (FRAME_UNWIND_H)
+#define FRAME_UNWIND_H 1
+
+struct frame_info;
+struct frame_id;
+struct frame_unwind;
+struct gdbarch;
+struct regcache;
+
+/* Return the frame unwind methods for the function that contains PC,
+   or NULL if this this unwinder can't handle this frame.  */
+
+typedef const struct frame_unwind *(frame_unwind_p_ftype) (CORE_ADDR pc);
+
+/* Add a frame unwinder to the list.  The predicates are polled in the
+   order that they are appended.  The initial list contains the dummy
+   frame's predicate.  */
+
+extern void frame_unwind_append_predicate (struct gdbarch *gdbarch,
+                                          frame_unwind_p_ftype *p);
+
+/* Iterate through the list of frame unwinders until one returns an
+   implementation.  */
+
+extern const struct frame_unwind *frame_unwind_find_by_pc (struct gdbarch
+                                                          *gdbarch,
+                                                          CORE_ADDR pc);
+
+/* Return the location (and possibly value) of REGNUM for the previous
+   (older, up) frame.  All parameters except VALUEP can be assumed to
+   be non NULL.  When VALUEP is NULL, just the location of the
+   register should be returned.
+
+   UNWIND_CACHE is provided as mechanism for implementing a per-frame
+   local cache.  It's initial value being NULL.  Memory for that cache
+   should be allocated using frame_obstack_zalloc().
+
+   Register window architectures (eg SPARC) should note that REGNUM
+   identifies the register for the previous frame.  For instance, a
+   request for the value of "o1" for the previous frame would be found
+   in the register "i1" in this FRAME.  */
+
+typedef void (frame_unwind_reg_ftype) (struct frame_info * frame,
+                                      void **unwind_cache,
+                                      int regnum,
+                                      int *optimized,
+                                      enum lval_type * lvalp,
+                                      CORE_ADDR *addrp,
+                                      int *realnump, void *valuep);
+
+/* Same as for registers above, but return the address at which the
+   calling frame would resume.  */
+
+typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame,
+                                          void **unwind_cache);
+
+/* Same as for registers above, but return the ID of the frame that
+   called this one.  */
+
+typedef void (frame_unwind_id_ftype) (struct frame_info * frame,
+                                     void **unwind_cache,
+                                     struct frame_id * id);
+
+
+struct frame_unwind
+{
+  /* Should the frame's type go here? */
+  /* Should an attribute indicating the frame's address-in-block go
+     here?  */
+  frame_unwind_pc_ftype *pc;
+  frame_unwind_id_ftype *id;
+  frame_unwind_reg_ftype *reg;
+};
+
+#endif
index 78811e4..f85b54a 100644 (file)
@@ -34,6 +34,7 @@
 #include "gdbcore.h"
 #include "annotate.h"
 #include "language.h"
+#include "frame-unwind.h"
 
 /* Return a frame uniq ID that can be used to, later, re-find the
    frame.  */
@@ -127,7 +128,7 @@ frame_pc_unwind (struct frame_info *frame)
 {
   if (!frame->pc_unwind_cache_p)
     {
-      frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache);
+      frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache);
       frame->pc_unwind_cache_p = 1;
     }
   return frame->pc_unwind_cache;
@@ -138,7 +139,7 @@ frame_id_unwind (struct frame_info *frame)
 {
   if (!frame->id_unwind_cache_p)
     {
-      frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache);
+      frame->unwind->id (frame, &frame->unwind_cache, &frame->id_unwind_cache);
       frame->id_unwind_cache_p = 1;
     }
   return frame->id_unwind_cache;
@@ -185,8 +186,8 @@ frame_register_unwind (struct frame_info *frame, int regnum,
     }
 
   /* Ask this frame to unwind its register.  */
-  frame->register_unwind (frame, &frame->unwind_cache, regnum,
-                         optimizedp, lvalp, addrp, realnump, bufferp);
+  frame->unwind->reg (frame, &frame->unwind_cache, regnum,
+                     optimizedp, lvalp, addrp, realnump, bufferp);
 }
 
 void
@@ -714,6 +715,14 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
   id->base = base;
 }
        
+const struct frame_unwind trad_frame_unwinder = {
+  frame_saved_regs_pc_unwind,
+  frame_saved_regs_id_unwind,
+  frame_saved_regs_register_unwind
+};
+const struct frame_unwind *trad_frame_unwind = &trad_frame_unwinder;
+
+
 /* Function: get_saved_register
    Find register number REGNUM relative to FRAME and put its (raw,
    target format) contents in *RAW_BUFFER.  
@@ -813,42 +822,6 @@ deprecated_generic_get_saved_register (char *raw_buffer, int *optimized,
     deprecated_read_register_gen (regnum, raw_buffer);
 }
 
-/* Using the PC, select a mechanism for unwinding a frame returning
-   the previous frame.  The register unwind function should, on
-   demand, initialize the ->context object.  */
-
-static void
-set_unwind_by_pc (CORE_ADDR pc, CORE_ADDR fp,
-                 frame_register_unwind_ftype **unwind_register,
-                 frame_pc_unwind_ftype **unwind_pc,
-                 frame_id_unwind_ftype **unwind_id)
-{
-  if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES)
-    {
-      /* Still need to set this to something.  The ``info frame'' code
-        calls this function to find out where the saved registers are.
-        Hopefully this is robust enough to stop any core dumps and
-        return vaguely correct values..  */
-      *unwind_register = frame_saved_regs_register_unwind;
-      *unwind_pc = frame_saved_regs_pc_unwind;
-      *unwind_id = frame_saved_regs_id_unwind;
-    }
-  else if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
-          ? DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0)
-          : pc_in_dummy_frame (pc))
-    {
-      *unwind_register = dummy_frame_register_unwind;
-      *unwind_pc = dummy_frame_pc_unwind;
-      *unwind_id = dummy_frame_id_unwind;
-    }
-  else
-    {
-      *unwind_register = frame_saved_regs_register_unwind;
-      *unwind_pc = frame_saved_regs_pc_unwind;
-      *unwind_id = frame_saved_regs_id_unwind;
-    }
-}
-
 /* Create an arbitrary (i.e. address specified by user) or innermost frame.
    Always returns a non-NULL value.  */
 
@@ -891,8 +864,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
     INIT_EXTRA_FRAME_INFO (0, fi);
 
   /* Select/initialize an unwind function.  */
-  set_unwind_by_pc (fi->pc, fi->frame, &fi->register_unwind,
-                   &fi->pc_unwind, &fi->id_unwind);
+  fi->unwind = frame_unwind_find_by_pc (current_gdbarch, fi->pc);
 
   return fi;
 }
@@ -1135,8 +1107,7 @@ get_prev_frame (struct frame_info *next_frame)
      (and probably other architectural information).  The PC lets you
      check things like the debug info at that point (dwarf2cfi?) and
      use that to decide how the frame should be unwound.  */
-  set_unwind_by_pc (prev->pc, prev->frame, &prev->register_unwind,
-                   &prev->pc_unwind, &prev->id_unwind);
+  prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc);
 
   /* NOTE: cagney/2002-11-18: The code segments, found in
      create_new_frame and get_prev_frame(), that initializes the
index 09df2b8..9cbdaa4 100644 (file)
 #define FRAME_H 1
 
 struct symtab_and_line;
+struct frame_unwind;
+
+/* The traditional frame unwinder.  */
+extern const struct frame_unwind *trad_frame_unwind;
 
 /* The frame object.  */
 
@@ -302,43 +306,6 @@ extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
    caller's frame.  */
 extern struct frame_id frame_id_unwind (struct frame_info *frame);
 
-\f
-/* Return the location (and possibly value) of REGNUM for the previous
-   (older, up) frame.  All parameters except VALUEP can be assumed to
-   be non NULL.  When VALUEP is NULL, just the location of the
-   register should be returned.
-
-   UNWIND_CACHE is provided as mechanism for implementing a per-frame
-   local cache.  It's initial value being NULL.  Memory for that cache
-   should be allocated using frame_obstack_zalloc().
-
-   Register window architectures (eg SPARC) should note that REGNUM
-   identifies the register for the previous frame.  For instance, a
-   request for the value of "o1" for the previous frame would be found
-   in the register "i1" in this FRAME.  */
-
-typedef void (frame_register_unwind_ftype) (struct frame_info *frame,
-                                           void **unwind_cache,
-                                           int regnum,
-                                           int *optimized,
-                                           enum lval_type *lvalp,
-                                           CORE_ADDR *addrp,
-                                           int *realnump,
-                                           void *valuep);
-
-/* Same as for registers above, but return the address at which the
-   calling frame would resume.  */
-
-typedef CORE_ADDR (frame_pc_unwind_ftype) (struct frame_info *frame,
-                                          void **unwind_cache);
-
-/* Same as for registers above, but return the ID of the frame that
-   called this one.  */
-
-typedef void (frame_id_unwind_ftype) (struct frame_info *frame,
-                                     void **unwind_cache,
-                                     struct frame_id *id);
-
 /* Describe the saved registers of a frame.  */
 
 #if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)
@@ -426,18 +393,14 @@ struct frame_info
        better all agree as to the contents.  */
     void *unwind_cache;
 
-    /* See description above.  The previous frame's registers.  */
-    frame_register_unwind_ftype *register_unwind;
+    /* The frame's unwinder.  */
+    const struct frame_unwind *unwind;
 
-    /* See description above.  The previous frame's resume address.
-       Save the previous PC in a local cache.  */
-    frame_pc_unwind_ftype *pc_unwind;
+    /* Cached copy of the previous frame's resume address.  */
     int pc_unwind_cache_p;
     CORE_ADDR pc_unwind_cache;
 
-    /* See description above.  The previous frame's resume address.
-       Save the previous PC in a local cache.  */
-    frame_id_unwind_ftype *id_unwind;
+    /* Cached copy of the previous frame's ID.  */
     int id_unwind_cache_p;
     struct frame_id id_unwind_cache;