public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, IA64] Fix building a bare-metal ia64 compiler
@ 2015-12-15 21:13 Bernd Edlinger
  2015-12-15 21:55 ` Jeff Law
  2015-12-15 23:55 ` Bernd Schmidt
  0 siblings, 2 replies; 9+ messages in thread
From: Bernd Edlinger @ 2015-12-15 21:13 UTC (permalink / raw)
  To: gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

[-- Attachment #1: Type: text/plain, Size: 870 bytes --]

Hi,

due to recent discussion on the basic asm, and the special handling of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler for ia64, but that did not work, because it seems to be impossible to build it without having a stdlib.h.

With the attached patch, I was finally able to build the cross compiler, by declaring abort in the way as it is done already in many other places at libgcc.

In case someone wants to know, working configure options are as follows:

../binutils-2.25.1/configure --prefix=../ia64-elf --target=ia64-unknown-elf

../gcc-trunk/configure --prefix=../ia64-elf --target=ia64-unknown-elf --enable-languages=c --with-gnu-as --disable-threads --disable-sjlj-exceptions --disable-libssp --disable-libquadmath


I have successfully built a bare-metal cross compiler with this patch.
Is it OK for trunk?


Thanks
Bernd.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-ia64-libgcc.diff --]
[-- Type: text/x-patch; name="patch-ia64-libgcc.diff", Size: 705 bytes --]

2015-12-15  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* unwind-generic.h: Don't include stdlib.h.
	Add a prototype for abort.


Index: libgcc/unwind-generic.h
===================================================================
--- libgcc/unwind-generic.h	(Revision 231598)
+++ libgcc/unwind-generic.h	(Arbeitskopie)
@@ -221,7 +221,9 @@ _Unwind_SjLj_Resume_or_Rethrow (struct _Unwind_Exc
    compatible with the standard ABI for IA-64, we inline these.  */
 
 #ifdef __ia64__
-#include <stdlib.h>
+/* We add a prototype for abort here to avoid creating a dependency on
+   target headers.  */
+extern void abort (void);
 
 static inline _Unwind_Ptr
 _Unwind_GetDataRelBase (struct _Unwind_Context *_C)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, IA64] Fix building a bare-metal ia64 compiler
  2015-12-15 21:13 [PATCH, IA64] Fix building a bare-metal ia64 compiler Bernd Edlinger
@ 2015-12-15 21:55 ` Jeff Law
  2015-12-16  4:50   ` Bernd Edlinger
  2015-12-15 23:55 ` Bernd Schmidt
  1 sibling, 1 reply; 9+ messages in thread
From: Jeff Law @ 2015-12-15 21:55 UTC (permalink / raw)
  To: Bernd Edlinger, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

On 12/15/2015 02:13 PM, Bernd Edlinger wrote:
> Hi,
>
> due to recent discussion on the basic asm, and the special handling of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler for ia64, but that did not work, because it seems to be impossible to build it without having a stdlib.h.
>
> With the attached patch, I was finally able to build the cross compiler, by declaring abort in the way as it is done already in many other places at libgcc.
>
> In case someone wants to know, working configure options are as follows:
>
> ../binutils-2.25.1/configure --prefix=../ia64-elf --target=ia64-unknown-elf
>
> ../gcc-trunk/configure --prefix=../ia64-elf --target=ia64-unknown-elf --enable-languages=c --with-gnu-as --disable-threads --disable-sjlj-exceptions --disable-libssp --disable-libquadmath
>
>
> I have successfully built a bare-metal cross compiler with this patch.
> Is it OK for trunk?
I wouldn't call it "many" places in libgcc.  I just see one -- fp-bit.c 
and that one is only to give "sane" handle to extended mode floating point.

For ia64-elf ISTM this header should be coming from newlib.


jeff

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, IA64] Fix building a bare-metal ia64 compiler
  2015-12-15 21:13 [PATCH, IA64] Fix building a bare-metal ia64 compiler Bernd Edlinger
  2015-12-15 21:55 ` Jeff Law
@ 2015-12-15 23:55 ` Bernd Schmidt
  2015-12-16  5:00   ` Bernd Edlinger
  2015-12-16 23:17   ` libgcc: unwind-ia64.c without malloc/free Bernd Edlinger
  1 sibling, 2 replies; 9+ messages in thread
From: Bernd Schmidt @ 2015-12-15 23:55 UTC (permalink / raw)
  To: Bernd Edlinger, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

On 12/15/2015 10:13 PM, Bernd Edlinger wrote:
> due to recent discussion on the basic asm, and the special handling
> of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler
> for ia64, but that did not work, because it seems to be impossible to
> build it without having a stdlib.h.

Actually David Howells has complained to me about this as well, it seems 
to be a problem when building a toolchain for kernel compilation.

> With the attached patch, I was finally able to build the cross
> compiler, by declaring abort in the way as it is done already in many
> other places at libgcc.

Can you just use __builtin_abort ()? Ok with that change.


Bernd

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, IA64] Fix building a bare-metal ia64 compiler
  2015-12-15 21:55 ` Jeff Law
