[patch RFC] Re: Notes on a frame_unwind_address_in_block problem

Daniel Jacobowitz drow@false.org
Wed Jan 3 16:13:00 GMT 2007


On Wed, Jan 03, 2007 at 12:37:00PM +0100, Mark Kettenis wrote:
> The basic principle of unwinding is that you get information about
> THIS_FRAME from NEXT_FRAME; you always walk the frame chain in one
> direction.  This means that the only requirement for calling
> frame_unwind_xxx functions is that you have a NEXT_FRAME.  Your change
> introduces a function that breaks this rule, by requiring THIS_FRAME
> to be there, walking the frame chain in the other direction.  And it
> didn't take you very long to hit the problem with that: infinite
> recursion.
> 
> Now the problem we're facing is that frame_unwind_address_in_block()
> (frame_func_unwind() is nothing but a fancy wrapper around that call)
> cannot be implemented reliably without knowledge about THIS_FRAME; it
> needs to know whether THIS_FRAME could be a fake frame set up by the
> kernel in order to determine whether it is a good idea to adjust the
> unwound PC or not.  In our current implementation that information is
> carried by the frame type.
> 
> The solution I think, is to pass this information explicitly to
> frame_unwind_address_in_block(), i.e. we change it's prototype from:

I've hit one hiccup with this... dwarf2_frame_this_id isn't calling
frame_unwind_address_in_block, just frame_func_unwind.  So, if
we want frame_func_unwind to do the right thing, that's the
call site which needs to know the right frame type.

The calls to frame_unwind_address_in_block in dwarf2-frame.c don't
matter; they're just trying to find the right FDE.  In fact, when I was
finished, the only calls to frame_unwind_address_in_block anywhere in
GDB which didn't hardcode NORMAL_FRAME were the ones in
get_frame_address_in_block and frame_func_unwind (as I'd expect;
the others are from unwinding except for one oddball).

I made frame_func_unwind look at THIS_FRAME, if one can be found.
That's OK in practice, given where all the calls to frame_func_unwind
are (all after the frame unwinder has been chosen), but it has the same
theoretical problem.

-      CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi);
+      struct frame_info *prev_frame = get_prev_frame_1 (fi);
+      enum frame_type prev_type = NORMAL_FRAME;
+      CORE_ADDR addr_in_block;
+
+      if (prev_frame != NULL)
+	prev_type = get_frame_type (prev_frame);
+      addr_in_block = frame_unwind_address_in_block (fi, prev_type);
+

Options that I see:
  - Add the argument to frame_func_unwind.  Big, messy, hard to test,
    but mostly mechanical.  I don't much like it, because it pushes
    this special case out to all the callers of that interface.
  - Use the version in this patch.
  - Add an assertion to frame_func_unwind that next_frame->prev and
    next_frame->prev->unwind are already set.  That's a bit of a
    compromise.  They always will be; every call to frame_func_unwind
    is during unwinding.  Unlike frame_unwind_address_in_block it
    is never called from a sniffer.
  - Define both frame_func_unwind and frame_unwind_address_in_block to
    assume that THIS_FRAME will be a normal frame and have them assume
    that.  Just a rearrangement of deck chairs from the other
    suggestions really.

What do you think?

-- 
Daniel Jacobowitz
CodeSourcery

