This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Fix Solaris 11/x86 MD_FALLBACK_FRAME_STATE_FOR
- From: Rainer Orth <ro at CeBiTec dot Uni-Bielefeld dot DE>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 24 Feb 2010 15:26:37 +0100
- Subject: 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;