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]

PATCH: Fix Solaris 11/x86 MD_FALLBACK_FRAME_STATE_FOR


A couple of EH-related testcases were failing on recent versions of
Solaris 11, both 32 and 64-bit.  Namely

FAIL: gnat.dg/null_pointer_deref1.adb execution test
FAIL: gnat.dg/null_pointer_deref2.adb execution test
FAIL: gnat.dg/stack_check1.adb execution test
FAIL: gnat.dg/stack_check2.adb execution test

FAIL: Throw_2 execution - source compiled test
FAIL: Throw_2 -findirect-dispatch execution - source compiled test
FAIL: Throw_2 -O3 execution - source compiled test
FAIL: Throw_2 -O3 -findirect-dispatch execution - source compiled test

As Eric had already suggested in the context of PR ada/41929 (a SPARC
problem but most likely related), investigating the
MD_FALLBACK_FRAME_STATE_FOR code in detail led to fixes for both the 32
and 64-bit problems.

* The 32-bit function, x86_fallback_frame_state, didn't yet account for
  the new __sighndlr code introduced in September 2009 to fix

  6881217 32bit stack frames should be aligned on 16-byte boundaries (for sse2 code)
  http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6881217

  The corresponding new code is here:

  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/i386/threads/asm_subr.s#87

  Doing so in the obvious way fixed the testcases.

* The 64-bit case was more involved: 

  The __sighndlr code had remained unchanged, but after quite some
  debugging I found that the offset to the ucontext_t structure on the
  stack had changed.  To verify the fix, I just changed the offset
  (which would break Solaris 10 and most likely older Solaris 11
  releases), which worked.  My first real attempt was to verify the
  ucontext_t found by checking the uc_flags (which always seem to be
  UC_ALL).  This should work as well, but a simpler approach came to
  mind: why not just follow the x86 lead and just use the ucontext_t *
  left on the stack itself?  In fact, the __sighndlr stack frame is just
  as expected once one realizes that the function is called with 4 args
  (see the comment below).

  After that change, the 64-bit testcases now work, too.  I've not yet
  verified this on Solaris 10 yet, though.

Though I can technically commit this myself, I'd like to get
confirmation from someone with a proper understanding of the AMD64 ABI
that this makes sense.

Thanks.
	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University


2010-02-17  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	* config/i386/sol2-unwind.h (x86_64_fallback_frame_state):
	Properly find ucontext_t * on Solaris 11.
	(x86_fallback_frame_state): Handle new Solaris 11 __sighndlr
	pattern.

diff -r 87abb3a355af -r e61d4f1c55e9 gcc/config/i386/sol2-unwind.h
--- a/gcc/config/i386/sol2-unwind.h	Wed Feb 17 23:05:39 2010 +0100
+++ b/gcc/config/i386/sol2-unwind.h	Thu Feb 18 02:23:43 2010 +0100
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for AMD x86-64 and x86.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -47,15 +47,25 @@
 	<__sighndlr+6>:      leaveq           <--- PC
 	<__sighndlr+7>:      retq  */
       *(unsigned long *)(pc - 6) == 0xc3c9d1ffe5894855)
-    /* We need to move up four frames (the kernel frame, the signal frame,
-       the call_user_handler frame and the __sighndlr frame).  Two of them
-       have the minimum stack frame size (kernel and __sighndlr frames),
-       the signal frame has a stack frame size of 32 and there is another
-       with a stack frame size of 112 bytes (the call_user_handler frame).
-       The ucontext_t structure is after this offset.  */
+    /* According to the OpenSolaris sources
+       (usr/src/lib/libc/amd64/threads/asm_subr.s), __sighndlr is called
+       with 4 args like this:
+
+       __sighndlr(int sig, siginfo_t *si, ucontext_t *uc, void (*hndlr)())
+
+       Thus, its stack frame looks as below (cf. i386.c, comment before
+       struct ix86_frame, for layout) and allows us to directly get at the
+       ucontext_t *.  */
     {
-      int off = 16 + 16 + 32 + 112;
-      mctx = &((ucontext_t *) (context->cfa + off))->uc_mcontext;
+      struct __sighndlr_frame {
+	void *saved_fp;
+	void *saved_pc;
+	void (*hndlr)(int);
+	ucontext_t *ucp;
+	siginfo_t *sip;
+	int signo;
+      } *sfp = context->cfa;
+      mctx = &sfp->ucp->uc_mcontext;
     }
   else
     return _URC_END_OF_STACK;
@@ -164,7 +174,25 @@
 	  && *(unsigned long *)(pc - 11) == 0x75ff1075
 	  && *(unsigned long *)(pc - 7)  == 0x0875ff0c
 	  && *(unsigned long *)(pc - 3)  == 0x831455ff
-	  && *(unsigned long *)(pc + 1)  == 0xc3c90cc4))
+	  && *(unsigned long *)(pc + 1)  == 0xc3c90cc4)
+      || /* Solaris 2.11
+	    -----------
+	  <__sighndlr+0>       	push   %ebp
+	  <__sighndlr+1>       	mov    %esp,%ebp
+	  <__sighndlr+3>       	and    $0xfffffff0,%esp
+	  <__sighndlr+6>       	sub    $0x4,%esp
+	  <__sighndlr+9>      	pushl  0x10(%ebp)
+	  <__sighndlr+12>      	pushl  0xc(%ebp)
+	  <__sighndlr+15>      	pushl  0x8(%ebp)
+	  <__sighndlr+18>      	call   *0x14(%ebp)
+	  <__sighndlr+21>      	leave                <--- PC
+	  <__sighndlr+22>      	ret  */
+	 (*(unsigned long *)(pc - 21) == 0x83ec8b55
+	  && *(unsigned long *)(pc - 17) == 0xec83f0e4
+	  && *(unsigned long *)(pc - 13)  == 0x1075ff04
+	  && *(unsigned long *)(pc - 9)  == 0xff0c75ff
+	  && *(unsigned long *)(pc - 5)  == 0x55ff0875
+	  && (*(unsigned long *)(pc - 1) & 0x00ffffff) == 0x00c3c914))
     {
       struct handler_args {
 	int signo;


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