Convert frame unwinders to use the current frame and
authorDaniel Jacobowitz <drow@false.org>
Wed, 30 Apr 2008 21:16:46 +0000 (21:16 +0000)
committerDaniel Jacobowitz <drow@false.org>
Wed, 30 Apr 2008 21:16:46 +0000 (21:16 +0000)
"struct value".

* frame.c (frame_debug): Make global.
(get_frame_id): Pass this frame to unwinder routines.
(frame_pc_unwind): Remove unused unwind->prev_pc support.
(do_frame_register_read): Do not discard the return value of
frame_register_read.
(frame_register_unwind): Remove debug messages.  Use
frame_unwind_register_value.
(frame_unwind_register_value, get_frame_register_value): New
functions.
(create_new_frame, get_frame_base_address, get_frame_locals_address)
(get_frame_args_address, get_frame_type): Pass this frame to
unwinder routines.
(frame_cleanup_after_sniffer, frame_prepare_for_sniffer): New
functions.
* frame.h: Update comments.
(frame_debug, frame_unwind_register_value, get_frame_register_value)
(frame_prepare_for_sniffer): Declare.
* frame-unwind.h: Update comments and parameter names.
(default_frame_sniffer): Declare.
(frame_prev_register_ftype): Return a struct value *.
(struct frame_unwind): Remove prev_pc member.
(frame_unwind_sniffer_ftype, frame_unwind_append_sniffer): Delete.
(frame_unwind_append_unwinder, frame_unwind_got_optimized)
(frame_unwind_got_register, frame_unwind_got_memory)
(frame_unwind_got_constant, frame_unwind_got_address): Declare.
* frame-base.h: Update comments and parameter names.
* valops.c (value_fetch_lazy): Use get_frame_register_value.  Iterate
if necessary.  Add debugging output.
* sentinel-frame.c (sentinel_frame_prev_register)
(sentinel_frame_this_id): Update for new signature.
(sentinel_frame_prev_pc): Delete.
(sentinel_frame_unwinder): Remove prev_pc.
* ia64-tdep.c (ia64_libunwind_frame_unwind): Do not initialize
prev_pc.
* libunwind-frame.c (libunwind_frame_unwind): Likewise.
* frame-unwind.c (struct frame_unwind_table_entry): Remove sniffer.
(frame_unwind_append_sniffer): Delete.
(frame_unwind_append_unwinder): New function.
(frame_unwind_find_by_frame): Take this frame.  Only use sniffers
from unwinders.  Use frame_prepare_for_sniffer.
(default_frame_sniffer, frame_unwind_got_optimized)
(frame_unwind_got_register, frame_unwind_got_memory)
(frame_unwind_got_constant, frame_unwind_got_address): New functions.
* dummy-frame.c (dummy_frame_sniffer): Use gdbarch_dummy_id.
(dummy_frame_prev_register, dummy_frame_this_id): Update for new
signature.
* gdbarch.sh: Replace unwind_dummy_id with dummy_id.
* gdbarch.c, gdbarch.c: Regenerated.
* frame-base.c (default_frame_base_address)
(default_frame_locals_address, default_frame_args_address): Update
for new signature.
(frame_base_find_by_frame): Pass this frame to unwinder routines.
* infcall.c (call_function_by_hand): Update comments.
* Makefile.in (frame-unwind.o): Update dependencies.

* gdbint.texinfo (Stack Frames): New chapter.
(Algorithms): Move Frames text to the new chapter.
(Target Conditionals): Delete SAVE_DUMMY_FRAME_TOS.  Document
gdbarch_dummy_id instead of gdbarch_unwind_dummy_id.

19 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/doc/ChangeLog
gdb/doc/gdbint.texinfo
gdb/dummy-frame.c
gdb/frame-base.c
gdb/frame-base.h
gdb/frame-unwind.c
gdb/frame-unwind.h
gdb/frame.c
gdb/frame.h
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/ia64-tdep.c
gdb/infcall.c
gdb/libunwind-frame.c
gdb/sentinel-frame.c
gdb/valops.c

index 7dbdef07e5f51cddbc2d1d023d57a1838ed97407..ec0e06c3e1c71a1f038849fef98518cbae5dc199 100644 (file)
@@ -1,3 +1,63 @@
+2008-04-30  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       Convert frame unwinders to use the current frame and
+       "struct value".
+
+       * frame.c (frame_debug): Make global.
+       (get_frame_id): Pass this frame to unwinder routines.
+       (frame_pc_unwind): Remove unused unwind->prev_pc support.
+       (do_frame_register_read): Do not discard the return value of
+       frame_register_read.
+       (frame_register_unwind): Remove debug messages.  Use
+       frame_unwind_register_value.
+       (frame_unwind_register_value, get_frame_register_value): New
+       functions.
+       (create_new_frame, get_frame_base_address, get_frame_locals_address)
+       (get_frame_args_address, get_frame_type): Pass this frame to
+       unwinder routines.
+       (frame_cleanup_after_sniffer, frame_prepare_for_sniffer): New
+       functions.
+       * frame.h: Update comments.
+       (frame_debug, frame_unwind_register_value, get_frame_register_value)
+       (frame_prepare_for_sniffer): Declare.
+       * frame-unwind.h: Update comments and parameter names.
+       (default_frame_sniffer): Declare.
+       (frame_prev_register_ftype): Return a struct value *.
+       (struct frame_unwind): Remove prev_pc member.
+       (frame_unwind_sniffer_ftype, frame_unwind_append_sniffer): Delete.
+       (frame_unwind_append_unwinder, frame_unwind_got_optimized)
+       (frame_unwind_got_register, frame_unwind_got_memory)
+       (frame_unwind_got_constant, frame_unwind_got_address): Declare.
+       * frame-base.h: Update comments and parameter names.
+       * valops.c (value_fetch_lazy): Use get_frame_register_value.  Iterate
+       if necessary.  Add debugging output.
+       * sentinel-frame.c (sentinel_frame_prev_register)
+       (sentinel_frame_this_id): Update for new signature.
+       (sentinel_frame_prev_pc): Delete.
+       (sentinel_frame_unwinder): Remove prev_pc.
+       * ia64-tdep.c (ia64_libunwind_frame_unwind): Do not initialize
+       prev_pc.
+       * libunwind-frame.c (libunwind_frame_unwind): Likewise.
+       * frame-unwind.c (struct frame_unwind_table_entry): Remove sniffer.
+       (frame_unwind_append_sniffer): Delete.
+       (frame_unwind_append_unwinder): New function.
+       (frame_unwind_find_by_frame): Take this frame.  Only use sniffers
+       from unwinders.  Use frame_prepare_for_sniffer.
+       (default_frame_sniffer, frame_unwind_got_optimized)
+       (frame_unwind_got_register, frame_unwind_got_memory)
+       (frame_unwind_got_constant, frame_unwind_got_address): New functions.
+       * dummy-frame.c (dummy_frame_sniffer): Use gdbarch_dummy_id.
+       (dummy_frame_prev_register, dummy_frame_this_id): Update for new
+       signature.
+       * gdbarch.sh: Replace unwind_dummy_id with dummy_id.
+       * gdbarch.c, gdbarch.c: Regenerated.
+       * frame-base.c (default_frame_base_address)
+       (default_frame_locals_address, default_frame_args_address): Update
+       for new signature.
+       (frame_base_find_by_frame): Pass this frame to unwinder routines.
+       * infcall.c (call_function_by_hand): Update comments.
+       * Makefile.in (frame-unwind.o): Update dependencies.
+
 2008-04-30  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * ada-lang.c (ada_value_primitive_packed_val): Only check
index 9304bc2f5864a94b48012f6de27dc90d71a59505..98ae55892f291d0326058ef6868301635a8de559 100644 (file)
@@ -2143,7 +2143,8 @@ frame.o: frame.c $(defs_h) $(frame_h) $(target_h) $(value_h) $(inferior_h) \
        $(annotate_h) $(language_h) $(frame_unwind_h) $(frame_base_h) \
        $(command_h) $(gdbcmd_h) $(observer_h) $(objfiles_h) $(exceptions_h)
 frame-unwind.o: frame-unwind.c $(defs_h) $(frame_h) $(frame_unwind_h) \
