This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: Support Solaris 11/SPARC in MD_FALLBACK_FRAME_STATE_FOR (PR ada/41929)


> All EH-related tests fail with a recent upgrade on Solaris 10. Interestingly,
> the old implementation keeps working with the upgrade.

I've applied the attached patch to mainline and 4.6 branch.  It reverts back to 
the old pattern matching code in the Solaris 8+ multi-threaded case, which is 
clearly more robust.  The rest is left unchanged.  Tested on 5 different OS 
versions (Solaris 8, Solaris 8 Containers, Solaris 9, old Solaris 10, recent 
Solaris 10).


2012-01-09  Eric Botcazou  <ebotcazou@adacore.com>

	PR ada/41929
	* config/sparc/sol2-unwind.h (sparc64_is_sighandler): Remove SAVPC and
	add CFA.  Revert back to old code for Solaris 8+ multi-threaded.
	(sparc_is_sighandler): Likewise.
	(MD_FALLBACK_FRAME_STATE_FOR): Adjust call to IS_SIGHANDLER.


-- 
Eric Botcazou
Index: config/sparc/sol2-unwind.h
===================================================================
--- config/sparc/sol2-unwind.h	(revision 183001)
+++ config/sparc/sol2-unwind.h	(working copy)
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for SPARC Solaris.
-   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -34,7 +34,7 @@ see the files COPYING3 and COPYING.RUNTI
 #define IS_SIGHANDLER sparc64_is_sighandler
 
 static int
-sparc64_is_sighandler (unsigned int *pc, unsigned int *savpc, int *nframes)
+sparc64_is_sighandler (unsigned int *pc, void *cfa, int *nframes)
 {
   if (/* Solaris 8 - single-threaded
 	----------------------------
@@ -110,38 +110,59 @@ sparc64_is_sighandler (unsigned int *pc,
       && pc[ 0] == 0x81c7e008
       && pc[ 1] == 0x81e80000)
     {
-      if (/* Solaris 8 /usr/lib/sparcv9/libthread.so.1
-	    ------------------------------------------
-	    Before patch 108827-08:
-	    <sigacthandler+1760>:     st  %g4, [ %i1 + 0x1c ]
-
-	    Since patch 108827-08:
-	    <sigacthandler+1816>:     st  %l0, [ %i4 + 0x10 ]  */
-	        savpc[-1] == 0xc826601c
-	     || savpc[-1] == 0xe0272010)
+      /* We have observed different calling frames among different
+	 versions of the operating system, so that we need to
+	 discriminate using the upper frame.  We look for the return
+	 address of the caller frame (there is an offset of 15 double
+	 words between the frame address and the place where this return
+	 address is stored) in order to do some more pattern matching.  */
+      unsigned int cuh_pattern
+	= *(unsigned int *)(*(unsigned long *)(cfa + 15*8) - 4);
+
+      if (cuh_pattern == 0xd25fa7ef)
 	{
-	  /* We need to move up three frames:
+	  /* This matches the call_user_handler pattern for Solaris 10.
+	     There are 2 cases so we look for the return address of the
+	     caller's caller frame in order to do more pattern matching.  */
+	  unsigned int sah_pattern
+	    = *(unsigned int *)(*(unsigned long *)(cfa + 176 + 15*8) - 4);
+
+          if (sah_pattern == 0x92100019)
+	    /* This is the same setup as for Solaris 9, see below.  */
+	    *nframes = 3;
+	  else
+	    /* The sigacthandler frame isn't present in the chain.
+	       We need to move up two frames:
 
 		<signal handler>	<-- context->cfa
 		__sighndlr
-		sigacthandler
+		call_user_handler frame
 		<kernel>
-	  */
-	  *nframes = 2;
+	    */
+	    *nframes = 2;
 	}
-      else /* Solaris 8 /usr/lib/lwp/sparcv9/libthread.so.1, Solaris 9+
-	     ----------------------------------------------------------  */
-	{
-	  /* We need to move up three frames:
+      else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x94100013)
+	/* This matches the call_user_handler pattern for Solaris 9 and
+	   for Solaris 8 running inside Solaris Containers respectively
+	   We need to move up three frames:
 
 		<signal handler>	<-- context->cfa
 		__sighndlr
 		call_user_handler
 		sigacthandler
 		<kernel>
-	  */
-	  *nframes = 3;
-	}
+	*/
+	*nframes = 3;
+      else
+	/* This is the default Solaris 8 case.
+	   We need to move up two frames:
+
+		<signal handler>	<-- context->cfa
+		__sighndlr
+		sigacthandler
+		<kernel>
+	*/
+	*nframes = 2;
       return 1;
     }
 