Index: alpha-mdebug-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-mdebug-tdep.c,v
retrieving revision 1.11
diff -u -p -r1.11 alpha-mdebug-tdep.c
--- alpha-mdebug-tdep.c	17 Dec 2005 22:33:59 -0000	1.11
+++ alpha-mdebug-tdep.c	3 Jan 2007 15:53:13 -0000
@@ -307,7 +307,7 @@ static const struct frame_unwind alpha_m
 const struct frame_unwind *
 alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   struct mdebug_extra_func_info *proc_desc;
 
   /* If this PC does not map to a PDR, then clearly this isn't an
@@ -364,7 +364,7 @@ static const struct frame_base alpha_mde
 static const struct frame_base *
 alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   struct mdebug_extra_func_info *proc_desc;
 
   /* If this PC does not map to a PDR, then clearly this isn't an
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.217
diff -u -p -r1.217 arm-tdep.c
--- arm-tdep.c	22 Nov 2006 18:51:58 -0000	1.217
+++ arm-tdep.c	3 Jan 2007 15:53:14 -0000
@@ -991,9 +991,11 @@ struct frame_unwind arm_stub_unwind = {
 static const struct frame_unwind *
 arm_stub_unwind_sniffer (struct frame_info *next_frame)
 {
+  CORE_ADDR addr_in_block;
   char dummy[4];
 
-  if (in_plt_section (frame_unwind_address_in_block (next_frame), NULL)
+  addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+  if (in_plt_section (addr_in_block, NULL)
       || target_read_memory (frame_pc_unwind (next_frame), dummy, 4) != 0)
     return &arm_stub_unwind;
 
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.64
diff -u -p -r1.64 dwarf2-frame.c
--- dwarf2-frame.c	28 Nov 2006 17:28:29 -0000	1.64
+++ dwarf2-frame.c	3 Jan 2007 15:53:15 -0000
@@ -770,7 +770,7 @@ dwarf2_frame_cache (struct frame_info *n
      frame_unwind_address_in_block does just this.  It's not clear how
      reliable the method is though; there is the potential for the
      register state pre-call being different to that on return.  */
-  fs->pc = frame_unwind_address_in_block (next_frame);
+  fs->pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
 
   /* Find the correct FDE.  */
   fde = dwarf2_frame_find_fde (&fs->pc);
@@ -1104,8 +1104,12 @@ dwarf2_frame_sniffer (struct frame_info 
 {
   /* Grab an address that is guarenteed to reside somewhere within the
      function.  frame_pc_unwind(), for a no-return next function, can
-     end up returning something past the end of this function's body.  */
-  CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
+     end up returning something past the end of this function's body.
+     If the frame we're sniffing for is a signal frame whose start
+     address is placed on the stack by the OS, its FDE must
+     extend one byte before its start address or we will miss it.  */
+  CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame,
+							NORMAL_FRAME);
   struct dwarf2_fde *fde = dwarf2_frame_find_fde (&block_addr);
   if (!fde)
     return NULL;
@@ -1149,8 +1153,9 @@ static const struct frame_base dwarf2_fr
 const struct frame_base *
 dwarf2_frame_base_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  if (dwarf2_frame_find_fde (&pc))
+  CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame,
+							NORMAL_FRAME);
+  if (dwarf2_frame_find_fde (&block_addr))
     return &dwarf2_frame_base;
 
   return NULL;
Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.17
diff -u -p -r1.17 frame-unwind.c
--- frame-unwind.c	17 Dec 2005 22:33:59 -0000	1.17
+++ frame-unwind.c	3 Jan 2007 15:53:15 -0000
@@ -28,6 +28,8 @@
 
 static struct gdbarch_data *frame_unwind_data;
 