-       $(gdb_assert_h) $(dummy_frame_h) $(gdb_obstack_h)
+       $(gdb_assert_h) $(dummy_frame_h) $(gdb_obstack_h) $(value_h) \
+       $(regcache_h)
 frv-linux-tdep.o: frv-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
        $(frame_h) $(osabi_h) $(regcache_h) $(elf_bfd_h) $(elf_frv_h) \
        $(frv_tdep_h) $(trad_frame_h) $(frame_unwind_h) $(regset_h) \
index 9cdf5d98099044672fbfe315d256080a868a5c88..2285c835ce729fca07d325f04808f410fc3fd263 100644 (file)
@@ -1,6 +1,13 @@
+2008-04-30  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdbint.texinfo (Stack Frames): New chapter.
+       (Algorithms): Move Frames text to the new chapter.
+       (Target Conditionals): Delete SAVE_DUMMY_FRAME_TOS.  Document
+       gdbarch_dummy_id instead of gdbarch_unwind_dummy_id.
+
 2008-04-24  Vladimir Prus  <vladimir@codesourcery.com>
 
-        * doc/gdb.texinfo (GDB/MI Output Syntax): Clarify that async
+        * gdb.texinfo (GDB/MI Output Syntax): Clarify that async
         output does not necessary include any tokens.
 
 2008-04-22  Corinna Vinschen  <vinschen@redhat.com>
 
 2007-12-17  Luis Machado  <luisgpm@br.ibm.com>
 
-       * doc/gdb.texinfo: Add new parameter's description.
+       * gdb.texinfo: Add new parameter's description.
 
 2007-12-16  Daniel Jacobowitz  <dan@codesourcery.com>
 
 
 2007-02-26  Daniel Jacobowitz  <dan@codesourcery.com>
 
-       * src/gdb/doc/gdb.texinfo (Standard Target Features): Mention
+       * gdb.texinfo (Standard Target Features): Mention
        case insensitivity.
        (ARM Features): Describe org.gnu.gdb.xscale.iwmmxt.
 
        (Target Description Format): Document new elements.  Use
        @smallexample.
        (Predefined Target Types, Standard Target Features): New sections.
-       * doc/gdbint.texinfo (Target Descriptions): New section.
+       * gdbint.texinfo (Target Descriptions): New section.
 
 2007-02-07  Daniel Jacobowitz  <dan@codesourcery.com>
 
 
 2006-07-05  Daniel Jacobowitz  <dan@codesourcery.com>
 
-       * doc/gdb.texinfo (KOD): Remove node.
+       * gdb.texinfo (KOD): Remove node.
        (GDB/MI Kod Commands): Remove commented out node.
 
 2006-07-01  Eli Zaretskii  <eliz@gnu.org>
index d578347b96701f254e508d876b45820019a24741..39cb031c38fc27f5517f232711c9cc22f93dcf9e 100644 (file)
@@ -76,6 +76,7 @@ as the mechanisms that adapt @value{GDBN} to specific hosts and targets.
 * Algorithms::
 * User Interface::
 * libgdb::
+* Stack Frames::
 * Symbol Handling::
 * Language Support::
 * Host Definition::
@@ -273,39 +274,6 @@ cases and real-world issues.  This chapter describes the basic
 algorithms and mentions some of the specific target definitions that
 they use.
 
-@section Frames
-
-@cindex frame
-@cindex call stack frame
-A frame is a construct that @value{GDBN} uses to keep track of calling
-and called functions.
-
-@cindex frame, unwind
-@value{GDBN}'s frame model, a fresh design, was implemented with the
-need to support @sc{dwarf}'s Call Frame Information in mind.  In fact,
-the term ``unwind'' is taken directly from that specification.
-Developers wishing to learn more about unwinders, are encouraged to
-read the @sc{dwarf} specification.
-
-@findex frame_register_unwind
-@findex get_frame_register
-@value{GDBN}'s model is that you find a frame's registers by
-``unwinding'' them from the next younger frame.  That is,
-@samp{get_frame_register} which returns the value of a register in
-frame #1 (the next-to-youngest frame), is implemented by calling frame
-#0's @code{frame_register_unwind} (the youngest frame).  But then the
-obvious question is: how do you access the registers of the youngest
-frame itself?
-
-@cindex sentinel frame
-@findex get_frame_type
-@vindex SENTINEL_FRAME
-To answer this question, GDB has the @dfn{sentinel} frame, the
-``-1st'' frame.  Unwinding registers from the sentinel frame gives you
-the current values of the youngest real frame's registers.  If @var{f}
-is a sentinel frame, then @code{get_frame_type (@var{f}) ==
-SENTINEL_FRAME}.
-
 @section Prologue Analysis
 
 @cindex prologue analysis
@@ -1853,6 +1821,127 @@ the query interface.  Each function is parameterized by a @code{ui-out}
 builder.  The result of the query is constructed using that builder
 before the query function returns.
 
