This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[cagney_tramp-20040309-branch] jumbo patch


Hello,

Attached is a jumbo patch that is the results of me trialing changes to "trad-frame" and a new "tramp-frame" (better name?) that are ment to make the problem of writing a traditional unwinder easier.

I've committed this to the new (but effectively still born) cagney_tramp-20040309-branch. Over comming weeks I'll be pulling out various ideas ideas in this patch and running them past people for integration into the mainline (I've already done the first -- pre_init data) in particular:

-- pre_init data
Already posted. Simplifies the handling of gdbarch_data allocated before the architecture has been fully initialized.


-- trad-frame
A generic "trad_frame_cache", the idea has already been posted to gdb@.

-- [sig]tramp-frame
For those signal trampolines that rely on magic instructions at a random address. Pass it a cache builder and the trampolines instruction sequence and it does the rest!


In doing this I've made some interface changes, namely:

-- make frame-unwind and frame-base more OO
In particular pass their vector as a parameter

-- add "const struct frame_data" to frame-* objects
so that multiple variants can be created

More in a few weeks (after 6.1 as this is pretty intrusive).

Andrew
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.518
diff -u -r1.518 Makefile.in
--- Makefile.in	28 Feb 2004 18:04:36 -0000	1.518
+++ Makefile.in	9 Mar 2004 22:44:58 -0000
@@ -541,6 +541,7 @@
 	stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
 	target.c thread.c top.c tracepoint.c \
 	trad-frame.c \
+	tramp-frame.c \
 	typeprint.c \
 	ui-out.c utils.c ui-file.h ui-file.c \
 	user-regs.c \
@@ -904,7 +905,8 @@
 	gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
 	cp-namespace.o \
 	reggroups.o \
-	trad-frame.o
+	trad-frame.o \
+	tramp-frame.o
 
 TSOBS = inflow.o
 
Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.27
diff -u -r1.27 dummy-frame.c
--- dummy-frame.c	10 Oct 2003 00:28:43 -0000	1.27
+++ dummy-frame.c	9 Mar 2004 22:44:58 -0000
@@ -32,7 +32,8 @@
 #include "command.h"
 #include "gdbcmd.h"
 
-static void dummy_frame_this_id (struct frame_info *next_frame,
+static void dummy_frame_this_id (const struct frame_unwind *self,
+				 struct frame_info *next_frame,
 				 void **this_prologue_cache,
 				 struct frame_id *this_id);
 
@@ -301,7 +302,8 @@
    register value is taken from the local copy of the register buffer.  */
 
 static void
-dummy_frame_prev_register (struct frame_info *next_frame,
+dummy_frame_prev_register (const struct frame_unwind *self,
+			   struct frame_info *next_frame,
 			   void **this_prologue_cache,
 			   int regnum, int *optimized,
 			   enum lval_type *lvalp, CORE_ADDR *addrp,
@@ -312,7 +314,7 @@
 
   /* Call the ID method which, if at all possible, will set the
      prologue cache.  */
-  dummy_frame_this_id (next_frame, this_prologue_cache, &id);
+  dummy_frame_this_id (self, next_frame, this_prologue_cache, &id);
   dummy = (*this_prologue_cache);
   gdb_assert (dummy != NULL);
 
@@ -341,7 +343,8 @@
    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 (const struct frame_unwind *self,
+		     struct frame_info *next_frame,
 		     void **this_prologue_cache,
 		     struct frame_id *this_id)
 {
@@ -400,7 +403,7 @@
 					     (*this_id).stack_addr);
 }
 
-static struct frame_unwind dummy_frame_unwind =
+static const struct frame_unwind dummy_frame_unwind =
 {
   DUMMY_FRAME,
   dummy_frame_this_id,
@@ -408,7 +411,8 @@
 };
 
 const struct frame_unwind *
-dummy_frame_sniffer (struct frame_info *next_frame)
+dummy_frame_sniffer (const struct frame_unwind_sniffer *self,
+		     struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
   if (DEPRECATED_PC_IN_CALL_DUMMY_P ()
Index: dummy-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.h,v
retrieving revision 1.12
diff -u -r1.12 dummy-frame.h
--- dummy-frame.h	16 Jul 2003 22:29:13 -0000	1.12
+++ dummy-frame.h	9 Mar 2004 22:44:58 -0000
@@ -26,6 +26,7 @@
 struct regcache;
 struct frame_unwind;
 struct frame_id;
+struct frame_unwind_sniffer;
 
 /* GENERIC DUMMY FRAMES
   
@@ -48,7 +49,8 @@
 /* If the PC falls in a dummy frame, return a dummy frame
    unwinder.  */
 
-extern const struct frame_unwind *dummy_frame_sniffer (struct frame_info *next_frame);
+const struct frame_unwind *dummy_frame_sniffer (const struct frame_unwind_sniffer *self,
+						struct frame_info *next_frame);
 
 /* Does the PC fall in a dummy frame?
 
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.31
diff -u -r1.31 dwarf2-frame.c
--- dwarf2-frame.c	16 Feb 2004 20:32:01 -0000	1.31
+++ dwarf2-frame.c	9 Mar 2004 22:44:59 -0000
@@ -730,7 +730,8 @@
 }
 
 static void
-dwarf2_frame_this_id (struct frame_info *next_frame, void **this_cache,
+dwarf2_frame_this_id (const struct frame_unwind *self,
+		      struct frame_info *next_frame, void **this_cache,
 		      struct frame_id *this_id)
 {
   struct dwarf2_frame_cache *cache =
@@ -740,7 +741,8 @@
 }
 
 static void
-dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+dwarf2_frame_prev_register (const struct frame_unwind *self,
+			    struct frame_info *next_frame, void **this_cache,
 			    int regnum, int *optimizedp,
 			    enum lval_type *lvalp, CORE_ADDR *addrp,
 			    int *realnump, void *valuep)
@@ -861,7 +863,8 @@
    response to the "info frame" command.  */
 
 static CORE_ADDR
-dwarf2_frame_base_address (struct frame_info *next_frame, void **this_cache)
+dwarf2_frame_base_address (const struct frame_base *self,
+			   struct frame_info *next_frame, void **this_cache)
 {
   struct dwarf2_frame_cache *cache =
     dwarf2_frame_cache (next_frame, this_cache);
@@ -1608,6 +1611,6 @@
 void
 _initialize_dwarf2_frame (void)
 {
-  dwarf2_frame_data = register_gdbarch_data (dwarf2_frame_init);
+  dwarf2_frame_data = register_gdbarch_data (NULL, dwarf2_frame_init);
   dwarf2_frame_objfile_data = register_objfile_data ();
 }
Index: frame-base.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-base.c,v
retrieving revision 1.8
diff -u -r1.8 frame-base.c
--- frame-base.c	4 Aug 2003 22:24:44 -0000	1.8
+++ frame-base.c	9 Mar 2004 22:44:59 -0000
@@ -22,6 +22,7 @@
 #include "defs.h"
 #include "frame-base.h"
 #include "frame.h"
+#include "gdb_obstack.h"
 
 /* A default frame base implementations.  If it wasn't for the old
    DEPRECATED_FRAME_LOCALS_ADDRESS and DEPRECATED_FRAME_ARGS_ADDRESS,
@@ -29,14 +30,16 @@
    really need to override this.  */
 
 static CORE_ADDR
-default_frame_base_address (struct frame_info *next_frame, void **this_cache)
+default_frame_base_address (const struct frame_base *self,
+			    struct frame_info *next_frame, void **this_cache)
 {
   struct frame_info *this_frame = get_prev_frame (next_frame);
   return get_frame_base (this_frame); /* sigh! */
 }
 
 static CORE_ADDR
-default_frame_locals_address (struct frame_info *next_frame, void **this_cache)
+default_frame_locals_address (const struct frame_base *self,
+			      struct frame_info *next_frame, void **this_cache)
 {
   if (DEPRECATED_FRAME_LOCALS_ADDRESS_P ())
     {
@@ -45,21 +48,22 @@
       struct frame_info *this_frame = get_prev_frame (next_frame);
       return DEPRECATED_FRAME_LOCALS_ADDRESS (this_frame);
     }
-  return default_frame_base_address (next_frame, this_cache);
+  return default_frame_base_address (self, next_frame, this_cache);
 }
 
 static CORE_ADDR
-default_frame_args_address (struct frame_info *next_frame, void **this_cache)
+default_frame_args_address (const struct frame_base *self,
+			    struct frame_info *next_frame, void **this_cache)
 {
   if (DEPRECATED_FRAME_ARGS_ADDRESS_P ())
     {
       struct frame_info *this_frame = get_prev_frame (next_frame);
       return DEPRECATED_FRAME_ARGS_ADDRESS (this_frame);
     }
-  return default_frame_base_address (next_frame, this_cache);
+  return default_frame_base_address (self, next_frame, this_cache);
 }
 
-const struct frame_base default_frame_base = {
+static const struct frame_base default_frame_base = {
   NULL, /* No parent.  */
   default_frame_base_address,
   default_frame_locals_address,
@@ -68,60 +72,60 @@
 
 static struct gdbarch_data *frame_base_data;
 
+struct frame_base_table_entry
+{
+  const struct frame_base_sniffer *sniffer;
+  struct frame_base_table_entry *next;
+};
+
 struct frame_base_table
 {
-  frame_base_sniffer_ftype **sniffer;
+  struct frame_base_table_entry *first;
   const struct frame_base *default_base;
-  int nr;
 };
 
 static void *
-frame_base_init (struct gdbarch *gdbarch)
-{
-  struct frame_base_table *table = XCALLOC (1, struct frame_base_table);
-  table->default_base = &default_frame_base;
-  return table;
-}
-
-static struct frame_base_table *
-frame_base_table (struct gdbarch *gdbarch)
+frame_base_init (struct obstack *obstack)
 {
-  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
-  if (table == NULL)
-    {
-      /* ULGH, called during architecture initialization.  Patch
-         things up.  */
-      table = frame_base_init (gdbarch);
-      set_gdbarch_data (gdbarch, frame_base_data, table);
-    }
-  return table;
+  return OBSTACK_ZALLOC (obstack, struct frame_base_table);
 }
 
 /* Append a predicate to the end of the table.  */
 static void
-append_predicate (struct frame_base_table *table,
-		  frame_base_sniffer_ftype *sniffer)
+append_predicate (struct gdbarch *gdbarch,
+		  const struct frame_base_sniffer *sniffer)
 {
-  table->sniffer = xrealloc (table->sniffer,
-			     ((table->nr + 1)
-			      * sizeof (frame_base_sniffer_ftype *)));
-  table->sniffer[table->nr] = sniffer;
-  table->nr++;
+  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
+  struct frame_base_table_entry **entry;
+
+  for (entry = &table->first; (*entry) != NULL; entry = &(*entry)->next);
+  (*entry) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_table_entry);
+  (*entry)->sniffer = sniffer;
 }
 
 void
 frame_base_append_sniffer (struct gdbarch *gdbarch,
 			   frame_base_sniffer_ftype *sniffer)
 {
-  struct frame_base_table *table = frame_base_table (gdbarch);
-  append_predicate (table, sniffer);
+  struct frame_base_sniffer *base_sniffer;
+
+  base_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_sniffer);
+  base_sniffer->sniffer = sniffer;
+  append_predicate (gdbarch, base_sniffer);
+}
+
+void
+frame_base_sniffer_append (struct gdbarch *gdbarch,
+			   const struct frame_base_sniffer *sniffer)
+{
+  append_predicate (gdbarch, sniffer);
 }
 
 void
 frame_base_set_default (struct gdbarch *gdbarch,
 			const struct frame_base *default_base)
 {
-  struct frame_base_table *table = frame_base_table (gdbarch);
+  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
   table->default_base = default_base;
 }
 
@@ -129,12 +133,14 @@
 frame_base_find_by_frame (struct frame_info *next_frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  struct frame_base_table *table = frame_base_table (gdbarch);
-  int i;
-  for (i = 0; i < table->nr; i++)
+  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
+  struct frame_base_table_entry *entry;
+
+  for (entry = table->first; entry != NULL; entry = entry->next)
     {
-      const struct frame_base *desc = NULL;
-      desc = table->sniffer[i] (next_frame);
+      const struct frame_base *desc;
+
+      desc = entry->sniffer->sniffer (entry->sniffer, next_frame);
       if (desc != NULL)
 	return desc;
     }
@@ -146,5 +152,5 @@
 void
 _initialize_frame_base (void)
 {
-  frame_base_data = register_gdbarch_data (frame_base_init);
+  frame_base_data = register_gdbarch_data (frame_base_init, NULL);
 }
Index: frame-base.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-base.h,v
retrieving revision 1.3
diff -u -r1.3 frame-base.h
--- frame-base.h	16 Jul 2003 22:29:13 -0000	1.3
+++ frame-base.h	9 Mar 2004 22:44:59 -0000
@@ -22,6 +22,8 @@
 #if !defined (FRAME_BASE_H)
 #define FRAME_BASE_H 1
 
+struct frame_base;
+struct frame_base_sniffer;
 struct frame_info;
 struct frame_id;
 struct frame_unwind;
@@ -44,17 +46,20 @@
 
 /* A generic base address.  */
 
-typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *next_frame,
+typedef CORE_ADDR (frame_this_base_ftype) (const struct frame_base *self,
+					   struct frame_info *next_frame,
 					   void **this_base_cache);
 
 /* The base address of the frame's local variables.  */
 
-typedef CORE_ADDR (frame_this_locals_ftype) (struct frame_info *next_frame,
+typedef CORE_ADDR (frame_this_locals_ftype) (const struct frame_base *self,
+					     struct frame_info *next_frame,
 					     void **this_base_cache);
 
 /* The base address of the frame's arguments / parameters.  */
 
-typedef CORE_ADDR (frame_this_args_ftype) (struct frame_info *next_frame,
+typedef CORE_ADDR (frame_this_args_ftype) (const struct frame_base *self,
+					   struct frame_info *next_frame,
 					   void **this_base_cache);
 
 struct frame_base
@@ -65,18 +70,28 @@
   frame_this_base_ftype *this_base;
   frame_this_locals_ftype *this_locals;
   frame_this_args_ftype *this_args;
+  struct frame_data *base_data;
 };
 
 /* Given the NEXT frame, return the frame base methods for THIS frame,
    or NULL if it can't handle THIS frame.  */
 
-typedef const struct frame_base *(frame_base_sniffer_ftype) (struct frame_info *next_frame);
+typedef const struct frame_base *(frame_base_sniffer_ftype)
+     (const struct frame_base_sniffer *self,
+      struct frame_info *next_frame);
+struct frame_base_sniffer
+{
+  frame_base_sniffer_ftype *sniffer;
+  const struct frame_data *sniffer_data;
+};
 
 /* Append a frame base sniffer to the list.  The sniffers are polled
    in the order that they are appended.  */
 
 extern void frame_base_append_sniffer (struct gdbarch *gdbarch,
 				       frame_base_sniffer_ftype *sniffer);
+extern void frame_base_sniffer_append (struct gdbarch *gdbarch,
+				       const struct frame_base_sniffer *sniffer);
 
 /* Set the default frame base.  If all else fails, this one is
    returned.  If this isn't set, the default is to use legacy code
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.8
diff -u -r1.8 frame-unwind.c
--- frame-unwind.c	22 Feb 2004 17:08:42 -0000	1.8
+++ frame-unwind.c	9 Mar 2004 22:44:59 -0000
@@ -24,48 +24,59 @@
 #include "frame-unwind.h"
 #include "gdb_assert.h"
 #include "dummy-frame.h"
+#include "gdb_obstack.h"
 
 static struct gdbarch_data *frame_unwind_data;
 
-struct frame_unwind_table
+struct frame_unwind_table_entry
 {
-  frame_unwind_sniffer_ftype **sniffer;
-  int nr;
+  const struct frame_unwind_sniffer *sniffer;
+  struct frame_unwind_table_entry *next;
 };
 
-/* Append a predicate to the end of the table.  */
-static void
-append_predicate (struct frame_unwind_table *table,
-		  frame_unwind_sniffer_ftype *sniffer)
-{
-  table->sniffer = xrealloc (table->sniffer, ((table->nr + 1)
-					      * sizeof (frame_unwind_sniffer_ftype *)));
-  table->sniffer[table->nr] = sniffer;
-  table->nr++;
-}
+struct frame_unwind_table
+{
+  struct frame_unwind_table_entry *first;
+};
 
 static void *
-frame_unwind_init (struct gdbarch *gdbarch)
+frame_unwind_init (struct obstack *obstack)
 {
-  struct frame_unwind_table *table = XCALLOC (1, struct frame_unwind_table);
-  append_predicate (table, dummy_frame_sniffer);
+  struct frame_unwind_table *table;
+  struct frame_unwind_sniffer *dummy_sniffer;
+
+  dummy_sniffer = OBSTACK_ZALLOC (obstack, struct frame_unwind_sniffer);
+  dummy_sniffer->sniffer = dummy_frame_sniffer;
+
+  table = OBSTACK_ZALLOC (obstack, struct frame_unwind_table);
+  table->first = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
+  table->first->sniffer = dummy_sniffer;
+
   return table;
 }
 
+/* Append a predicate to the end of the table.  */
+
+void
+frame_unwind_sniffer_append (struct gdbarch *gdbarch,
+			     const struct frame_unwind_sniffer *sniffer)
+{
+  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table_entry **entry;
+  for (entry = &table->first; (*entry) != NULL; entry = &(*entry)->next);
+  (*entry) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
+  (*entry)->sniffer = sniffer;
+}
+
 void
 frame_unwind_append_sniffer (struct gdbarch *gdbarch,
 			     frame_unwind_sniffer_ftype *sniffer)
 {
-  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, sniffer);
+  struct frame_unwind_sniffer *unwind_sniffer;
+
+  unwind_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_sniffer);
+  unwind_sniffer->sniffer = sniffer;
+  frame_unwind_sniffer_append (gdbarch, unwind_sniffer);
 }
 
 const struct frame_unwind *
@@ -74,16 +85,18 @@
   int i;
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table_entry *entry;
   if (!DEPRECATED_USE_GENERIC_DUMMY_FRAMES && legacy_frame_p (gdbarch))
     /* Seriously old code.  Don't even try to use this new mechanism.
        (Note: The variable USE_GENERIC_DUMMY_FRAMES is deprecated, not
        the dummy frame mechanism.  All architectures should be using
        generic dummy frames).  */
     return legacy_saved_regs_unwind;
-  for (i = 0; i < table->nr; i++)
+  for (entry = table->first; entry != NULL; entry = entry->next)
     {
       const struct frame_unwind *desc;
-      desc = table->sniffer[i] (next_frame);
+      gdb_assert (entry->sniffer->sniffer != NULL);
+      desc = entry->sniffer->sniffer (entry->sniffer, next_frame);
       if (desc != NULL)
 	return desc;
     }
@@ -95,5 +108,5 @@
 void
 _initialize_frame_unwind (void)
 {
-  frame_unwind_data = register_gdbarch_data (frame_unwind_init);
+  frame_unwind_data = register_gdbarch_data (frame_unwind_init, NULL);
 }
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.9
diff -u -r1.9 frame-unwind.h
--- frame-unwind.h	16 Jul 2003 22:29:13 -0000	1.9
+++ frame-unwind.h	9 Mar 2004 22:44:59 -0000
@@ -65,7 +65,8 @@
    with the other unwind methods.  Memory for that cache should be
    allocated using frame_obstack_zalloc().  */
 
-typedef void (frame_this_id_ftype) (struct frame_info *next_frame,
+typedef void (frame_this_id_ftype) (const struct frame_unwind *self,
+				    struct frame_info *next_frame,
 				    void **this_prologue_cache,
 				    struct frame_id *this_id);
 
@@ -101,13 +102,15 @@
    with the other unwind methods.  Memory for that cache should be
    allocated using frame_obstack_zalloc().  */
 
-typedef void (frame_prev_register_ftype) (struct frame_info *next_frame,
-					  void **this_prologue_cache,
-					  int prev_regnum,
-					  int *optimized,
-					  enum lval_type * lvalp,
-					  CORE_ADDR *addrp,
-					  int *realnump, void *valuep);
+typedef void (frame_prev_register_ftype)
+     (const struct frame_unwind *self,
+      struct frame_info *next_frame,
+      void **this_prologue_cache,
+      int prev_regnum,
+      int *optimized,
+      enum lval_type * lvalp,
+      CORE_ADDR *addrp,
+      int *realnump, void *valuep);
 
 struct frame_unwind
 {
@@ -118,20 +121,33 @@
      here?  */
   frame_this_id_ftype *this_id;
   frame_prev_register_ftype *prev_register;
+  const struct frame_data *unwind_data;
 };
 
 /* Given the NEXT frame, take a wiff of THIS frame's registers (namely
    the PC and attributes) and if it is the applicable unwinder return
    the unwind methods, or NULL if it is not.  */
 
-typedef const struct frame_unwind *(frame_unwind_sniffer_ftype) (struct frame_info *next_frame);
+struct frame_unwind_sniffer;
+
+typedef const struct frame_unwind *(frame_unwind_sniffer_ftype)
+     (const struct frame_unwind_sniffer *self,
+      struct frame_info *next_frame);
+
+struct frame_unwind_sniffer
+{
+  frame_unwind_sniffer_ftype *sniffer;
+  const struct frame_data *sniffer_data;
+};
 
 /* Add a frame sniffer to the list.  The predicates are polled in the
    order that they are appended.  The initial list contains the dummy
    frame sniffer.  */
 
-extern void frame_unwind_append_sniffer (struct gdbarch *gdbarch,
-					 frame_unwind_sniffer_ftype *sniffer);
+void frame_unwind_append_sniffer (struct gdbarch *gdbarch,
+				  frame_unwind_sniffer_ftype *sniffer);
+void frame_unwind_sniffer_append (struct gdbarch *gdbarch,
+				  const struct frame_unwind_sniffer *sniffer);
 
 /* Iterate through the next frame's sniffers until one returns with an
    unwinder implementation.  */
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.162
diff -u -r1.162 frame.c
--- frame.c	16 Feb 2004 21:49:21 -0000	1.162
+++ frame.c	9 Mar 2004 22:44:59 -0000
@@ -237,7 +237,8 @@
 	  fi->type = fi->unwind->type;
 	}
       /* Find THIS frame's ID.  */
-      fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value);
+      fi->unwind->this_id (fi->unwind, fi->next, &fi->prologue_cache,
+			   &fi->this_id.value);
       fi->this_id.p = 1;
       if (frame_debug)
 	{
@@ -429,7 +430,7 @@
 }
 
 CORE_ADDR
-frame_func_unwind (struct frame_info *fi)
+frame_unwind_func_by_symtab (struct frame_info *fi)
 {
   if (!fi->prev_func.p)
     {
@@ -447,6 +448,12 @@
 }
 
 CORE_ADDR
+frame_func_unwind (struct frame_info *fi)
+{
+  return frame_unwind_func_by_symtab (fi);
+}
+
+CORE_ADDR
 get_frame_func (struct frame_info *fi)
 {
   return frame_func_unwind (fi->next);
@@ -544,7 +551,8 @@
   /* Ask this frame to unwind its register.  See comment in
      "frame-unwind.h" for why NEXT frame and this unwind cace are
      passed in.  */
-  frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum,
+  frame->unwind->prev_register (frame->unwind, frame->next,
+				&frame->prologue_cache, regnum,
 				optimizedp, lvalp, addrp, realnump, bufferp);
 
   if (frame_debug)
@@ -938,7 +946,8 @@
    most frame.  */
 
 static void
-legacy_saved_regs_prev_register (struct frame_info *next_frame,
+legacy_saved_regs_prev_register (const struct frame_unwind *self,
+				 struct frame_info *next_frame,
 				 void **this_prologue_cache,
 				 int regnum, int *optimizedp,
 				 enum lval_type *lvalp, CORE_ADDR *addrp,
@@ -1024,7 +1033,8 @@
 }
 
 static void
-legacy_saved_regs_this_id (struct frame_info *next_frame,
+legacy_saved_regs_this_id (const struct frame_unwind *self,
+			   struct frame_info *next_frame,
 			   void **this_prologue_cache,
 			   struct frame_id *id)
 {
@@ -1444,7 +1454,8 @@
   /* Still don't want to worry about this except on the innermost
      frame.  This macro will set FROMLEAF if THIS_FRAME is a frameless
      function invocation.  */
-  if (this_frame->level == 0)
+  if (this_frame->level == 0
+      && this_frame->unwind->type == UNKNOWN_FRAME)
     /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
        the frame chain, not just the inner most frame!  The generic,
        per-architecture, frame code should handle this and the below
@@ -1485,7 +1496,8 @@
          this to after the ffi test; I'd rather have backtraces from
          start go curfluy than have an abort called from main not show
          main.  */
-      if (DEPRECATED_FRAME_CHAIN_P ())
+      if (DEPRECATED_FRAME_CHAIN_P ()
+	  && this_frame->unwind->type == UNKNOWN_FRAME)
 	address = DEPRECATED_FRAME_CHAIN (this_frame);
       else
 	{
@@ -1501,7 +1513,7 @@
 	     using the method deprecated_set_frame_type().  */
 	  prev->type = prev->unwind->type;
 	  /* Find PREV frame's ID.  */
-	  prev->unwind->this_id (this_frame,
+	  prev->unwind->this_id (prev->unwind, this_frame,
 				 &prev->prologue_cache,
 				 &prev->this_id.value);
 	  prev->this_id.p = 1;
@@ -1656,10 +1668,25 @@
   if (prev->unwind == NULL)
     prev->unwind = frame_unwind_find_by_frame (prev->next);
 
-  /* If the unwinder provides a frame type, use it.  Otherwize
-     continue on to that heuristic mess.  */
-  if (prev->unwind->type != UNKNOWN_FRAME)
+  /* If the unwinder provides a frame type (i.e., is a new style
+     unwinder), use it.  Otherwize continue on to that heuristic
+     mess.  */
+  switch (prev->unwind->type)
     {
+    case SIGTRAMP_FRAME:
+      prev->type = prev->unwind->type;
+      prev->unwind->this_id (prev->unwind, prev->next,
+			     &prev->prologue_cache,
+			     &prev->this_id.value);
+      if (frame_debug)
+	{
+	  fprintf_unfiltered (gdb_stdlog, "-> ");
+	  fprint_frame (gdb_stdlog, prev);
+	  fprintf_unfiltered (gdb_stdlog, " } // legacy with sigtramp type\n");
+	}
+      return prev;
+    case DUMMY_FRAME:
+    case NORMAL_FRAME:
       prev->type = prev->unwind->type;
       if (prev->type == NORMAL_FRAME)
 	/* FIXME: cagney/2003-06-16: would get_frame_pc() be better?  */
@@ -1672,6 +1699,10 @@
 	  fprintf_unfiltered (gdb_stdlog, " } // legacy with unwound type\n");
 	}
       return prev;
+    case UNKNOWN_FRAME:
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, "bad switch");
     }
 
   /* NOTE: cagney/2002-11-18: The code segments, found in
@@ -2055,8 +2086,8 @@
   /* Sneaky: If the low-level unwind and high-level base code share a
      common unwinder, let them share the prologue cache.  */
   if (fi->base->unwind == fi->unwind)
-    return fi->base->this_base (fi->next, &fi->prologue_cache);
-  return fi->base->this_base (fi->next, &fi->base_cache);
+    return fi->base->this_base (fi->base, fi->next, &fi->prologue_cache);
+  return fi->base->this_base (fi->base, fi->next, &fi->base_cache);
 }
 
 CORE_ADDR
@@ -2074,7 +2105,7 @@
     cache = &fi->prologue_cache;
   else
     cache = &fi->base_cache;
-  return fi->base->this_locals (fi->next, cache);
+  return fi->base->this_locals (fi->base, fi->next, cache);
 }
 
 CORE_ADDR
@@ -2092,7 +2123,7 @@
     cache = &fi->prologue_cache;
   else
     cache = &fi->base_cache;
-  return fi->base->this_args (fi->next, cache);
+  return fi->base->this_args (fi->base, fi->next, cache);
 }
 
 /* Level of the selected frame: 0 for innermost, 1 for its caller, ...
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.119
diff -u -r1.119 frame.h
--- frame.h	16 Feb 2004 21:49:21 -0000	1.119
+++ frame.h	9 Mar 2004 22:44:59 -0000
@@ -260,6 +260,7 @@
 /* Following on from the `resume' address.  Return the entry point
    address of the function containing that resume address, or zero if
    that function isn't known.  */
+extern CORE_ADDR frame_unwind_func_by_symtab (struct frame_info *fi);
 extern CORE_ADDR frame_func_unwind (struct frame_info *fi);
 extern CORE_ADDR get_frame_func (struct frame_info *fi);
 
Index: gdb_obstack.h
===================================================================
RCS file: /cvs/src/src/gdb/gdb_obstack.h,v
retrieving revision 1.2
diff -u -r1.2 gdb_obstack.h
--- gdb_obstack.h	9 Feb 2004 23:50:55 -0000	1.2
+++ gdb_obstack.h	9 Mar 2004 22:44:59 -0000
@@ -24,6 +24,10 @@
 
 #include "obstack.h"
 
+#define OBSTACK_ZALLOC(OBSTACK,TYPE) (memset (obstack_alloc ((OBSTACK), sizeof (TYPE)), 0, sizeof (TYPE)))
+
+#define OBSTACK_CALLOC(OBSTACK,NUMBER,TYPE) (memset (obstack_alloc ((OBSTACK), (NUMBER) * sizeof (TYPE)), 0, (NUMBER) * sizeof (TYPE)))
+
 /* Unless explicitly specified, GDB obstacks always use xmalloc() and
    xfree().  */
 /* Note: ezannoni 2004-02-09: One could also specify the allocation
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.275
diff -u -r1.275 gdbarch.c
--- gdbarch.c	16 Feb 2004 21:49:21 -0000	1.275
+++ gdbarch.c	9 Mar 2004 22:44:59 -0000
@@ -5382,7 +5382,8 @@
 {
   unsigned index;
   int init_p;
-  gdbarch_data_init_ftype *init;
+  gdbarch_data_pre_init_ftype *pre_init;
+  gdbarch_data_post_init_ftype *post_init;
 };
 
 struct gdbarch_data_registration
@@ -5403,10 +5404,12 @@
 };
 
 struct gdbarch_data *
-register_gdbarch_data (gdbarch_data_init_ftype *init)
+register_gdbarch_data (gdbarch_data_pre_init_ftype *pre_init,
+		       gdbarch_data_post_init_ftype *post_init)
 {
   struct gdbarch_data_registration **curr;
   /* Append the new registraration.  */
+  gdb_assert ((pre_init != NULL) != (post_init != NULL));
   for (curr = &gdbarch_data_registry.registrations;
        (*curr) != NULL;
        curr = &(*curr)->next);
@@ -5414,7 +5417,8 @@
   (*curr)->next = NULL;
   (*curr)->data = XMALLOC (struct gdbarch_data);
   (*curr)->data->index = gdbarch_data_registry.nr++;
-  (*curr)->data->init = init;
+  (*curr)->data->pre_init = pre_init;
+  (*curr)->data->post_init = post_init;
   (*curr)->data->init_p = 1;
   return (*curr)->data;
 }
@@ -5450,23 +5454,23 @@
 gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *data)
 {
   gdb_assert (data->index < gdbarch->nr_data);
-  /* The data-pointer isn't initialized, call init() to get a value but
-     only if the architecture initializaiton has completed.  Otherwise
-     punt - hope that the caller knows what they are doing.  */
-  if (gdbarch->data[data->index] == NULL
-      && gdbarch->initialized_p)
+  if (gdbarch->data[data->index] == NULL)
     {
       /* Be careful to detect an initialization cycle.  */
       gdb_assert (data->init_p);
       data->init_p = 0;
-      gdb_assert (data->init != NULL);
-      gdbarch->data[data->index] = data->init (gdbarch);
+      if (data->pre_init != NULL)
+	gdbarch->data[data->index] = data->pre_init (gdbarch->obstack);
+      else if (gdbarch->initialized_p
+	       && data->post_init != NULL)
+	gdbarch->data[data->index] = data->post_init (gdbarch);
+      else
+	internal_error (__FILE__, __LINE__, "Bad initialization method");
       data->init_p = 1;
       gdb_assert (gdbarch->data[data->index] != NULL);
     }
   return gdbarch->data[data->index];
 }
-
 
 
 /* Keep a registry of swapped data required by GDB modules. */
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.238
diff -u -r1.238 gdbarch.h
--- gdbarch.h	16 Feb 2004 21:49:21 -0000	1.238
+++ gdbarch.h	9 Mar 2004 22:44:59 -0000
@@ -48,6 +48,7 @@
 struct regset;
 struct disassemble_info;
 struct target_ops;
+struct obstack;
 
 extern struct gdbarch *current_gdbarch;
 
@@ -2534,11 +2535,13 @@
 
 struct gdbarch_data;
 
-typedef void *(gdbarch_data_init_ftype) (struct gdbarch *gdbarch);
-extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_init_ftype *init);
+typedef void *(gdbarch_data_pre_init_ftype) (struct obstack *obstack);
+typedef void *(gdbarch_data_post_init_ftype) (struct gdbarch *gdbarch);
+extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_pre_init_ftype *pre,
+                                                   gdbarch_data_post_init_ftype *post);
 extern void set_gdbarch_data (struct gdbarch *gdbarch,
-			      struct gdbarch_data *data,
-			      void *pointer);
+                              struct gdbarch_data *data,
+                              void *pointer);
 
 extern void *gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *);
 
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.301
diff -u -r1.301 gdbarch.sh
--- gdbarch.sh	16 Feb 2004 21:49:21 -0000	1.301
+++ gdbarch.sh	9 Mar 2004 22:44:59 -0000
@@ -890,6 +890,7 @@
 struct regset;
 struct disassemble_info;
 struct target_ops;
+struct obstack;
 
 extern struct gdbarch *current_gdbarch;
 
@@ -1218,11 +1219,13 @@
 
 struct gdbarch_data;
 
-typedef void *(gdbarch_data_init_ftype) (struct gdbarch *gdbarch);
-extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_init_ftype *init);
+typedef void *(gdbarch_data_pre_init_ftype) (struct obstack *obstack);
+typedef void *(gdbarch_data_post_init_ftype) (struct gdbarch *gdbarch);
+extern struct gdbarch_data *register_gdbarch_data (gdbarch_data_pre_init_ftype *pre,
+                                                   gdbarch_data_post_init_ftype *post);
 extern void set_gdbarch_data (struct gdbarch *gdbarch,
-			      struct gdbarch_data *data,
-			      void *pointer);
+                              struct gdbarch_data *data,
+                              void *pointer);
 
 extern void *gdbarch_data (struct gdbarch *gdbarch, struct gdbarch_data *);
 