+static int searching_for_unwind;
+
 struct frame_unwind_table_entry
 {
   frame_unwind_sniffer_ftype *sniffer;
@@ -83,6 +85,12 @@ frame_unwind_prepend_unwinder (struct gd
   (*table->osabi_head) = entry;
 }
 
+static void
+clear_searching_flag (void *arg)
+{
+  searching_for_unwind = 0;
+}
+
 const struct frame_unwind *
 frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache)
 {
@@ -90,6 +98,15 @@ frame_unwind_find_by_frame (struct frame
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
   struct frame_unwind_table_entry *entry;
+  struct cleanup *back_to;
+
+  /* Check if we were re-entered, and assert instead of running out
+     of stack.  This happens if the sniffer calls anything which
+     requires NEXT_FRAME's unwinder, for instance frame_func_unwind.  */
+  gdb_assert (!searching_for_unwind);
+  searching_for_unwind = 1;
+  back_to = make_cleanup (clear_searching_flag, NULL);
+
   for (entry = table->list; entry != NULL; entry = entry->next)
     {
       if (entry->sniffer != NULL)
@@ -97,15 +114,22 @@ frame_unwind_find_by_frame (struct frame
 	  const struct frame_unwind *desc = NULL;
 	  desc = entry->sniffer (next_frame);
 	  if (desc != NULL)
-	    return desc;
+	    {
+	      do_cleanups (back_to);
+	      return desc;
+	    }
 	}
       if (entry->unwinder != NULL)
 	{
 	  if (entry->unwinder->sniffer (entry->unwinder, next_frame,
 					this_cache))
-	    return entry->unwinder;
+	    {
+	      do_cleanups (back_to);
+	      return entry->unwinder;
+	    }
 	}
     }
+  do_cleanups (back_to);
   internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed"));
 }
 
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.215
diff -u -p -r1.215 frame.c
--- frame.c	10 Nov 2006 20:11:35 -0000	1.215
+++ frame.c	3 Jan 2007 15:53:15 -0000
@@ -477,7 +477,14 @@ frame_func_unwind (struct frame_info *fi
     {
       /* Make certain that this, and not the adjacent, function is
          found.  */
-      CORE_ADDR addr_in_block = frame_unwind_address_in_block (fi);
+      struct frame_info *prev_frame = get_prev_frame_1 (fi);
+      enum frame_type prev_type = NORMAL_FRAME;
+      CORE_ADDR addr_in_block;
+
+      if (prev_frame != NULL)
+	prev_type = get_frame_type (prev_frame);
+      addr_in_block = frame_unwind_address_in_block (fi, prev_type);
+
       fi->prev_func.p = 1;
       fi->prev_func.addr = get_pc_function_start (addr_in_block);
       if (frame_debug)
@@ -1412,20 +1419,31 @@ get_frame_pc (struct frame_info *frame)
   return frame_pc_unwind (frame->next);
 }
 
-/* Return an address of that falls within the frame's code block.  */
+/* Return an address that falls within NEXT_FRAME's caller's code
+   block, assuming that the caller is a THIS_TYPE frame.  */
 
 CORE_ADDR
-frame_unwind_address_in_block (struct frame_info *next_frame)
+frame_unwind_address_in_block (struct frame_info *next_frame,
+			       enum frame_type this_type)
 {
   /* A draft address.  */
   CORE_ADDR pc = frame_pc_unwind (next_frame);
 
+  /* If NEXT_FRAME was called by a signal frame or dummy frame, then
+     we shold not adjust the unwound PC.  These frames may not call
+     their next frame in the normal way; the operating system or GDB
+     may have pushed their resume address manually onto the stack, so
+     it may be the very first instruction.  Even if the resume address
+     was not manually pushed, they expect to be returned to.  */
+  if (this_type != NORMAL_FRAME)
+    return pc;
+
   /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel),
      and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS
      frame's PC ends up pointing at the instruction fallowing the
      "call".  Adjust that PC value so that it falls on the call
      instruction (which, hopefully, falls within THIS frame's code
-     block.  So far it's proved to be a very good approximation.  See
+     block).  So far it's proved to be a very good approximation.  See
      get_frame_type() for why ->type can't be used.  */
   if (next_frame->level >= 0
       && get_frame_type (next_frame) == NORMAL_FRAME)
@@ -1436,7 +1454,8 @@ frame_unwind_address_in_block (struct fr
 CORE_ADDR
 get_frame_address_in_block (struct frame_info *this_frame)
 {
-  return frame_unwind_address_in_block (this_frame->next);
+  return frame_unwind_address_in_block (this_frame->next,
+					get_frame_type (this_frame));
 }
 
 static int
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.150
diff -u -p -r1.150 frame.h
--- frame.h	10 Nov 2006 20:11:35 -0000	1.150
+++ frame.h	3 Jan 2007 15:53:15 -0000
@@ -183,6 +183,25 @@ extern int frame_id_inner (struct frame_
 extern void fprint_frame_id (struct ui_file *file, struct frame_id id);
 
 
+/* Frame types.  Some are real, some are signal trampolines, and some
+   are completely artificial (dummy).  */
+
+enum frame_type
+{
+  /* A true stack frame, created by the target program during normal
+     execution.  */
+  NORMAL_FRAME,
+  /* A fake frame, created by GDB when performing an inferior function
+     call.  */
+  DUMMY_FRAME,
+  /* In a signal handler, various OSs handle this in various ways.
+     The main thing is that the frame may be far from normal.  */
+  SIGTRAMP_FRAME,
+  /* Sentinel or registers frame.  This frame obtains register values
+     direct from the inferior's registers.  */
+  SENTINEL_FRAME
+};
+
 /* For every stopped thread, GDB tracks two frames: current and
    selected.  Current frame is the inner most frame of the selected
    thread.  Selected frame is the one being examined by the the GDB
@@ -264,7 +283,13 @@ extern CORE_ADDR get_frame_pc (struct fr
    the frame's block.  */
 
 extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame);
-extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame);
+
+/* Similar to get_frame_address_in_block, find an address in the
+   block which logically called NEXT_FRAME, assuming it was a THIS_TYPE
+   frame.  */
+
+extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame,
+						enum frame_type this_type);
 
 /* The frame's inner-most bound.  AKA the stack-pointer.  Confusingly
    known as top-of-stack.  */
@@ -374,24 +399,8 @@ extern CORE_ADDR get_frame_args_address 
    for an invalid frame).  */
 extern int frame_relative_level (struct frame_info *fi);
 