+@node Stack Frames
+@chapter Stack Frames
+
+@cindex frame
+@cindex call stack frame
+A frame is a construct that @value{GDBN} uses to keep track of calling
+and called functions.
+
+@cindex unwind frame
+@value{GDBN}'s frame model, a fresh design, was implemented with the
+need to support @sc{dwarf}'s Call Frame Information in mind.  In fact,
+the term ``unwind'' is taken directly from that specification.
+Developers wishing to learn more about unwinders, are encouraged to
+read the @sc{dwarf} specification, available from
+@url{http://www.dwarfstd.org}.
+
+@findex frame_register_unwind
+@findex get_frame_register
+@value{GDBN}'s model is that you find a frame's registers by
+``unwinding'' them from the next younger frame.  That is,
+@samp{get_frame_register} which returns the value of a register in
+frame #1 (the next-to-youngest frame), is implemented by calling frame
+#0's @code{frame_register_unwind} (the youngest frame).  But then the
+obvious question is: how do you access the registers of the youngest
+frame itself?
+
+@cindex sentinel frame
+@findex get_frame_type
+@vindex SENTINEL_FRAME
+To answer this question, GDB has the @dfn{sentinel} frame, the
+``-1st'' frame.  Unwinding registers from the sentinel frame gives you
+the current values of the youngest real frame's registers.  If @var{f}
+is a sentinel frame, then @code{get_frame_type (@var{f}) @equiv{}
+SENTINEL_FRAME}.
+
+@section Selecting an Unwinder
+
+@findex frame_unwind_prepend_unwinder
+@findex frame_unwind_append_unwinder
+The architecture registers a list of frame unwinders (@code{struct
+frame_unwind}), using the functions
+@code{frame_unwind_prepend_unwinder} and
+@code{frame_unwind_append_unwinder}.  Each unwinder includes a
+sniffer.  Whenever @value{GDBN} needs to unwind a frame (to fetch the
+previous frame's registers or the current frame's ID), it calls
+registered sniffers in order to find one which recognizes the frame.
+The first time a sniffer returns non-zero, the corresponding unwinder
+is assigned to the frame.
+
+@section Unwinding the Frame ID
+@cindex frame ID
+
+Every frame has an associated ID, of type @code{struct frame_id}.
+The ID includes the stack base and function start address for
+the frame.  The ID persists through the entire life of the frame,
+including while other called frames are running; it is used to
+locate an appropriate @code{struct frame_info} from the cache.
+
+Every time the inferior stops, and at various other times, the frame
+cache is flushed.  Because of this, parts of @value{GDBN} which need
+to keep track of individual frames cannot use pointers to @code{struct
+frame_info}.  A frame ID provides a stable reference to a frame, even
+when the unwinder must be run again to generate a new @code{struct
+frame_info} for the same frame.
+
+The frame's unwinder's @code{this_id} method is called to find the ID.
+Note that this is different from register unwinding, where the next
+frame's @code{prev_register} is called to unwind this frame's
+registers.
+
+Both stack base and function address are required to identify the
+frame, because a recursive function has the same function address for
+two consecutive frames and a leaf function may have the same stack
+address as its caller.  On some platforms, a third address is part of
+the ID to further disambiguate frames---for instance, on IA-64
+the separate register stack address is included in the ID.
+
+An invalid frame ID (@code{null_frame_id}) returned from the
+@code{this_id} method means to stop unwinding after this frame.
+
+@section Unwinding Registers
+
+Each unwinder includes a @code{prev_register} method.  This method
+takes a frame, an associated cache pointer, and a register number.
+It returns a @code{struct value *} describing the requested register,
+as saved by this frame.  This is the value of the register that is
+current in this frame's caller.
+
+The returned value must have the same type as the register.  It may
+have any lvalue type.  In most circumstances one of these routines
+will generate the appropriate value:
+
+@table @code
+@item frame_unwind_got_optimized
+@findex frame_unwind_got_optimized
+This register was not saved.
+
+@item frame_unwind_got_register
+@findex frame_unwind_got_register
+This register was copied into another register in this frame.  This
+is also used for unchanged registers; they are ``copied'' into the
+same register.
+
+@item frame_unwind_got_memory
+@findex frame_unwind_got_memory
+This register was saved in memory.
+
+@item frame_unwind_got_constant
+@findex frame_unwind_got_constant
+This register was not saved, but the unwinder can compute the previous
+value some other way.
+
+@item frame_unwind_got_address
+@findex frame_unwind_got_address
+Same as @code{frame_unwind_got_constant}, except that the value is a target
+address.  This is frequently used for the stack pointer, which is not
+explicitly saved but has a known offset from this frame's stack
+pointer.  For architectures with a flat unified address space, this is
+generally the same as @code{frame_unwind_got_constant}.
+@end table
+
 @node Symbol Handling
 
 @chapter Symbol Handling
@@ -3943,14 +4032,6 @@ This method replaces @w{@code{gdbarch_call_dummy_location (@var{gdbarch})}} and
 Return the name of register @var{regnr} as a string.  May return @code{NULL}
 to indicate that @var{regnr} is not a valid register.
 
-@item SAVE_DUMMY_FRAME_TOS (@var{sp})
-@findex SAVE_DUMMY_FRAME_TOS
-@anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to
-notify the target dependent code of the top-of-stack value that will be
-passed to the inferior code.  This is the value of the @code{SP}
-after both the dummy frame and space for parameters/results have been
-allocated on the stack.  @xref{gdbarch_unwind_dummy_id}.
-
 @item int gdbarch_sdb_reg_to_regnum (@var{gdbarch}, @var{sdb_regnr})
 @findex gdbarch_sdb_reg_to_regnum
 Use this function to convert sdb register @var{sdb_regnr} into @value{GDBN}
@@ -4132,13 +4213,12 @@ the @code{opcodes} library (@pxref{Support Libraries, ,Opcodes}).
 @file{include/dis-asm.h} used to pass information to the instruction
 decoding routine.
 
-@item frame_id gdbarch_unwind_dummy_id (@var{gdbarch}, @var{frame})
-@findex gdbarch_unwind_dummy_id
-@anchor{gdbarch_unwind_dummy_id} Given @var{frame} return a @w{@code{struct
+@item frame_id gdbarch_dummy_id (@var{gdbarch}, @var{frame})
+@findex gdbarch_dummy_id
+@anchor{gdbarch_dummy_id} Given @var{frame} return a @w{@code{struct
 frame_id}} that uniquely identifies an inferior function call's dummy
 frame.  The value returned must match the dummy frame stack value
-previously saved using @code{SAVE_DUMMY_FRAME_TOS}.
-@xref{SAVE_DUMMY_FRAME_TOS}.
+previously saved by @code{call_function_by_hand}.
 
 @item DEPRECATED_USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
 @findex DEPRECATED_USE_STRUCT_CONVENTION
index 3095f76bf8992da4d381fc4f56227c159d9320ad..4c044ef3df46e348bc383b36e5130c90db670236 100644 (file)
@@ -39,7 +39,7 @@ struct dummy_frame
 {
   struct dummy_frame *next;
   /* This frame's ID.  Must match the value returned by
-     gdbarch_unwind_dummy_id.  */
+     gdbarch_dummy_id.  */
   struct frame_id id;
   /* The caller's regcache.  */
   struct regcache *regcache;
@@ -124,7 +124,7 @@ struct dummy_frame_cache
 
 int
 dummy_frame_sniffer (const struct frame_unwind *self,
-                    struct frame_info *next_frame,
+                    struct frame_info *this_frame,
                     void **this_prologue_cache)
 {
   struct dummy_frame *dummyframe;
@@ -141,12 +141,9 @@ dummy_frame_sniffer (const struct frame_unwind *self,
   /* Don't bother unles there is at least one dummy frame.  */
   if (dummy_frame_stack != NULL)
     {
-      /* Use an architecture specific method to extract the prev's
-        dummy ID from the next frame.  Note that this method uses
-        frame_register_unwind to obtain the register values needed to
-        determine the dummy frame's ID.  */
-      this_id = gdbarch_unwind_dummy_id (get_frame_arch (next_frame), 
-                                        next_frame);
+      /* Use an architecture specific method to extract this frame's
+        dummy ID, assuming it is a dummy frame.  */
+      this_id = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
 
       /* Use that ID to find the corresponding cache entry.  */
       for (dummyframe = dummy_frame_stack;
@@ -170,43 +167,37 @@ dummy_frame_sniffer (const struct frame_unwind *self,
 /* Given a call-dummy dummy-frame, return the registers.  Here the
    register value is taken from the local copy of the register buffer.  */
 
-static void
-dummy_frame_prev_register (struct frame_info *next_frame,
+static struct value *
+dummy_frame_prev_register (struct frame_info *this_frame,
                           void **this_prologue_cache,
-                          int regnum, int *optimized,
-                          enum lval_type *lvalp, CORE_ADDR *addrp,
-                          int *realnum, gdb_byte *bufferp)
+                          int regnum)
 {
-  /* The dummy-frame sniffer always fills in the cache.  */
   struct dummy_frame_cache *cache = (*this_prologue_cache);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct value *reg_val;
+
+  /* The dummy-frame sniffer always fills in the cache.  */
   gdb_assert (cache != NULL);
 
   /* Describe the register's location.  Generic dummy frames always
      have the register value in an ``expression''.  */
-  *optimized = 0;
-  *lvalp = not_lval;
-  *addrp = 0;
-  *realnum = -1;
-
-  /* If needed, find and return the value of the register.  */
-  if (bufferp != NULL)
-    {
-      /* Return the actual value.  */
-      /* Use the regcache_cooked_read() method so that it, on the fly,
-         constructs either a raw or pseudo register from the raw
-         register cache.  */
-      regcache_cooked_read (cache->prev_regcache, regnum, bufferp);
-    }
+  reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
+
+  /* Use the regcache_cooked_read() method so that it, on the fly,
+     constructs either a raw or pseudo register from the raw
+     register cache.  */
+  regcache_cooked_read (cache->prev_regcache, regnum,
+                       value_contents_writeable (reg_val));
+  return reg_val;
 }
 
-/* Assuming that THIS frame is a dummy (remember, the NEXT and not
-   THIS frame is passed in), return the ID of THIS frame.  That ID is
+/* Assuming that THIS frame is a dummy, return the ID of THIS frame.  That ID is
    determined by examining the NEXT frame's unwound registers using
-   the method unwind_dummy_id().  As a side effect, THIS dummy frame's
+   the method dummy_id().  As a side effect, THIS dummy frame's
    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 (struct frame_info *this_frame,
                     void **this_prologue_cache,
                     struct frame_id *this_id)
 {
index b85d2de385d202f7d2f7e2ff8078896d97db7f8f..e7b6cdd0c40f76250417273535fc362d1a1262ff 100644 (file)
    really need to override this.  */
 
 static CORE_ADDR
-default_frame_base_address (struct frame_info *next_frame, void **this_cache)
+default_frame_base_address (struct frame_info *this_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 (struct frame_info *this_frame, void **this_cache)
 {
-  return default_frame_base_address (next_frame, this_cache);
+  return default_frame_base_address (this_frame, this_cache);
 }
 
 static CORE_ADDR
-default_frame_args_address (struct frame_info *next_frame, void **this_cache)
+default_frame_args_address (struct frame_info *this_frame, void **this_cache)
 {
-  return default_frame_base_address (next_frame, this_cache);
+  return default_frame_base_address (this_frame, this_cache);
 }
 
 const struct frame_base default_frame_base = {
@@ -97,16 +96,16 @@ frame_base_set_default (struct gdbarch *gdbarch,
 }
 
 const struct frame_base *
-frame_base_find_by_frame (struct frame_info *next_frame)
+frame_base_find_by_frame (struct frame_info *this_frame)
 {
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
   struct frame_base_table_entry *entry;
 
   for (entry = table->head; entry != NULL; entry = entry->next)
     {
       const struct frame_base *desc = NULL;
-      desc = entry->sniffer (next_frame);
+      desc = entry->sniffer (this_frame);
       if (desc != NULL)
        return desc;
     }
index 8fbcb28df036a11abfa9879ec1e29ea4961301d7..7f10e1e16506411127e6811c6af6d5e77cb56053 100644 (file)
@@ -28,9 +28,9 @@ struct gdbarch;
 struct regcache;
 
 /* 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'.
+   and that this is a `normal frame'; use THIS frame, and implicitly
+   the NEXT frame's 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
@@ -42,17 +42,17 @@ struct regcache;
 
 /* A generic base address.  */
 
-typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *next_frame,
+typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *this_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) (struct frame_info *this_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) (struct frame_info *this_frame,
                                           void **this_base_cache);
 
 struct frame_base
@@ -65,10 +65,10 @@ struct frame_base
   frame_this_args_ftype *this_args;
 };
 
-/* Given the NEXT frame, return the frame base methods for THIS frame,
+/* Given THIS 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) (struct frame_info *this_frame);
 
 /* Append a frame base sniffer to the list.  The sniffers are polled
    in the order that they are appended.  */
@@ -86,6 +86,6 @@ extern void frame_base_set_default (struct gdbarch *gdbarch,
 /* Iterate through the list of frame base handlers until one returns
    an implementation.  */
 
-extern const struct frame_base *frame_base_find_by_frame (struct frame_info *next_frame);
+extern const struct frame_base *frame_base_find_by_frame (struct frame_info *this_frame);
 
 #endif
index 3a2cb7a1f739d6e0f656cbd85c6d18795cb0b4b7..738425943343128f1612826c9d58cca64543d702 100644 (file)
 #include "defs.h"
 #include "frame.h"
 #include "frame-unwind.h"
-#include "gdb_assert.h"
 #include "dummy-frame.h"
+#include "value.h"
+#include "regcache.h"
+
+#include "gdb_assert.h"
 #include "gdb_obstack.h"
 
 static struct gdbarch_data *frame_unwind_data;
 
 struct frame_unwind_table_entry
 {
-  frame_unwind_sniffer_ftype *sniffer;
   const struct frame_unwind *unwinder;
   struct frame_unwind_table_entry *next;
 };
@@ -54,19 +56,6 @@ frame_unwind_init (struct obstack *obstack)
   return table;
 }
 
-void
-frame_unwind_append_sniffer (struct gdbarch *gdbarch,
-                            frame_unwind_sniffer_ftype *sniffer)
-{
-  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
-  struct frame_unwind_table_entry **ip;
-
-  /* Find the end of the list and insert the new entry there.  */
-  for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next);
-  (*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
-  (*ip)->sniffer = sniffer;
-}
-
 void
 frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
                                const struct frame_unwind *unwinder)
@@ -81,32 +70,123 @@ frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
   (*table->osabi_head) = entry;
 }
 
+void
+frame_unwind_append_unwinder (struct gdbarch *gdbarch,
+                             const struct frame_unwind *unwinder)
+{
+  struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
+  struct frame_unwind_table_entry **ip;
+
+  /* Find the end of the list and insert the new entry there.  */
+  for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next);
+  (*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
+  (*ip)->unwinder = unwinder;
+}
+
 const struct frame_unwind *
-frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache)
+frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache)
 {
   int i;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
   struct frame_unwind_table_entry *entry;
+  struct cleanup *old_cleanup;
   for (entry = table->list; entry != NULL; entry = entry->next)
     {
-      if (entry->sniffer != NULL)
-       {
-         const struct frame_unwind *desc = NULL;
-         desc = entry->sniffer (next_frame);
-         if (desc != NULL)
-           return desc;
-       }
-      if (entry->unwinder != NULL)
+      struct cleanup *old_cleanup;
+
+      old_cleanup = frame_prepare_for_sniffer (this_frame, entry->unwinder);
+      if (entry->unwinder->sniffer (entry->unwinder, this_frame,
+                                   this_cache))
        {
-         if (entry->unwinder->sniffer (entry->unwinder, next_frame,
-                                       this_cache))
-           return entry->unwinder;
+         discard_cleanups (old_cleanup);
+         return entry->unwinder;
        }
+      do_cleanups (old_cleanup);
     }
   internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed"));
 }
 
+/* A default frame sniffer which always accepts the frame.  Used by
+   fallback prologue unwinders.  */
+
+int
+default_frame_sniffer (const struct frame_unwind *self,
+                      struct frame_info *this_frame,
+                      void **this_prologue_cache)
+{
+  return 1;
+}
+
+/* Helper functions for value-based register unwinding.  These return
+   a (possibly lazy) value of the appropriate type.  */
+
+/* Return a value which indicates that FRAME did not save REGNUM.  */
+
+struct value *
+frame_unwind_got_optimized (struct frame_info *frame, int regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct value *reg_val;
+
+  reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
+  set_value_optimized_out (reg_val, 1);
+  return reg_val;
+}
+
+/* Return a value which indicates that FRAME copied REGNUM into
+   register NEW_REGNUM.  */
+
+struct value *
+frame_unwind_got_register (struct frame_info *frame, int regnum, int new_regnum)
+{
+  return value_of_register_lazy (frame, new_regnum);
+}
+
+/* Return a value which indicates that FRAME saved REGNUM in memory at
+   ADDR.  */
+
+struct value *
+frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  return value_at_lazy (register_type (gdbarch, regnum), addr);
+}
+
+/* Return a value which indicates that FRAME's saved version of
+   REGNUM has a known constant (computed) value of VAL.  */
+
+struct value *
+frame_unwind_got_constant (struct frame_info *frame, int regnum,
+                          ULONGEST val)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct value *reg_val;
+
+  reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
+  store_unsigned_integer (value_contents_writeable (reg_val),
+                         register_size (gdbarch, regnum), val);
+  return reg_val;
+}
+
+/* Return a value which indicates that FRAME's saved version of REGNUM
+   has a known constant (computed) value of ADDR.  Convert the
+   CORE_ADDR to a target address if necessary.  */
+
+struct value *
+frame_unwind_got_address (struct frame_info *frame, int regnum,
+                         CORE_ADDR addr)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct value *reg_val;
+
+  reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
+  pack_long (value_contents_writeable (reg_val),
+            register_type (gdbarch, regnum), addr);
+  return reg_val;
+}
+
 extern initialize_file_ftype _initialize_frame_unwind; /* -Wmissing-prototypes */
 
 void
index 8140a801300eb74033c156e5fb5e360090c56151..9ffafffb26fb742b239c581f04b97fb93df45a04 100644 (file)
@@ -26,6 +26,7 @@ struct frame_id;
 struct frame_unwind;
 struct gdbarch;
 struct regcache;
+struct value;
 
 #include "frame.h"             /* For enum frame_type.  */
 
@@ -41,17 +42,24 @@ struct regcache;
    as where this frame's prologue stores the previous frame's
    registers.  */
 
-/* Given the NEXT frame, take a wiff of THIS frame's registers (namely
+/* Given THIS frame, take a whiff of its registers (namely
    the PC and attributes) and if SELF is the applicable unwinder,
    return non-zero.  Possibly also initialize THIS_PROLOGUE_CACHE.  */
 
 typedef int (frame_sniffer_ftype) (const struct frame_unwind *self,
-                                  struct frame_info *next_frame,
+                                  struct frame_info *this_frame,
                                   void **this_prologue_cache);
 
+/* A default frame sniffer which always accepts the frame.  Used by
+   fallback prologue unwinders.  */
+
+int default_frame_sniffer (const struct frame_unwind *self,
+                          struct frame_info *this_frame,
+                          void **this_prologue_cache);
+
 /* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
-   use the NEXT frame, and its register unwind method, to determine
-   the frame ID of THIS frame.
+   use THIS frame, and through it the NEXT frame's register unwind
+   method, to determine the frame ID of THIS frame.
 
    A frame ID provides an invariant that can be used to re-identify an
    instance of a frame.  It is a combination of the frame's `base' and
@@ -72,14 +80,14 @@ typedef int (frame_sniffer_ftype) (const struct frame_unwind *self,
    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) (struct frame_info *this_frame,
                                    void **this_prologue_cache,
                                    struct frame_id *this_id);
 
 /* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
-   use the NEXT frame, and its register unwind method, to unwind THIS
-   frame's registers (returning the value of the specified register
-   REGNUM in the previous frame).
+   use THIS frame, and implicitly the NEXT frame's register unwind
+   method, to unwind THIS frame's registers (returning the value of
+   the specified register REGNUM in the previous frame).
 
    Traditionally, THIS frame's registers were unwound by examining
    THIS frame's function's prologue and identifying which registers
@@ -91,37 +99,22 @@ typedef void (frame_this_id_ftype) (struct frame_info *next_frame,
    register in the previous frame is found in memory at SP+12, and
    THIS frame's SP can be obtained by unwinding the NEXT frame's SP.
 
-   Why not pass in THIS_FRAME?  By passing in NEXT frame and THIS
-   cache, the supplied parameters are consistent with the sibling
-   function THIS_ID.
+   This function takes THIS_FRAME as an argument.  It can find the
+   values of registers in THIS frame by calling get_frame_register
+   (THIS_FRAME), and reinvoke itself to find other registers in the
+   PREVIOUS frame by calling frame_unwind_register (THIS_FRAME).
 
-   Can the code call ``frame_register (get_prev_frame (NEXT_FRAME))''?
-   Won't the call frame_register (THIS_FRAME) be faster?  Well,
-   ignoring the possability that the previous frame does not yet
-   exist, the ``frame_register (FRAME)'' function is expanded to
-   ``frame_register_unwind (get_next_frame (FRAME)'' and hence that
-   call will expand to ``frame_register_unwind (get_next_frame
-   (get_prev_frame (NEXT_FRAME)))''.  Might as well call
-   ``frame_register_unwind (NEXT_FRAME)'' directly.
+   The result is a GDB value object describing the register value.  It
+   may be a lazy reference to memory, a lazy reference to the value of
+   a register in THIS frame, or a non-lvalue.
 
    THIS_PROLOGUE_CACHE can be used to share any prolog analysis data
    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, gdb_byte *valuep);
-
-/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
-   use the NEXT frame, and its register unwind method, to return the PREV
-   frame's program-counter.  */
-
-typedef CORE_ADDR (frame_prev_pc_ftype) (struct frame_info *next_frame,
-                                        void **this_prologue_cache);
+typedef struct value * (frame_prev_register_ftype)
+  (struct frame_info *this_frame, void **this_prologue_cache,
+   int regnum);
 
 /* Deallocate extra memory associated with the frame cache if any.  */
 
@@ -139,7 +132,6 @@ struct frame_unwind
   frame_prev_register_ftype *prev_register;
   const struct frame_data *unwind_data;
   frame_sniffer_ftype *sniffer;
-  frame_prev_pc_ftype *prev_pc;
   frame_dealloc_cache_ftype *dealloc_cache;
 };
 
@@ -152,23 +144,50 @@ struct frame_unwind
 extern void frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
                                           const struct frame_unwind *unwinder);
 
-/* 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);
-
 /* 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);
+extern void frame_unwind_append_unwinder (struct gdbarch *gdbarch,
+                                         const struct frame_unwind *unwinder);
 
-/* Iterate through the next frame's sniffers until one returns with an
+/* Iterate through sniffers for THIS frame until one returns with an
    unwinder implementation.  Possibly initialize THIS_CACHE.  */
 
-extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *next_frame,
+extern const struct frame_unwind *frame_unwind_find_by_frame (struct frame_info *this_frame,
                                                              void **this_cache);
 
+/* Helper functions for value-based register unwinding.  These return
+   a (possibly lazy) value of the appropriate type.  */
+
+/* Return a value which indicates that FRAME did not save REGNUM.  */
+
+struct value *frame_unwind_got_optimized (struct frame_info *frame,
+                                         int regnum);
+
+/* Return a value which indicates that FRAME copied REGNUM into
+   register NEW_REGNUM.  */
+
+struct value *frame_unwind_got_register (struct frame_info *frame, int regnum,
+                                        int new_regnum);
+
+/* Return a value which indicates that FRAME saved REGNUM in memory at
+   ADDR.  */
+
+struct value *frame_unwind_got_memory (struct frame_info *frame, int regnum,
+                                      CORE_ADDR addr);
+
+/* Return a value which indicates that FRAME's saved version of
+   REGNUM has a known constant (computed) value of VAL.  */
+
+struct value *frame_unwind_got_constant (struct frame_info *frame, int regnum,
+                                        ULONGEST val);
+
+/* Return a value which indicates that FRAME's saved version of REGNUM
+   has a known constant (computed) value of ADDR.  Convert the
+   CORE_ADDR to a target address if necessary.  */
+
+struct value *frame_unwind_got_address (struct frame_info *frame, int regnum,
+                                       CORE_ADDR addr);
+
 #endif
index 9434ce79d670f505eb7bf6f109791e1511ecc36d..f59cbebac7721bdf053eaf0add129aa12b87cc59 100644 (file)
@@ -113,7 +113,7 @@ struct frame_info
 
 /* Flag to control debugging.  */
 
-static int frame_debug;
+int frame_debug;
 static void
 show_frame_debug (struct ui_file *file, int from_tty,
                  struct cmd_list_element *c, const char *value)
@@ -255,10 +255,9 @@ get_frame_id (struct frame_info *fi)
                            fi->level);
       /* Find the unwinder.  */
       if (fi->unwind == NULL)
-       fi->unwind = frame_unwind_find_by_frame (fi->next,
-                                                &fi->prologue_cache);
+       fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
       /* Find THIS frame's ID.  */
-      fi->unwind->this_id (fi->next, &fi->prologue_cache, &fi->this_id.value);
+      fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value);
       fi->this_id.p = 1;
       if (frame_debug)
        {
@@ -427,15 +426,7 @@ frame_pc_unwind (struct frame_info *this_frame)
   if (!this_frame->prev_pc.p)
     {
       CORE_ADDR pc;
-      if (this_frame->unwind == NULL)
-       this_frame->unwind
-         = frame_unwind_find_by_frame (this_frame->next,
-                                       &this_frame->prologue_cache);
-      if (this_frame->unwind->prev_pc != NULL)
-       /* A per-frame unwinder, prefer it.  */
-       pc = this_frame->unwind->prev_pc (this_frame->next,
-                                         &this_frame->prologue_cache);
-      else if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
+      if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
        {
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
@@ -495,8 +486,7 @@ get_frame_func (struct frame_info *fi)
 static int
 do_frame_register_read (void *src, int regnum, gdb_byte *buf)
 {
-  frame_register_read (src, regnum, buf);
-  return 1;
+  return frame_register_read (src, regnum, buf);
 }
 
 struct regcache *
@@ -552,15 +542,7 @@ frame_register_unwind (struct frame_info *frame, int regnum,
                       int *optimizedp, enum lval_type *lvalp,
                       CORE_ADDR *addrp, int *realnump, gdb_byte *bufferp)
 {
-  struct frame_unwind_cache *cache;
-
-  if (frame_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "\
-{ frame_register_unwind (frame=%d,regnum=%d(%s),...) ",
-                         frame->level, regnum,
-                         frame_map_regnum_to_name (frame, regnum));
-    }
+  struct value *value;
 
   /* Require all but BUFFERP to be valid.  A NULL BUFFERP indicates
      that the value proper does not need to be fetched.  */
@@ -570,43 +552,23 @@ frame_register_unwind (struct frame_info *frame, int regnum,
   gdb_assert (realnump != NULL);
   /* gdb_assert (bufferp != NULL); */
 
-  /* NOTE: cagney/2002-11-27: A program trying to unwind a NULL frame
-     is broken.  There is always a frame.  If there, for some reason,
-     isn't a frame, there is some pretty busted code as it should have
-     detected the problem before calling here.  */
-  gdb_assert (frame != NULL);
+  value = frame_unwind_register_value (frame, regnum);
 
-  /* Find the unwinder.  */
-  if (frame->unwind == NULL)
-    frame->unwind = frame_unwind_find_by_frame (frame->next,
-                                               &frame->prologue_cache);
+  gdb_assert (value != NULL);
 
-  /* Ask this frame to unwind its register.  See comment in
-     "frame-unwind.h" for why NEXT frame and this unwind cache are
-     passed in.  */
-  frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum,
-                               optimizedp, lvalp, addrp, realnump, bufferp);
+  *optimizedp = value_optimized_out (value);
+  *lvalp = VALUE_LVAL (value);
+  *addrp = VALUE_ADDRESS (value);
+  *realnump = VALUE_REGNUM (value);
 
-  if (frame_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog, "->");
-      fprintf_unfiltered (gdb_stdlog, " *optimizedp=%d", (*optimizedp));
-      fprintf_unfiltered (gdb_stdlog, " *lvalp=%d", (int) (*lvalp));
-      fprintf_unfiltered (gdb_stdlog, " *addrp=0x%s", paddr_nz ((*addrp)));
-      fprintf_unfiltered (gdb_stdlog, " *bufferp=");
-      if (bufferp == NULL)
-       fprintf_unfiltered (gdb_stdlog, "<NULL>");
-      else
-       {
-         int i;
-         const unsigned char *buf = bufferp;
-         fprintf_unfiltered (gdb_stdlog, "[");
-         for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
-           fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
-         fprintf_unfiltered (gdb_stdlog, "]");
-       }
-      fprintf_unfiltered (gdb_stdlog, " }\n");
-    }
+  if (bufferp)
+    memcpy (bufferp, value_contents_all (value),
+           TYPE_LENGTH (value_type (value)));
+
+  /* Dispose of the new value.  This prevents watchpoints from
+     trying to watch the saved frame pointer.  */
+  release_value (value);
+  value_free (value);
 }
 
 void
@@ -647,6 +609,71 @@ get_frame_register (struct frame_info *frame,
   frame_unwind_register (frame->next, regnum, buf);
 }
 
+struct value *
+frame_unwind_register_value (struct frame_info *frame, int regnum)
+{
+  struct value *value;
+
+  gdb_assert (frame != NULL);
+
+  if (frame_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "\
+{ frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
+                         frame->level, regnum,
+                         frame_map_regnum_to_name (frame, regnum));
+    }
+
+  /* Find the unwinder.  */
+  if (frame->unwind == NULL)
+    frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
+
+  /* Ask this frame to unwind its register.  */
+  value = frame->unwind->prev_register (frame, &frame->prologue_cache, regnum);
+
+  if (frame_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "->");
+      if (value_optimized_out (value))
+       fprintf_unfiltered (gdb_stdlog, " optimized out");
+      else
+       {
+         if (VALUE_LVAL (value) == lval_register)
+           fprintf_unfiltered (gdb_stdlog, " register=%d",
+                               VALUE_REGNUM (value));
+         else if (VALUE_LVAL (value) == lval_memory)
+           fprintf_unfiltered (gdb_stdlog, " address=0x%s",
+                               paddr_nz (VALUE_ADDRESS (value)));
+         else
+           fprintf_unfiltered (gdb_stdlog, " computed");
+
+         if (value_lazy (value))
+           fprintf_unfiltered (gdb_stdlog, " lazy");
+         else
+           {
+             int i;
+             const gdb_byte *buf = value_contents (value);
+
+             fprintf_unfiltered (gdb_stdlog, " bytes=");
+             fprintf_unfiltered (gdb_stdlog, "[");
+             for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
+               fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
+             fprintf_unfiltered (gdb_stdlog, "]");
+           }
+       }
+
+      fprintf_unfiltered (gdb_stdlog, " }\n");
+    }
+
+  return value;
+}
+
+struct value *
+get_frame_register_value (struct frame_info *frame, int regnum)
+{
+  return frame_unwind_register_value (frame->next, regnum);
+}
+
 LONGEST
 frame_unwind_register_signed (struct frame_info *frame, int regnum)
 {
@@ -1022,7 +1049,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
 
   /* Select/initialize both the unwind function and the frame's type
      based on the PC.  */
-  fi->unwind = frame_unwind_find_by_frame (fi->next, &fi->prologue_cache);
+  fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
 
   fi->this_id.p = 1;
   deprecated_update_frame_base_hack (fi, addr);
@@ -1569,8 +1596,8 @@ get_frame_base_address (struct frame_info *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);
+    return fi->base->this_base (fi, &fi->prologue_cache);
+  return fi->base->this_base (fi, &fi->base_cache);
 }
 
 CORE_ADDR
