This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[patch rfc] Per-frame frame-base
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Wed, 26 Mar 2003 15:37:22 -0500
- Subject: [patch rfc] Per-frame frame-base
Hello,
Ref: frame->unwind->this_base()
http://sources.redhat.com/ml/gdb/2003-03/msg00238.html
Ref: cagney_framebase-20030326-branch
The attached patch introduces new per-frame methods:
get_frame_base_address()
get_frame_locals_address()
get_frame_args_address()
as successors to the old FRAME_LOCALS_ADDRESS(), FRAME_ARGS_ADDRESS(),
and get_frame_base()
These debug-info specific methods are expected to return various
addresses, within a frame, which that same debug-info can use. For
instance, a frame with dwarf2 debug info would provide dwarf2 version of
the above that return DW_AT_frame_base in all cases.
These methods are:
- per frame
Each frame, can have a different implementation. The implementation
being selected on the basis of the high-level debug info that needs
those corresponding values. One frame stabs, the next dwarf2, the next
nothing.
- unwind netural
These methods are not tied to the frame's register unwind code. A frame
might mix'n'match a dwarf2 frame-base with a libunwind frame-unwind.
Going through the old methods:
FRAME_LOCALS_ADDRESS(), FRAME_ARGS_ADDRESS(): These were hard-wired to
return a value that assumed a specific ABI and debug info. Both those
restrictions have been removed.
get_frame_base(): This was hardwired to return the frame->frame (what
ever that ended up being). Code then tried to use that value both as a
frame identifier, and as a higher-level frame base. It didn't work.
New code should instead use get_frame_id() XOR get_frame_*_address().
Other stuff:
The implementation is very much modeled on the frame-unwind code. Debug
readers are expected to register their own high level frame-base handler.
In the case of a frame using both a prologue based frame-unwind and
frame-base, there is an oportunity to share a common cache. The code
handles this with:
+ /* 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)
+ cache = &fi->prologue_cache;
+ else
+ cache = &fi->base_cache;
so I guess that is cheap inheritance.
It adds a note to dwarf2loc and dwarf2expr pointing out that they can,
and should, implement a dwarf2 specific frame-base. If nothing else,
this makes the dwarf2 frame addresses visible to the user (via `info
frame'), which is much less confusing then the current situtation where
`info frame' prints irellevant prologue based values :-( (there is also
an oportunity for some value caching using the frame).
A follow on d10v change is to modify its frame ID / frame base methods
so that they return different values. At present they return the same
value and that is very wrong :-( I believe that the i386 is hitting the
same problem.
Baring comment, I'll commit it in a week, I'll, for the moment, toss it
on a branch.
Andrew
2003-03-26 Andrew Cagney <cagney at redhat dot com>
Add frame debug info addresses:
* frame-base.c: New file.
* frame-base.h: New file.
* frame.h (struct frame_base): Add opaque declaration.
(get_frame_base): Update comment.
(get_frame_base_address): Declare.
(get_frame_locals_address): Declare.
(get_frame_args_address): Declare.
(struct frame_info): Add "base" and "base_cache". Update
comments on the unwinder.
* frame.c: Include "frame-base.h".
(get_frame_locals_address): New function.
(get_frame_base_address): New function.
(get_frame_args_address): New function.
* findvar.c (read_var_value): Use get_frame_locals_address.
* stack.c (frame_info): Use get_frame_locals_address and
get_frame_args_address.
(FRAME_ARGS_ADDRESS_CORRECT): Delete conditionally defined macro,
moved to "frame-base.c".
* Makefile.in (frame_base_h): Define.
(frame.o): Update dependencies.
(d10v-tdep.o): Update dependencies.
(frame-base.o): Add dependencies.
(SFILES): Add frame-base.c.
(COMMON_OBS): Add frame-base.o.
* printcmd.c (print_frame_nameless_args): Ditto.
* symtab.h (address_class): Update comments.
* dwarf2loc.c (dwarf_expr_frame_base): Add note about
get_frame_base_address.
* dwarf2expr.c (execute_stack_op): Ditto.
* d10v-tdep.c: Include "frame-base.h".
(d10v_frame_unwind): Make constant.
(d10v_frame_base_address): New function.
(d10v_frame_base): New variable.
(d10v_gdbarch_init): Set frame_base default.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.351
diff -u -r1.351 Makefile.in
--- Makefile.in 26 Mar 2003 03:39:42 -0000 1.351
+++ Makefile.in 26 Mar 2003 18:21:47 -0000
@@ -517,6 +517,7 @@
dummy-frame.c dwarfread.c dwarf2expr.c dwarf2loc.c dwarf2read.c \
elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
+ frame-base.c \
frame-unwind.c \
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
hpacc-abi.c \
@@ -641,6 +642,7 @@
f_lang_h = f-lang.h
frame_h = frame.h
frame_unwind_h = frame-unwind.h
+frame_base_h = frame-base.h
gdb_events_h = gdb-events.h
gdb_stabs_h = gdb-stabs.h
gdb_h = gdb.h
@@ -858,6 +860,7 @@
nlmread.o serial.o mdebugread.o top.o utils.o \
ui-file.o \
frame.o frame-unwind.o doublest.o \
+ frame-base.o \
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
reggroups.o
@@ -1618,11 +1621,11 @@
$(gdbtypes_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(value_h) \
$(opcode_cris_h) $(arch_utils_h) $(regcache_h) $(symfile_h) \
$(solib_h) $(solib_svr4_h) $(gdb_string_h)
-d10v-tdep.o: d10v-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(gdbtypes_h) \
- $(gdbcmd_h) $(gdbcore_h) $(gdb_string_h) $(value_h) $(inferior_h) \
- $(dis_asm_h) $(symfile_h) $(objfiles_h) $(language_h) $(arch_utils_h) \
- $(regcache_h) $(floatformat_h) $(gdb_sim_d10v_h) $(sim_regno_h) \
- $(gdb_assert_h)
+d10v-tdep.o: d10v-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
+ $(frame_base_h) $(symtab_h) $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(gdb_string_h) $(value_h) $(inferior_h) $(dis_asm_h) $(symfile_h) \
+ $(objfiles_h) $(language_h) $(arch_utils_h) $(regcache_h) \
+ $(floatformat_h) $(gdb_sim_d10v_h) $(sim_regno_h) $(gdb_assert_h)
dbug-rom.o: dbug-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
$(serial_h) $(regcache_h) $(m68k_tdep_h)
dbxread.o: dbxread.c $(defs_h) $(gdb_string_h) $(gdb_obstack_h) \
@@ -1702,9 +1705,10 @@
$(terminal_h) $(gdbthread_h) $(command_h)
frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(builtin_regs_h) \
- $(gdb_obstack_h) $(dummy_frame_h) $(gdbcore_h) $(annotate_h) \
- $(language_h) $(frame_unwind_h) $(command_h) $(gdbcmd_h) \
- $(sentinel_frame_h)
+ $(gdb_obstack_h) $(dummy_frame_h) $(sentinel_frame_h) $(gdbcore_h) \
+ $(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \
+ $(command_h) $(gdbcmd_h)
+frame-base.o: frame-base.c $(defs_h) $(frame_base_h)
frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \
$(gdb_assert_h) $(dummy_frame_h) $(legacy_frame_h)
frv-tdep.o: frv-tdep.c $(defs_h) $(inferior_h) $(symfile_h) $(gdbcore_h) \
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.90
diff -u -r1.90 d10v-tdep.c
--- d10v-tdep.c 25 Mar 2003 22:56:39 -0000 1.90
+++ d10v-tdep.c 26 Mar 2003 18:21:49 -0000
@@ -25,6 +25,7 @@
#include "defs.h"
#include "frame.h"
#include "frame-unwind.h"
+#include "frame-base.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "gdbcmd.h"
@@ -1558,8 +1559,7 @@
}
}
-
-static struct frame_unwind d10v_frame_unwind = {
+static const struct frame_unwind d10v_frame_unwind = {
d10v_frame_this_id,
d10v_frame_prev_register
};
@@ -1570,6 +1570,21 @@
return &d10v_frame_unwind;
}
+static CORE_ADDR
+d10v_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+ struct d10v_unwind_cache *info
+ = d10v_frame_unwind_cache (next_frame, this_cache);
+ return info->base;
+}
+
+static const struct frame_base d10v_frame_base = {
+ &d10v_frame_unwind,
+ d10v_frame_base_address,
+ d10v_frame_base_address,
+ d10v_frame_base_address
+};
+
/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
dummy frame. The frame ID's base needs to match the TOS value
saved by save_dummy_frame_tos(), and the PC match the dummy frame's
@@ -1719,6 +1734,7 @@
set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info);
frame_unwind_append_predicate (gdbarch, d10v_frame_p);
+ frame_base_set_default (gdbarch, &d10v_frame_base);
/* Methods for saving / extracting a dummy frame's ID. */
set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id);
Index: dwarf2expr.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.c,v
retrieving revision 1.3
diff -u -r1.3 dwarf2expr.c
--- dwarf2expr.c 5 Mar 2003 18:00:02 -0000 1.3
+++ dwarf2expr.c 26 Mar 2003 18:21:49 -0000
@@ -454,6 +454,9 @@
afterwards, effectively erasing whatever the recursive
call put there. */
before_stack_len = ctx->stack_len;
+ /* FIXME: cagney/2003-03-26: This code should be using
+ get_frame_base_address(), and then implement a dwarf2
+ specific this_base method. */
(ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
dwarf_expr_eval (ctx, datastart, datalen);
result = dwarf_expr_fetch (ctx, 0);
Index: dwarf2loc.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2loc.c,v
retrieving revision 1.3
diff -u -r1.3 dwarf2loc.c
--- dwarf2loc.c 5 Mar 2003 18:00:02 -0000 1.3
+++ dwarf2loc.c 26 Mar 2003 18:21:49 -0000
@@ -87,6 +87,9 @@
static void
dwarf_expr_frame_base (void *baton, unsigned char **start, size_t * length)
{
+ /* FIXME: cagney/2003-03-26: This code should be using
+ get_frame_base_address(), and then implement a dwarf2 specific
+ this_base method. */
struct symbol *framefunc;
struct dwarf2_locexpr_baton *symbaton;
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
Index: findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.52
diff -u -r1.52 findvar.c
--- findvar.c 14 Mar 2003 17:07:00 -0000 1.52
+++ findvar.c 26 Mar 2003 18:21:49 -0000
@@ -533,7 +533,7 @@
case LOC_LOCAL_ARG:
if (frame == NULL)
return 0;
- addr = FRAME_LOCALS_ADDRESS (frame);
+ addr = get_frame_locals_address (frame);
addr += SYMBOL_VALUE (var);
break;
Index: frame-base.c
===================================================================
RCS file: frame-base.c
diff -N frame-base.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ frame-base.c 26 Mar 2003 18:21:49 -0000
@@ -0,0 +1,154 @@
+/* Definitions for frame address handler, for GDB, the GNU debugger.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame-base.h"
+#include "frame.h"
+
+/* A default frame base implementations. If it wasn't for the old
+ FRAME_LOCALS_ADDRESS and FRAME_ARGS_ADDRESS, these could be
+ combined into a single function. All architectures really need to
+ override this. */
+
+static CORE_ADDR
+default_frame_base_address (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)
+{
+ struct frame_info *this_frame = get_prev_frame (next_frame);
+ return FRAME_LOCALS_ADDRESS (this_frame);
+}
+
+static CORE_ADDR
+default_frame_args_address (struct frame_info *next_frame, void **this_cache)
+{
+ struct frame_info *this_frame = get_prev_frame (next_frame);
+ /* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
+ that if it is unsure about the answer, it returns 0 instead of
+ guessing (this happens on the VAX and i960, for example).
+
+ On most machines, we never have to guess about the args address,
+ so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
+#ifdef FRAME_ARGS_ADDRESS_CORRECT
+ return FRAME_ARGS_ADDRESS_CORRECT (this_frame);
+#else
+ return FRAME_ARGS_ADDRESS (this_frame);
+#endif
+}
+
+const struct frame_base default_frame_base = {
+ NULL, /* No parent. */
+ default_frame_base_address,
+ default_frame_locals_address,
+ default_frame_args_address
+};
+
+static struct gdbarch_data *frame_base_data;
+
+struct frame_base_table
+{
+ frame_base_p_ftype **p;
+ 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 void
+frame_base_free (struct gdbarch *gdbarch, void *data)
+{
+ struct frame_base_table *table =
+ gdbarch_data (gdbarch, frame_base_data);
+ xfree (table->p);
+ xfree (table);
+}
+
+static struct frame_base_table *
+frame_base_table (struct gdbarch *gdbarch)
+{
+ 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;
+}
+
+/* Append a predicate to the end of the table. */
+static void
+append_predicate (struct frame_base_table *table, frame_base_p_ftype *p)
+{
+ table->p = xrealloc (table->p, ((table->nr + 1)
+ * sizeof (frame_base_p_ftype *)));
+ table->p[table->nr] = p;
+ table->nr++;
+}
+
+void
+frame_base_append_predicate (struct gdbarch *gdbarch,
+ frame_base_p_ftype *p)
+{
+ struct frame_base_table *table = frame_base_table (gdbarch);
+ append_predicate (table, p);
+}
+
+void
+frame_base_set_default (struct gdbarch *gdbarch,
+ const struct frame_base *default_base)
+{
+ struct frame_base_table *table = frame_base_table (gdbarch);
+ table->default_base = default_base;
+}
+
+const struct frame_base *
+frame_base_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ int i;
+ struct frame_base_table *table = frame_base_table (gdbarch);
+ for (i = 0; i < table->nr; i++)
+ {
+ const struct frame_base *desc = table->p[i] (pc);
+ if (desc != NULL)
+ return desc;
+ }
+ return table->default_base;
+}
+
+void
+_initialize_frame_base (void)
+{
+ frame_base_data = register_gdbarch_data (frame_base_init,
+ frame_base_free);
+}
Index: frame-base.h
===================================================================
RCS file: frame-base.h
diff -N frame-base.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ frame-base.h 26 Mar 2003 18:21:49 -0000
@@ -0,0 +1,94 @@
+/* Definitions for a frame base, for GDB, the GNU debugger.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#if !defined (FRAME_BASE_H)
+#define FRAME_BASE_H 1
+
+struct frame_info;
+struct frame_id;
+struct frame_unwind;
+struct frame_base;
+struct gdbarch;
+struct regcache;
+
+/* Return the frame base methods for the function that contains PC, or
+ NULL if it can't handle this frame. */
+
+typedef const struct frame_base *(frame_base_p_ftype) (CORE_ADDR pc);
+
+/* Add a frame base handler to the list. The predicates are polled in
+ the order that they are appended. */
+
+extern void frame_base_append_predicate (struct gdbarch *gdbarch,
+ frame_base_p_ftype *p);
+
+/* 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
+ that uses things like the frame ID's base (ulgh!). */
+
+extern void frame_base_set_default (struct gdbarch *gdbarch,
+ const struct frame_base *def);
+
+/* Iterate through the list of frame base handlers until one returns
+ an implementation. */
+
+extern const struct frame_base *frame_base_find_by_pc (struct gdbarch *gdbarch,
+ CORE_ADDR pc);
+
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+ and that this is a `normal frame'; use the NEXT frame, and its
+ register unwind method, to determine the address of THIS frame's
+ `base'.
+
+ The exact meaning of `base' is highly dependant on the type of the
+ debug info. It is assumed that dwarf2, stabs, ... will each
+ provide their own methods.
+
+ A typical implmentation will return the same value for base,
+ locals-base and args-base. That value, however, will likely be
+ different to the frame ID's stack address. */
+
+/* A generic base address. */
+
+typedef CORE_ADDR (frame_this_base_ftype) (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,
+ 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,
+ void **this_base_cache);
+
+struct frame_base
+{
+ /* If non-NULL, a low-level unwinder that shares its implementation
+ with this high-level frame-base method. */
+ const struct frame_unwind *unwind;
+ frame_this_base_ftype *this_base;
+ frame_this_locals_ftype *this_locals;
+ frame_this_args_ftype *this_args;
+};
+
+#endif
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.89
diff -u -r1.89 frame.c
--- frame.c 26 Mar 2003 00:00:07 -0000 1.89
+++ frame.c 26 Mar 2003 18:21:50 -0000
@@ -36,6 +36,7 @@
#include "annotate.h"
#include "language.h"
#include "frame-unwind.h"
+#include "frame-base.h"
#include "command.h"
#include "gdbcmd.h"
@@ -1625,6 +1626,58 @@
get_frame_base (struct frame_info *fi)
{
return fi->frame;
+}
+
+/* High-level offsets into the frame. Used by the debug info. */
+
+CORE_ADDR
+get_frame_base_address (struct frame_info *fi)
+{
+ if (fi->type != NORMAL_FRAME)
+ return 0;
+ if (fi->base == NULL)
+ fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+ /* 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);
+}
+
+CORE_ADDR
+get_frame_locals_address (struct frame_info *fi)
+{
+ void **cache;
+ if (fi->type != NORMAL_FRAME)
+ return 0;
+ /* If there isn't a frame address method, find it. */
+ if (fi->base == NULL)
+ fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+ /* 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)
+ cache = &fi->prologue_cache;
+ else
+ cache = &fi->base_cache;
+ return fi->base->this_locals (fi->next, cache);
+}
+
+CORE_ADDR
+get_frame_args_address (struct frame_info *fi)
+{
+ void **cache;
+ if (fi->type != NORMAL_FRAME)
+ return 0;
+ /* If there isn't a frame address method, find it. */
+ if (fi->base == NULL)
+ fi->base = frame_base_find_by_pc (current_gdbarch, get_frame_pc (fi));
+ /* 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)
+ cache = &fi->prologue_cache;
+ else
+ cache = &fi->base_cache;
+ return fi->base->this_args (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.76
diff -u -r1.76 frame.h
--- frame.h 24 Mar 2003 03:54:47 -0000 1.76
+++ frame.h 26 Mar 2003 18:21:50 -0000
@@ -25,6 +25,7 @@
struct symtab_and_line;
struct frame_unwind;
+struct frame_base;
struct block;
/* A legacy unwinder to prop up architectures using the old style
@@ -169,47 +170,25 @@
extern void find_frame_sal (struct frame_info *frame,
struct symtab_and_line *sal);
-/* Return the frame address from FI. Except in the machine-dependent
- *FRAME* macros, a frame address has no defined meaning other than
- as a magic cookie which identifies a frame over calls to the
- inferior (um, SEE NOTE BELOW). The only known exception is
- inferior.h (DEPRECATED_PC_IN_CALL_DUMMY) [ON_STACK]; see comments
- there. You cannot assume that a frame address contains enough
- information to reconstruct the frame; if you want more than just to
- identify the frame (e.g. be able to fetch variables relative to
- that frame), then save the whole struct frame_info (and the next
- struct frame_info, since the latter is used for fetching variables
- on some machines) (um, again SEE NOTE BELOW).
-
- NOTE: cagney/2002-11-18: Actually, the frame address isn't
- sufficient for identifying a frame, and the counter examples are
- wrong!
-
- Code that needs to (re)identify a frame must use get_frame_id() and
- frame_find_by_id() (and in the future, a frame_compare() function
- instead of INNER_THAN()). Two reasons: an architecture (e.g.,
- ia64) can have more than one frame address (due to multiple stack
- pointers) (frame ID is going to be expanded to accomodate this);
- successive frameless function calls can only be differientated by
- comparing both the frame's base and the frame's enclosing function
- (frame_find_by_id() is going to be modified to perform this test).
-
- The generic dummy frame version of DEPRECATED_PC_IN_CALL_DUMMY() is
- able to identify a dummy frame using only the PC value. So the
- frame address is not needed. In fact, most
- DEPRECATED_PC_IN_CALL_DUMMY() calls now pass zero as the frame/sp
- values as the caller knows that those values won't be used. Once
- all architectures are using generic dummy frames,
- DEPRECATED_PC_IN_CALL_DUMMY() can drop the sp/frame parameters.
- When it comes to finding a dummy frame, the next frame's frame ID
- (with out duing an unwind) can be used (ok, could if it wasn't for
- the need to change the way the PPC defined frame base in a strange
- way).
-
- Modern architectures should be using something like dwarf2's
- location expression to describe where a variable lives. Such
- expressions specify their own debug info centric frame address.
- Consequently, a generic frame address is pretty meaningless. */
+/* Return the frame base (what ever that is) (DEPRECATED).
+
+ Old code was trying to use this single method for two conflicting
+ purposes. Such code needs to be updated to use either of:
+
+ get_frame_id: A low level frame unique identifier, that consists of
+ both a stack and a function address, that can be used to uniquely
+ identify a frame. This value is determined by the frame's
+ low-level unwinder, the stack part [typically] being the
+ top-of-stack of the previous frame, and the function part being the
+ function's start address. Since the correct identification of a
+ frameless function requires both the a stack and function address,
+ the old get_frame_base method was not sufficient.
+
+ get_frame_base_address: get_frame_locals_address:
+ get_frame_args_address: A set of high-level debug-info dependant
+ addresses that fall within the frame. These addresses almost
+ certainly will not match the stack address part of a frame ID (as
+ returned by get_frame_base). */
extern CORE_ADDR get_frame_base (struct frame_info *);
@@ -218,6 +197,25 @@
FI is NULL, return the null_frame_id. */
extern struct frame_id get_frame_id (struct frame_info *fi);
+/* Assuming that a frame is `normal', return its base-address, or 0 if
+ the information isn't available. NOTE: This address is really only
+ meaningful to the frame's high-level debug info. */
+extern CORE_ADDR get_frame_base_address (struct frame_info *);
+
+/* Assuming that a frame is `normal', return the address of the first
+ local variable, or 0 if the information isn't available. NOTE:
+ This address is really only meaningful to the frame's high-level
+ debug info. Typically, the argument and locals share a single
+ base-address. */
+extern CORE_ADDR get_frame_locals_address (struct frame_info *);
+
+/* Assuming that a frame is `normal', return the address of the first
+ parameter, or 0 if that information isn't available. NOTE: This
+ address is really only meaningful to the frame's high-level debug
+ info. Typically, the argument and locals share a single
+ base-address. */
+extern CORE_ADDR get_frame_args_address (struct frame_info *);
+
/* The frame's level: 0 for innermost, 1 for its caller, ...; or -1
for an invalid frame). */
extern int frame_relative_level (struct frame_info *fi);
@@ -398,11 +396,12 @@
related unwind data. */
struct context *context;
- /* Prologue cache shared between the unwind functions. See
- "frame-unwind.h" for more information. */
+ /* The frame's low-level unwinder and corresponding cache. The
+ low-level unwinder is responsible for unwinding register values
+ for the previous frame. The low-level unwind methods are
+ selected based on the presence, or otherwize, of register
+ unwind information such as CFI. */
void *prologue_cache;
-
- /* The frame's unwinder. */
const struct frame_unwind *unwind;
/* Cached copy of the previous frame's resume address. */
@@ -412,6 +411,12 @@
/* This frame's ID. Note that the frame's ID, base and PC contain
redundant information. */
struct frame_id id;
+
+ /* The frame's high-level base methods, and corresponding cache.
+ The high level base methods are selected based on the frame's
+ debug info. */
+ const struct frame_base *base;
+ void *base_cache;
/* Pointers to the next (down, inner, younger) and previous (up,
outer, older) frame_info's in the frame cache. */
Index: printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.57
diff -u -r1.57 printcmd.c
--- printcmd.c 18 Mar 2003 22:03:29 -0000 1.57
+++ printcmd.c 26 Mar 2003 18:21:51 -0000
@@ -1959,7 +1959,7 @@
#ifdef NAMELESS_ARG_VALUE
NAMELESS_ARG_VALUE (fi, start, &arg_value);
#else
- argsaddr = FRAME_ARGS_ADDRESS (fi);
+ argsaddr = get_frame_args_address (fi);
if (!argsaddr)
return;
Index: stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.71
diff -u -r1.71 stack.c
--- stack.c 13 Mar 2003 21:45:41 -0000 1.71
+++ stack.c 26 Mar 2003 18:21:51 -0000
@@ -600,16 +600,6 @@
/* NOTREACHED */
}
-/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
- that if it is unsure about the answer, it returns 0
- instead of guessing (this happens on the VAX and i960, for example).
-
- On most machines, we never have to guess about the args address,
- so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
-#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
-#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
-#endif
-
/* Print verbosely the selected frame or the frame at address ADDR.
This means absolutely all information in the frame is printed. */
@@ -743,7 +733,7 @@
{
/* Address of the argument list for this frame, or 0. */
- CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
+ CORE_ADDR arg_list = get_frame_args_address (fi);
/* Number of args for this frame, or -1 if unknown. */
int numargs;
@@ -770,7 +760,7 @@
}
{
/* Address of the local variables for this frame, or 0. */
- CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi);
+ CORE_ADDR arg_list = get_frame_locals_address (fi);
if (arg_list == 0)
printf_filtered (" Locals at unknown address,");
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.65
diff -u -r1.65 symtab.h
--- symtab.h 3 Mar 2003 18:34:12 -0000 1.65
+++ symtab.h 26 Mar 2003 18:21:51 -0000
@@ -402,8 +402,8 @@
/* Value is in register number SYMBOL_VALUE. Just like LOC_REGISTER
except this is an argument. Probably the cleaner way to handle
this would be to separate address_class (which would include
- separate ARG and LOCAL to deal with FRAME_ARGS_ADDRESS versus
- FRAME_LOCALS_ADDRESS), and an is_argument flag.
+ separate ARG and LOCAL to deal with get_frame_args_address()
+ versus get_frame_locals_address()), and an is_argument flag.
For some symbol formats (stabs, for some compilers at least),
the compiler generates two symbols, an argument and a register.
@@ -447,9 +447,9 @@
/* Value is arg at SYMBOL_VALUE offset in stack frame. Differs from
LOC_LOCAL in that symbol is an argument; differs from LOC_ARG in
- that we find it in the frame (FRAME_LOCALS_ADDRESS), not in the
- arglist (FRAME_ARGS_ADDRESS). Added for i960, which passes args
- in regs then copies to frame. */
+ that we find it in the frame (get_frame_locals_address()), not in
+ the arglist (get_frame_args_address()). Added for i960, which
+ passes args in regs then copies to frame. */
LOC_LOCAL_ARG,