-/* Return the frame's type.  Some are real, some are signal
-   trampolines, and some are completely artificial (dummy).  */
+/* Return the frame's type.  */
 
-enum frame_type
-{
-  /* A true stack frame, created by the target program during normal
-     execution.  */
-  NORMAL_FRAME,
-  /* A fake frame, created by GDB when performing an inferior function
-     call.  */
-  DUMMY_FRAME,
-  /* In a signal handler, various OSs handle this in various ways.
-     The main thing is that the frame may be far from normal.  */
-  SIGTRAMP_FRAME,
-  /* Sentinel or registers frame.  This frame obtains register values
-     direct from the inferior's registers.  */
-  SENTINEL_FRAME
-};
 extern enum frame_type get_frame_type (struct frame_info *);
 
 /* For frames where we can not unwind further, describe why.  */
Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.223
diff -u -p -r1.223 hppa-tdep.c
--- hppa-tdep.c	8 Aug 2006 21:32:48 -0000	1.223
+++ hppa-tdep.c	3 Jan 2007 15:53:16 -0000
@@ -1786,9 +1786,14 @@ hppa_skip_prologue (CORE_ADDR pc)
 static struct unwind_table_entry *
 hppa_find_unwind_entry_in_block (struct frame_info *f)
 {
-  CORE_ADDR pc;
+  CORE_ADDR pc = frame_unwind_address_in_block (f, NORMAL_FRAME);
 
-  pc = frame_unwind_address_in_block (f);
+  /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the
+     result of frame_unwind_address_in_block implies a problem.
+     The bits should have been removed earlier, before the return
+     value of frame_pc_unwind.  That might be happening already;
+     if it isn't, it should be fixed.  Then this call can be
+     removed.  */
   pc = gdbarch_addr_bits_remove (get_frame_arch (f), pc);
   return find_unwind_entry (pc);
 }
