This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch/rfa] Fix some corner cases in hppa stack unwinding


This fixes a few more corner cases that were not handled properly 
in the hppa frame unwinder.

Fixes the (regression) FAILs in gdb.base/recurse.exp that Michael
observed against gdb-6.1.

ok to apply?

randolph

p.s. it's probably possible to come up with a tricky test case where the
unwinder will still break:

frame 0: sets/saves frame pointer, start unwinding after fp is set but
         before it is saved
frame 1 .. n-1: does not set/save frame pointer
frame n: requires frame pointer to unwind properly (e.g. calls alloca())
frame n+1 ... 

in this case frame n will not unwind properly because we cannot retrieve
the correct fp from the stack (the one that has not yet been saved).

any suggestions about how to fix this? i'll try to come up with a new
test case for this. this is not a very likely scenario normally, but
with software watchpoints and a recursive function that calls alloca(),
it's probably possible to trigger it. I'm not sure what we can do 
about it though.

2004-06-06  Randolph Chung  <tausq@debian.org>

	* hppa-tdep.c (hppa_frame_cache): Handle the cases when we start
	unwinding after sp has been saved to the stack but before the end
	of the prologue, and after the fp has been modified but before it has
	been saved to the stack.
	(hppa_frame_base_address, hppa_frame_base, hppa_frame_base_sniffer): 
	Remove superfluous definitions.
	(hppa_gdbarch_init): Remove superfluous frame base sniffer.

Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.166
diff -u -p -r1.166 hppa-tdep.c
--- hppa-tdep.c	30 May 2004 14:11:00 -0000	1.166
+++ hppa-tdep.c	6 Jun 2004 20:26:02 -0000
@@ -1744,7 +1789,8 @@ hppa_frame_cache (struct frame_info *nex
         and saved on the stack, the Save_SP flag is set.  We use this to
         decide whether to use the frame pointer for unwinding.
 	
-	fp should never be zero here; checking just in case. 
+	fp may be zero if it is not available in an inner frame because
+	it has been modified by not yet saved.
 	
         TODO: For the HP compiler, maybe we should use the alloca_frame flag 
 	instead of Save_SP.  */
@@ -1760,10 +1806,9 @@ hppa_frame_cache (struct frame_info *nex
 	  fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }",
  	    paddr_nz (cache->base));
       }
-     else if (frame_pc_unwind (next_frame) >= prologue_end)
+     else if (u->Save_SP 
+	      && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
       {
-        if (u->Save_SP && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
-          {
             /* Both we're expecting the SP to be saved and the SP has been
 	       saved.  The entry SP value is saved at this frame's SP
 	       address.  */
@@ -1772,29 +1817,17 @@ hppa_frame_cache (struct frame_info *nex
 	    if (hppa_debug)
 	      fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }",
 			          paddr_nz (cache->base));
-          }
-        else
-          {
-            /* The prologue has been slowly allocating stack space.  Adjust
-	     the SP back.  */
-            cache->base = this_sp - frame_size;
-	    if (hppa_debug)
-	      fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
-			          paddr_nz (cache->base));
-
-          }
       }
     else
       {
-	/* This frame has not yet been created. */
-        cache->base = this_sp;
-
+        /* The prologue has been slowly allocating stack space.  Adjust
+	   the SP back.  */
+        cache->base = this_sp - frame_size;
 	if (hppa_debug)
-	  fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [before prologue] } ",
+	  fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
 			      paddr_nz (cache->base));
 
       }
-
     trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
   }
 
@@ -1821,6 +1854,14 @@ hppa_frame_cache (struct frame_info *nex
 	}
     }
 
+  /* If the frame pointer was not saved in this frame, but we should be saving
+     it, set it to an invalid value so that another frame will not pick up the 
+     wrong frame pointer.  This can happen if we start unwinding after the 
+     frame pointer has been modified, but before we've saved it to the
+     stack.  */
+  if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM))
+    trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, 0);
+
   {
     /* Convert all the offsets into addresses.  */
     int reg;
@@ -1978,28 +2020,6 @@ hppa_fallback_unwind_sniffer (struct fra
   return &hppa_fallback_frame_unwind;
 }
 
-static CORE_ADDR
-hppa_frame_base_address (struct frame_info *next_frame,
-				void **this_cache)
-{
-  struct hppa_frame_cache *info = hppa_frame_cache (next_frame,
-							   this_cache);
-  return info->base;
-}
-
-static const struct frame_base hppa_frame_base = {
-  &hppa_frame_unwind,
-  hppa_frame_base_address,
-  hppa_frame_base_address,
-  hppa_frame_base_address
-};
-
-static const struct frame_base *
-hppa_frame_base_sniffer (struct frame_info *next_frame)
-{
-  return &hppa_frame_base;
-}
-
 /* Stub frames, used for all kinds of call stubs.  */
 struct hppa_stub_unwind_cache
 {
@@ -2505,7 +2535,6 @@ hppa_gdbarch_init (struct gdbarch_info i
   frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
   frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer);
-  frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
 
   return gdbarch;
 }

-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]