Index: gnu-v3-abi.c
===================================================================
RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v
retrieving revision 1.20
diff -u -r1.20 gnu-v3-abi.c
--- gnu-v3-abi.c	5 Dec 2003 04:25:09 -0000	1.20
+++ gnu-v3-abi.c	9 Mar 2004 22:44:59 -0000
@@ -422,7 +422,7 @@
 static void
 init_gnuv3_ops (void)
 {
-  vtable_type_gdbarch_data = register_gdbarch_data (build_gdb_vtable_type);
+  vtable_type_gdbarch_data = register_gdbarch_data (NULL, build_gdb_vtable_type);
 
   gnu_v3_abi_ops.shortname = "gnu-v3";
   gnu_v3_abi_ops.longname = "GNU G++ Version 3 ABI";
Index: ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.11
diff -u -r1.11 ppcnbsd-tdep.c
--- ppcnbsd-tdep.c	10 Nov 2003 22:47:28 -0000	1.11
+++ ppcnbsd-tdep.c	9 Mar 2004 22:44:59 -0000
@@ -30,6 +30,8 @@
 #include "ppc-tdep.h"
 #include "ppcnbsd-tdep.h"
 #include "nbsd-tdep.h"
+#include "tramp-frame.h"
+#include "trad-frame.h"
 
 #include "solib-svr4.h"
 
@@ -228,6 +230,57 @@
 }
 
 static void
+ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self,
+			     struct frame_info *next_frame,
+			     struct trad_frame_cache *this_cache,
+			     CORE_ADDR func)
+{
+  CORE_ADDR offset;
+  int i;
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  this_cache->this_base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  offset = this_cache->this_base + 0x18 + 2 * tdep->wordsize;
+  for (i = 0; i < 32; i++)
+    {
+      int regnum = i + tdep->ppc_gp0_regnum;
+      this_cache->prev_regs[regnum].addr = offset;
+      offset += tdep->wordsize;
+    }
+  this_cache->prev_regs[tdep->ppc_lr_regnum].addr = offset;
+  offset += tdep->wordsize;
+  this_cache->prev_regs[tdep->ppc_cr_regnum].addr = offset;
+  offset += tdep->wordsize;
+  this_cache->prev_regs[tdep->ppc_xer_regnum].addr = offset;
+  offset += tdep->wordsize;
+  this_cache->prev_regs[tdep->ppc_ctr_regnum].addr = offset;
+  offset += tdep->wordsize;
+  this_cache->prev_regs[PC_REGNUM].addr = offset; /* SRR0? */
+  offset += tdep->wordsize;
+
+  /* Construct the frame ID using the function start.  */
+  this_cache->this_id = frame_id_build (this_cache->this_base, func);
+}
+
+/* Given the NEXTE frame, examine the instructions at and around this
+   frame's resume address (aka PC) to see of they look like a signal
+   trampoline.  Return the address of the trampolines first
+   instruction, or zero if it isn't a signal trampoline.  */
+
+static const struct tramp_frame ppcnbsd_sigtramp = {
+  4, /* insn size */
+  { /* insn */
+    0x38610018, /* addi r3,r1,24 */
+    0x38000127, /* li r0,295 */
+    0x44000002, /* sc */
+    0x38000001, /* li r0,1 */
+    0x44000002, /* sc */
+  },
+  ppcnbsd_sigtramp_cache_init
+};
+
+static void
 ppcnbsd_init_abi (struct gdbarch_info info,
                   struct gdbarch *gdbarch)
 {
@@ -237,6 +290,7 @@
   set_gdbarch_return_value (gdbarch, ppcnbsd_return_value);
   set_solib_svr4_fetch_link_map_offsets (gdbarch,
                                 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+  tramp_frame_append (gdbarch, &ppcnbsd_sigtramp);
 }
 
 void
Index: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.109
diff -u -r1.109 regcache.c
--- regcache.c	29 Feb 2004 17:01:38 -0000	1.109
+++ regcache.c	9 Mar 2004 22:44:59 -0000
@@ -1705,7 +1705,7 @@
 void
 _initialize_regcache (void)
 {
-  regcache_descr_handle = register_gdbarch_data (init_regcache_descr);
+  regcache_descr_handle = register_gdbarch_data (NULL, init_regcache_descr);
   DEPRECATED_REGISTER_GDBARCH_SWAP (current_regcache);
   DEPRECATED_REGISTER_GDBARCH_SWAP (deprecated_registers);
   DEPRECATED_REGISTER_GDBARCH_SWAP (deprecated_register_valid);
Index: reggroups.c
===================================================================
RCS file: /cvs/src/src/gdb/reggroups.c,v
retrieving revision 1.8
diff -u -r1.8 reggroups.c
--- reggroups.c	22 Aug 2003 09:49:01 -0000	1.8
+++ reggroups.c	9 Mar 2004 22:44:59 -0000
@@ -268,7 +268,7 @@
 void
 _initialize_reggroup (void)
 {
-  reggroups_data = register_gdbarch_data (reggroups_init);
+  reggroups_data = register_gdbarch_data (NULL, reggroups_init);
 
   /* The pre-defined list of groups.  */
   add_group (&default_groups, general_reggroup, XMALLOC (struct reggroup_el));
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.130
diff -u -r1.130 remote.c
--- remote.c	25 Feb 2004 20:41:00 -0000	1.130
+++ remote.c	9 Mar 2004 22:45:00 -0000
@@ -5456,7 +5456,7 @@
   struct cmd_list_element *tmpcmd;
 
   /* architecture specific data */
-  remote_gdbarch_data_handle = register_gdbarch_data (init_remote_state);
+  remote_gdbarch_data_handle = register_gdbarch_data (NULL, init_remote_state);
 
   /* Old tacky stuff.  NOTE: This comes after the remote protocol so
      that the remote protocol has been initialized.  */
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.183
diff -u -r1.183 rs6000-tdep.c
--- rs6000-tdep.c	2 Mar 2004 02:20:25 -0000	1.183
+++ rs6000-tdep.c	9 Mar 2004 22:45:00 -0000
@@ -50,6 +50,10 @@
 #include "gdb_assert.h"
 #include "dis-asm.h"
 
+#include "trad-frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+
 /* If the kernel has to deliver a signal, it pushes a sigcontext
    structure on the stack and then calls the signal handler, passing
    the address of the sigcontext in an argument register. Usually
@@ -65,6 +69,7 @@
 
 struct rs6000_framedata
   {
+    CORE_ADDR func_start;	/* true function start */
     int offset;			/* total size of frame --- the distance
 				   by which we decrement sp to allocate
 				   the frame */
@@ -502,6 +507,7 @@
   int minimal_toc_loaded = 0;
   int prev_insn_was_prologue_insn = 1;
   int num_skip_non_prologue_insns = 0;
+  int num_skip_syscall_insn = 0;
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (current_gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   
@@ -521,6 +527,7 @@
     lim_pc = refine_prologue_limit (pc, lim_pc);
 
   memset (fdata, 0, sizeof (struct rs6000_framedata));
+  fdata->func_start = pc;
   fdata->saved_gpr = -1;
   fdata->saved_fpr = -1;
   fdata->saved_vr = -1;
@@ -549,9 +556,65 @@
 	break;
       op = extract_signed_integer (buf, 4);
 
+      /* A PPC64 GNU/Linux system call function starts with a
+	 non-threaded fast-path, only when that fails is a stack frame
+	 created, treat it as several functions:
+
+	 *INDENT-OFF*
+	 NAME:
+	 	SINGLE_THREAD_P
+	 	bne- .Lpseudo_cancel
+	 __NAME_nocancel:
+	 	li r0,162
+	 	sc
+	 	bnslr+
+	 	b 0x7fe014ef64 <.__syscall_error>
+	 Lpseudo_cancel:
+	 	stdu r1,-128(r1)
+	 	...
+	 *INDENT-ON* */
+      if (((op & 0xffff0000) == 0x38000000 /* li r0,N */
+	   && pc == fdata->func + 0)
+	  || (op == 0x44000002 /* sc */
+	      && pc == fdata->func + 4
+	      && num_skip_syscall_insn == 1)
+	  || (op == 0x4ca30020 /* bnslr+ */
+	      && pc == fdata->func + 8
+	      && num_skip_syscall_insn == 2))
+	{
+	  num_skip_syscall_insn++;
+	  continue;
+	}
+      else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */
+	       && pc == fdata->func + 12
+	       && num_skip_syscall_insn == 3)
+	{
+	  num_skip_syscall_insn++;
+	  fdata->func_start = pc;
+	  continue;
+	}
+
       if ((op & 0xfc1fffff) == 0x7c0802a6)
 	{			/* mflr Rx */
-	  lr_reg = (op & 0x03e00000);
+	  /* Since shared library / PIC code, which needs to get its
+	     address at runtime, can appear to save more than one link
+	     register vis:
+
+	     *INDENT-OFF*
+	     stwu r1,-304(r1)
+	     mflr r3
+	     bl 0xff570d0 (blrl)
+	     stw r30,296(r1)
+	     mflr r30
+	     stw r31,300(r1)
+	     stw r3,308(r1);
+	     ...
+	     *INDENT-ON*
+
+	     remember just the first one, but skip over additional
+	     ones.  */
+	  if (lr_reg < 0)
+	    lr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
@@ -1862,12 +1925,12 @@
 	case 0:
 	  return builtin_type_int0;
 	case 4:
-	  return builtin_type_int32;
+	  return builtin_type_uint32;
 	case 8:
 	  if (tdep->ppc_ev0_regnum <= n && n <= tdep->ppc_ev31_regnum)
 	    return builtin_type_vec64;
 	  else
-	    return builtin_type_int64;
+	    return builtin_type_uint64;
 	  break;
 	case 16:
 	  return builtin_type_vec128;
@@ -2622,6 +2685,164 @@
     return print_insn_little_powerpc (memaddr, info);
 }
 
+static CORE_ADDR
+rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_unsigned (next_frame, PC_REGNUM);
+}
+
+static struct frame_id
+rs6000_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_id_build (frame_unwind_register_unsigned (next_frame,
+							 SP_REGNUM),
+			 frame_pc_unwind (next_frame));
+}
+
+static void
+rs6000_trad_frame_init (const struct trad_frame *self,
+			struct frame_info *next_frame,
+			struct trad_frame_cache *this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct rs6000_framedata fdata;
+  CORE_ADDR base;
+  int wordsize = tdep->wordsize;
+
+  skip_prologue (frame_unwind_func_by_symtab (next_frame),
+		 frame_pc_unwind (next_frame), &fdata);
+
+  /* If there were any saved registers, figure out parent's stack
+     pointer.  */
+  /* The following is true only if the frame doesn't have a call to
+     alloca(), FIXME.  */
+
+  if (fdata.saved_fpr == 0
+      && fdata.saved_gpr == 0
+      && fdata.saved_vr == 0
+      && fdata.saved_ev == 0
+      && fdata.lr_offset == 0
+      && fdata.cr_offset == 0
+      && fdata.vr_offset == 0
+      && fdata.ev_offset == 0)
+    base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  else
+    {
+      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+	 address of the current frame.  Things might be easier if the
+	 ->frame pointed to the outer-most address of the frame.  In
+	 the mean time, the address of the prev frame is used as the
+	 base address of this frame.  */
+      base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+      if (!fdata.frameless)
+	/* Frameless really means stackless.  */
+	base = read_memory_addr (base, wordsize);
+    }
+  trad_frame_set_value (this_cache, SP_REGNUM, base);
+
+  /* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.
+     All fpr's from saved_fpr to fp31 are saved.  */
+
+  if (fdata.saved_fpr >= 0)
+    {
+      int i;
+      CORE_ADDR fpr_addr = base + fdata.fpr_offset;
+      for (i = fdata.saved_fpr; i < 32; i++)
+	{
+	  this_cache->prev_regs[FP0_REGNUM + i].addr = fpr_addr;
+	  fpr_addr += 8;
+	}
+    }
+
+  /* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
+     All gpr's from saved_gpr to gpr31 are saved.  */
+
+  if (fdata.saved_gpr >= 0)
+    {
+      int i;
+      CORE_ADDR gpr_addr = base + fdata.gpr_offset;
+      for (i = fdata.saved_gpr; i < 32; i++)
+	{
+	  this_cache->prev_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+	  gpr_addr += wordsize;
+	}
+    }
+
+  /* if != -1, fdata.saved_vr is the smallest number of saved_vr.
+     All vr's from saved_vr to vr31 are saved.  */
+  if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
+    {
+      if (fdata.saved_vr >= 0)
+	{
+	  int i;
+	  CORE_ADDR vr_addr = base + fdata.vr_offset;
+	  for (i = fdata.saved_vr; i < 32; i++)
+	    {
+	      this_cache->prev_regs[tdep->ppc_vr0_regnum + i].addr = vr_addr;
+	      vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum);
+	    }
+	}
+    }
+
+  /* if != -1, fdata.saved_ev is the smallest number of saved_ev.
+     All vr's from saved_ev to ev31 are saved. ????? */
+  if (tdep->ppc_ev0_regnum != -1 && tdep->ppc_ev31_regnum != -1)
+    {
+      if (fdata.saved_ev >= 0)
+	{
+	  int i;
+	  CORE_ADDR ev_addr = base + fdata.ev_offset;
+	  for (i = fdata.saved_ev; i < 32; i++)
+	    {
+	      this_cache->prev_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr;
+              this_cache->prev_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + 4;
+	      ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
+            }
+	}
+    }
+
+  /* If != 0, fdata.cr_offset is the offset from the frame that
+     holds the CR.  */
+  if (fdata.cr_offset != 0)
+    this_cache->prev_regs[tdep->ppc_cr_regnum].addr = base + fdata.cr_offset;
+
+  /* If != 0, fdata.lr_offset is the offset from the frame that
+     holds the LR.  */
+  if (fdata.lr_offset != 0)
+    this_cache->prev_regs[tdep->ppc_lr_regnum].addr = base + fdata.lr_offset;
+  /* The PC is found in the link register.  */
+  this_cache->prev_regs[PC_REGNUM] = this_cache->prev_regs[tdep->ppc_lr_regnum];
+
+  /* If != 0, fdata.vrsave_offset is the offset from the frame that
+     holds the VRSAVE.  */
+  if (fdata.vrsave_offset != 0)
+    this_cache->prev_regs[tdep->ppc_vrsave_regnum].addr = base + fdata.vrsave_offset;
+
+  if (fdata.alloca_reg < 0)
+    /* If no alloca register used, then fi->frame is the value of the
+       %sp for this frame, and it is good enough.  */
+    this_cache->this_base = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
+  else
+    this_cache->this_base = frame_unwind_register_unsigned (next_frame,
+						       fdata.alloca_reg);
+  this_cache->this_id = frame_id_build (base, fdata.func);
+}
+
+static int
+rs6000_trad_frame_sniffer (const struct trad_frame *self,
+			   struct frame_info *next_frame)
+{
+  return 1;
+}
+
+struct trad_frame rs6000_trad_frame = {
+  NORMAL_FRAME,
+  rs6000_trad_frame_sniffer,
+  rs6000_trad_frame_init,
+};
+
+
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
    during this debugging session.