@@ -181,7 +202,7 @@ sparc64_frob_update_context (struct _Unw
 #define IS_SIGHANDLER sparc_is_sighandler
 
 static int
-sparc_is_sighandler (unsigned int *pc, unsigned int * savpc, int *nframes)
+sparc_is_sighandler (unsigned int *pc, void *cfa, int *nframes)
 {
   if (/* Solaris 8, 9 - single-threaded
         -------------------------------
@@ -209,7 +230,7 @@ sparc_is_sighandler (unsigned int *pc, u
       && pc[-1] == 0x9410001a
       && pc[ 0] == 0x80a62008)
     {
-      /* Need to move up one frame:
+      /* We need to move up one frame:
 
 		<signal handler>	<-- context->cfa
 		sigacthandler
@@ -240,7 +261,7 @@ sparc_is_sighandler (unsigned int *pc, u
       && pc[ 1] == 0x81e80000
       && pc[ 2] == 0x80a26000)
     {
-      /* Need to move up one frame:
+      /* We need to move up one frame:
 
 		<signal handler>	<-- context->cfa
 		__libthread_segvhdlr
@@ -267,33 +288,59 @@ sparc_is_sighandler (unsigned int *pc, u
      && pc[ 0] == 0x81c7e008
      && pc[ 1] == 0x81e80000)
     {
-      if (/* Solaris 8 /usr/lib/libthread.so.1
-	    ----------------------------------
-	    <sigacthandler+1796>:     mov  %i0, %o0  */
-	  savpc[-1] == 0x90100018)
+      /* We have observed different calling frames among different
+	 versions of the operating system, so that we need to
+	 discriminate using the upper frame.  We look for the return
+	 address of the caller frame (there is an offset of 15 words
+	 between the frame address and the place where this return
+	 address is stored) in order to do some more pattern matching.  */
+      unsigned int cuh_pattern
+	= *(unsigned int *)(*(unsigned int *)(cfa + 15*4) - 4);
+
+      if (cuh_pattern == 0xd407a04c)
 	{
-	  /* We need to move up two frames:
+	  /* This matches the call_user_handler pattern for Solaris 10.
+	     There are 2 cases so we look for the return address of the
+	     caller's caller frame in order to do more pattern matching.  */
+	  unsigned int sah_pattern
+	    = *(unsigned int *)(*(unsigned int *)(cfa + 96 + 15*4) - 4);
+
+          if (sah_pattern == 0x92100019)
+	    /* This is the same setup as for Solaris 9, see below.  */
+	    *nframes = 3;
+	  else
+	    /* The sigacthandler frame isn't present in the chain.
+	       We need to move up two frames:
 
 		<signal handler>	<-- context->cfa
 		__sighndlr
-		sigacthandler
+		call_user_handler frame
 		<kernel>
-	  */
-	  *nframes = 2;
+	    */
+	    *nframes = 2;
 	}
-      else /* Solaris 8 /usr/lib/lwp/libthread.so.1, Solaris 9+
-	     --------------------------------------------------  */
-	{
-	  /* We need to move up three frames:
+      else if (cuh_pattern == 0x9410001a || cuh_pattern == 0x9410001b)
+	/* This matches the call_user_handler pattern for Solaris 9 and
+	   for Solaris 8 running inside Solaris Containers respectively.
+	   We need to move up three frames:
 
 		<signal handler>	<-- context->cfa
 		__sighndlr
 		call_user_handler
 		sigacthandler
 		<kernel>
-	  */
-	  *nframes = 3;
-	}
+	*/
+	*nframes = 3;
+      else
+	/* This is the default Solaris 8 case.
+	   We need to move up two frames:
+
+		<signal handler>	<-- context->cfa
+		__sighndlr
+		sigacthandler
+		<kernel>
+	*/
+	*nframes = 2;
       return 1;
     }
 
@@ -331,7 +378,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unw
       return _URC_NO_REASON;
     }
 
-  if (IS_SIGHANDLER (pc, (unsigned int *)fp->fr_savpc, &nframes))
+  if (IS_SIGHANDLER (pc, this_cfa, &nframes))
     {
       struct handler_args {
 	struct frame frwin;

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