@ 2015-12-16  4:50   ` Bernd Edlinger
  0 siblings, 0 replies; 9+ messages in thread
From: Bernd Edlinger @ 2015-12-16  4:50 UTC (permalink / raw)
  To: Jeff Law, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

Hi,

On 15.12.2015 22:55, Jeff Law wrote:
> On 12/15/2015 02:13 PM, Bernd Edlinger wrote:
>> Hi,
>>
>> due to recent discussion on the basic asm, and the special handling 
>> of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler 
>> for ia64, but that did not work, because it seems to be impossible to 
>> build it without having a stdlib.h.
>>
>> With the attached patch, I was finally able to build the cross 
>> compiler, by declaring abort in the way as it is done already in many 
>> other places at libgcc.
>>
>> In case someone wants to know, working configure options are as follows:
>>
>> ../binutils-2.25.1/configure --prefix=../ia64-elf 
>> --target=ia64-unknown-elf
>>
>> ../gcc-trunk/configure --prefix=../ia64-elf --target=ia64-unknown-elf 
>> --enable-languages=c --with-gnu-as --disable-threads 
>> --disable-sjlj-exceptions --disable-libssp --disable-libquadmath
>>
>>
>> I have successfully built a bare-metal cross compiler with this patch.
>> Is it OK for trunk?
> I wouldn't call it "many" places in libgcc.  I just see one -- 
> fp-bit.c and that one is only to give "sane" handle to extended mode 
> floating point.

there is also unwind-arm-common.inc, which is included by 
./config/arm/unwind-arm.h
and ./config/c6x/unwind-c6x.h, so yes, not many, only few.

> For ia64-elf ISTM this header should be coming from newlib

but I don't want to use newlib or glibc, I just wanted to see if my 
other patch breaks something.


Bernd.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, IA64] Fix building a bare-metal ia64 compiler
  2015-12-15 23:55 ` Bernd Schmidt
@ 2015-12-16  5:00   ` Bernd Edlinger
  2015-12-16 15:35     ` Bernd Edlinger
  2015-12-16 23:17   ` libgcc: unwind-ia64.c without malloc/free Bernd Edlinger
  1 sibling, 1 reply; 9+ messages in thread
From: Bernd Edlinger @ 2015-12-16  5:00 UTC (permalink / raw)
  To: Bernd Schmidt, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

Hi,

On 16.12.2015 00:55 Bernd Schmidt wrote:
> On 12/15/2015 10:13 PM, Bernd Edlinger wrote:
>> due to recent discussion on the basic asm, and the special handling
>> of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler
>> for ia64, but that did not work, because it seems to be impossible to
>> build it without having a stdlib.h.
>
> Actually David Howells has complained to me about this as well, it 
> seems to be a problem when building a toolchain for kernel compilation.

yes.  I am not sure, if this is also problematic, when building a 
cross-glibc,
then I need also a cross C compiler first, build glibc, and install .h 
and objects
to the sysroot, then I build gcc again, with all languages.

>
>> With the attached patch, I was finally able to build the cross
>> compiler, by declaring abort in the way as it is done already in many
>> other places at libgcc.
>
> Can you just use __builtin_abort ()? Ok with that change.
>

I will try, but ./config/ia64/unwind-ia64.c includes this header,
and it also uses abort () at many places.  So I'd expect warnings
there.


Thanks
Bernd.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, IA64] Fix building a bare-metal ia64 compiler
  2015-12-16  5:00   ` Bernd Edlinger
