Re: GCC reuses stack slot in setjmp-calling function -- is it a bug or feature?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Konstantin Vladimirov writes:
 > Hi,
 > 
 > Minimal reproduction for x86:
 > 
 > #include <setjmp.h>
 > #include <stdio.h>
 > #include <stdlib.h>
 > 
 > jmp_buf something_happened;
 > int key_gdata = 2;
 > 
 > int store_data;
 > 
 > void __attribute__((noinline))
 > initiate(void)
 > {
 >   longjmp(something_happened, 1);
 > }
 > 
 > int __attribute__ ((noinline))
 > foo(int x)
 > {
 >   return x + 1;
 > }
 > 
 > int __attribute__((noinline))
 > amibuggy(int x, int y1, int y2, int y3)
 > {
 >   int nextdata, idx, key_data;
 > 
 >   key_data = key_gdata;
 > 
 >   if (setjmp(something_happened))
 >     {
 >       if (key_data != key_gdata)
 >         {
 >           fprintf(stderr, "Test failed: data = %d, g_data = %d\n",
 > key_data, key_gdata);
 >           abort();
 >         }
 >       else
 >         {
 >           fprintf(stdout, "Test passed\n");
 >           fprintf(stdout, "data = %d, g_data = %d\n", key_data, key_gdata);
 >           return 0;
 >         }
 >     }
 > 
 >   store_data = key_data;
 >   nextdata = key_gdata;
 > 
 >   idx = foo(nextdata);
 > 
 >   for (;idx != 0; --idx)
 >     {
 >       int tmp = store_data;
 >       nextdata += foo(tmp);
 >       store_data = foo(nextdata);
 >     }
 > 
 >   initiate();
 >   return 0;
 > }
 > 
 > int
 > main(void)
 > {
 >   amibuggy(9, 5, 16, 36);
 >   amibuggy(0, 0, 0, 0);
 >   return 0;
 > }
 > 
 > 
 > Compile with gcc-4.7.2 with line:
 > 
 > gcc -O2 repro.c -o repro.x86
 > 
 > Now run and you will see test "magically" failed.
 > 
 > What happens? Compiler on register allocation pass decided to reuse
 > stack slot 12(%rsp) where key_data persisted.
 > 
 > movl key_gdata(%rip), %eax
 > movl %eax, 12(%rsp)
 > call _setjmp
 > 
 > ... and later ...
 > 
 > .L10:
 > movl 12(%rsp), %edi <--- oops!
 > call foo
 > 
 > setjmp stored stack pointer, next frame slot is overwritten by
 > spill/fill (because compiler thinks that key_data is already dead at
 > this point. Then everything explodes.
 > 
 > I am not sure that it is a bug, but situation is rather complicated
 > for programmer -- I think in this case programmer really may rely on
 > context restoring after longjmp, and surprise is really great.
 > 
 > Question to gcc-help: Please comment on should I file this in
 > bugzilla, or should I live with it.
 > 
 > Question to gcc: Really I found this problem in private backend and
 > want to fix it for my users, no matter first answer is yes or no.
 > Maybe somehow restrict stack slot reusage if function calls setjmp.
 > But I am not so good in reload internals. Any advices about how to
 > locally fix it in private backend sources (I haven't still done any
 > changes to normal gcc-4.7.2, just added new machine description) are
 > very appreciated.

You need to read the C standard and understand the restrictions it
places on the values of non-volatile automatic variables when setjmp
returns due to a longjmp.  Look for "The longjmp function" in
WG14/n1124.pdf or n1494.pdf.

Then you'll need to use "volatile" or restructure your code slightly.




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux