Bug 44554 - Stack space after sigsetjmp is reused
Summary: Stack space after sigsetjmp is reused
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.4.4
: P3 major
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-06-16 07:02 UTC by Christian Eggers
Modified: 2011-01-28 11:30 UTC (History)
5 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: arm-linux-gnueabi
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2011-01-28 10:03:46


Attachments
Preprocessed source (1.16 KB, text/plain)
2010-06-16 07:17 UTC, Christian Eggers
Details
Object file (for reference) (1.50 KB, application/octet-stream)
2010-06-16 07:18 UTC, Christian Eggers
Details
A patch that should fix it (1.63 KB, patch)
2010-09-28 10:52 UTC, Bernd Schmidt
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Christian Eggers 2010-06-16 07:02:18 UTC
This bug has originally been reported on Glibc bugtracker:
http://sourceware.org/bugzilla/show_bug.cgi?id=11670
Please look here first for a detailed description.

The __sigsetjmp function returns twice so it's not allowed to reuse stack space of existing automatic variables after this function has been called.

C-Code:
---------
void *x = malloc(something);
do {
  __pthread_unwind_buf_t __cancel_buf;
  void *y = x;
  
  int not_first_call = __sigsetjmp((struct __jmp_buf_tag *) (void *)
         __cancel_buf.__cancel_jmp_buf, 0);
  if (not_first_call) {
    free(y);
    __pthread_unwind_next (&__cancel_buf);
    /* NOTREACHED */
  }
  
  do {
    ...
  } while (0);
  free(y);
} while(0);

In the resulting assembler code the second "free(y)" is "replaced" by "free(x)" and the stack space for y is used for something else. This causes problems when __sigsetjmp() returns the second time because the stack memory for "y" may already contain the value of another variable at this time.

