[Gc] Gc segfault with gcc-3.4 and Gc segfault under valgrind

Andrew Haley aph at redhat.com
Thu Nov 16 05:29:51 PST 2006


Eric Deplagne writes:
 > On jeu, 16 nov 2006 12:46:26 +0000, Andrew Haley wrote:
 > > Eric Deplagne writes:
 > >  >   Hi,
 > >  > 
 > >  >     I've found out what was causing the segfault with gcc-3.4, and it
 > >  >     was not the gc.
 > >  > 
 > >  >     It was in fact the choice-point library, which also deals with the stack,
 > >  >     in order to release the constraint of longjmp being called from a function
 > >  >     called from the function calling setjmp.
 > >  > 
 > >  >     Let me explain what was going on, it's a good piece of gcc optimisation problem.
 > >  > 
 > >  >     The problem is the use of an asm() instruction to get the stack pointer,
 > >  >     as the following simple test_asm.c shows:
 > >  >     (btw, I could not reproduce it on any other gcc than gcc-3.4,
 > >  >      so maybe a (know ?) gcc-3.4 bug, or is it simply a bad idea in the first place ?)
 > >  > 
 > >  >     #include <stdio.h>
 > >  > 
 > >  >     void *s1;
 > >  >     void *s2;
 > >  > 
 > >  >     int main(void) {
 > >  >       void *s3;
 > >  >       
 > >  >       asm ("mov %%esp,%0" : "=g" (s1) : : "esp");
 > >  > 
 > >  >       asm ("mov %%esp,%0" : "=g" (s2));
 > >  > 
 > >  >       s3=(void *)(((int)s1)+((int)s2));
 > >  > 
 > >  >       printf("s3=s1+s2=%p\n",s3);
 > >  > 
 > >  >       printf("s1=%p, s2=%p\n",s1,s2);
 > >  > 
 > >  >       s3=(void *)(((int)s1)+((int)s2));
 > >  > 
 > >  >       printf("s3=s1+s2=%p\n",s3);
 > >  > 
 > >  >       return 0;
 > >  >     }
 > > 
 > > It's not a bug.
 > > 
 > > gcc is reordering instructions and eliminating memory accesses.  The
 > > essential problem here is that gcc isn't being told enough about the
 > > data flow in the asm instructions: they have no inputs and an output,
 > > and apart from the clobber they are identical.  So, gcc knows that
 > > these asms will give identical results, no matter where they are
 > > executed.  gcc also knows that s3 may be replaced by (s1+s2) and that
 > > s2==s1.
 > > 
 > > gcc doesn't know that sp is used as an input to these asms.
 > > 
 > > I'd make the asms volatile, which will prevent gcc from eliminating
 > > them or redordering them.
 > 
 >   It's not reordering the two asm() statements, if it's whay you mean.

Yes, it is.  On the asm output you posted there are three asm outputs;
in your C source there were only two.

#APP
        mov %esp,%eax   # s1
#NO_APP
        movl    %esp, %ebp      #,
        subl    $24, %esp       #,
        addl    %eax, %eax      # s3
        andl    $-16, %esp      #,
        subl    $16, %esp       #,
#APP
        mov %esp,s2     # s2
        mov %esp,s1     # s1
#NO_APP


 >   $cat test_asm2.c
 >   #include <stdio.h>
 > 
 >   void *s2;
 > 
 >   int main(void) {
 >     void *s3;
 > 
 >     asm ("mov %%esp,%0" : "=g" (s2));
 > 
 >     s3=s2+1;
 > 
 >     printf("s3=s2+1=%p\n",s3);
 > 
 >     printf("s2=%p\n",s2);
 > 
 >     s3=s2+1;
 > 
 >     printf("s3=s2+1=%p\n",s3);
 > 
 >     return 0;
 >   }
 > 
 >   $ ./test_asm2
 >   s3=s2+1=0xbf9495f9
 >   s2=0xbf9495f0
 >   s3=s2+1=0xbf9495f1

Same thing:

#APP
        mov %esp,%eax   # s2
#NO_APP
        movl    %esp, %ebp      #,
        subl    $8, %esp        #,
        incl    %eax    # s3
        andl    $-16, %esp      #,
        subl    $16, %esp       #,
        movl    %eax, 4(%esp)   # s3,
        movl    $.LC0, (%esp)   #,
#APP
        mov %esp,s2     # s2
#NO_APP

 >   I understand the problem is that gcc doesn't know esp is read,
 >   but I really can't feel sure about any way of telling it which
 >   would not be by artefact... (btw, gcc does not know that s1==s2)
 >
 >   The clobber-list is for written registers, that's not really the case.
 >   Making the asm() statement "volatile" is for it not to be removed,
 >   it won't be removed here, and if I did not use the result, I would
 >   actually want it removed. Or did I get the meaning of volatile wrong ?
 >   (making s2 a volatile variable makes nothing but warnings).

Yes, you did get the meaning of volatile wrong.  volatile stops it
from being moved or from being executed more than once.  Your're
telling gcc that this asm depends on something that gcc doesn't know
about.  For example, if you have an asm that reads a counter, you have
to make that asm volatile or gcc will assume that its result does not
change.

Andrew.


More information about the Gc mailing list