@@ -1585,10 +1612,8 @@ get_frame_locals_address (struct frame_info *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);
+    return fi->base->this_locals (fi, &fi->prologue_cache);
+  return fi->base->this_locals (fi, &fi->base_cache);
 }
 
 CORE_ADDR
@@ -1603,10 +1628,8 @@ get_frame_args_address (struct frame_info *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);
+    return fi->base->this_args (fi, &fi->prologue_cache);
+  return fi->base->this_args (fi, &fi->base_cache);
 }
 
 /* Level of the selected frame: 0 for innermost, 1 for its caller, ...
@@ -1627,8 +1650,7 @@ get_frame_type (struct frame_info *frame)
   if (frame->unwind == NULL)
     /* Initialize the frame's unwinder because that's what
        provides the frame's type.  */
-    frame->unwind = frame_unwind_find_by_frame (frame->next, 
-                                               &frame->prologue_cache);
+    frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
   return frame->unwind->type;
 }
 
@@ -1769,6 +1791,50 @@ frame_stop_reason_string (enum unwind_stop_reason reason)
     }
 }
 
+/* Clean up after a failed (wrong unwinder) attempt to unwind past
+   FRAME.  */
+
+static void
+frame_cleanup_after_sniffer (void *arg)
+{
+  struct frame_info *frame = arg;
+
+  /* The sniffer should not allocate a prologue cache if it did not
+     match this frame.  */
+  gdb_assert (frame->prologue_cache == NULL);
+
+  /* No sniffer should extend the frame chain; sniff based on what is
+     already certain.  */
+  gdb_assert (!frame->prev_p);
+
+  /* The sniffer should not check the frame's ID; that's circular.  */
+  gdb_assert (!frame->this_id.p);
+
+  /* Clear cached fields dependent on the unwinder.
+
+     The previous PC is independent of the unwinder, but the previous
+     function is not (see frame_unwind_address_in_block).  */
+  frame->prev_func.p = 0;
+  frame->prev_func.addr = 0;
+
+  /* Discard the unwinder last, so that we can easily find it if an assertion
+     in this function triggers.  */
+  frame->unwind = NULL;
+}
+
+/* Set FRAME's unwinder temporarily, so that we can call a sniffer.
+   Return a cleanup which should be called if unwinding fails, and
+   discarded if it succeeds.  */
+
+struct cleanup *
+frame_prepare_for_sniffer (struct frame_info *frame,
+                          const struct frame_unwind *unwind)
+{
+  gdb_assert (frame->unwind == NULL);
+  frame->unwind = unwind;
+  return make_cleanup (frame_cleanup_after_sniffer, frame);
+}
+
 extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */
 
 static struct cmd_list_element *set_backtrace_cmdlist;