ASM output:
---------
 120:   ebfffffe        bl      0 <malloc>
 124:   e50b0280        str     r0, [fp, #-640] ; 0x280   <-- x is @ fp,0x280
 128:   e51bc280        ldr     ip, [fp, #-640] ; 0x280
 12c:   e3a01000        mov     r1, #0
 130:   e24b0f53        sub     r0, fp, #332    ; 0x14c
 134:   e50bc2b8        str     ip, [fp, #-696] ; 0x2b8   <-- y is @ fp,0x2b8
 138:   ebfffffe        bl      0 <__sigsetjmp>
...
 1f4:   e50b52b8        str     r5, [fp, #-696] ; 0x2b8   <-- y is overwritten
...
 408:   e51b0280        ldr     r0, [fp, #-640] ; 0x280   <-- y has been
 40c:   ebffff15        bl      68 <thread_cancel0>           replaced by x
---------
Comment 1 Christian Eggers 2010-06-16 07:17:19 UTC
Created attachment 20925 [details]
Preprocessed source

compile with arm-linux-gnueabi-gcc -mcpu=arm920t -Os -o test.o -c test.i

This file is a stripped down version of the original source. Here __sigsetjmp is used twice because pthread_cleanup_push()/pthread_cleanup_pop() are used nested:

a = malloc();
pthread_cleanup_push(handler, a);
x = malloc() 
pthread_cleanup_push(handler, x)
...
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);

The code is arranged in a way the the problem happens for both instances of __cancel_arg are affected.

The bug is little bit "volatile", if you change the source it will usually disappear or move to another position. For instance you may try removing the marked line:

  comp_1 = 0.0;
  comp_2 = 0.0;
  for (i = 0; i < num_1 - delay1; ++i)
  {
-->   comp_1 += conj(comp_out[i]) * comp_out[i];
      comp_2 += conj(comp_out[i]) * comp_in[i];
  }

siglongjmp() is only used for demonstration purposes. You can also link with "-pthreads -lm" to a full executable demo.
Comment 2 Christian Eggers 2010-06-16 07:18:25 UTC
Created attachment 20926 [details]
Object file (for reference)
Comment 3 Richard Biener 2010-06-16 08:58:46 UTC
you need to mark y and x volatile.
Comment 4 Andreas Schwab 2010-06-16 09:06:22 UTC
If the variable is not modified between setjmp and longjmp the compiler is required to preserve its value.
Comment 5 Jakub Jelinek 2010-06-16 09:45:34 UTC
The __cancel_arg variables are pseudos until ira, apparently during IRA the 2 stack slots chosen for those are shared between __cancel_arg vars and other vars used later in the function.  Do we need to act as if -fno-ira-share-spill-slots
is set in cfun->calls_setjmp functions?
Comment 6 Christian Eggers 2010-06-17 18:56:41 UTC
(In reply to comment #5)
> Do we need to act as if
> -fno-ira-share-spill-slots
> is set in cfun->calls_setjmp functions?

At least in my case "-Os -fno-ira-share-spill-slots" seems to solve the problem. This applies also to the original (not stripped down) version of the code.

Comment 7 Ian Bolton 2010-09-08 08:49:15 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > Do we need to act as if
> > -fno-ira-share-spill-slots
> > is set in cfun->calls_setjmp functions?
> 
> At least in my case "-Os -fno-ira-share-spill-slots" seems to solve the
> problem. This applies also to the original (not stripped down) version of the
> code.
> 

Is this still a bug then?  Should ira-share-spill-slots be automatically disabled for the caller function when a callee function can return twice?

Comment 8 Christian Eggers 2010-09-08 11:12:12 UTC
(In reply to comment #7)
> Is this still a bug then?  Should ira-share-spill-slots be automatically
> disabled for the caller function when a callee function can return twice?
> 
I've never tested with gcc-4.5.x, but in 4.4.x the problem is still present. 

Unfortunately -fno-ira-share-spill-slots seems to introduce another bug which leads to wrong computations (nearly at the same code position where I had the problems mentioned is this report). 

At this moment I can not provide a detailed report for this problem, but perhaps it's the same as http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40386.
Comment 9 Vladimir Makarov 2010-09-08 20:06:42 UTC
(In reply to comment #8)
> (In reply to comment #7)
> > Is this still a bug then?  Should ira-share-spill-slots be automatically
> > disabled for the caller function when a callee function can return twice?
> > 
> I've never tested with gcc-4.5.x, but in 4.4.x the problem is still present. 
> 
> Unfortunately -fno-ira-share-spill-slots seems to introduce another bug which
> leads to wrong computations (nearly at the same code position where I had the
> problems mentioned is this report). 
> 
> At this moment I can not provide a detailed report for this problem, but
> perhaps it's the same as http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40386.
> 

I've submitted a patch solving PR40386.  So now we can solve this problem by preventing slot sharing when setjmp is used.

I'll send a patch soon.
Comment 10 Christian Eggers 2010-09-09 06:17:43 UTC
(In reply to comment #9)
> I've submitted a patch solving PR40386.  So now we can solve this problem by
> preventing slot sharing when setjmp is used.
> 
> I'll send a patch soon.

Could you please send me both patches? I would like to test whether both problems are solved (at least for me).

regards
Christian


Comment 11 Vladimir Makarov 2010-09-09 13:54:05 UTC
Subject: Bug 44554

Author: vmakarov
Date: Thu Sep  9 13:53:32 2010
New Revision: 164102

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164102
Log:
2010-09-09  Vladimir Makarov  <vmakarov@redhat.com>

	PR middle-end/44554
	* ira.c (ira): Switch off sharing spill slots if setjmp is called.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ira.c

Comment 12 Vladimir Makarov 2010-09-09 13:56:00 UTC
Subject: Bug 44554

Author: vmakarov
Date: Thu Sep  9 13:55:35 2010
New Revision: 164105

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164105
Log:
2010-09-09  Vladimir Makarov  <vmakarov@redhat.com>

	PR middle-end/44554
	* ira.c (ira): Switch off sharing spill slots if setjmp is called.


Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/ira.c

Comment 13 Vladimir Makarov 2010-09-09 13:58:45 UTC
Subject: Bug 44554

Author: vmakarov
Date: Thu Sep  9 13:58:24 2010
New Revision: 164107

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164107
Log:
2010-09-09  Vladimir Makarov  <vmakarov@redhat.com>

	PR middle-end/44554
	* ira.c (ira): Switch off sharing spill slots if setjmp is called.


Modified:
    branches/gcc-4_4-branch/gcc/ChangeLog
    branches/gcc-4_4-branch/gcc/ira.c

Comment 14 Bernd Schmidt 2010-09-28 10:52:13 UTC
Created attachment 21901 [details]
A patch that should fix it

Please verify whether this fixes it.
Comment 15 Christian Eggers 2010-09-28 11:01:05 UTC
(In reply to comment #14)
> Created attachment 21901 [details]
> A patch that should fix it
> 
> Please verify whether this fixes it.

Hasn't it already been fixed in comment #11? My plan was to wait until release of gcc-4.4.5 and test then. Are additional changes required to fix this bug?
Comment 16 Bernd Schmidt 2010-09-28 14:00:30 UTC
Argh, wrong PR.  I wanted 45445.
Comment 17 Ian Bolton 2011-01-28 10:03:46 UTC
(In reply to comment #15)
> (In reply to comment #14)
> > Created attachment 21901 [details]
> > A patch that should fix it
> > 
> > Please verify whether this fixes it.
> 
> Hasn't it already been fixed in comment #11? My plan was to wait until release
> of gcc-4.4.5 and test then. Are additional changes required to fix this bug?

gcc 4.4.5 was released in October.  Please can you confirm if this is now fixed.
Comment 18 Christian Eggers 2011-01-28 10:29:12 UTC
(In reply to comment #17)
> gcc 4.4.5 was released in October.  Please can you confirm if this is now
> fixed.

I think THIS bug is fixed in 4.4.5. Unfortunately I've still problems with wrong computations as already mentioned in comment #8. But this would either be related to PR40386 or it's another bug.
Comment 19 Ian Bolton 2011-01-28 11:30:50 UTC
(In reply to comment #18)
> (In reply to comment #17)
> > gcc 4.4.5 was released in October.  Please can you confirm if this is now
> > fixed.
> 
> I think THIS bug is fixed in 4.4.5. Unfortunately I've still problems with
> wrong computations as already mentioned in comment #8. But this would either be
> related to PR40386 or it's another bug.

I think it's best to raise a new bug, and CC Vladimir Makarov and Jeff Law.  It will help to hear about the specific issues you are still seeing within that bug report.