diff mbox

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

Message ID 201201091048.29633.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Jan. 9, 2012, 9:48 a.m. UTC
> 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.

Comments

Rainer Orth Jan. 16, 2012, 12:01 p.m. UTC | #1
Eric Botcazou <ebotcazou@adacore.com> writes:

>> 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).

Unfortunately, this version completely breaks Solaris 11.  Given that
your primary (only?) justification for this patch seems to be a 7-year
old Beta version of Solaris 10 (s10_72) nobody in his right mind should
be running right now, I suggest simply reverting this patch.

	Rainer
Eric Botcazou Jan. 17, 2012, 11:17 a.m. UTC | #2
> Unfortunately, this version completely breaks Solaris 11.  Given that
> your primary (only?) justification for this patch seems to be a 7-year
> old Beta version of Solaris 10 (s10_72) nobody in his right mind should
> be running right now, I suggest simply reverting this patch.

I think that we shoudn't have changed the pattern matching code in the first 
place, as it had gradually evolved over almost an entire decade.  It was quite 
robust as a consequence and the new code is clearly inferior in this respect.

Usually adapting it to a new version of the OS only takes a handful of minutes.
Would you mind having a quick look?  I don't have access to Solaris 11 myself.
Rainer Orth Jan. 17, 2012, 12:40 p.m. UTC | #3
Eric Botcazou <ebotcazou@adacore.com> writes:

>> Unfortunately, this version completely breaks Solaris 11.  Given that
>> your primary (only?) justification for this patch seems to be a 7-year
>> old Beta version of Solaris 10 (s10_72) nobody in his right mind should
>> be running right now, I suggest simply reverting this patch.
>
> I think that we shoudn't have changed the pattern matching code in the first 
> place, as it had gradually evolved over almost an entire decade.  It was quite 
> robust as a consequence and the new code is clearly inferior in this respect.
>
> Usually adapting it to a new version of the OS only takes a handful of minutes.

That's not my experience in the first place: when I tried to get it
working on Solaris 11, I failed so completely that I decided to instead
follow the route already trodden by the Solaris/x86 file.

> Would you mind having a quick look?  I don't have access to Solaris 11 myself.

I doubt I'll have the time: there's quite a lot on my plate before 4.7.0
and I don't have that much time left for gcc issues these days.

Again: what's the justification for changing this code so late in the
game when it has been like this since 4.6.0 with no issues?  I don't buy
it that support for s10_72 (a 7-year old Solaris 10 Beta) is enough to
break Solaris 11 (the current shipping release).

	Rainer
diff mbox

Patch

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;