@@ -2874,8 +3095,6 @@
        Problem is, 220 isn't frame (16 byte) aligned.  Round it up to
        224.  */
     set_gdbarch_frame_red_zone_size (gdbarch, 224);
-  set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
-  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
 
   set_gdbarch_deprecated_register_convertible (gdbarch, rs6000_register_convertible);
   set_gdbarch_deprecated_register_convert_to_virtual (gdbarch, rs6000_register_convert_to_virtual);
@@ -2896,7 +3115,6 @@
     set_gdbarch_push_dummy_call (gdbarch, rs6000_push_dummy_call);
 
   set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address);
-  set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame);
 
   set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
@@ -2918,14 +3136,6 @@
     set_gdbarch_use_struct_convention (gdbarch,
 				       rs6000_use_struct_convention);
 
-  set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation);
-  set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
-
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
-  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
-  set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first);
-
   if (!sysv_abi)
     {
       /* Handle RS/6000 function pointers (which are really function
@@ -2933,15 +3143,37 @@
       set_gdbarch_convert_from_func_ptr_addr (gdbarch,
 	rs6000_convert_from_func_ptr_addr);
     }
-  set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address);
-  set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
 
   /* Helpers for function argument information.  */
   set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
+
+  switch (info.osabi)
+    {
+    case GDB_OSABI_NETBSD_AOUT:
+    case GDB_OSABI_NETBSD_ELF:
+    case GDB_OSABI_UNKNOWN:
+    case GDB_OSABI_LINUX:
+      set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
+      trad_frame_append (gdbarch, &rs6000_trad_frame);
+      set_gdbarch_unwind_dummy_id (gdbarch, rs6000_unwind_dummy_id);
+      break;
+    default:
+      set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
+      set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+      set_gdbarch_deprecated_pop_frame (gdbarch, rs6000_pop_frame);
+      set_gdbarch_deprecated_frame_args_address (gdbarch, rs6000_frame_args_address);
+      set_gdbarch_deprecated_frame_locals_address (gdbarch, rs6000_frame_args_address);
+      set_gdbarch_deprecated_saved_pc_after_call (gdbarch, rs6000_saved_pc_after_call);
+      set_gdbarch_deprecated_frameless_function_invocation (gdbarch, rs6000_frameless_function_invocation);
+      set_gdbarch_deprecated_frame_chain (gdbarch, rs6000_frame_chain);
+      set_gdbarch_deprecated_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
+      set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
+      set_gdbarch_deprecated_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
+      set_gdbarch_deprecated_init_frame_pc_first (gdbarch, rs6000_init_frame_pc_first);
+    }
 
   if (from_xcoff_exec)
     {
Index: sentinel-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/sentinel-frame.c,v
retrieving revision 1.8
diff -u -r1.8 sentinel-frame.c
--- sentinel-frame.c	8 Jun 2003 18:27:14 -0000	1.8
+++ sentinel-frame.c	9 Mar 2004 22:45:00 -0000
@@ -45,7 +45,8 @@
 /* Here the register value is taken direct from the register cache.  */
 
 static void
-sentinel_frame_prev_register (struct frame_info *next_frame,
+sentinel_frame_prev_register (const struct frame_unwind *self,
+			      struct frame_info *next_frame,
 			      void **this_prologue_cache,
 			      int regnum, int *optimized,
 			      enum lval_type *lvalp, CORE_ADDR *addrp,
@@ -71,7 +72,8 @@
 }
 
 static void
-sentinel_frame_this_id (struct frame_info *next_frame,
+sentinel_frame_this_id (const struct frame_unwind *self,
+			struct frame_info *next_frame,
 			void **this_prologue_cache,
 			struct frame_id *this_id)
 {
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.41
diff -u -r1.41 solib-svr4.c
--- solib-svr4.c	21 Feb 2004 18:34:45 -0000	1.41
+++ solib-svr4.c	9 Mar 2004 22:45:00 -0000
@@ -1588,7 +1588,7 @@
 _initialize_svr4_solib (void)
 {
   fetch_link_map_offsets_gdbarch_data =
-    register_gdbarch_data (init_fetch_link_map_offsets);
+    register_gdbarch_data (NULL, init_fetch_link_map_offsets);
 
   svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses;
   svr4_so_ops.free_so = svr4_free_so;
Index: trad-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/trad-frame.c,v
retrieving revision 1.4
diff -u -r1.4 trad-frame.c
--- trad-frame.c	20 Aug 2003 22:30:17 -0000	1.4
+++ trad-frame.c	9 Mar 2004 22:45:00 -0000
@@ -1,6 +1,6 @@
 /* Traditional frame unwind support, for GDB the GNU Debugger.
 
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,101 +21,131 @@
 
 #include "defs.h"
 #include "frame.h"
+#include "frame-unwind.h"
 #include "trad-frame.h"
 #include "regcache.h"
+#include "frame-base.h"
+#include "gdb_assert.h"
 
 /* A traditional frame is unwound by analysing the function prologue
    and using the information gathered to track registers.  For
    non-optimized frames, the technique is reliable (just need to check
    for all potential instruction sequences).  */
 
-struct trad_frame_saved_reg *
-trad_frame_alloc_saved_regs (struct frame_info *next_frame)
+struct trad_frame_cache *
+trad_frame_cache_zalloc (struct frame_info *next_frame)
 {
-  int regnum;
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  int numregs = NUM_REGS + NUM_PSEUDO_REGS;
-  struct trad_frame_saved_reg *this_saved_regs
-    = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
+  const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+  struct trad_frame_cache *trad_cache;
+  int regnum;
+
+  trad_cache = FRAME_OBSTACK_ZALLOC (struct trad_frame_cache);
+  trad_cache->prev_regs = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
   for (regnum = 0; regnum < numregs; regnum++)
     {
-      this_saved_regs[regnum].realreg = regnum;
-      this_saved_regs[regnum].addr = -1;
+      trad_cache->prev_regs[regnum].realreg = regnum;
+      trad_cache->prev_regs[regnum].addr = -1;
     }      
-  return this_saved_regs;
+  return trad_cache;
 }
 
 enum { REG_VALUE = -1, REG_UNKNOWN = -2 };
 
 int
-trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
+trad_frame_value_p (struct trad_frame_cache *this_cache, int regnum)
 {
-  return (this_saved_regs[regnum].realreg == REG_VALUE);
+  return (this_cache->prev_regs[regnum].realreg == REG_VALUE);
 }
 
 int
-trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[], int regnum)
+trad_frame_addr_p (struct trad_frame_cache *this_cache, int regnum)
 {
-  return (this_saved_regs[regnum].realreg >= 0
-	  && this_saved_regs[regnum].addr != -1);
+  return (this_cache->prev_regs[regnum].realreg >= 0
+	  && this_cache->prev_regs[regnum].addr != -1);
 }
 
 int
-trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
+trad_frame_realreg_p (struct trad_frame_cache *this_cache,
 		      int regnum)
 {
-  return (this_saved_regs[regnum].realreg >= 0
-	  && this_saved_regs[regnum].addr == -1);
+  return (this_cache->prev_regs[regnum].realreg >= 0
+	  && this_cache->prev_regs[regnum].addr == -1);
 }
 
 void
-trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
+trad_frame_set_value (struct trad_frame_cache *this_cache,
 		      int regnum, LONGEST val)
 {
   /* Make the REALREG invalid, indicating that the ADDR contains the
      register's value.  */
-  this_saved_regs[regnum].realreg = REG_VALUE;
-  this_saved_regs[regnum].addr = val;
+  this_cache->prev_regs[regnum].realreg = REG_VALUE;
+  this_cache->prev_regs[regnum].addr = val;
 }
 
 void
-trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
+trad_frame_set_unknown (struct trad_frame_cache *this_cache,
 			int regnum)
 {
   /* Make the REALREG invalid, indicating that the value is not known.  */
-  this_saved_regs[regnum].realreg = REG_UNKNOWN;
-  this_saved_regs[regnum].addr = -1;
+  this_cache->prev_regs[regnum].realreg = REG_UNKNOWN;
+  this_cache->prev_regs[regnum].addr = -1;
 }
 
-void
-trad_frame_prev_register (struct frame_info *next_frame,
-			  struct trad_frame_saved_reg this_saved_regs[],
+struct frame_data
+{
+  const struct frame_unwind *frame_unwind;
+  const struct frame_base *frame_base;
+  const struct trad_frame *trad_frame;
+};
+
+static struct trad_frame_cache *
+trad_frame_cache (const struct frame_data *self,
+		  struct frame_info *next_frame,
+		  void **this_cache)
+{
+  if ((*this_cache) == NULL)
+    {
+      (*this_cache) = trad_frame_cache_zalloc (next_frame);
+      gdb_assert (self->trad_frame->init != NULL);
+      self->trad_frame->init (self->trad_frame, next_frame, (*this_cache));
+    }
+  return (*this_cache);
+}
+
+static void
+trad_frame_prev_register (const struct frame_unwind *self,
+			  struct frame_info *next_frame,
+			  void **this_cache,
 			  int regnum, int *optimizedp,
 			  enum lval_type *lvalp, CORE_ADDR *addrp,
 			  int *realregp, void *bufferp)
 {
+  struct trad_frame_cache *trad_cache
+    = trad_frame_cache (self->unwind_data, next_frame, this_cache);
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  if (trad_frame_addr_p (this_saved_regs, regnum))
+
+  if (trad_frame_addr_p (trad_cache, regnum))
     {
       /* The register was saved in memory.  */
       *optimizedp = 0;
       *lvalp = lval_memory;
-      *addrp = this_saved_regs[regnum].addr;
+      *addrp = trad_cache->prev_regs[regnum].addr;
       *realregp = -1;
       if (bufferp != NULL)
 	{
 	  /* Read the value in from memory.  */
-	  get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
+	  get_frame_memory (next_frame, trad_cache->prev_regs[regnum].addr, bufferp,
 			    register_size (gdbarch, regnum));
 	}
     }
-  else if (trad_frame_realreg_p (this_saved_regs, regnum))
+  else if (trad_frame_realreg_p (trad_cache, regnum))
     {
       /* Ask the next frame to return the value of the register.  */
-      frame_register_unwind (next_frame, this_saved_regs[regnum].realreg,
+      frame_register_unwind (next_frame, trad_cache->prev_regs[regnum].realreg,
 			     optimizedp, lvalp, addrp, realregp, bufferp);
     }
-  else if (trad_frame_value_p (this_saved_regs, regnum))
+  else if (trad_frame_value_p (trad_cache, regnum))
     {
       /* The register's value is available.  */
       *optimizedp = 0;
@@ -124,11 +154,96 @@
       *realregp = -1;
       if (bufferp != NULL)
 	store_unsigned_integer (bufferp, register_size (gdbarch, regnum),
-				this_saved_regs[regnum].addr);
+				trad_cache->prev_regs[regnum].addr);
     }
   else
     {
       error ("Register %s not available",
 	     gdbarch_register_name (gdbarch, regnum));
     }
+}
+
+static void
+trad_frame_this_id (const struct frame_unwind *self,
+		    struct frame_info *next_frame, void **this_cache,
+		    struct frame_id *this_id)
+{
+  struct trad_frame_cache *trad_cache
+    = trad_frame_cache (self->unwind_data, next_frame, this_cache);
+  (*this_id) = trad_cache->this_id;
+}
+
+static const struct frame_unwind *
+trad_frame_unwind_sniffer (const struct frame_unwind_sniffer *self,
+			   struct frame_info *next_frame)
+{
+  const struct trad_frame *trad_frame = self->sniffer_data->trad_frame;
+  gdb_assert (trad_frame->sniffer != NULL);
+  if (trad_frame->sniffer (trad_frame, next_frame))
+    return self->sniffer_data->frame_unwind;
+  else
+    return NULL;
+}
+
+static CORE_ADDR
+trad_frame_base (const struct frame_base *self,
+		 struct frame_info *next_frame,
+		 void **this_cache)
+{
+  struct trad_frame_cache *trad_cache
+    = trad_frame_cache (self->base_data, next_frame, this_cache);
+  return trad_cache->this_base;
+}
+
+static const struct frame_base *
+trad_frame_base_sniffer (const struct frame_base_sniffer *self,
+			 struct frame_info *next_frame)
+{
+  const struct trad_frame *trad_frame = self->sniffer_data->trad_frame;
+  gdb_assert (trad_frame->sniffer != NULL);
+  if (trad_frame->sniffer (trad_frame, next_frame))
+    return self->sniffer_data->frame_base;
+  else
+    return NULL;
+}
+
+void
+trad_frame_append (struct gdbarch *gdbarch,
+		   const struct trad_frame *trad_frame)
+{
+  struct frame_data *data;
+  struct frame_unwind *unwind;
+  struct frame_unwind_sniffer *unwind_sniffer;
+  struct frame_base *base;
+  struct frame_base_sniffer *base_sniffer;
+
+  data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
+  unwind = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
+  unwind_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_sniffer);
+  base = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base);
+  base_sniffer = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_base_sniffer);
+
+  data->frame_unwind = unwind;
+  data->frame_base = base; 
+  data->trad_frame = trad_frame;
+
+  unwind->type = trad_frame->type;
+  unwind->this_id = trad_frame_this_id;
+  unwind->prev_register = trad_frame_prev_register;
+  unwind->unwind_data = data;
+  unwind_sniffer->sniffer = trad_frame_unwind_sniffer;
+  unwind_sniffer->sniffer_data = data;
+
+  frame_unwind_sniffer_append (gdbarch, unwind_sniffer);
+
+  base->base_data = data;
+  base->unwind = unwind;
+  base->this_base = trad_frame_base;
+  base->this_locals = trad_frame_base;
+  base->this_args = trad_frame_base;
+
+  base_sniffer->sniffer = trad_frame_base_sniffer;
+  base_sniffer->sniffer_data = data;
+
+  frame_base_sniffer_append (gdbarch, base_sniffer);
 }
Index: trad-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/trad-frame.h,v
retrieving revision 1.4
diff -u -r1.4 trad-frame.h
--- trad-frame.h	1 Jul 2003 13:25:19 -0000	1.4
+++ trad-frame.h	9 Mar 2004 22:45:00 -0000
@@ -1,6 +1,6 @@
 /* Traditional frame unwind support, for GDB the GNU Debugger.
 
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,6 +23,9 @@
 #define TRAD_FRAME_H
 
 struct frame_info;
+struct trad_frame;
+
+#include "frame.h"	/* For frame_id.  */
 
 /* A traditional saved regs table, indexed by REGNUM, encoding where
    the value of REGNUM for the previous frame can be found in this
@@ -56,33 +59,55 @@
   int realreg;
 };
 
-/* Encode REGNUM value in the trad-frame.  */
-void trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
-			   int regnum, LONGEST val);
+struct trad_frame_cache
+{
+  struct frame_id this_id;
+  CORE_ADDR this_base;
+  struct trad_frame_saved_reg *prev_regs;
+};
 
-/* Mark REGNUM as unknown.  */
-void trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
+/* Encode REGNUM's value in the trad-frame.  */
+void trad_frame_set_value (struct trad_frame_cache *this_cache,
+			   int regnum, LONGEST val);
+void trad_frame_set_addr (struct trad_frame_cache *this_cache,
+			  int regnum, CORE_ADDR addr);
+void trad_frame_set_realreg (struct trad_frame_cache *this_cache,
+			     int regnum, int realreg);
+void trad_frame_set_unknown (struct trad_frame_cache *this_cache,
 			     int regnum);
 
+/* Set the offset of a register, and then update all offsets.  Useful
+   when the offset of a register is known before its absolute
+   address.  */
+void trad_frame_set_offset (struct trad_frame_cache *this_cache,
+			    int regnum, LONGEST addr);
+void trad_frame_add_addr (struct trad_frame_cache *this_cache,
+			  int regnum, CORE_ADDR addr);
+
 /* Convenience functions, return non-zero if the register has been
    encoded as specified.  */
-int trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_value_p (struct trad_frame_cache *this_cache,
 			int regnum);
-int trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_addr_p (struct trad_frame_cache *this_cache,
 		       int regnum);
-int trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_realreg_p (struct trad_frame_cache *this_cache,
 			  int regnum);
 
+typedef void (trad_frame_init_ftype) (const struct trad_frame *self,
+				      struct frame_info *next_frame,
+				      struct trad_frame_cache *this_cache);
+typedef int (trad_frame_sniffer_ftype) (const struct trad_frame *self,
+					struct frame_info *next_frame);
 
-/* Return a freshly allocated (and initialized) trad_frame array.  */
-struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *next_frame);
+struct trad_frame
+{
+  enum frame_type type;
+  trad_frame_sniffer_ftype *sniffer;
+  trad_frame_init_ftype *init;
+  const struct trad_frame_data *trad_data;
+};
 
-/* Given the trad_frame info, return the location of the specified
-   register.  */
-void trad_frame_prev_register (struct frame_info *next_frame,
-			       struct trad_frame_saved_reg this_saved_regs[],
-			       int regnum, int *optimizedp,
-			       enum lval_type *lvalp, CORE_ADDR *addrp,
-			       int *realregp, void *bufferp);
+void trad_frame_append (struct gdbarch *gdbarch,
+			const struct trad_frame *trad_frame);
 
 #endif
Index: user-regs.c
===================================================================
RCS file: /cvs/src/src/gdb/user-regs.c,v
retrieving revision 1.4
diff -u -r1.4 user-regs.c
--- user-regs.c	9 Mar 2004 20:03:37 -0000	1.4
+++ user-regs.c	9 Mar 2004 22:45:00 -0000
@@ -207,5 +207,5 @@
 void
 _initialize_user_regs (void)
 {
-  user_regs_data = register_gdbarch_data (user_regs_init);
+  user_regs_data = register_gdbarch_data (NULL, user_regs_init);
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]