From patchwork Sun Apr 10 01:52:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 90491 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 C35941007D1 for ; Sun, 10 Apr 2011 11:52:26 +1000 (EST) Received: (qmail 24805 invoked by alias); 10 Apr 2011 01:52:23 -0000 Received: (qmail 24782 invoked by uid 22791); 10 Apr 2011 01:52:21 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-qw0-f47.google.com (HELO mail-qw0-f47.google.com) (209.85.216.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 10 Apr 2011 01:52:15 +0000 Received: by qwh5 with SMTP id 5so3307904qwh.20 for ; Sat, 09 Apr 2011 18:52:14 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.63.143 with SMTP id b15mr3047612qci.136.1302400333778; Sat, 09 Apr 2011 18:52:13 -0700 (PDT) Received: by 10.229.34.71 with HTTP; Sat, 9 Apr 2011 18:52:13 -0700 (PDT) In-Reply-To: References: <4D8A4391.9000400@redhat.com> <201103231922.p2NJMa2p013170@d06av02.portsmouth.uk.ibm.com> Date: Sat, 9 Apr 2011 18:52:13 -0700 Message-ID: Subject: Re: PATCH: PR other/48007: Unwind library doesn't work with UNITS_PER_WORD > sizeof (void *) From: "H.J. Lu" To: Ulrich Weigand Cc: Richard Henderson , Jakub Jelinek , Ian Lance Taylor , Andrew Pinski , GCC Patches 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 On Thu, Mar 24, 2011 at 12:15 AM, H.J. Lu wrote: > On Wed, Mar 23, 2011 at 12:22 PM, Ulrich Weigand wrote: >> Richard Henderson wrote: >>> Because, really, if we consider the structure truly public, we can't even >>> change the number of registers for a given port to support new features of >>> the cpu. >> >> Indeed, and I remember we got bitten by that a long time ago, which is why >> s390.h now has this comment: >> >> /* Number of hardware registers that go into the DWARF-2 unwind info. >>   To avoid ABI incompatibility, this number must not change even as >>   'fake' hard registers are added or removed.  */ >> #define DWARF_FRAME_REGISTERS 34 >> >>> I don't suppose there's any way that we can declare these old >>> programs Just Broken, and drop this compatibility stuff? >> >> I wouldn't like that ... we did run into this problem in the wild, and >> some s390 users really run very old programs for some reason. >> >> However, I'm wondering: this bug that leaked the implementation of >> _Unwind_Context only ever affected the *original* version of the >> structure -- it was fixed before the extended context was ever >> added, right? >> >> If this is true, we'd still need to keep the original context format >> unchanged, but we'd be free to modify the *extended* format at any >> time, without ABI considerations and need for further versioning ... >> > > From what I can tell, the issues are: > > 1. _Unwind_Context is supposed to be opaque and we are free to > change it.  We should be able to extend DWARF_FRAME_REGISTERS > to support the new hard registers if needed, without breaking binary > compatibility. > 2.  _Unwind_Context was leaked and wasn't really opaque.  To > provide backward binary compatibility, we are stuck with what we > had. > > Is that possible to implement something along the line: > > 1. Add some bits to _Unwind_Context so that we can detect > the leaked _Unwind_Context. > 2. When a leaked _Unwind_Context is detected at run-time, > as a compile time option, a target can either provide binary > compatibility or issue a run-time error. This is the attempt to implement it. Any comments? Thanks. diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 25990b4..5fa2723 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -59,6 +59,12 @@ #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) #endif +#ifndef UNIQUE_UNWIND_CONTEXT +#if defined __x86_64 && !defined __LP64__ +# define UNIQUE_UNWIND_CONTEXT +#endif +#endif + /* This is the register and unwind state for a particular frame. This provides the information necessary to unwind up past a frame and return to its caller. */ @@ -69,6 +75,15 @@ struct _Unwind_Context void *ra; void *lsda; struct dwarf_eh_bases bases; +#ifdef UNIQUE_UNWIND_CONTEXT + /* Used to check for unique _Unwind_Context. */ + void *dwarf_reg_size_table; + /* Signal frame context. */ +#define SIGNAL_FRAME_BIT ((_Unwind_Word) 1 >> 0) + _Unwind_Word flags; + _Unwind_Word args_size; + _Unwind_Word value[DWARF_FRAME_REGISTERS+1]; +#else /* Signal frame context. */ #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) /* Context which has version/args_size/by_value fields. */ @@ -79,6 +94,7 @@ struct _Unwind_Context _Unwind_Word version; _Unwind_Word args_size; char by_value[DWARF_FRAME_REGISTERS+1]; +#endif }; /* Byte size of every register managed by these routines. */ @@ -144,11 +160,13 @@ _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) context->flags &= ~SIGNAL_FRAME_BIT; } +#ifndef UNIQUE_UNWIND_CONTEXT static inline _Unwind_Word _Unwind_IsExtendedContext (struct _Unwind_Context *context) { return context->flags & EXTENDED_CONTEXT_BIT; } +#endif /* Get the value of register INDEX as saved in CONTEXT. */ @@ -168,8 +186,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index) size = dwarf_reg_size_table[index]; ptr = context->reg[index]; +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (context->dwarf_reg_size_table == &dwarf_reg_size_table); + if (context->reg[index] == &context->value[index]) + return context->value[index]; +#else if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; +#endif /* This will segfault if the register hasn't been saved. */ if (size == sizeof(_Unwind_Ptr)) @@ -207,11 +231,20 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); size = dwarf_reg_size_table[index]; +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (context->dwarf_reg_size_table == &dwarf_reg_size_table); + if (context->reg[index] == &context->value[index]) + { + context->value[index] = val; + return; + } +#else if (_Unwind_IsExtendedContext (context) && context->by_value[index]) { context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; return; } +#endif ptr = context->reg[index]; @@ -230,8 +263,10 @@ static inline void * _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifndef UNIQUE_UNWIND_CONTEXT if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return &context->reg[index]; +#endif return context->reg[index]; } @@ -241,8 +276,10 @@ static inline void _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifndef UNIQUE_UNWIND_CONTEXT if (_Unwind_IsExtendedContext (context)) context->by_value[index] = 0; +#endif context->reg[index] = p; } @@ -254,10 +291,15 @@ _Unwind_SetGRValue (struct _Unwind_Context *context, int index, { index = DWARF_REG_TO_UNWIND_COLUMN (index); gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Word)); + context->value[index] = val; + context->reg[index] = &context->value[index]; +#else gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr)); - context->by_value[index] = 1; context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; +#endif } /* Return nonzero if register INDEX is stored by value rather than @@ -267,7 +309,11 @@ static inline int _Unwind_GRByValue (struct _Unwind_Context *context, int index) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifdef UNIQUE_UNWIND_CONTEXT + return context->reg[index] == &context->value[index]; +#else return context->by_value[index]; +#endif } /* Retrieve the return address for CONTEXT. */ @@ -1217,7 +1263,11 @@ __frame_state_for (void *pc_target, struct frame_state *state_in) int reg; memset (&context, 0, sizeof (struct _Unwind_Context)); +#ifdef UNIQUE_UNWIND_CONTEXT + context.dwarf_reg_size_table = &dwarf_reg_size_table; +#else context.flags = EXTENDED_CONTEXT_BIT; +#endif context.ra = pc_target + 1; if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) @@ -1455,7 +1505,11 @@ uw_init_context_1 (struct _Unwind_Context *context, memset (context, 0, sizeof (struct _Unwind_Context)); context->ra = ra; +#ifdef UNIQUE_UNWIND_CONTEXT + context->dwarf_reg_size_table = &dwarf_reg_size_table; +#else context->flags = EXTENDED_CONTEXT_BIT; +#endif code = uw_frame_state_for (context, &fs); gcc_assert (code == _URC_NO_REASON); @@ -1537,8 +1591,13 @@ uw_install_context_1 (struct _Unwind_Context *current, void *c = current->reg[i]; void *t = target->reg[i]; +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (current->reg[i] != ¤t->value[i]); + if (target->reg[i] == &target->value[i] && c) +#else gcc_assert (current->by_value[i] == 0); if (target->by_value[i] && c) +#endif { _Unwind_Word w; _Unwind_Ptr p;