This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[cagney_framefunc-20030403-branch] Half working frame ID eq
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 03 Apr 2003 12:03:14 -0500
- Subject: [cagney_framefunc-20030403-branch] Half working frame ID eq
Hello,
I've created cagney_framefunc-20030403-branch as a test bed for
frame_id_eq().
Attatched is the branches first jumbo patch. It gets things half
working (PPC and d10v are ok but the i386 fails).
The change:
- renames of the internal frame_id fields: pc -> func_addr, base ->
stack_addr
- adds new methods get_frame_func() and frame_func_unwind() that
cache/return a frame's function
- eliminates the redundant frame->pc (frame->next->pc_unwind_cache) and
frame->frame (frame->id.stack_addr)
- tweaks to d10v so that it returns the func addr
(*) adds nasty hacks to frame.c that, for legacy targets, badly fudge
frame->id.func_base
- makes many 'set frame debug' additions
Expect to see random bits of this separated out and committed to the
mainline. Testing / fixing needs to continue for a bit longer.
Feel free to try it,
Andrew
? diffs
? testsuite/diffs
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.4035
diff -u -r1.4035 ChangeLog
--- ChangeLog 3 Apr 2003 00:09:57 -0000 1.4035
+++ ChangeLog 3 Apr 2003 16:43:56 -0000
@@ -1,3 +1,52 @@
+2003-04-03 Andrew Cagney <cagney at redhat dot com>
+
+ * frame.c (frame_id_eq): Update. Compare function addresses.
+ (get_frame_func): New function.
+ (frame_func_unwind): New function.
+ (legacy_get_prev_frame): Move linking of prev to next to the start
+ of the function.
+ (frame_id_p): Update.
+ (get_frame_id): Return the frame's "id". Do not set "frame".
+ (frame_id_build): Update.
+ (frame_id_inner): Update.
+ (create_sentinel_frame): Do not set the "pc".
+ (select_frame): Use get_frame_pc.
+ (legacy_saved_regs_this_id): Use frame_id_build.
+ (create_new_frame): Set the frame's ID. Store the PC in the
+ sentinel frame's PC unwind cache.
+ (legacy_get_prev_frame): Do not set "pc" or "frame". Instead use
+ frame_pc_unwind, frame_id_build, deprecated_update_frame_pc_hack,
+ and deprecated_update_frame_base_hack.
+ (get_prev_frame): Do not set "pc" or "frame", instead use
+ frame_pc_unwind.
+ (get_frame_pc): Use frame_pc_unwind.
+ (find_frame_sal): Use get_frame_pc.
+ (get_frame_base): Return the frame ID's stack address.
+ (deprecated_update_frame_base_hack): Set the frame ID's stack
+ address.
+ (frame_id_eq, frame_id_p, frame_id_inner, get_frame_id): Add debug
+ print statements.
+
+ * d10v-tdep.c (d10v_frame_unwind_cache): Use frame_func_unwind.
+ (d10v_frame_this_id): Get the frame's function.
+ (d10v_frame_this_id): Use frame_id_eq.
+ (d10v_unwind_dummy_id): Use frame_id_build.
+
+ * stack.c (print_frame_info): Use get_frame_pc.
+
+ * dummy-frame.c (dummy_frame_this_id): Use frame_id_build. Update
+ parameter to find_dummy_frame.
+
+ * breakpoint.c (print_one_breakpoint): Update.
+
+ * frame.h (struct frame_id): Rename "base" to "stack_addr",
+ replace "pc" with "func_addr".
+ (frame_id_build): Update parameter names and comment.
+ (struct frame_info): Delete "frame" and "pc" fields.
+ (frame_func_unwind): Declare.
+ (get_frame_func): Declare.
+ (struct frame_info): Add field "func".
+
2003-04-02 Bob Rossi <bob_rossi at cox dot net>
* Makefile.in (SUBDIR_MI_OBS): Add "mi-cmd-file.o".
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.117
diff -u -r1.117 breakpoint.c
--- breakpoint.c 31 Mar 2003 19:01:18 -0000 1.117
+++ breakpoint.c 3 Apr 2003 16:43:57 -0000
@@ -3418,7 +3418,7 @@
ui_out_text (uiout, "\tstop only in stack frame at ");
/* FIXME: cagney/2002-12-01: Shouldn't be poeking around inside
the frame ID. */
- ui_out_field_core_addr (uiout, "frame", b->frame_id.base);
+ ui_out_field_core_addr (uiout, "frame", b->frame_id.stack_addr);
ui_out_text (uiout, "\n");
}
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.101
diff -u -r1.101 d10v-tdep.c
--- d10v-tdep.c 1 Apr 2003 19:55:03 -0000 1.101
+++ d10v-tdep.c 3 Apr 2003 16:43:58 -0000
@@ -720,8 +720,8 @@
info->sp_offset = 0;
info->uses_frame = 0;
- for (pc = get_pc_function_start (frame_pc_unwind (next_frame));
- pc < frame_pc_unwind (next_frame);
+ for (pc = frame_func_unwind (next_frame);
+ pc > 0 && pc < frame_pc_unwind (next_frame);
pc += 4)
{
op = (unsigned long) read_memory_integer (pc, 4);
@@ -1453,8 +1453,8 @@
CORE_ADDR base;
CORE_ADDR pc;
- /* The PC is easy. */
- pc = frame_pc_unwind (next_frame);
+ /* The PC/FUNC is easy. */
+ pc = frame_func_unwind (next_frame);
/* This is meant to halt the backtrace at "_start". Make sure we
don't halt it at a generic dummy frame. */
@@ -1474,8 +1474,8 @@
compare the frame's PC value. */
if (frame_relative_level (next_frame) >= 0
&& get_frame_type (next_frame) != DUMMY_FRAME
- && get_frame_id (next_frame).pc == pc
- && get_frame_id (next_frame).base == base)
+ && frame_id_eq (get_frame_id (next_frame),
+ frame_id_build (base, pc)))
return;
(*this_id) = frame_id_build (base, pc);
@@ -1588,10 +1588,8 @@
{
ULONGEST base;
struct frame_id id;
- id.pc = frame_pc_unwind (next_frame);
frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
- id.base = d10v_make_daddr (base);
- return id;
+ return frame_id_build (d10v_make_daddr (base), frame_pc_unwind (next_frame));
}
static gdbarch_init_ftype d10v_gdbarch_init;
Index: dummy-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dummy-frame.c,v
retrieving revision 1.15
diff -u -r1.15 dummy-frame.c
--- dummy-frame.c 31 Mar 2003 23:52:37 -0000 1.15
+++ dummy-frame.c 3 Apr 2003 16:43:58 -0000
@@ -374,8 +374,7 @@
same sequence as is found a traditional unwinder. Once all
architectures supply the unwind_dummy_id method, this code
can go away. */
- (*this_id).base = read_fp ();
- (*this_id).pc = read_pc ();
+ (*this_id) = frame_id_build (read_fp (), read_pc ());
}
else if (legacy_frame_p (current_gdbarch)
&& get_prev_frame (next_frame))
@@ -384,8 +383,9 @@
get_prev_frame code has already created THIS frame and linked
it in to the frame chain (a pretty bold assumption), extract
the ID from THIS base / pc. */
- (*this_id).base = get_frame_base (get_prev_frame (next_frame));
- (*this_id).pc = get_frame_pc (get_prev_frame (next_frame));
+ (*this_id)
+ = frame_id_build (get_frame_base (get_prev_frame (next_frame)),
+ get_frame_pc (get_prev_frame (next_frame)));
}
else
{
@@ -398,7 +398,8 @@
(*this_id) = null_frame_id;
return;
}
- (*this_prologue_cache) = find_dummy_frame ((*this_id).pc, (*this_id).base);
+ (*this_prologue_cache) = find_dummy_frame ((*this_id).func_addr,
+ (*this_id).stack_addr);
}
static struct frame_unwind dummy_frame_unwind =
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.93
diff -u -r1.93 frame.c
--- frame.c 1 Apr 2003 19:11:01 -0000 1.93
+++ frame.c 3 Apr 2003 16:43:58 -0000
@@ -48,6 +48,23 @@
static int backtrace_below_main;
+/* Utility to print a frame ID. */
+static void
+fprint_frame_id (struct ui_file *file, struct frame_id id)
+{
+ fprintf_unfiltered (file, "stack=0x%s func=0x%s",
+ paddr (id.stack_addr),
+ paddr (id.func_addr));
+}
+
+static void
+fprint_frame (struct ui_file *file, struct frame_info *fi)
+{
+ fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ",
+ fi->level, paddr (get_frame_pc (fi)));
+ fprint_frame_id (gdb_stdlog, fi->id);
+}
+
/* Return a frame uniq ID that can be used to, later, re-find the
frame. */
@@ -64,52 +81,99 @@
/* Find THIS frame's ID. */
fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->id);
fi->id_p = 1;
- /* FIXME: cagney/2002-12-18: Instead of this hack, should only
- store the frame ID in PREV_FRAME. Unfortunatly, some
- architectures (HP/UX) still reply on EXTRA_FRAME_INFO and,
- hence, still poke at the "struct frame_info" object directly. */
- fi->frame = fi->id.base;
+ if (frame_debug)
+ {
+ fprint_frame (gdb_stdlog, fi);
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
}
- return frame_id_build (fi->frame, fi->pc);
+ return fi->id;
}
const struct frame_id null_frame_id; /* All zeros. */
struct frame_id
-frame_id_build (CORE_ADDR base, CORE_ADDR func_or_pc)
+frame_id_build (CORE_ADDR stack_addr, CORE_ADDR func_addr)
{
struct frame_id id;
- id.base = base;
- id.pc = func_or_pc;
+ id.stack_addr = stack_addr;
+ id.func_addr = func_addr;
return id;
}
int
frame_id_p (struct frame_id l)
{
+ int p;
/* The .func can be NULL but the .base cannot. */
- return (l.base != 0);
+ p = (l.stack_addr != 0);
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "ID ");
+ fprint_frame_id (gdb_stdlog, l);
+ if (p)
+ fprintf_unfiltered (gdb_stdlog, " .OK");
+ else
+ fprintf_unfiltered (gdb_stdlog, " !OK");
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+ return p;
}
int
frame_id_eq (struct frame_id l, struct frame_id r)
{
- /* If .base is different, the frames are different. */
- if (l.base != r.base)
- return 0;
- /* Add a test to check that the frame ID's are for the same function
- here. */
- return 1;
+ int eq;
+ /* Compare stacks. The stack addresses must always match and can
+ never be zero. */
+ if (l.stack_addr == 0 || r.stack_addr == 0)
+ eq = 0;
+ else if (l.stack_addr != r.stack_addr)
+ eq = 0;
+ /* Compare functions. A zero function address acts like a wild
+ card, otherwize a perfect match is expected. */
+ else if (l.func_addr == 0 || r.func_addr == 0)
+ eq = 1;
+ else if (l.func_addr == r.func_addr)
+ eq = 1;
+ else
+ /* No luck. */
+ eq = 0;
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "ID ");
+ fprint_frame_id (gdb_stdlog, l);
+ if (eq)
+ fprintf_unfiltered (gdb_stdlog, " .EQ ");
+ else
+ fprintf_unfiltered (gdb_stdlog, " !EQ ");
+ fprintf_unfiltered (gdb_stdlog, "ID ");
+ fprint_frame_id (gdb_stdlog, r) ;
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+ return eq;
}
int
frame_id_inner (struct frame_id l, struct frame_id r)
{
+ int inner;
/* Only return non-zero when strictly inner than. Note that, per
comment in "frame.h", there is some fuzz here. Frameless
functions are not strictly inner than (same .base but different
.func). */
- return INNER_THAN (l.base, r.base);
+ inner = gdbarch_inner_than (current_gdbarch, l.stack_addr, r.stack_addr);
+ if (frame_debug)
+ {
+ fprint_frame_id (gdb_stdlog, l);
+ if (inner)
+ fprintf_unfiltered (gdb_stdlog, " .INNER ");
+ else
+ fprintf_unfiltered (gdb_stdlog, " !INNER ");
+ fprint_frame_id (gdb_stdlog, r);
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+ return inner;
}
struct frame_info *
@@ -192,6 +256,24 @@
return this_frame->pc_unwind_cache;
}
+CORE_ADDR
+frame_func_unwind (struct frame_info *this_frame)
+{
+ if (!this_frame->func.p)
+ {
+ CORE_ADDR pc = frame_pc_unwind (this_frame);
+ this_frame->func.cache = get_pc_function_start (pc);
+ }
+ return this_frame->func.cache;
+}
+
+CORE_ADDR
+get_frame_func (struct frame_info *this_frame)
+{
+ return frame_func_unwind (this_frame->next);
+}
+
+
static int
do_frame_unwind_register (void *src, int regnum, void *buf)
{
@@ -503,15 +585,15 @@
frame->prologue_cache = sentinel_frame_cache (regcache);
/* For the moment there is only one sentinel frame implementation. */
frame->unwind = sentinel_frame_unwind;
+ /* Give it a really large frame ID. */
+ frame->id_p = 1;
+ if (INNER_THAN (1, 2))
+ frame->id = frame_id_build (0, 0);
+ else
+ frame->id = frame_id_build (-1, 0);
/* Link this frame back to itself. The frame is self referential
(the unwound PC is the same as the pc), so make it so. */
frame->next = frame;
- /* Always unwind the PC as part of creating this frame. This
- ensures that the frame's PC points at something valid. */
- /* FIXME: cagney/2003-01-10: Problem here. Unwinding a sentinel
- frame's PC may require information such as the frame's thread's
- stop reason. Is it possible to get to that? */
- frame->pc = frame_pc_unwind (frame);
return frame;
}
@@ -585,6 +667,10 @@
if (catch_exceptions (uiout, unwind_to_current_frame, sentinel_frame,
NULL, RETURN_MASK_ERROR) != 0)
{
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Oops!\n");
+ }
/* Oops! Fake a current frame? Is this useful? It has a PC
of zero, for instance. */
current_frame = sentinel_frame;
@@ -641,7 +727,7 @@
source language of this frame, and switch to it if desired. */
if (fi)
{
- s = find_pc_symtab (fi->pc);
+ s = find_pc_symtab (get_frame_pc (fi));
if (s
&& s->language != current_language->la_language
&& s->language != language_unknown
@@ -756,8 +842,7 @@
unwinding a sentinel frame, the PC of which is pointing at a
stack dummy. Fake up the dummy frame's ID using the same
sequence as is found a traditional unwinder. */
- (*id).base = read_fp ();
- (*id).pc = read_pc ();
+ (*id) = frame_id_build (read_fp (), 0 /*read_pc ()*/);
return;
}
@@ -810,8 +895,7 @@
/* FIXME: cagney/2002-06-08: This should probably return the frame's
function and not the PC (a.k.a. resume address). */
pc = frame_pc_unwind (next_frame);
- id->pc = pc;
- id->base = base;
+ (*id) = frame_id_build (base, 0 /*pc*/);
}
const struct frame_unwind legacy_saved_regs_unwinder = {
@@ -955,16 +1039,25 @@
fi = frame_obstack_zalloc (sizeof (struct frame_info));
- fi->frame = addr;
- fi->pc = pc;
+ /* FIXME: cagney/2003-04-02: Should this instead try to map that pc
+ onto a function. */
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog, "create new frame\n");
+
+ fi->id = frame_id_build (addr, pc);
+ fi->id_p = 1;
+
fi->next = create_sentinel_frame (current_regcache);
+ fi->next->pc_unwind_cache = pc;
+ fi->next->pc_unwind_cache_p = 1;
+
fi->type = frame_type_from_pc (pc);
if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
DEPRECATED_INIT_EXTRA_FRAME_INFO (0, fi);
/* Select/initialize an unwind function. */
- fi->unwind = frame_unwind_find_by_pc (current_gdbarch, fi->pc);
+ fi->unwind = frame_unwind_find_by_pc (current_gdbarch, get_frame_pc (fi));
return fi;
}
@@ -1033,6 +1126,13 @@
prev = FRAME_OBSTACK_ZALLOC (struct frame_info);
prev->level = this_frame->level + 1;
+ /* Link prev to this. This ensures that functions such as
+ get_frame_pc(), called by all the deprecated init functions
+ below, and implemented using frame_pc_unwind (prev->next) work.
+ Don't link this to prev as this stops functions walking up the
+ frame chain to this partially initialized method. */
+ prev->next = this_frame;
+
/* NOTE: cagney/2002-11-18: Should have been correctly setting the
frame's type here, before anything else, and not last, at the
bottom of this function. The various
@@ -1069,8 +1169,7 @@
because (well ignoring the PPC) a dummy frame can be located
using THIS_FRAME's frame ID. */
- prev->pc = frame_pc_unwind (this_frame);
- if (prev->pc == 0)
+ if (frame_pc_unwind (this_frame) == 0)
{
/* The allocated PREV_FRAME will be reclaimed when the frame
obstack is next purged. */
@@ -1079,10 +1178,11 @@
"Outermost frame - unwound PC zero\n");
return NULL;
}
- prev->type = frame_type_from_pc (prev->pc);
+ prev->type = frame_type_from_pc (frame_pc_unwind (this_frame));
/* Set the unwind functions based on that identified PC. */
- prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc);
+ prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
+ frame_pc_unwind (this_frame));
/* Find the prev's frame's ID. */
if (prev->type == DUMMY_FRAME
@@ -1113,8 +1213,7 @@
using the same sequence as is found a traditional
unwinder. Once all architectures supply the
unwind_dummy_id method, this code can go away. */
- prev->id.base = read_fp ();
- prev->id.pc = read_pc ();
+ prev->id = frame_id_build (read_fp (), read_pc ());
}
/* Check that the unwound ID is valid. */
@@ -1135,15 +1234,8 @@
after the switch to storing the frame ID, instead of the
frame base, in the frame object. */
- /* FIXME: cagney/2002-12-18: Instead of this hack, should only
- store the frame ID in PREV_FRAME. Unfortunatly, some
- architectures (HP/UX) still reply on EXTRA_FRAME_INFO and,
- hence, still poke at the "struct frame_info" object directly. */
- prev->frame = prev->id.base;
-
/* Link it in. */
this_frame->prev = prev;
- prev->next = this_frame;
/* FIXME: cagney/2002-01-19: This call will go away. Instead of
initializing extra info, all frames will use the frame_cache
@@ -1157,6 +1249,16 @@
{
DEPRECATED_INIT_EXTRA_FRAME_INFO (0, prev);
}
+
+ if (prev->type == NORMAL_FRAME)
+ prev->id.func_addr = get_pc_function_start (prev->id.func_addr);
+
+ if (frame_debug)
+ {
+ fprint_frame (gdb_stdlog, prev);
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+
return prev;
}
@@ -1219,7 +1321,7 @@
/* Link in the already allocated prev frame. */
this_frame->prev = prev;
prev->next = this_frame;
- prev->frame = address;
+ deprecated_update_frame_base_hack (prev, address);
/* This change should not be needed, FIXME! We should determine
whether any targets *need* DEPRECATED_INIT_FRAME_PC to happen
@@ -1295,7 +1397,8 @@
that PC value. */
if (DEPRECATED_INIT_FRAME_PC_FIRST_P ())
- prev->pc = (DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev));
+ deprecated_update_frame_pc_hack
+ (prev, DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev));
if (DEPRECATED_INIT_EXTRA_FRAME_INFO_P ())
DEPRECATED_INIT_EXTRA_FRAME_INFO (fromleaf, prev);
@@ -1304,15 +1407,16 @@
FRAME_SAVED_PC may use that queue to figure out its value (see
tm-sparc.h). We want the pc saved in the inferior frame. */
if (DEPRECATED_INIT_FRAME_PC_P ())
- prev->pc = DEPRECATED_INIT_FRAME_PC (fromleaf, prev);
+ deprecated_update_frame_pc_hack
+ (prev, DEPRECATED_INIT_FRAME_PC (fromleaf, prev));
/* If ->frame and ->pc are unchanged, we are in the process of
getting ourselves into an infinite backtrace. Some architectures
check this in DEPRECATED_FRAME_CHAIN or thereabouts, but it seems
like there is no reason this can't be an architecture-independent
check. */
- if (prev->frame == this_frame->frame
- && prev->pc == this_frame->pc)
+ if (this_frame->level > 0
+ && frame_id_eq (get_frame_id (prev), get_frame_id (this_frame)))
{
this_frame->prev = NULL;
obstack_free (&frame_cache_obstack, prev);
@@ -1323,7 +1427,8 @@
(and probably other architectural information). The PC lets you
check things like the debug info at that point (dwarf2cfi?) and
use that to decide how the frame should be unwound. */
- prev->unwind = frame_unwind_find_by_pc (current_gdbarch, prev->pc);
+ prev->unwind = frame_unwind_find_by_pc (current_gdbarch,
+ get_frame_pc (prev));
/* NOTE: cagney/2002-11-18: The code segments, found in
create_new_frame and get_prev_frame(), that initializes the
@@ -1335,8 +1440,8 @@
before the INIT function has been called. */
if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
&& (DEPRECATED_PC_IN_CALL_DUMMY_P ()
- ? DEPRECATED_PC_IN_CALL_DUMMY (prev->pc, 0, 0)
- : pc_in_dummy_frame (prev->pc)))
+ ? DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (prev), 0, 0)
+ : pc_in_dummy_frame (get_frame_pc (prev))))
prev->type = DUMMY_FRAME;
else
{
@@ -1347,8 +1452,9 @@
Unforunatly, its the INIT code that sets the PC (Hmm, catch
22). */
char *name;
- find_pc_partial_function (prev->pc, &name, NULL, NULL);
- if (PC_IN_SIGTRAMP (prev->pc, name))
+ find_pc_partial_function (get_frame_pc (prev),
+ &name, NULL, NULL);
+ if (PC_IN_SIGTRAMP (get_frame_pc (prev), name))
prev->type = SIGTRAMP_FRAME;
/* FIXME: cagney/2002-11-11: Leave prev->type alone. Some
architectures are forcing the frame's type in INIT so we
@@ -1358,6 +1464,17 @@
go away. */
}
+ if (frame_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "frame %d @0x%s: ID ",
+ prev->level, paddr (get_frame_pc (prev)));
+ fprint_frame_id (gdb_stdlog, prev->id);
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ }
+
+ if (prev->type == NORMAL_FRAME)
+ prev->id.func_addr = get_pc_function_start (prev->id.func_addr);
+
return prev;
}
@@ -1551,8 +1668,7 @@
because (well ignoring the PPC) a dummy frame can be located
using THIS_FRAME's frame ID. */
- prev_frame->pc = frame_pc_unwind (this_frame);
- if (prev_frame->pc == 0)
+ if (frame_pc_unwind (this_frame) == 0)
{
/* The allocated PREV_FRAME will be reclaimed when the frame
obstack is next purged. */
@@ -1561,11 +1677,11 @@
"Outermost frame - unwound PC zero\n");
return NULL;
}
- prev_frame->type = frame_type_from_pc (prev_frame->pc);
+ prev_frame->type = frame_type_from_pc (frame_pc_unwind (this_frame));
/* Set the unwind functions based on that identified PC. */
prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
- prev_frame->pc);
+ frame_pc_unwind (this_frame));
/* The prev's frame's ID is computed by demand in get_frame_id(). */
@@ -1591,7 +1707,7 @@
CORE_ADDR
get_frame_pc (struct frame_info *frame)
{
- return frame->pc;
+ return frame_pc_unwind (frame->next);
}
static int
@@ -1614,7 +1730,7 @@
void
find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
{
- (*sal) = find_pc_line (frame->pc, pc_notcurrent (frame));
+ (*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame));
}
/* Per "frame.h", return the ``address'' of the frame. Code should
@@ -1622,13 +1738,7 @@
CORE_ADDR
get_frame_base (struct frame_info *fi)
{
- if (!fi->id_p)
- {
- /* HACK: Force the ID code to (indirectly) initialize the
- ->frame pointer. */
- get_frame_id (fi);
- }
- return fi->frame;
+ return get_frame_id (fi).stack_addr;
}
/* High-level offsets into the frame. Used by the debug info. */
@@ -1757,8 +1867,6 @@
void
deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
{
- /* See comment in "frame.h". */
- frame->pc = pc;
/* NOTE: cagney/2003-03-11: Some architectures (e.g., Arm) are
maintaining a locally allocated frame object. Since such frame's
are not in the frame chain, it isn't possible to assume that the
@@ -1776,8 +1884,8 @@
void
deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
{
- /* See comment in "frame.h". */
- frame->frame = base;
+ frame->id_p = 1;
+ frame->id.stack_addr = base;
}
void
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.80
diff -u -r1.80 frame.h
--- frame.h 1 Apr 2003 19:26:52 -0000 1.80
+++ frame.h 3 Apr 2003 16:43:59 -0000
@@ -43,15 +43,18 @@
struct frame_id
{
- /* The frame's address. This should be constant through out the
- lifetime of a frame. */
+ /* The frame's stack address. This shall be constant through out
+ the lifetime of a frame. Since the frame's lifetime includes the
+ prologue, and the value needs to always fall on or within the
+ bounds of the frame, this stack value is best pointed at the
+ inner-most address of the previous frame. */
/* NOTE: cagney/2002-11-16: The ia64 has two stacks and hence two
frame bases. This will need to be expanded to accomodate that. */
- CORE_ADDR base;
- /* The frame's current PC. While the PC within the function may
- change, the function that contains the PC does not. Should this
- instead be the frame's function? */
- CORE_ADDR pc;
+ CORE_ADDR stack_addr;
+ /* The frame's function address. This shall be constant through out
+ the lifetime of the frame. While the PC within the function may
+ change, the function that contains the PC does not. */
+ CORE_ADDR func_addr;
};
/* Methods for constructing and comparing Frame IDs.
@@ -65,12 +68,11 @@
/* For convenience. All fields are zero. */
extern const struct frame_id null_frame_id;
-/* Construct a frame ID. The second parameter isn't yet well defined.
- It might be the containing function, or the resume PC (see comment
- above in `struct frame_id')? A func/pc of zero indicates a
- wildcard (i.e., do not use func in frame ID comparisons). */
-extern struct frame_id frame_id_build (CORE_ADDR base,
- CORE_ADDR func_or_pc);
+/* Construct a frame ID. The first parameter is the frame's stack
+ address, and the second the frame's function (or zero, to indicate
+ a wild card). */
+extern struct frame_id frame_id_build (CORE_ADDR stack_addr,
+ CORE_ADDR func_addr);
/* Returns non-zero when L is a valid frame (a valid frame has a
non-zero .base). */
@@ -309,6 +311,13 @@
extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
+/* Unwind/return the frame's function, or 0 if the frame's function is
+ unknown. This is a wrapper to get_pc_function_start of
+ frame_pc_unwind. */
+extern CORE_ADDR frame_func_unwind (struct frame_info *frame);
+extern CORE_ADDR get_frame_func (struct frame_info *frame);
+
+
/* Discard the specified frame. Restoring the registers to the state
of the caller. */
extern void frame_pop (struct frame_info *frame);
@@ -344,17 +353,6 @@
struct frame_info
{
- /* Nominal address of the frame described. See comments at
- get_frame_base() about what this means outside the *FRAME*
- macros; in the *FRAME* macros, it can mean whatever makes most
- sense for this machine. */
- CORE_ADDR frame;
-
- /* Address at which execution is occurring in this frame.
- For the innermost frame, it's the current pc.
- For other frames, it is a pc saved in the next frame. */
- CORE_ADDR pc;
-
/* Level of this frame. The inner-most (youngest) frame is at
level 0. As you move towards the outer-most (oldest) frame,
the level increases. This is a cached value. It could just as
@@ -407,6 +405,13 @@
/* Cached copy of the previous frame's resume address. */
int pc_unwind_cache_p;
CORE_ADDR pc_unwind_cache;
+
+ /* Cached copy of the previous frame's function. */
+ struct
+ {
+ int p;
+ CORE_ADDR cache;
+ } func;
/* This frame's ID. Note that the frame's ID, base and PC contain
redundant information. */
Index: stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.72
diff -u -r1.72 stack.c
--- stack.c 1 Apr 2003 19:11:01 -0000 1.72
+++ stack.c 3 Apr 2003 16:44:04 -0000
@@ -216,7 +216,7 @@
if (ui_out_is_mi_like_p (uiout))
{
annotate_frame_address ();
- ui_out_field_core_addr (uiout, "addr", fi->pc);
+ ui_out_field_core_addr (uiout, "addr", get_frame_pc (fi));
annotate_frame_address_end ();
}