@ 2015-12-16 15:35     ` Bernd Edlinger
  0 siblings, 0 replies; 9+ messages in thread
From: Bernd Edlinger @ 2015-12-16 15:35 UTC (permalink / raw)
  To: Bernd Schmidt, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor



On 16.12.2015 05:59, Bernd Edlinger wrote:
> Hi,
>
> On 16.12.2015 00:55 Bernd Schmidt wrote:
>> On 12/15/2015 10:13 PM, Bernd Edlinger wrote:
>>> due to recent discussion on the basic asm, and the special handling
>>> of ASM_INPUT in ia64, I tried to build a bare-metal cross-compiler
>>> for ia64, but that did not work, because it seems to be impossible to
>>> build it without having a stdlib.h.
>>
>> Actually David Howells has complained to me about this as well, it 
>> seems to be a problem when building a toolchain for kernel compilation.
>
> yes.  I am not sure, if this is also problematic, when building a 
> cross-glibc,
> then I need also a cross C compiler first, build glibc, and install .h 
> and objects
> to the sysroot, then I build gcc again, with all languages.
>
>>
>>> With the attached patch, I was finally able to build the cross
>>> compiler, by declaring abort in the way as it is done already in many
>>> other places at libgcc.
>>
>> Can you just use __builtin_abort ()? Ok with that change.
>>
>
> I will try, but ./config/ia64/unwind-ia64.c includes this header,
> and it also uses abort () at many places.  So I'd expect warnings
> there.
>
>

OK, no new warnings, because tsystem.h defines a prototype of abort.

=> checked in as r231697.

But I see that unwind-ia64.c does not only use abort, but also malloc and
free too.

If I see that right, the stack walk will crash if malloc fails. What happens
on this target, if new throws out_of_memory?

I think this function should be rewritten to use alloca instead.
(I have an idea how this could be done, but no way to test a patch :(


Bernd.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* libgcc: unwind-ia64.c without malloc/free
  2015-12-15 23:55 ` Bernd Schmidt
  2015-12-16  5:00   ` Bernd Edlinger
@ 2015-12-16 23:17   ` Bernd Edlinger
  2015-12-17 13:18     ` Bernd Schmidt
  1 sibling, 1 reply; 9+ messages in thread
From: Bernd Edlinger @ 2015-12-16 23:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor, Bernd Schmidt

[-- Attachment #1: Type: text/plain, Size: 560 bytes --]

Hi,

this is just an idea, how to avoid use of malloc in unwind-ia64.c.

I can compile this with my cross-compiler, but can not test anything.

If you find it interesting, then someone should continue this work and test
and/or fix it until it really works.

The idea is, I can use alloca instead of malloc: this is re-entrant, and
works also with zero free memory.  The allocations have to be done
in the main loop, and the state machine, is always guaranteed to have
at least one available memory block.  What do you think?


Regards,
Bernd.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-unwind-ia64.diff --]
[-- Type: text/x-patch; name="patch-unwind-ia64.diff", Size: 13057 bytes --]

Index: libgcc/config/ia64/unwind-ia64.c
===================================================================
--- libgcc/config/ia64/unwind-ia64.c	(revision 231696)
+++ libgcc/config/ia64/unwind-ia64.c	(working copy)
@@ -129,6 +129,14 @@ struct unw_labeled_state {
   struct unw_reg_state saved_state;
 };
 
+struct unw_alloc_context
+{
+  struct unw_reg_state     *avail_reg_state;
+  struct unw_labeled_state *avail_labeled_state;
+  struct unw_reg_state     **dup_state_result;
+  struct unw_reg_state     *dup_state_param;
+};
+
 typedef struct unw_state_record
 {
   unsigned int first_region : 1;	/* is this the first region? */
@@ -152,9 +160,10 @@ typedef struct unw_state_record
 
   struct unw_labeled_state *labeled_states;	/* list of all labeled states */
   struct unw_reg_state curr;	/* current state */
+  struct unw_alloc_context ac;
 
   _Unwind_Personality_Fn personality;
-  
+
 } _Unwind_FrameState;
 
 enum unw_nat_type
@@ -237,128 +246,44 @@ static unsigned char const save_order[] =
 \f
 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
 
-/* MASK is a bitmap describing the allocation state of emergency buffers,
-   with bit set indicating free. Return >= 0 if allocation is successful;
-   < 0 if failure.  */
-
-static inline int
-atomic_alloc (unsigned int *mask)
-{
-  unsigned int old = *mask, ret, new;
-
-  while (1)
-    {
-      if (old == 0)
-	return -1;
-      ret = old & -old;
-      new = old & ~ret;
-      new = __sync_val_compare_and_swap (mask, old, new);
-      if (old == new)
-	break;
-      old = new;
-    }
-
-  return __builtin_ffs (ret) - 1;
-}
-
-/* Similarly, free an emergency buffer.  */
-
-static inline void
-atomic_free (unsigned int *mask, int bit)
-{
-  __sync_xor_and_fetch (mask, 1 << bit);
-}
-
-
-#define SIZE(X)		(sizeof(X) / sizeof(*(X)))
-#define MASK_FOR(X)	((2U << (SIZE (X) - 1)) - 1)
-#define PTR_IN(X, P)	((P) >= (X) && (P) < (X) + SIZE (X))
-
-static struct unw_reg_state emergency_reg_state[32];
-static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
-
-static struct unw_labeled_state emergency_labeled_state[8];
-static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
-
-#ifdef ENABLE_MALLOC_CHECKING
-static int reg_state_alloced;
-static int labeled_state_alloced;
-#endif
-
 /* Allocation and deallocation of structures.  */
 
 static struct unw_reg_state *
-alloc_reg_state (void)
+alloc_reg_state (struct unw_alloc_context *ac)
 {
   struct unw_reg_state *rs;
 
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced++;
-#endif
+  rs = ac->avail_reg_state;
+  if (rs)
+    ac->avail_reg_state = rs->next;
 
-  rs = malloc (sizeof (struct unw_reg_state));
-  if (!rs)
-    {
-      int n = atomic_alloc (&emergency_reg_state_free);
-      if (n >= 0)
-	rs = &emergency_reg_state[n];
-    }
-
   return rs;
 }
 
 static void
-free_reg_state (struct unw_reg_state *rs)
+free_reg_state (struct unw_reg_state *rs, struct unw_alloc_context *ac)
 {
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_reg_state, rs))
-    atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
-  else
-    free (rs);
+  rs->next = ac->avail_reg_state;
+  ac->avail_reg_state = rs;
 }
 
 static struct unw_labeled_state *
-alloc_label_state (void)
+alloc_label_state (struct unw_alloc_context *ac)
 {
   struct unw_labeled_state *ls;
 
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced++;
-#endif
+  ls = ac->avail_labeled_state;
+  ac->avail_labeled_state = NULL;
 
-  ls = malloc(sizeof(struct unw_labeled_state));
-  if (!ls)
-    {
-      int n = atomic_alloc (&emergency_labeled_state_free);
-      if (n >= 0)
-	ls = &emergency_labeled_state[n];
-    }
-
   return ls;
 }
 
-static void
-free_label_state (struct unw_labeled_state *ls)
-{
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_labeled_state, ls))
-    atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
-  else
-    free (ls);
-}
-
 /* Routines to manipulate the state stack.  */
 
 static void
 push (struct unw_state_record *sr)
 {
-  struct unw_reg_state *rs = alloc_reg_state ();
+  struct unw_reg_state *rs = alloc_reg_state (&sr->ac);
   memcpy (rs, &sr->curr, sizeof (*rs));
   sr->curr.next = rs;
 }
@@ -371,34 +296,40 @@ pop (struct unw_state_record *sr)
   if (!rs)
     abort ();
   memcpy (&sr->curr, rs, sizeof(*rs));
-  free_reg_state (rs);
+  free_reg_state (rs, &sr->ac);
 }
 
 /* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
 
-static struct unw_reg_state *
-dup_state_stack (struct unw_reg_state *rs)
+static void
+dup_state_stack (struct unw_reg_state **result, struct unw_reg_state *rs,
+		 struct unw_alloc_context *ac)
 {
-  struct unw_reg_state *copy, *prev = NULL, *first = NULL;
+  struct unw_reg_state *copy;
 
   while (rs)
     {
-      copy = alloc_reg_state ();
+      copy = alloc_reg_state (ac);
+      if (!copy)
+	{
+	  ac->dup_state_result = result;
+	  ac->dup_state_param = rs;
+	  return;
+	}
       memcpy (copy, rs, sizeof(*copy));
-      if (first)
-	prev->next = copy;
-      else
-	first = copy;
+      *result = copy;
+      result = &copy->next;
       rs = rs->next;
-      prev = copy;
     }
 
-  return first;
+  *result = NULL;
+  ac->dup_state_result = NULL;
+  ac->dup_state_param = NULL;
 }
 
 /* Free all stacked register states (but not RS itself).  */
 static void
-free_state_stack (struct unw_reg_state *rs)
+free_state_stack (struct unw_reg_state *rs, struct unw_alloc_context *ac)
 {
   struct unw_reg_state *p, *next;
 
@@ -405,26 +336,10 @@ static void
   for (p = rs->next; p != NULL; p = next)
     {
       next = p->next;
-      free_reg_state (p);
+      free_reg_state (p, ac);
     }
   rs->next = NULL;
 }
-
-/* Free all labeled states.  */
-
-static void
-free_label_states (struct unw_labeled_state *ls)
-{
-  struct unw_labeled_state *next;
-
-  for (; ls ; ls = next)
-    {
-      next = ls->next;
-
-      free_state_stack (&ls->saved_state);
-      free_label_state (ls);
-    }
-}
 \f
 /* Unwind decoder routines */
 
@@ -823,10 +738,10 @@ desc_copy_state (unw_word label, struct unw_state_
   for (ls = sr->labeled_states; ls; ls = ls->next)
     {
       if (ls->label == label)
-        {
-	  free_state_stack (&sr->curr);
+	{
+	  free_state_stack (&sr->curr, &sr->ac);
    	  memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
-	  sr->curr.next = dup_state_stack (ls->saved_state.next);
+	  dup_state_stack (&sr->curr.next, ls->saved_state.next, &sr->ac);
 	  return;
 	}
     }
@@ -836,11 +751,11 @@ desc_copy_state (unw_word label, struct unw_state_
 static inline void
 desc_label_state (unw_word label, struct unw_state_record *sr)
 {
-  struct unw_labeled_state *ls = alloc_label_state ();
+  struct unw_labeled_state *ls = alloc_label_state (&sr->ac);
 
   ls->label = label;
   memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
-  ls->saved_state.next = dup_state_stack (sr->curr.next);
+  dup_state_stack (&ls->saved_state.next, sr->curr.next, &sr->ac);
 
   /* Insert into list of labeled states.  */
   ls->next = sr->labeled_states;
@@ -1061,7 +976,7 @@ unw_decode_uleb128 (unsigned char **dpp)
 static unsigned char *
 unw_decode_x1 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, abreg;
   unw_word t, off;
@@ -1080,7 +995,7 @@ unw_decode_x1 (unsigned char *dp,
 static unsigned char *
 unw_decode_x2 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, abreg, x, ytreg;
   unw_word t;
@@ -1100,7 +1015,7 @@ unw_decode_x2 (unsigned char *dp,
 static unsigned char *
 unw_decode_x3 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, abreg, qp;
   unw_word t, off;
@@ -1122,7 +1037,7 @@ unw_decode_x3 (unsigned char *dp,
 static unsigned char *
 unw_decode_x4 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
   unw_word t;
@@ -1143,7 +1058,8 @@ unw_decode_x4 (unsigned char *dp,
 }
 
 static unsigned char *
-unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   int body = (code & 0x20) != 0;
   unw_word rlen;
@@ -1154,7 +1070,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r2 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, mask, grsave;
   unw_word rlen;
@@ -1169,7 +1086,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r3 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word rlen;
 
@@ -1179,7 +1097,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unsigned char brmask = (code & 0x1f);
 
@@ -1188,7 +1107,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p2_p5 (unsigned char *dp, unsigned char code,
+		  struct unw_state_record *arg)
 {
   if ((code & 0x10) == 0)
     {
@@ -1237,7 +1157,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p6 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   int gregs = (code & 0x10) != 0;
   unsigned char mask = (code & 0x0f);
@@ -1250,7 +1171,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p7_p10 (unsigned char *dp, unsigned char code,
+		   struct unw_state_record *arg)
 {
   unsigned char r, byte1, byte2;
   unw_word t, size;
@@ -1349,7 +1271,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word label = (code & 0x1f);
 
@@ -1361,7 +1284,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b2 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word t;
 
@@ -1371,7 +1295,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b3_x4 (unsigned char *dp, unsigned char code,
+		  struct unw_state_record *arg)
 {
   unw_word t, ecount, label;
 
@@ -1401,7 +1326,8 @@ static unsigned char *
   return dp;
 }
 
-typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
+typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char,
+				       struct unw_state_record *arg);
 
 static const unw_decoder unw_decode_table[2][8] =
 {
@@ -1432,7 +1358,8 @@ static const unw_decoder unw_decode_table[2][8] =
  * Decode one descriptor and return address of next descriptor.
  */
 static inline unsigned char *
-unw_decode (unsigned char *dp, int inside_body, void *arg)
+unw_decode (unsigned char *dp, int inside_body,
+	    struct unw_state_record *arg)
 {
   unw_decoder decoder;
   unsigned char code;
@@ -1845,16 +1772,24 @@ uw_frame_state_for (struct _Unwind_Context *contex
   insn = (unsigned char *) (unw + 1);
   insn_end = (unsigned char *) (unw + 1 + length);
   while (!fs->done && insn < insn_end)
-    insn = unw_decode (insn, fs->in_body, fs);
+    {
+      if (fs->ac.avail_reg_state == NULL)
+	{
+	  fs->ac.avail_reg_state = alloca (sizeof (struct unw_reg_state));
+	  fs->ac.avail_reg_state->next = NULL;
+	}
+      if (fs->ac.avail_labeled_state == NULL)
+	fs->ac.avail_labeled_state = alloca (sizeof (struct unw_labeled_state));
+      insn = unw_decode (insn, fs->in_body, fs);
+      while (fs->ac.dup_state_result != NULL)
+	{
+	  fs->ac.avail_reg_state = alloca (sizeof (struct unw_reg_state));
+	  fs->ac.avail_reg_state->next = NULL;
+	  dup_state_stack (fs->ac.dup_state_result,
+			   fs->ac.dup_state_param, &fs->ac);
+	}
+    }
 
-  free_label_states (fs->labeled_states);
-  free_state_stack (&fs->curr);
-
-#ifdef ENABLE_MALLOC_CHECKING
-  if (reg_state_alloced || labeled_state_alloced)
-    abort ();
-#endif
-
   /* If we're in the epilogue, sp has been restored and all values
      on the memory stack below psp also have been restored.  */
   if (fs->when_target > fs->epilogue_start)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: patch-unwind-ia64.diff --]
[-- Type: text/x-patch; name="patch-unwind-ia64.diff", Size: 13057 bytes --]

Index: libgcc/config/ia64/unwind-ia64.c
===================================================================
--- libgcc/config/ia64/unwind-ia64.c	(revision 231696)
+++ libgcc/config/ia64/unwind-ia64.c	(working copy)
@@ -129,6 +129,14 @@ struct unw_labeled_state {
   struct unw_reg_state saved_state;
 };
 
+struct unw_alloc_context
+{
+  struct unw_reg_state     *avail_reg_state;
+  struct unw_labeled_state *avail_labeled_state;
+  struct unw_reg_state     **dup_state_result;
+  struct unw_reg_state     *dup_state_param;
+};
+
 typedef struct unw_state_record
 {
   unsigned int first_region : 1;	/* is this the first region? */
@@ -152,9 +160,10 @@ typedef struct unw_state_record
 
   struct unw_labeled_state *labeled_states;	/* list of all labeled states */
   struct unw_reg_state curr;	/* current state */
+  struct unw_alloc_context ac;
 
   _Unwind_Personality_Fn personality;
-  
+
 } _Unwind_FrameState;
 
 enum unw_nat_type
@@ -237,128 +246,44 @@ static unsigned char const save_order[] =
 \f
 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
 
-/* MASK is a bitmap describing the allocation state of emergency buffers,
-   with bit set indicating free. Return >= 0 if allocation is successful;
-   < 0 if failure.  */
-
-static inline int
-atomic_alloc (unsigned int *mask)
-{
-  unsigned int old = *mask, ret, new;
-
-  while (1)
-    {
-      if (old == 0)
-	return -1;
-      ret = old & -old;
-      new = old & ~ret;
-      new = __sync_val_compare_and_swap (mask, old, new);
-      if (old == new)
-	break;
-      old = new;
-    }
-
-  return __builtin_ffs (ret) - 1;
-}
-
-/* Similarly, free an emergency buffer.  */
-
-static inline void
-atomic_free (unsigned int *mask, int bit)
-{
-  __sync_xor_and_fetch (mask, 1 << bit);
-}
-
-
-#define SIZE(X)		(sizeof(X) / sizeof(*(X)))
-#define MASK_FOR(X)	((2U << (SIZE (X) - 1)) - 1)
-#define PTR_IN(X, P)	((P) >= (X) && (P) < (X) + SIZE (X))
-
-static struct unw_reg_state emergency_reg_state[32];
-static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
-
-static struct unw_labeled_state emergency_labeled_state[8];
-static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
-
-#ifdef ENABLE_MALLOC_CHECKING
-static int reg_state_alloced;
-static int labeled_state_alloced;
-#endif
-
 /* Allocation and deallocation of structures.  */
 
 static struct unw_reg_state *
-alloc_reg_state (void)
+alloc_reg_state (struct unw_alloc_context *ac)
 {
   struct unw_reg_state *rs;
 
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced++;
-#endif
+  rs = ac->avail_reg_state;
+  if (rs)
+    ac->avail_reg_state = rs->next;
 
-  rs = malloc (sizeof (struct unw_reg_state));
-  if (!rs)
-    {
-      int n = atomic_alloc (&emergency_reg_state_free);
-      if (n >= 0)
-	rs = &emergency_reg_state[n];
-    }
-
   return rs;
 }
 
 static void
-free_reg_state (struct unw_reg_state *rs)
+free_reg_state (struct unw_reg_state *rs, struct unw_alloc_context *ac)
 {
-#ifdef ENABLE_MALLOC_CHECKING
-  reg_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_reg_state, rs))
-    atomic_free (&emergency_reg_state_free, rs - emergency_reg_state);
-  else
-    free (rs);
+  rs->next = ac->avail_reg_state;
+  ac->avail_reg_state = rs;
 }
 
 static struct unw_labeled_state *
-alloc_label_state (void)
+alloc_label_state (struct unw_alloc_context *ac)
 {
   struct unw_labeled_state *ls;
 
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced++;
-#endif
+  ls = ac->avail_labeled_state;
+  ac->avail_labeled_state = NULL;
 
-  ls = malloc(sizeof(struct unw_labeled_state));
-  if (!ls)
-    {
-      int n = atomic_alloc (&emergency_labeled_state_free);
-      if (n >= 0)
-	ls = &emergency_labeled_state[n];
-    }
-
   return ls;
 }
 
-static void
-free_label_state (struct unw_labeled_state *ls)
-{
-#ifdef ENABLE_MALLOC_CHECKING
-  labeled_state_alloced--;
-#endif
-
-  if (PTR_IN (emergency_labeled_state, ls))
-    atomic_free (&emergency_labeled_state_free, emergency_labeled_state - ls);
-  else
-    free (ls);
-}
-
 /* Routines to manipulate the state stack.  */
 
 static void
 push (struct unw_state_record *sr)
 {
-  struct unw_reg_state *rs = alloc_reg_state ();
+  struct unw_reg_state *rs = alloc_reg_state (&sr->ac);
   memcpy (rs, &sr->curr, sizeof (*rs));
   sr->curr.next = rs;
 }
@@ -371,34 +296,40 @@ pop (struct unw_state_record *sr)
   if (!rs)
     abort ();
   memcpy (&sr->curr, rs, sizeof(*rs));
-  free_reg_state (rs);
+  free_reg_state (rs, &sr->ac);
 }
 
 /* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
 
-static struct unw_reg_state *
-dup_state_stack (struct unw_reg_state *rs)
+static void
+dup_state_stack (struct unw_reg_state **result, struct unw_reg_state *rs,
+		 struct unw_alloc_context *ac)
 {
-  struct unw_reg_state *copy, *prev = NULL, *first = NULL;
+  struct unw_reg_state *copy;
 
   while (rs)
     {
-      copy = alloc_reg_state ();
+      copy = alloc_reg_state (ac);
+      if (!copy)
+	{
+	  ac->dup_state_result = result;
+	  ac->dup_state_param = rs;
+	  return;
+	}
       memcpy (copy, rs, sizeof(*copy));
-      if (first)
-	prev->next = copy;
-      else
-	first = copy;
+      *result = copy;
+      result = &copy->next;
       rs = rs->next;
-      prev = copy;
     }
 
-  return first;
+  *result = NULL;
+  ac->dup_state_result = NULL;
+  ac->dup_state_param = NULL;
 }
 
 /* Free all stacked register states (but not RS itself).  */
 static void
-free_state_stack (struct unw_reg_state *rs)
+free_state_stack (struct unw_reg_state *rs, struct unw_alloc_context *ac)
 {
   struct unw_reg_state *p, *next;
 
@@ -405,26 +336,10 @@ static void
   for (p = rs->next; p != NULL; p = next)
     {
       next = p->next;
-      free_reg_state (p);
+      free_reg_state (p, ac);
     }
   rs->next = NULL;
 }
-
-/* Free all labeled states.  */
-
-static void
-free_label_states (struct unw_labeled_state *ls)
-{
-  struct unw_labeled_state *next;
-
-  for (; ls ; ls = next)
-    {
-      next = ls->next;
-
-      free_state_stack (&ls->saved_state);
-      free_label_state (ls);
-    }
-}
 \f
 /* Unwind decoder routines */
 
@@ -823,10 +738,10 @@ desc_copy_state (unw_word label, struct unw_state_
   for (ls = sr->labeled_states; ls; ls = ls->next)
     {
       if (ls->label == label)
-        {
-	  free_state_stack (&sr->curr);
+	{
+	  free_state_stack (&sr->curr, &sr->ac);
    	  memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
-	  sr->curr.next = dup_state_stack (ls->saved_state.next);
+	  dup_state_stack (&sr->curr.next, ls->saved_state.next, &sr->ac);
 	  return;
 	}
     }
@@ -836,11 +751,11 @@ desc_copy_state (unw_word label, struct unw_state_
 static inline void
 desc_label_state (unw_word label, struct unw_state_record *sr)
 {
-  struct unw_labeled_state *ls = alloc_label_state ();
+  struct unw_labeled_state *ls = alloc_label_state (&sr->ac);
 
   ls->label = label;
   memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
-  ls->saved_state.next = dup_state_stack (sr->curr.next);
+  dup_state_stack (&ls->saved_state.next, sr->curr.next, &sr->ac);
 
   /* Insert into list of labeled states.  */
   ls->next = sr->labeled_states;
@@ -1061,7 +976,7 @@ unw_decode_uleb128 (unsigned char **dpp)
 static unsigned char *
 unw_decode_x1 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, abreg;
   unw_word t, off;
@@ -1080,7 +995,7 @@ unw_decode_x1 (unsigned char *dp,
 static unsigned char *
 unw_decode_x2 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, abreg, x, ytreg;
   unw_word t;
@@ -1100,7 +1015,7 @@ unw_decode_x2 (unsigned char *dp,
 static unsigned char *
 unw_decode_x3 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, abreg, qp;
   unw_word t, off;
@@ -1122,7 +1037,7 @@ unw_decode_x3 (unsigned char *dp,
 static unsigned char *
 unw_decode_x4 (unsigned char *dp,
 	       unsigned char code __attribute__((unused)),
-	       void *arg)
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
   unw_word t;
@@ -1143,7 +1058,8 @@ unw_decode_x4 (unsigned char *dp,
 }
 
 static unsigned char *
-unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   int body = (code & 0x20) != 0;
   unw_word rlen;
@@ -1154,7 +1070,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r2 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unsigned char byte1, mask, grsave;
   unw_word rlen;
@@ -1169,7 +1086,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_r3 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word rlen;
 
@@ -1179,7 +1097,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unsigned char brmask = (code & 0x1f);
 
@@ -1188,7 +1107,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p2_p5 (unsigned char *dp, unsigned char code,
+		  struct unw_state_record *arg)
 {
   if ((code & 0x10) == 0)
     {
@@ -1237,7 +1157,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p6 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   int gregs = (code & 0x10) != 0;
   unsigned char mask = (code & 0x0f);
@@ -1250,7 +1171,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_p7_p10 (unsigned char *dp, unsigned char code,
+		   struct unw_state_record *arg)
 {
   unsigned char r, byte1, byte2;
   unw_word t, size;
@@ -1349,7 +1271,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b1 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word label = (code & 0x1f);
 
@@ -1361,7 +1284,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b2 (unsigned char *dp, unsigned char code,
+	       struct unw_state_record *arg)
 {
   unw_word t;
 
@@ -1371,7 +1295,8 @@ static unsigned char *
 }
 
 static unsigned char *
-unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
+unw_decode_b3_x4 (unsigned char *dp, unsigned char code,
+		  struct unw_state_record *arg)
 {
   unw_word t, ecount, label;
 
@@ -1401,7 +1326,8 @@ static unsigned char *
   return dp;
 }
 
-typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
+typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char,
+				       struct unw_state_record *arg);
 
 static const unw_decoder unw_decode_table[2][8] =
 {
@@ -1432,7 +1358,8 @@ static const unw_decoder unw_decode_table[2][8] =
  * Decode one descriptor and return address of next descriptor.
  */
 static inline unsigned char *
-unw_decode (unsigned char *dp, int inside_body, void *arg)
+unw_decode (unsigned char *dp, int inside_body,
+	    struct unw_state_record *arg)
 {
   unw_decoder decoder;
   unsigned char code;
@@ -1845,16 +1772,24 @@ uw_frame_state_for (struct _Unwind_Context *contex
   insn = (unsigned char *) (unw + 1);
   insn_end = (unsigned char *) (unw + 1 + length);
   while (!fs->done && insn < insn_end)
-    insn = unw_decode (insn, fs->in_body, fs);
+    {
+      if (fs->ac.avail_reg_state == NULL)
+	{
+	  fs->ac.avail_reg_state = alloca (sizeof (struct unw_reg_state));
+	  fs->ac.avail_reg_state->next = NULL;
+	}
+      if (fs->ac.avail_labeled_state == NULL)
+	fs->ac.avail_labeled_state = alloca (sizeof (struct unw_labeled_state));
+      insn = unw_decode (insn, fs->in_body, fs);
+      while (fs->ac.dup_state_result != NULL)
+	{
+	  fs->ac.avail_reg_state = alloca (sizeof (struct unw_reg_state));
+	  fs->ac.avail_reg_state->next = NULL;
+	  dup_state_stack (fs->ac.dup_state_result,
+			   fs->ac.dup_state_param, &fs->ac);
+	}
+    }
 
-  free_label_states (fs->labeled_states);
-  free_state_stack (&fs->curr);
-
-#ifdef ENABLE_MALLOC_CHECKING
-  if (reg_state_alloced || labeled_state_alloced)
-    abort ();
-#endif
-
   /* If we're in the epilogue, sp has been restored and all values
      on the memory stack below psp also have been restored.  */
   if (fs->when_target > fs->epilogue_start)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: libgcc: unwind-ia64.c without malloc/free
  2015-12-16 23:17   ` libgcc: unwind-ia64.c without malloc/free Bernd Edlinger
