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

Eric Deplagne Eric.Deplagne at wanadoo.fr
Thu Nov 16 05:57:10 PST 2006


On Thu, 16 Nov 2006 13:29:51 +0000, Andrew Haley wrote:
> 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.

  OK...

  What I have trouble with it that it is not reordering the two asm()
  statements with respect to each other. But it is reordering one of
  them for optimisation purposes.

> #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.

  Like it could just move it outside of the loop.

  Means "asm volatile" is the thing to do in my case, if I wanted to keep the asm()...

  Still funny only gcc-3.4 did reorder the thing...

-- 
  Eric Deplagne
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://napali.hpl.hp.com/pipermail/gc/attachments/20061116/f8fd9e43/attachment-0001.pgp


More information about the Gc mailing list