[cagney_tramp-20040309-branch] jumbo patch

Andrew Cagney
2004-03-09T22:58:33Z

[-- Attachment #1: Type: text/plain, Size: 1235 bytes --]

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

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 64658 bytes --]

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);
}
\f
+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);
}