Yet another IA64 unwinder patch

Boehm, Hans hans_boehm@hp.com
Fri Mar 22 18:36:00 GMT 2002


OK for the trunk and branch?

The unwinder was not correctly unwinding through signal frames.  If the
signal occurrs in a leaf procedure, it's important to restore b0, since
otherwise we can't unwind any further.  The rule for using b0 to as the
return pointer was too restrictive.  Bsp was not getting adjusted correctly
when going back from a leaf procedure to its caller.

This may err on the side of restoring some registers when unwinding through
a signal frame that aren't actually needed.  That seemed safer than the
other kind of error.  But I'll be happy to take things out if someone is
sure they're unnecessary.

This fixes the last exception failure in the libjava tests, namely
PR218.java.

Again, this is presumed to be temporary until we replace this with the
generic unwinder.

Hans


	* config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR):
	Restore more of the signal context.	Set no_reg_stack_frame.
	* config/ia64/unwind-ia64.c (unw_state_record):
	Add no_reg_stack_frame, comments.
	(uw_frame_state_for): Use b0 to unwind through leaf.
	(uw_update_context): Adjust bsp when unwinding from leaf,
	but not signal frame.
	
Index: gcc/config/ia64/linux.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/linux.h,v
retrieving revision 1.15
diff -u -r1.15 linux.h
--- linux.h	2002/01/21 02:24:02	1.15
+++ linux.h	2002/03/23 01:42:46
@@ -98,10 +98,16 @@
       (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs);				\
       (CONTEXT)->lc_loc = &(sc_->sc_ar_lc);				\
       (CONTEXT)->unat_loc = &(sc_->sc_ar_unat);
\
+      (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]);				\
+      (CONTEXT)->bsp = sc_->sc_ar_bsp;					\
       (CONTEXT)->pr = sc_->sc_pr;					\
       (CONTEXT)->psp = sc_->sc_gr[12];					\
+      (CONTEXT)->gp = sc_->sc_gr[1];					\
+      /* Signal frame doesn't have an associated reg. stack frame */	\
+      /* other than what we adjust for below.			  */	\
+      (FS) -> no_reg_stack_frame = 1;					\
 									\
-      /* Don't touch the branch registers.  The kernel doesn't		\
+      /* Don't touch the branch registers o.t. b0.  The kernel doesn't	\
 	 pass the preserved branch registers in the sigcontext but	\
 	 leaves them intact, so there's no need to do anything		\
 	 with them here.  */						\
Index: gcc/config/ia64/unwind-ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/unwind-ia64.c,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 unwind-ia64.c
--- unwind-ia64.c	2002/03/15 01:50:54	1.5.2.1
+++ unwind-ia64.c	2002/03/23 01:42:46
@@ -138,7 +138,7 @@
   unsigned int done : 1;		/* are we done scanning descriptors?
*/
   unsigned int any_spills : 1;		/* got any register spills? */
   unsigned int in_body : 1;	/* are we inside a body? */
-
+  unsigned int no_reg_stack_frame : 1;	/* Don't adjust bsp for i&l regs */
   unsigned char *imask;		/* imask of of spill_mask record or
NULL */
   unsigned long pr_val;		/* predicate values */
   unsigned long pr_mask;	/* predicate mask */
@@ -193,8 +193,11 @@
 
   /* Preserved state.  */
   unsigned long *bsp_loc;	/* previous bsp save location */
+  				/* Appears to be write-only?	*/
   unsigned long *bspstore_loc;
-  unsigned long *pfs_loc;
+  unsigned long *pfs_loc;	/* Save location for pfs in current	*/
+  				/* (corr. to sp) frame.  Target 	*/
+  				/* contains cfm for caller.		*/
   unsigned long *pri_unat_loc;
   unsigned long *unat_loc;
   unsigned long *lc_loc;
@@ -1582,7 +1585,8 @@
     }
 
   /* If RP did't get saved, generate entry for the return link register.
*/
-  if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
+  if (fs->curr.reg[UNW_REG_RP].where == UNW_WHERE_NONE
+      || fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
     {
       fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
       fs->curr.reg[UNW_REG_RP].when = -1;
@@ -1769,7 +1773,10 @@
 
   /* Unwind BSP for the local registers allocated this frame.  */
   /* ??? What to do with stored BSP or BSPSTORE registers.  */
-  if (fs->when_target > fs->curr.reg[UNW_REG_PFS].when)
+  /* We assert that we are either at a call site, or we have	*/
+  /* just unwound through a signal frame.  In either case	*/
+  /* pfs_loc is valid.						*/
+  if (!(fs -> no_reg_stack_frame))
     {
       unsigned long pfs = *context->pfs_loc;
       unsigned long sol = (pfs >> 7) & 0x7f;



More information about the Gcc-patches mailing list