From e451a093c2066e286a604d6b1e404689ae80ea51 Mon Sep 17 00:00:00 2001 From: hjl Date: Mon, 8 Aug 2011 13:26:06 +0000 Subject: [PATCH] Fix Dwarf unwind library for UNITS_PER_WORD > sizeof (void *) gcc/ 2011-08-08 H.J. Lu PR other/48007 * config.gcc (libgcc_tm_file): Add i386/value-unwind.h for Linux/x86. * system.h (REG_VALUE_IN_UNWIND_CONTEXT): Poisoned. (ASSUME_EXTENDED_UNWIND_CONTEXT): Likewise. * unwind-dw2.c (ASSUME_EXTENDED_UNWIND_CONTEXT): New. (_Unwind_Context_Reg_Val): Likewise. (_Unwind_Get_Unwind_Word): Likewise. (_Unwind_Get_Unwind_Context_Reg_Val): Likewise. (_Unwind_Context): Use _Unwind_Context_Reg_Val on the reg field. (_Unwind_IsExtendedContext): Check ASSUME_EXTENDED_UNWIND_CONTEXT for EXTENDED_CONTEXT_BIT. (__frame_state_for): Likewise. (uw_init_context_1): Likewise. (_Unwind_GetGR): Updated. (_Unwind_SetGR): Likewise. (_Unwind_GetGRPtr): Likewise. (_Unwind_SetGRPtr): Likewise. (_Unwind_SetGRValue): Likewise. (_Unwind_GRByValue): Likewise. (uw_install_context_1): Likewise. * doc/tm.texi.in: Document REG_VALUE_IN_UNWIND_CONTEXT and ASSUME_EXTENDED_UNWIND_CONTEXT. * doc/tm.texi: Regenerated. libgcc/ 2011-08-08 H.J. Lu PR other/48007 * config/i386/value-unwind.h: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177563 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 30 ++++++++++++++++ gcc/config.gcc | 1 + gcc/doc/tm.texi | 18 ++++++++++ gcc/doc/tm.texi.in | 18 ++++++++++ gcc/system.h | 3 +- libgcc/ChangeLog | 5 +++ libgcc/config/i386/value-unwind.h | 26 ++++++++++++++ libgcc/unwind-dw2.c | 75 ++++++++++++++++++++++++++++++--------- 8 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 libgcc/config/i386/value-unwind.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac35dd68115..d1371d2b25d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2011-08-08 H.J. Lu + + PR other/48007 + * config.gcc (libgcc_tm_file): Add i386/value-unwind.h for + Linux/x86. + + * system.h (REG_VALUE_IN_UNWIND_CONTEXT): Poisoned. + (ASSUME_EXTENDED_UNWIND_CONTEXT): Likewise. + + * unwind-dw2.c (ASSUME_EXTENDED_UNWIND_CONTEXT): New. + (_Unwind_Context_Reg_Val): Likewise. + (_Unwind_Get_Unwind_Word): Likewise. + (_Unwind_Get_Unwind_Context_Reg_Val): Likewise. + (_Unwind_Context): Use _Unwind_Context_Reg_Val on the reg field. + (_Unwind_IsExtendedContext): Check ASSUME_EXTENDED_UNWIND_CONTEXT + for EXTENDED_CONTEXT_BIT. + (__frame_state_for): Likewise. + (uw_init_context_1): Likewise. + (_Unwind_GetGR): Updated. + (_Unwind_SetGR): Likewise. + (_Unwind_GetGRPtr): Likewise. + (_Unwind_SetGRPtr): Likewise. + (_Unwind_SetGRValue): Likewise. + (_Unwind_GRByValue): Likewise. + (uw_install_context_1): Likewise. + + * doc/tm.texi.in: Document REG_VALUE_IN_UNWIND_CONTEXT and + ASSUME_EXTENDED_UNWIND_CONTEXT. + * doc/tm.texi: Regenerated. + 2011-08-08 Rainer Orth * Makefile.in (gengtype$(exeext)): Add $(LDFLAGS). diff --git a/gcc/config.gcc b/gcc/config.gcc index 716fa224b2a..ec13d93b3d5 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2663,6 +2663,7 @@ esac case ${target} in i[34567]86-*-linux* | x86_64-*-linux*) tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386" + libgcc_tm_file="${libgcc_tm_file} i386/value-unwind.h" ;; i[34567]86-*-* | x86_64-*-*) tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 097531f7f6b..74a232412d1 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3725,6 +3725,24 @@ return @code{@var{regno}}. @end defmac +@defmac REG_VALUE_IN_UNWIND_CONTEXT + +Define this macro if the target stores register values as +@code{_Unwind_Word} type in unwind context. It should be defined if +target register size is larger than the size of @code{void *}. The +default is to store register values as @code{void *} type. + +@end defmac + +@defmac ASSUME_EXTENDED_UNWIND_CONTEXT + +Define this macro to be 1 if the target always uses extended unwind +context with version, args_size and by_value fields. If it is undefined, +it will be defined to 1 when @code{REG_VALUE_IN_UNWIND_CONTEXT} is +defined and 0 otherwise. + +@end defmac + @node Elimination @subsection Eliminating Frame Pointer and Arg Pointer diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 01beeb47920..f63fe4a0c2b 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3711,6 +3711,24 @@ return @code{@var{regno}}. @end defmac +@defmac REG_VALUE_IN_UNWIND_CONTEXT + +Define this macro if the target stores register values as +@code{_Unwind_Word} type in unwind context. It should be defined if +target register size is larger than the size of @code{void *}. The +default is to store register values as @code{void *} type. + +@end defmac + +@defmac ASSUME_EXTENDED_UNWIND_CONTEXT + +Define this macro to be 1 if the target always uses extended unwind +context with version, args_size and by_value fields. If it is undefined, +it will be defined to 1 when @code{REG_VALUE_IN_UNWIND_CONTEXT} is +defined and 0 otherwise. + +@end defmac + @node Elimination @subsection Eliminating Frame Pointer and Arg Pointer diff --git a/gcc/system.h b/gcc/system.h index a7db6f58f85..9698c613f35 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -802,7 +802,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; /* Target macros only used for code built for the target, that have moved to libgcc-tm.h or have never been present elsewhere. */ #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX \ - MD_UNWIND_SUPPORT MD_FROB_UPDATE_CONTEXT ENABLE_EXECUTE_STACK + MD_UNWIND_SUPPORT MD_FROB_UPDATE_CONTEXT ENABLE_EXECUTE_STACK \ + REG_VALUE_IN_UNWIND_CONTEXT ASSUME_EXTENDED_UNWIND_CONTEXT /* Other obsolete target macros, or macros that used to be in target headers and were not used, and may be obsolete or may never have diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 79020025415..9148c9badc2 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2011-08-08 H.J. Lu + + PR other/48007 + * config/i386/value-unwind.h: New. + 2011-08-06 Richard Sandiford * config.host (*-*-darwin*, *-*-freebsd*, *-*-linux*, frv-*-*linux*) diff --git a/libgcc/config/i386/value-unwind.h b/libgcc/config/i386/value-unwind.h new file mode 100644 index 00000000000..0dceb5c85c6 --- /dev/null +++ b/libgcc/config/i386/value-unwind.h @@ -0,0 +1,26 @@ +/* Store register values as _Unwind_Word type in DWARF2 EH unwind context. + 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. + + 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 + . */ + +/* Define this macro if the target stores register values as _Unwind_Word + type in unwind context. Only enable it for x32. */ +#if defined __x86_64 && !defined __LP64__ +# define REG_VALUE_IN_UNWIND_CONTEXT +#endif diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index 19da29982b6..92aa233eb26 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -59,12 +59,50 @@ #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) #endif +#ifdef REG_VALUE_IN_UNWIND_CONTEXT +typedef _Unwind_Word _Unwind_Context_Reg_Val; + +#ifndef ASSUME_EXTENDED_UNWIND_CONTEXT +#define ASSUME_EXTENDED_UNWIND_CONTEXT 1 +#endif + +static inline _Unwind_Word +_Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val) +{ + return val; +} + +static inline _Unwind_Context_Reg_Val +_Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val) +{ + return val; +} +#else +typedef void *_Unwind_Context_Reg_Val; + +static inline _Unwind_Word +_Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val) +{ + return (_Unwind_Word) (_Unwind_Internal_Ptr) val; +} + +static inline _Unwind_Context_Reg_Val +_Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val) +{ + return (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) val; +} +#endif + +#ifndef ASSUME_EXTENDED_UNWIND_CONTEXT +#define ASSUME_EXTENDED_UNWIND_CONTEXT 0 +#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. */ struct _Unwind_Context { - void *reg[DWARF_FRAME_REGISTERS+1]; + _Unwind_Context_Reg_Val reg[DWARF_FRAME_REGISTERS+1]; void *cfa; void *ra; void *lsda; @@ -147,7 +185,8 @@ _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) static inline _Unwind_Word _Unwind_IsExtendedContext (struct _Unwind_Context *context) { - return context->flags & EXTENDED_CONTEXT_BIT; + return (ASSUME_EXTENDED_UNWIND_CONTEXT + || (context->flags & EXTENDED_CONTEXT_BIT)); } /* Get the value of register INDEX as saved in CONTEXT. */ @@ -156,7 +195,7 @@ inline _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *context, int index) { int size; - void *ptr; + _Unwind_Context_Reg_Val val; #ifdef DWARF_ZERO_REG if (index == DWARF_ZERO_REG) @@ -166,18 +205,18 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index) index = DWARF_REG_TO_UNWIND_COLUMN (index); gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); size = dwarf_reg_size_table[index]; - ptr = context->reg[index]; + val = context->reg[index]; if (_Unwind_IsExtendedContext (context) && context->by_value[index]) - return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; + return _Unwind_Get_Unwind_Word (val); /* This will segfault if the register hasn't been saved. */ if (size == sizeof(_Unwind_Ptr)) - return * (_Unwind_Ptr *) ptr; + return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val; else { gcc_assert (size == sizeof(_Unwind_Word)); - return * (_Unwind_Word *) ptr; + return * (_Unwind_Word *) (_Unwind_Internal_Ptr) val; } } @@ -209,11 +248,11 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) if (_Unwind_IsExtendedContext (context) && context->by_value[index]) { - context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; + context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val); return; } - ptr = context->reg[index]; + ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index]; if (size == sizeof(_Unwind_Ptr)) * (_Unwind_Ptr *) ptr = val; @@ -232,7 +271,7 @@ _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) index = DWARF_REG_TO_UNWIND_COLUMN (index); if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return &context->reg[index]; - return context->reg[index]; + return (void *) (_Unwind_Internal_Ptr) context->reg[index]; } /* Set the pointer to a register INDEX as saved in CONTEXT. */ @@ -243,7 +282,7 @@ _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) index = DWARF_REG_TO_UNWIND_COLUMN (index); if (_Unwind_IsExtendedContext (context)) context->by_value[index] = 0; - context->reg[index] = p; + context->reg[index] = (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) p; } /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ @@ -254,10 +293,10 @@ _Unwind_SetGRValue (struct _Unwind_Context *context, int index, { index = DWARF_REG_TO_UNWIND_COLUMN (index); gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); - gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr)); + gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Context_Reg_Val)); context->by_value[index] = 1; - context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; + context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val); } /* Return nonzero if register INDEX is stored by value rather than @@ -1215,7 +1254,8 @@ __frame_state_for (void *pc_target, struct frame_state *state_in) int reg; memset (&context, 0, sizeof (struct _Unwind_Context)); - context.flags = EXTENDED_CONTEXT_BIT; + if (!ASSUME_EXTENDED_UNWIND_CONTEXT) + context.flags = EXTENDED_CONTEXT_BIT; context.ra = pc_target + 1; if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) @@ -1453,7 +1493,8 @@ uw_init_context_1 (struct _Unwind_Context *context, memset (context, 0, sizeof (struct _Unwind_Context)); context->ra = ra; - context->flags = EXTENDED_CONTEXT_BIT; + if (!ASSUME_EXTENDED_UNWIND_CONTEXT) + context->flags = EXTENDED_CONTEXT_BIT; code = uw_frame_state_for (context, &fs); gcc_assert (code == _URC_NO_REASON); @@ -1532,8 +1573,8 @@ uw_install_context_1 (struct _Unwind_Context *current, for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) { - void *c = current->reg[i]; - void *t = target->reg[i]; + void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i]; + void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i]; gcc_assert (current->by_value[i] == 0); if (target->by_value[i] && c) -- 2.11.0