index 6d935965be69c61ff95ef48242887f47de8cd179..c1f9d7eea7be4d9f185ea262acf68e7180789b24 100644 (file)
@@ -144,6 +144,10 @@ struct frame_id
 /* For convenience.  All fields are zero.  */
 extern const struct frame_id null_frame_id;
 
+/* Flag to control debugging.  */
+
+extern int frame_debug;
+
 /* Construct a frame ID.  The first parameter is the frame's constant
    stack address (typically the outer-bound), and the second the
    frame's constant code address (typically the entry point).
@@ -460,13 +464,19 @@ extern void frame_register_unwind (struct frame_info *frame, int regnum,
 /* Fetch a register from this, or unwind a register from the next
    frame.  Note that the get_frame methods are wrappers to
    frame->next->unwind.  They all [potentially] throw an error if the
-   fetch fails.  */
+   fetch fails.  The value methods never return NULL, but usually
+   do return a lazy value.  */
 
 extern void frame_unwind_register (struct frame_info *frame,
                                   int regnum, gdb_byte *buf);
 extern void get_frame_register (struct frame_info *frame,
                                int regnum, gdb_byte *buf);
 
+struct value *frame_unwind_register_value (struct frame_info *frame,
+                                          int regnum);
+struct value *get_frame_register_value (struct frame_info *frame,
+                                       int regnum);
+
 extern LONGEST frame_unwind_register_signed (struct frame_info *frame,
                                             int regnum);
 extern LONGEST get_frame_register_signed (struct frame_info *frame,
@@ -666,6 +676,12 @@ extern void (*deprecated_selected_frame_level_changed_hook) (int);
 
 extern void return_command (char *, int);
 
+/* Set FRAME's unwinder temporarily, so that we can call a sniffer.
+   Return a cleanup which should be called if unwinding fails, and
+   discarded if it succeeds.  */
+
+struct cleanup *frame_prepare_for_sniffer (struct frame_info *frame,
+                                          const struct frame_unwind *unwind);
 
 /* Notes (cagney/2002-11-27, drow/2003-09-06):
 
index f63dcdc60809c7305686710fa5101f0037e28c4f..7984423286830fd6702372101007395bfb589c8d 100644 (file)
@@ -162,7 +162,7 @@ struct gdbarch
   gdbarch_dwarf2_reg_to_regnum_ftype *dwarf2_reg_to_regnum;
   gdbarch_register_name_ftype *register_name;
   gdbarch_register_type_ftype *register_type;
-  gdbarch_unwind_dummy_id_ftype *unwind_dummy_id;
+  gdbarch_dummy_id_ftype *dummy_id;
   int deprecated_fp_regnum;
   gdbarch_push_dummy_call_ftype *push_dummy_call;
   int call_dummy_location;
@@ -284,7 +284,7 @@ struct gdbarch startup_gdbarch =
   no_op_reg_to_regnum,  /* dwarf2_reg_to_regnum */
   0,  /* register_name */
   0,  /* register_type */
-  0,  /* unwind_dummy_id */
+  0,  /* dummy_id */
   -1,  /* deprecated_fp_regnum */
   0,  /* push_dummy_call */
   0,  /* call_dummy_location */
@@ -522,7 +522,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if (gdbarch->register_name == 0)
     fprintf_unfiltered (log, "\n\tregister_name");
   /* Skip verify of register_type, has predicate */
-  /* Skip verify of unwind_dummy_id, has predicate */
+  /* Skip verify of dummy_id, has predicate */
   /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */
   /* Skip verify of push_dummy_call, has predicate */
   /* Skip verify of call_dummy_location, invalid_p == 0 */
@@ -714,6 +714,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: double_format = %s\n",
                       pformat (gdbarch->double_format));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_dummy_id_p() = %d\n",
