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]

 



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.

---
With best regards, Konstantin




[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