@@ -2440,7 +2445,7 @@ static const struct frame_unwind hppa_st
 static const struct frame_unwind *
 hppa_stub_unwind_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   struct gdbarch *gdbarch = get_frame_arch (next_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
Index: m88k-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m88k-tdep.c,v
retrieving revision 1.19
diff -u -p -r1.19 m88k-tdep.c
--- m88k-tdep.c	17 Dec 2005 22:34:01 -0000	1.19
+++ m88k-tdep.c	3 Jan 2007 15:53:16 -0000
@@ -661,10 +661,7 @@ m88k_frame_cache (struct frame_info *nex
 
   cache->pc = frame_func_unwind (next_frame);
   if (cache->pc != 0)
-    {
-      CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame);
-      m88k_analyze_prologue (cache->pc, addr_in_block, cache);
-    }
+    m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
 
   /* Calculate the stack pointer used in the prologue.  */
   if (cache->fp_offset != -1)
Index: mips-mdebug-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-mdebug-tdep.c,v
retrieving revision 1.7
diff -u -p -r1.7 mips-mdebug-tdep.c
--- mips-mdebug-tdep.c	25 Apr 2006 18:58:09 -0000	1.7
+++ mips-mdebug-tdep.c	3 Jan 2007 15:53:16 -0000
@@ -412,7 +412,7 @@ static const struct frame_unwind mips_md
 static const struct frame_unwind *
 mips_mdebug_frame_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   CORE_ADDR startaddr = 0;
   struct mdebug_extra_func_info *proc_desc;
   int kernel_trap;
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.399
diff -u -p -r1.399 mips-tdep.c
--- mips-tdep.c	28 Nov 2006 22:14:31 -0000	1.399
+++ mips-tdep.c	3 Jan 2007 15:53:16 -0000
@@ -1698,7 +1698,7 @@ static const struct frame_unwind mips_in
 static const struct frame_unwind *
 mips_insn16_frame_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   if (mips_pc_is_mips16 (pc))
     return &mips_insn16_frame_unwind;
   return NULL;
@@ -2018,7 +2018,7 @@ static const struct frame_unwind mips_in
 static const struct frame_unwind *
 mips_insn32_frame_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   if (! mips_pc_is_mips16 (pc))
     return &mips_insn32_frame_unwind;
   return NULL;
@@ -2113,7 +2113,7 @@ static const struct frame_unwind *
 mips_stub_frame_sniffer (struct frame_info *next_frame)
 {
   struct obj_section *s;
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
 
   if (in_plt_section (pc, NULL))
     return &mips_stub_frame_unwind;
Index: s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.156
diff -u -p -r1.156 s390-tdep.c
--- s390-tdep.c	28 Nov 2006 21:41:02 -0000	1.156
+++ s390-tdep.c	3 Jan 2007 15:53:16 -0000
@@ -1575,14 +1575,15 @@ static const struct frame_unwind s390_st
 static const struct frame_unwind *
 s390_stub_frame_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR addr_in_block;
   bfd_byte insn[S390_MAX_INSTR_SIZE];
 
   /* If the current PC points to non-readable memory, we assume we
      have trapped due to an invalid function pointer call.  We handle
      the non-existing current function like a PLT stub.  */
-  if (in_plt_section (pc, NULL)
-      || s390_readinstruction (insn, pc) < 0)
+  addr_in_block = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+  if (in_plt_section (addr_in_block, NULL)
+      || s390_readinstruction (insn, frame_pc_unwind (next_frame)) < 0)
     return &s390_stub_frame_unwind;
   return NULL;
 }
Index: sparc-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-tdep.c,v
retrieving revision 1.175
diff -u -p -r1.175 sparc-tdep.c
--- sparc-tdep.c	29 Dec 2006 21:00:47 -0000	1.175
+++ sparc-tdep.c	3 Jan 2007 15:53:17 -0000
@@ -701,10 +701,7 @@ sparc_frame_cache (struct frame_info *ne
 
   cache->pc = frame_func_unwind (next_frame);
   if (cache->pc != 0)
-    {
-      CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame);
-      sparc_analyze_prologue (cache->pc, addr_in_block, cache);
-    }
+    sparc_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
 
   if (cache->frameless_p)
     {
@@ -1054,7 +1051,7 @@ sparc32_stabs_argument_has_addr (struct 
 static int
 sparc32_dwarf2_struct_return_p (struct frame_info *next_frame)
 {
-  CORE_ADDR pc = frame_unwind_address_in_block (next_frame);
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
   struct symbol *sym = find_pc_function (pc);
 
   if (sym)
Index: sparc64obsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64obsd-tdep.c,v
retrieving revision 1.20
diff -u -p -r1.20 sparc64obsd-tdep.c
--- sparc64obsd-tdep.c	31 Dec 2006 01:28:07 -0000	1.20
+++ sparc64obsd-tdep.c	3 Jan 2007 15:53:17 -0000
@@ -205,7 +205,7 @@ sparc64obsd_sigtramp_frame_sniffer (stru
 /* Kernel debugging support.  */
 
 static struct sparc_frame_cache *
-sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
+sparc64obsd_trapframe_cache (struct frame_info *next_frame, void **this_cache)
 {
   struct sparc_frame_cache *cache;
   CORE_ADDR sp, trapframe_addr;
@@ -267,15 +267,17 @@ static const struct frame_unwind sparc64
 static const struct frame_unwind *
 sparc64obsd_trapframe_sniffer (struct frame_info *next_frame)
 {
+  CORE_ADDR pc;
   ULONGEST pstate;
   char *name;
 
   /* Check whether we are in privileged mode, and bail out if we're not.  */
-  pstate = frame_unwind_register_unsigned(next_frame, SPARC64_PSTATE_REGNUM);
+  pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM);
   if ((pstate & SPARC64_PSTATE_PRIV) == 0)
     return NULL;
 
-  find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
+  pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
+  find_pc_partial_function (pc, &name, NULL, NULL);
   if (name && strcmp (name, "Lslowtrap_reenter") == 0)
     return &sparc64obsd_trapframe_unwind;
 



More information about the Gdb-patches mailing list