@ 2015-12-17 13:18     ` Bernd Schmidt
  2015-12-17 14:01       ` Jeff Law
  0 siblings, 1 reply; 9+ messages in thread
From: Bernd Schmidt @ 2015-12-17 13:18 UTC (permalink / raw)
  To: Bernd Edlinger, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

On 12/17/2015 12:17 AM, Bernd Edlinger wrote:
> this is just an idea, how to avoid use of malloc in unwind-ia64.c.
[...]
> What do you think?

Not worth worrying about IMO. I think ia64 is dead and best left to rest 
in maintenance mode.


Bernd

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: libgcc: unwind-ia64.c without malloc/free
  2015-12-17 13:18     ` Bernd Schmidt
@ 2015-12-17 14:01       ` Jeff Law
  0 siblings, 0 replies; 9+ messages in thread
From: Jeff Law @ 2015-12-17 14:01 UTC (permalink / raw)
  To: Bernd Schmidt, Bernd Edlinger, gcc-patches; +Cc: Steve Ellcey, Ian Lance Taylor

On 12/17/2015 06:17 AM, Bernd Schmidt wrote:
> On 12/17/2015 12:17 AM, Bernd Edlinger wrote:
>> this is just an idea, how to avoid use of malloc in unwind-ia64.c.
> [...]
>> What do you think?
>
> Not worth worrying about IMO. I think ia64 is dead and best left to rest
> in maintenance mode.
Agreed.  And in general using alloca is a problem waiting to happen 
unless you can prove there's no way to blow out the stack.   I can't 
count the number of problems of that nature we've fixed in glibc over 
the last 5 years when the hackers realized that was a great attack vector.

jeff

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-12-17 14:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-15 21:13 [PATCH, IA64] Fix building a bare-metal ia64 compiler Bernd Edlinger
2015-12-15 21:55 ` Jeff Law
2015-12-16  4:50   ` Bernd Edlinger
2015-12-15 23:55 ` Bernd Schmidt
2015-12-16  5:00   ` Bernd Edlinger
2015-12-16 15:35     ` Bernd Edlinger
2015-12-16 23:17   ` libgcc: unwind-ia64.c without malloc/free Bernd Edlinger
2015-12-17 13:18     ` Bernd Schmidt
2015-12-17 14:01       ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).