From patchwork Mon Jul 16 12:52:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 171182 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 C5B8E2C00E0 for ; Mon, 16 Jul 2012 22:52:37 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1343047958; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=MkzkuBa5ClUY7uP0fMlC w5gp8SE=; b=i2abFScs4RWFJ4fsK/lovCM4wfxS1sGgFots9gBrSp1AlBNh85wq kCQFezgC9qDtS71DFa+abI9f7OoilU2nKQbvnG3lp4emiVE07VaccvuIXtwCgUNp T7fV5BkukxuHvsguKYMeyeDMiLKEMVhA/a4WQe4npo6esHWVdRuqKiI= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type:Content-Disposition:User-Agent:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=HgoX27FGBYncWfC54uFAWgsrkoSCLmAZtSVKAizeKCXCycsMKhKb3TNCnEJYvq kNZ5lhP/VoayHbHgVjNOkGv3fpGNnnh5leM4DneEGjW8RUNjFB14X0BW4yHEEMJ3 5h0yhG7CmTrAShIa9nDdyW3xyy7YM011+XGUn6iRKkeno=; Received: (qmail 30997 invoked by alias); 16 Jul 2012 12:52:24 -0000 Received: (qmail 30737 invoked by uid 22791); 16 Jul 2012 12:52:20 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_HOSTKARMA_NO X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 16 Jul 2012 12:52:07 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id D2D9E1C74F9; Mon, 16 Jul 2012 08:52:06 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id W6ayy0TCu8Yy; Mon, 16 Jul 2012 08:52:06 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [205.232.38.4]) by rock.gnat.com (Postfix) with ESMTP id AF82D1C74D5; Mon, 16 Jul 2012 08:52:06 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id ACFD03FF09; Mon, 16 Jul 2012 08:52:06 -0400 (EDT) Date: Mon, 16 Jul 2012 08:52:06 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Tristan Gingold Subject: [Ada] Improve support of Storage_Error for Windows 64 SEH Message-ID: <20120716125206.GA22621@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) 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 Work to support Windows 64 SEH: allow to convert an exception code to an Ada exception ID and message; Optimize the propagation of Storage_Error on Windows 64 SEH to avoid requiring a too large stack area. 2012-07-16 Tristan Gingold * seh_init.c (__gnat_map_SEH): New function extracted from __gnat_SEH_error_handler. * raise-gcc.c: __gnat_personality_seh0: Directly transforms Windows system exception into GCC one when possible, in order to save stack room (particularly useful when Storage_Error will be propagated). Index: raise-gcc.c =================================================================== --- raise-gcc.c (revision 189524) +++ raise-gcc.c (working copy) @@ -1213,9 +1213,23 @@ #ifdef __SEH__ #define STATUS_USER_DEFINED (1U << 29) + +/* From unwind-seh.c. */ +#define GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C') +#define GCC_EXCEPTION(TYPE) \ + (STATUS_USER_DEFINED | ((TYPE) << 24) | GCC_MAGIC) +#define STATUS_GCC_THROW GCC_EXCEPTION (0) + EXCEPTION_DISPOSITION __gnat_SEH_error_handler (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); +struct Exception_Data * +__gnat_map_SEH (EXCEPTION_RECORD* ExceptionRecord, const char **msg); + +struct _Unwind_Exception * +__gnat_create_machine_occurrence_from_signal_handler (Exception_Id, + const char *); + /* Unwind opcodes. */ #define UWOP_PUSH_NONVOL 0 #define UWOP_ALLOC_LARGE 1 @@ -1295,7 +1309,10 @@ exceptions. */ if (!(ms_exc->ExceptionCode & STATUS_USER_DEFINED)) { + struct Exception_Data *exception; + const char *msg; ULONG64 excpip = (ULONG64) ms_exc->ExceptionAddress; + if (excpip != 0 && excpip >= (ms_disp->ImageBase + ms_disp->FunctionEntry->BeginAddress) @@ -1353,7 +1370,26 @@ __gnat_adjust_context ((unsigned char *)(mf_imagebase + mf_func->UnwindData), mf_rsp); } - __gnat_SEH_error_handler (ms_exc, this_frame, ms_orig_context, ms_disp); + + exception = __gnat_map_SEH (ms_exc, &msg); + if (exception != NULL) + { + struct _Unwind_Exception *exc; + + /* Directly convert the system exception to a GCC one. + This is really breaking the API, but is necessary for stack size + reasons: the normal way is to call Raise_From_Signal_Handler, + which build the exception and calls _Unwind_RaiseException, which + unwinds the stack and will call this personality routine. But + the Windows unwinder needs about 2KB of stack. */ + exc = __gnat_create_machine_occurrence_from_signal_handler + (exception, msg); + memset (exc->private_, 0, sizeof (exc->private_)); + ms_exc->ExceptionCode = STATUS_GCC_THROW; + ms_exc->NumberParameters = 1; + ms_exc->ExceptionInformation[0] = (ULONG_PTR)exc; + } + } return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context, Index: seh_init.c =================================================================== --- seh_init.c (revision 189524) +++ seh_init.c (working copy) @@ -68,20 +68,21 @@ #include #include +/* Prototypes. */ extern void _global_unwind2 (void *); EXCEPTION_DISPOSITION __gnat_SEH_error_handler (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); -EXCEPTION_DISPOSITION -__gnat_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord, - void *EstablisherFrame, - struct _CONTEXT* ContextRecord ATTRIBUTE_UNUSED, - void *DispatcherContext ATTRIBUTE_UNUSED) +struct Exception_Data * +__gnat_map_SEH (EXCEPTION_RECORD* ExceptionRecord, const char **msg); + +/* Convert an SEH exception to an Ada one. Return the exception ID + and set MSG with the corresponding message. */ + +struct Exception_Data * +__gnat_map_SEH (EXCEPTION_RECORD* ExceptionRecord, const char **msg) { - struct Exception_Data *exception; - const char *msg; - switch (ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: @@ -92,93 +93,95 @@ || IsBadCodePtr ((void *)(ExceptionRecord->ExceptionInformation[1] + 4096))) { - exception = &program_error; - msg = "EXCEPTION_ACCESS_VIOLATION"; + *msg = "EXCEPTION_ACCESS_VIOLATION"; + return &program_error; } else { /* otherwise it is a stack overflow */ - exception = &storage_error; - msg = "stack overflow or erroneous memory access"; + *msg = "stack overflow or erroneous memory access"; + return &storage_error; } - break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - exception = &constraint_error; - msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; - break; + *msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + return &constraint_error; case EXCEPTION_DATATYPE_MISALIGNMENT: - exception = &constraint_error; - msg = "EXCEPTION_DATATYPE_MISALIGNMENT"; - break; + *msg = "EXCEPTION_DATATYPE_MISALIGNMENT"; + return &constraint_error; case EXCEPTION_FLT_DENORMAL_OPERAND: - exception = &constraint_error; - msg = "EXCEPTION_FLT_DENORMAL_OPERAND"; - break; + *msg = "EXCEPTION_FLT_DENORMAL_OPERAND"; + return &constraint_error; case EXCEPTION_FLT_DIVIDE_BY_ZERO: - exception = &constraint_error; - msg = "EXCEPTION_FLT_DENORMAL_OPERAND"; - break; + *msg = "EXCEPTION_FLT_DENORMAL_OPERAND"; + return &constraint_error; case EXCEPTION_FLT_INVALID_OPERATION: - exception = &constraint_error; - msg = "EXCEPTION_FLT_INVALID_OPERATION"; - break; + *msg = "EXCEPTION_FLT_INVALID_OPERATION"; + return &constraint_error; case EXCEPTION_FLT_OVERFLOW: - exception = &constraint_error; - msg = "EXCEPTION_FLT_OVERFLOW"; - break; + *msg = "EXCEPTION_FLT_OVERFLOW"; + return &constraint_error; case EXCEPTION_FLT_STACK_CHECK: - exception = &program_error; - msg = "EXCEPTION_FLT_STACK_CHECK"; - break; + *msg = "EXCEPTION_FLT_STACK_CHECK"; + return &program_error; case EXCEPTION_FLT_UNDERFLOW: - exception = &constraint_error; - msg = "EXCEPTION_FLT_UNDERFLOW"; - break; + *msg = "EXCEPTION_FLT_UNDERFLOW"; + return &constraint_error; case EXCEPTION_INT_DIVIDE_BY_ZERO: - exception = &constraint_error; - msg = "EXCEPTION_INT_DIVIDE_BY_ZERO"; - break; + *msg = "EXCEPTION_INT_DIVIDE_BY_ZERO"; + return &constraint_error; case EXCEPTION_INT_OVERFLOW: - exception = &constraint_error; - msg = "EXCEPTION_INT_OVERFLOW"; - break; + *msg = "EXCEPTION_INT_OVERFLOW"; + return &constraint_error; case EXCEPTION_INVALID_DISPOSITION: - exception = &program_error; - msg = "EXCEPTION_INVALID_DISPOSITION"; - break; + *msg = "EXCEPTION_INVALID_DISPOSITION"; + return &program_error; case EXCEPTION_NONCONTINUABLE_EXCEPTION: - exception = &program_error; - msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; - break; + *msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + return &program_error; case EXCEPTION_PRIV_INSTRUCTION: - exception = &program_error; - msg = "EXCEPTION_PRIV_INSTRUCTION"; - break; + *msg = "EXCEPTION_PRIV_INSTRUCTION"; + return &program_error; case EXCEPTION_SINGLE_STEP: - exception = &program_error; - msg = "EXCEPTION_SINGLE_STEP"; - break; + *msg = "EXCEPTION_SINGLE_STEP"; + return &program_error; case EXCEPTION_STACK_OVERFLOW: - exception = &storage_error; - msg = "EXCEPTION_STACK_OVERFLOW"; - break; + *msg = "EXCEPTION_STACK_OVERFLOW"; + return &storage_error; default: + *msg = NULL; + return NULL; + } +} + +EXCEPTION_DISPOSITION +__gnat_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord, + void *EstablisherFrame, + struct _CONTEXT* ContextRecord ATTRIBUTE_UNUSED, + void *DispatcherContext ATTRIBUTE_UNUSED) +{ + struct Exception_Data *exception; + const char *msg; + + exception = __gnat_map_SEH (ExceptionRecord, &msg); + + if (exception == NULL) + { #if defined (_WIN64) && defined (__SEH__) /* On Windows x64, do not transform other exception as they could be caught by user (when SEH is used to propagate exceptions). */