Message ID | AANLkTi=hA05XuTsEUAeimD1M2a_W8z=v=OPQSvM1mfSq@mail.gmail.com |
---|---|
State | New |
Headers | show |
"H.J. Lu" <hjl.tools@gmail.com> writes:
> Here is the updated patch. It has
This patch is OK if it bootstraps and passes tests.
Thanks.
Ian
On Tue, Mar 22, 2011 at 04:19:46PM +0100, Ulrich Weigand wrote: > Ian Lance Taylor wrote: > > "H.J. Lu" <hjl.tools@gmail.com> writes: > > > > > Here is the updated patch. It has > > > > This patch is OK if it bootstraps and passes tests. > > I thought the _Unwind_Context structure was part of the libgcc ABI > and should only be changed by appending to the end and/or updating > the version field? It is, so a change like this should be guarded by some preprocessor conditionals if it makes any difference on any target (not sure if we have any targets where a union containing void * and uintptr_t would be layed out differently in a structure from void *, but certainly on targets where _Unwind_Word is larger than void * and they aren't new targets we risk ABI issues). The problem is when some binaries link against older libgcc.a and are used together with dynamically linked libgcc_s.so. Jakub
Jakub Jelinek <jakub@redhat.com> writes: > On Tue, Mar 22, 2011 at 04:19:46PM +0100, Ulrich Weigand wrote: >> Ian Lance Taylor wrote: >> > "H.J. Lu" <hjl.tools@gmail.com> writes: >> > >> > > Here is the updated patch. It has >> > >> > This patch is OK if it bootstraps and passes tests. >> >> I thought the _Unwind_Context structure was part of the libgcc ABI >> and should only be changed by appending to the end and/or updating >> the version field? > > It is, so a change like this should be guarded by some preprocessor > conditionals if it makes any difference on any target (not sure if > we have any targets where a union containing void * and uintptr_t > would be layed out differently in a structure from void *, but > certainly on targets where _Unwind_Word is larger than void * > and they aren't new targets we risk ABI issues). > The problem is when some binaries link against older libgcc.a > and are used together with dynamically linked libgcc_s.so. Any target on which _Unwind_Word is larger than void * is broken today, so I don't think we need to care about that case. But, yes, if there is a target in which the union would be laid out differently than the simple field, then there is a problem. I think this is an unlikely case. Does anybody know of a target where that might occur? Ian
On Tue, Mar 22, 2011 at 9:42 AM, Ian Lance Taylor <iant@google.com> wrote: > > Any target on which _Unwind_Word is larger than void * is broken today, > so I don't think we need to care about that case. So a MIPS N32 is broken? Lots of people use that target already and nothing like this has showed up yet. Thanks, Andrew Pinski
Andrew Pinski <pinskia@gmail.com> writes: > On Tue, Mar 22, 2011 at 9:42 AM, Ian Lance Taylor <iant@google.com> wrote: >> >> Any target on which _Unwind_Word is larger than void * is broken today, >> so I don't think we need to care about that case. > > So a MIPS N32 is broken? Lots of people use that target already and > nothing like this has showed up yet. That is a fair question. It does seem to me that it must be broken in some cases. _Unwind_GetGRPtr will return &context->reg[index], which is a void** cast to void*. We will then pass that to _Unwind_SetGRPtr. If we later call _Unwind_SetGR on that register, it will write a value of size _Unwind_Word through that pointer. Similarly if we call _Unwind_GetGR, it will read a value of size _Unwind_Word. In both cases, we will be accessing a 4-byte field as an 8-byte value. If MIPS N32 works today, then something must be ensuring that that sequence can never occur, or that for some reason it never matters. Does anybody disagree with this analysis? Ian
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 25990b4..1cb4b47 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -59,12 +59,19 @@ #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) #endif +/* A reister is stored either by reference or by value. */ +union _Unwind_Register +{ + void *ref; + _Unwind_Word val; +}; + /* 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]; + union _Unwind_Register reg[DWARF_FRAME_REGISTERS+1]; void *cfa; void *ra; void *lsda; @@ -156,7 +163,7 @@ inline _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *context, int index) { int size; - void *ptr; + union _Unwind_Register reg; #ifdef DWARF_ZERO_REG if (index == DWARF_ZERO_REG) @@ -166,18 +173,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]; + reg = context->reg[index]; if (_Unwind_IsExtendedContext (context) && context->by_value[index]) - return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; + return reg.val; /* This will segfault if the register hasn't been saved. */ if (size == sizeof(_Unwind_Ptr)) - return * (_Unwind_Ptr *) ptr; + return * (_Unwind_Ptr *) reg.ref; else { gcc_assert (size == sizeof(_Unwind_Word)); - return * (_Unwind_Word *) ptr; + return * (_Unwind_Word *) reg.ref; } } @@ -209,11 +216,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].val = val; return; } - ptr = context->reg[index]; + ptr = context->reg[index].ref; if (size == sizeof(_Unwind_Ptr)) * (_Unwind_Ptr *) ptr = val; @@ -231,8 +238,8 @@ _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 *) &context->reg[index].val; + return context->reg[index].ref; } /* Set the pointer to a register INDEX as saved in CONTEXT. */ @@ -243,7 +250,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].ref = p; } /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ @@ -254,10 +261,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_Word)); context->by_value[index] = 1; - context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; + context->reg[index].val = val; } /* Return nonzero if register INDEX is stored by value rather than @@ -1534,8 +1541,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 = current->reg[i].ref; + void *t = target->reg[i].ref; gcc_assert (current->by_value[i] == 0); if (target->by_value[i] && c)