OSDN Git Service

PR ada/41929
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Jan 2012 09:50:19 +0000 (09:50 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 9 Jan 2012 09:50:19 +0000 (09:50 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183005 138bc75d-0d04-0410-961f-82ee72b054a4

libgcc/ChangeLog
libgcc/config/sparc/sol2-unwind.h

index 90cc782..3f23e72 100644 (file)
@@ -1,3 +1,11 @@
+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.
+
 2012-01-06  Tristan Gingold  <gingold@adacore.com>
 
        * config/ia64/t-ia64 (LIB1ASMFUNCS): Move backward
index 54a97b0..ea4c541 100644 (file)
@@ -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.RUNTIME respectively.  If not, see
 #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, unsigned int *savpc, int *nframes)
       && 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 _Unwind_Context *context,
 #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, unsigned int * savpc, int *nframes)
       && 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, unsigned int * savpc, int *nframes)
       && 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, unsigned int * savpc, int *nframes)
      && 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 _Unwind_Context *context,
       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;