+                      gdbarch_dummy_id_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: dummy_id = <0x%lx>\n",
+                      (long) gdbarch->dummy_id);
   fprintf_unfiltered (file,
                       "gdbarch_dump: dwarf2_reg_to_regnum = <0x%lx>\n",
                       (long) gdbarch->dwarf2_reg_to_regnum);
@@ -978,12 +984,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: target_desc = %s\n",
                       paddr_d ((long) gdbarch->target_desc));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_unwind_dummy_id_p() = %d\n",
-                      gdbarch_unwind_dummy_id_p (gdbarch));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: unwind_dummy_id = <0x%lx>\n",
-                      (long) gdbarch->unwind_dummy_id);
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
                       gdbarch_unwind_pc_p (gdbarch));
@@ -1646,27 +1646,27 @@ set_gdbarch_register_type (struct gdbarch *gdbarch,
 }
 
 int
-gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch)
+gdbarch_dummy_id_p (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  return gdbarch->unwind_dummy_id != NULL;
+  return gdbarch->dummy_id != NULL;
 }
 
 struct frame_id
-gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info)
+gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
   gdb_assert (gdbarch != NULL);
-  gdb_assert (gdbarch->unwind_dummy_id != NULL);
+  gdb_assert (gdbarch->dummy_id != NULL);
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_dummy_id called\n");
-  return gdbarch->unwind_dummy_id (gdbarch, info);
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_dummy_id called\n");
+  return gdbarch->dummy_id (gdbarch, this_frame);
 }
 
 void
-set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch,
-                             gdbarch_unwind_dummy_id_ftype unwind_dummy_id)
+set_gdbarch_dummy_id (struct gdbarch *gdbarch,
+                      gdbarch_dummy_id_ftype dummy_id)
 {
-  gdbarch->unwind_dummy_id = unwind_dummy_id;
+  gdbarch->dummy_id = dummy_id;
 }
 
 int
index 220c2dda7c0ad04300bb26418b940c160109fa6c..e568993dc8642ee93dd976f8cc89c310ca36b0c3 100644 (file)
@@ -254,13 +254,13 @@ extern void set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch_register
 
 /* See gdbint.texinfo, and PUSH_DUMMY_CALL. */
 
-extern int gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch);
+extern int gdbarch_dummy_id_p (struct gdbarch *gdbarch);
 
-typedef struct frame_id (gdbarch_unwind_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *info);
-extern struct frame_id gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info);
-extern void set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, gdbarch_unwind_dummy_id_ftype *unwind_dummy_id);
+typedef struct frame_id (gdbarch_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame);
+extern struct frame_id gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame);
+extern void set_gdbarch_dummy_id (struct gdbarch *gdbarch, gdbarch_dummy_id_ftype *dummy_id);
 
-/* Implement UNWIND_DUMMY_ID and PUSH_DUMMY_CALL, then delete
+/* Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete
    deprecated_fp_regnum. */
 
 extern int gdbarch_deprecated_fp_regnum (struct gdbarch *gdbarch);
index 91d970e95c70e210acc3675c87495cce4afb3da8..e3efdc80b434e1db63162ca9b82ae7893aabb6da 100755 (executable)
@@ -434,8 +434,8 @@ m:const char *:register_name:int regnr:regnr::0
 M:struct type *:register_type:int reg_nr:reg_nr
 
 # See gdbint.texinfo, and PUSH_DUMMY_CALL.
-M:struct frame_id:unwind_dummy_id:struct frame_info *info:info
-# Implement UNWIND_DUMMY_ID and PUSH_DUMMY_CALL, then delete
+M:struct frame_id:dummy_id:struct frame_info *this_frame:this_frame
+# Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete
 # deprecated_fp_regnum.
 v:int:deprecated_fp_regnum:::-1:-1::0
 
index dd2064c9ba9ad91e639e1613e7cbc80f2f084238..ebde4dc3723f7824ac564d47c2aa587120479cb3 100644 (file)
@@ -2803,7 +2803,6 @@ static const struct frame_unwind ia64_libunwind_frame_unwind =
   ia64_libunwind_frame_prev_register,
   NULL,
   NULL,
-  NULL,
   libunwind_frame_dealloc_cache
 };
 
index ca4785e2e9e597aa32aef8761e8187723aeecc6e..c065b59b42d2355e822f32dda4dabba39b2f96cd 100644 (file)
@@ -462,7 +462,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
         pushed) GDB won't be able to correctly perform back traces.
         If a target is having trouble with backtraces, first thing to
         do is add FRAME_ALIGN() to the architecture vector. If that
-        fails, try unwind_dummy_id().
+        fails, try dummy_id().
 
          If the ABI specifies a "Red Zone" (see the doco) the code
          below will quietly trash it.  */
