From patchwork Fri Jun 10 11:03:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rainer Orth X-Patchwork-Id: 99883 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B4E0AB700D for ; Fri, 10 Jun 2011 21:04:25 +1000 (EST) Received: (qmail 26286 invoked by alias); 10 Jun 2011 11:04:23 -0000 Received: (qmail 26262 invoked by uid 22791); 10 Jun 2011 11:04:21 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, TW_IB, TW_XD, TW_XF, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from snape.CeBiTec.Uni-Bielefeld.DE (HELO smtp-relay.CeBiTec.Uni-Bielefeld.DE) (129.70.160.84) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 10 Jun 2011 11:04:07 +0000 Received: from localhost (localhost.CeBiTec.Uni-Bielefeld.DE [127.0.0.1]) by smtp-relay.CeBiTec.Uni-Bielefeld.DE (Postfix) with ESMTP id 88DBB345; Fri, 10 Jun 2011 13:04:05 +0200 (CEST) Received: from smtp-relay.CeBiTec.Uni-Bielefeld.DE ([127.0.0.1]) by localhost (malfoy.CeBiTec.Uni-Bielefeld.DE [127.0.0.1]) (amavisd-new, port 10024) with LMTP id oRY7PybgqXOs; Fri, 10 Jun 2011 13:03:59 +0200 (CEST) Received: from manam.CeBiTec.Uni-Bielefeld.DE (manam.CeBiTec.Uni-Bielefeld.DE [129.70.161.120]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp-relay.CeBiTec.Uni-Bielefeld.DE (Postfix) with ESMTPS id D4545344; Fri, 10 Jun 2011 13:03:59 +0200 (CEST) Received: (from ro@localhost) by manam.CeBiTec.Uni-Bielefeld.DE (8.14.4+Sun/8.14.4/Submit) id p5AB3xsC013402; Fri, 10 Jun 2011 13:03:59 +0200 (MEST) From: Rainer Orth To: Olivier Hainque Cc: gcc-patches@gcc.gnu.org Subject: Re: unwinding fallback for mips-irix6 n32 References: <20101226094957.GA13777@cardhu.act-europe.fr> Date: Fri, 10 Jun 2011 13:03:59 +0200 In-Reply-To: <20101226094957.GA13777@cardhu.act-europe.fr> (Olivier Hainque's message of "Sun, 26 Dec 2010 10:49:57 +0100") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (usg-unix-v) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello Olivier, > We have been using an unwinding fallback on mips-irix6/n32 for a while > (number of years) across different versions of GCC (3.4, 4.1, 4.3, and > 4.5 lately). > > We haven't submitted this for inclusion so far because of the pretty > limited range of supported configurations (irix 6, n32 abi only). > > Exchanges offlist suggested that it could be of interest nevertheless, > so here it is. > > Our latest port was to gcc 4.5. The attached patch is a minor > adaptation of that to mainline. I tested that a non bootstrap build > proceeds fine and that a basic test involving SEGV in Ada works as > expected. > > Rainer kindly offered to perform more thorough testing, to validate > that this indeed reduces the amount of failures he has been observing. I've finally gotten around to this. Apart from some comment and code cleanups along the lines of the sol2-unwind.h files, I had to minimally adapt the N32 multithreaded code sequence for IRIX 6.5.30 that I'm running here. While I was at it, I added N64 support which proved to be almost trivial. You'll probably have to adapt this for the version of IRIX 6.5 you're running, or we could simply skip the single varying insn. With this patch, a couple of gnat.dg tests are fixed: * N32: -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 * N64: -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 64-bit stack_check2.adb remains broken, though. It SEGVs in memcpy, but the stack is corrupted, so I cannot say yet what's going on. I'll run a full bootstrap over the weekend. It seems that the remaining libjava failures are unrelated. I may backport this to the 4.6 branch after some time (trivial apart from the gcc -> libgcc move). I will only try 4.5 if I manage to add O32 support. This might be a non-trivial excercise since the libc implementation is quite different. Thanks for providing the patch. Rainer 2011-05-29 Olivier Hainque Rainer Orth libgcc: * config/mips/irix6-unwind.h: New file. * config.host (mips-sgi-irix6.5*): Set md_unwind_header. diff --git a/libgcc/config.host b/libgcc/config.host --- a/libgcc/config.host +++ b/libgcc/config.host @@ -456,6 +456,7 @@ microblaze*-*-*) mips-sgi-irix6.5*) tmake_file="mips/t-irix6 t-crtfm t-slibgcc mips/t-slibgcc-irix" extra_parts="crtbegin.o crtend.o crtfastmath.o irix-crti.o irix-crtn.o" + md_unwind_header=mips/irix6-unwind.h ;; mips*-*-netbsd*) # NetBSD/mips, either endian. ;; diff --git a/libgcc/config/mips/irix6-unwind.h b/libgcc/config/mips/irix6-unwind.h new file mode 100644 --- /dev/null +++ b/libgcc/config/mips/irix6-unwind.h @@ -0,0 +1,180 @@ +/* DWARF2 EH unwinding support for MIPS IRIX 6. + Copyright (C) 2011 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +/* This code was developed-for and only tested-in limited ABI + configurations. Characterize that. */ + +#if defined (_ABIN32) || defined (_ABI64) +#define SUPPORTED_ABI 1 +#else +#define SUPPORTED_ABI 0 +#endif + +#include + +#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state + +/* Look at the code around RA to see if it matches a sighandler caller with a + sigcontext_t * argument (SA_SIGINFO cleared). Return that pointer argument + if it does match, or 0 otherwise. */ + +static sigcontext_t * +sigcontext_for (unsigned int *ra, void *cfa) +{ + /* IRIX 6.5, mono-threaded application. We're lucky enough to be able + to expect a short very sighandler specific sequence around. + + <_sigtramp+124>: li v0,1088 (SYS_sigreturn) + <_sigtramp+128>: syscall */ + + if ( ra[6] == 0x24020440 + && ra[7] == 0x0000000c) + return (sigcontext_t *)(cfa + 0x30); + + /* IRIX 6.5 variants, multi-threaded application, pthreads. Nothing really + sighandler specific handy, so match a fairly long constant sequence. */ + +#if _MIPS_SIM == _ABIN32 + /* + : sd s0,0(sp) + : sll ra,a0,0x2 + : addiu t9,t9,-28584/-28456/-28448 + : lw s0,3804(at) + : addu t9,t9,ra + : lw t9,0(t9) + : ld at,3696(at) + : ld s2,88(s0) + : jalr t9 + : sd at,88(s0) */ + if ( ra[-10] == 0xffb00000 + && ra[ -9] == 0x0004f880 + && (ra[-8] == 0x27399058 + || ra[-8] == 0x273990d8 + || ra[-8] == 0x273990e0) + && ra[ -7] == 0x8c300edc + && ra[ -6] == 0x033fc821 + && ra[ -5] == 0x8f390000 + && ra[ -4] == 0xdc210e70 + && ra[ -3] == 0xde120058 + && ra[ -2] == 0x0320f809 + && ra[ -1] == 0xfe010058) + +#elif _MIPS_SIM == _ABI64 + /* + : sd s0,0(sp) + : daddu t9,t9,ra + : dsll ra,a0,0x3 + : ld s0,3880(at) + : daddu t9,t9,ra + : ld t9,0(t9) + : ld at,3696(at) + : ld s2,152(s0) + : jalr t9 + : sd at,152(s0) */ + if ( ra[-10] == 0xffb00000 + && ra[ -9] == 0x033fc82d + && ra[ -8] == 0x0004f8f8 + && ra[ -7] == 0xdc300f28 + && ra[ -6] == 0x033fc82d + && ra[ -5] == 0xdf390000 + && ra[ -4] == 0xdc210e70 + && ra[ -3] == 0xde120098 + && ra[ -2] == 0x0320f809 + && ra[ -1] == 0xfe010098) +#endif + return (sigcontext_t *)(cfa + 0x60); + + return 0; +} + +#define SIGCTX_GREG_ADDR(REGNO,SIGCTX) \ + ((void *) &(SIGCTX)->sc_regs[REGNO]) + +#define SIGCTX_FPREG_ADDR(REGNO,SIGCTX) \ + ((void *) &(SIGCTX)->sc_fpregs[REGNO]) + +static _Unwind_Reason_Code +mips_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + /* Return address and CFA of the frame we're attempting to unwind through, + possibly a signal handler. */ + void *ctx_ra = (void *)context->ra; + void *ctx_cfa = (void *)context->cfa; + + /* CFA of the intermediate abstract kernel frame between the interrupted + code and the signal handler, if we're indeed unwinding through a signal + handler. */ + void *k_cfa; + + /* Pointer to the sigcontext_t structure pushed by the kernel when we're + unwinding through a signal handler setup with SA_SIGINFO cleared. */ + sigcontext_t *sigctx; + int i; + + if (! SUPPORTED_ABI) + return _URC_END_OF_STACK; + + sigctx = sigcontext_for (ctx_ra, ctx_cfa); + + if (sigctx == 0) + return _URC_END_OF_STACK; + + /* The abstract kernel frame's CFA is extactly the stack pointer + value at the interruption point. */ + k_cfa = *(void **)SIGCTX_GREG_ADDR (CTX_SP, sigctx); + + /* State the rules to compute the CFA we have the value of: use the + previous CFA and offset by the difference between the two. See + uw_update_context_1 for the supporting details. */ + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = __builtin_dwarf_sp_column (); + fs->regs.cfa_offset = k_cfa - ctx_cfa; + + /* Fill the internal frame_state structure with information stating where + each register of interest can be found from the CFA. */ + for (i = 0; i <= 31; i ++) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = SIGCTX_GREG_ADDR (i, sigctx) - k_cfa; + } + + for (i = 0; i <= 31; i ++) + { + fs->regs.reg[32+i].how = REG_SAVED_OFFSET; + fs->regs.reg[32+i].loc.offset = SIGCTX_FPREG_ADDR (i, sigctx) - k_cfa; + } + + /* State the rules to find the kernel's code "return address", which is the + address of the active instruction when the signal was caught. */ + fs->retaddr_column = DWARF_FRAME_RETURN_COLUMN; + fs->regs.reg[fs->retaddr_column].how = REG_SAVED_OFFSET; + fs->regs.reg[fs->retaddr_column].loc.offset = (void *)&sigctx->sc_pc - k_cfa; + fs->signal_frame = 1; + + return _URC_NO_REASON; +}