@@ -656,7 +656,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
      ID so that the breakpoint code can correctly re-identify the
      dummy breakpoint.  */
   /* Sanity.  The exact same SP value is returned by PUSH_DUMMY_CALL,
-     saved as the dummy-frame TOS, and used by unwind_dummy_id to form
+     saved as the dummy-frame TOS, and used by dummy_id to form
      the frame ID's stack address.  */
   dummy_id = frame_id_build (sp, bp_addr);
 
@@ -671,7 +671,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
     sal.section = find_pc_overlay (sal.pc);
     /* Sanity.  The exact same SP value is returned by
        PUSH_DUMMY_CALL, saved as the dummy-frame TOS, and used by
-       unwind_dummy_id to form the frame ID's stack address.  */
+       dummy_id to form the frame ID's stack address.  */
     bpt = set_momentary_breakpoint (sal, dummy_id, bp_call_dummy);
     bpt->disposition = disp_del;
   }
index c70c5516ac862db56f0da7aab780196f8a3b6e3f..223c3c052de9e9812779ff95f728106b9dd97721 100644 (file)
@@ -214,7 +214,6 @@ static const struct frame_unwind libunwind_frame_unwind =
   libunwind_frame_prev_register,
   NULL,
   NULL,
-  NULL,
   libunwind_frame_dealloc_cache
 };
 
index ccf03591423cadf96f221ecaad610865a7cc6f53..4ad3a4b07bddf5fa39255184978e93c99a79805d 100644 (file)
@@ -42,34 +42,31 @@ sentinel_frame_cache (struct regcache *regcache)
 
 /* Here the register value is taken direct from the register cache.  */
 
-static void
-sentinel_frame_prev_register (struct frame_info *next_frame,
+static struct value *
+sentinel_frame_prev_register (struct frame_info *this_frame,
                              void **this_prologue_cache,
-                             int regnum, int *optimized,
-                             enum lval_type *lvalp, CORE_ADDR *addrp,
-                             int *realnum, gdb_byte *bufferp)
+                             int regnum)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct frame_unwind_cache *cache = *this_prologue_cache;
-  /* Describe the register's location.  A reg-frame maps all registers
-     onto the corresponding hardware register.  */
-  *optimized = 0;
-  *lvalp = lval_register;
-  *addrp = 0;
-  *realnum = regnum;
-
-  /* If needed, find and return the value of the register.  */
-  if (bufferp != NULL)
-    {
-      /* Return the actual value.  */
-      /* Use the regcache_cooked_read() method so that it, on the fly,
-         constructs either a raw or pseudo register from the raw
-         register cache.  */
-      regcache_cooked_read (cache->regcache, regnum, bufferp);
-    }
+  struct value *value;
+
+  /* Return the actual value.  */
+  value = allocate_value (register_type (gdbarch, regnum));
+  VALUE_LVAL (value) = lval_register;
+  VALUE_REGNUM (value) = regnum;
+  VALUE_FRAME_ID (value) = get_frame_id (this_frame);
+
+  /* Use the regcache_cooked_read() method so that it, on the fly,
+     constructs either a raw or pseudo register from the raw
+     register cache.  */
+  regcache_cooked_read (cache->regcache, regnum, value_contents_raw (value));
+
+  return value;
 }
 
 static void
-sentinel_frame_this_id (struct frame_info *next_frame,
+sentinel_frame_this_id (struct frame_info *this_frame,
                        void **this_prologue_cache,
                        struct frame_id *this_id)
 {
@@ -79,22 +76,11 @@ sentinel_frame_this_id (struct frame_info *next_frame,
   internal_error (__FILE__, __LINE__, _("sentinel_frame_this_id called"));
 }
 
-static CORE_ADDR
-sentinel_frame_prev_pc (struct frame_info *next_frame,
-                       void **this_prologue_cache)
-{
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  return gdbarch_unwind_pc (gdbarch, next_frame);
-}
-
 const struct frame_unwind sentinel_frame_unwinder =
 {
   SENTINEL_FRAME,
   sentinel_frame_this_id,
-  sentinel_frame_prev_register,
-  NULL, /* unwind_data */
-  NULL, /* sniffer */
-  sentinel_frame_prev_pc,
+  sentinel_frame_prev_register
 };
 
 const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;
index 7f9868cd3919fa2f3e968cba9210bc94ab9fc55f..d601974fba93c70739f3f7e3f27d4080964de590 100644 (file)
@@ -622,24 +622,87 @@ value_fetch_lazy (struct value *val)
     }
   else if (VALUE_LVAL (val) == lval_register)
     {
-      struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (val));
-      int regnum = VALUE_REGNUM (val);
+      struct frame_info *frame;
+      int regnum;
       struct type *type = check_typedef (value_type (val));
+      struct value *new_val = val, *mark = value_mark ();
 
-      gdb_assert (frame != NULL);
+      /* Offsets are not supported here; lazy register values must
+        refer to the entire register.  */
+      gdb_assert (value_offset (val) == 0);
 
-      /* Convertible register routines are used for multi-register
-        values and for interpretation in different types (e.g. float
-        or int from a double register).  Lazy register values should
-        have the register's natural type, so they do not apply.  */
-      gdb_assert (!gdbarch_convert_register_p (get_frame_arch (frame), regnum,
-                                              type));
+      while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
+       {
+         frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
+         regnum = VALUE_REGNUM (new_val);
+
+         gdb_assert (frame != NULL);
+
+         /* Convertible register routines are used for multi-register
+            values and for interpretation in different types
+            (e.g. float or int from a double register).  Lazy
+            register values should have the register's natural type,
+            so they do not apply.  */
+         gdb_assert (!gdbarch_convert_register_p (get_frame_arch (frame),
+                                                  regnum, type));
+
+         new_val = get_frame_register_value (frame, regnum);
+       }
 
-      /* Get the data.  */
-      if (!get_frame_register_bytes (frame, regnum, value_offset (val),
-                                    TYPE_LENGTH (value_type (val)),
-                                    value_contents_raw (val)))
+      /* If it's still lazy (for instance, a saved register on the
+        stack), fetch it.  */
+      if (value_lazy (new_val))
+       value_fetch_lazy (new_val);
+
+      /* If the register was not saved, mark it unavailable.  */
+      if (value_optimized_out (new_val))
        set_value_optimized_out (val, 1);
+      else
+       memcpy (value_contents_raw (val), value_contents (new_val),
+               TYPE_LENGTH (type));
+
+      if (frame_debug)
+       {
+         frame = frame_find_by_id (VALUE_FRAME_ID (val));
+         regnum = VALUE_REGNUM (val);
+
+         fprintf_unfiltered (gdb_stdlog, "\
+{ value_fetch_lazy (frame=%d,regnum=%d(%s),...) ",
+                             frame_relative_level (frame), regnum,
+                             frame_map_regnum_to_name (frame, regnum));
+
+         fprintf_unfiltered (gdb_stdlog, "->");
+         if (value_optimized_out (new_val))
+           fprintf_unfiltered (gdb_stdlog, " optimized out");
+         else
+           {
+             int i;
+             const gdb_byte *buf = value_contents (new_val);
+
+             if (VALUE_LVAL (new_val) == lval_register)
+               fprintf_unfiltered (gdb_stdlog, " register=%d",
+                                   VALUE_REGNUM (new_val));
+             else if (VALUE_LVAL (new_val) == lval_memory)
+               fprintf_unfiltered (gdb_stdlog, " address=0x%s",
+                                   paddr_nz (VALUE_ADDRESS (new_val)));
+             else
+               fprintf_unfiltered (gdb_stdlog, " computed");
+
+             fprintf_unfiltered (gdb_stdlog, " bytes=");
+             fprintf_unfiltered (gdb_stdlog, "[");
+             for (i = 0;
+                  i < register_size (get_frame_arch (frame), regnum);
+                  i++)
+               fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
+             fprintf_unfiltered (gdb_stdlog, "]");
+           }
+
+         fprintf_unfiltered (gdb_stdlog, " }\n");
+       }
+
+      /* Dispose of the intermediate values.  This prevents
+        watchpoints from trying to watch the saved frame pointer.  */
+      value_free_to_mark (mark);
     }
   else
     internal_error (__FILE__, __LINE__, "Unexpected lazy value type.");