bug-glibc
[Top][All Lists]
Advanced

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

Re: fix for atexit() bug in glibc 2.2.3


From: Franz Sirl
Subject: Re: fix for atexit() bug in glibc 2.2.3
Date: Sun, 20 May 2001 13:55:21 +0200

The patch for the gcc-2_95-branch (including other stuff) is at 
<ftp://devel.linuxppc.org/users/fsirl/>
and should fix this problem.

Bernd, can you commit the minimum patch I applied  to the mainline and the 
3.0 branch to the gcc-2_95-branch? This should do it for now (the glibc case) 
and we can talk about refinements after my vacation.

Franz.

On Sunday 20 May 2001 09:52, Andreas Jaeger wrote:
> Hi Mark and Franz, FYI: it seems that even gcc 2.95.3 on i686 miscompiles
> weak symbols.
>
> Andreas, this is a compiler bug you encounter.  Franz has some patches
> to fix this and I hope he'll point you to them, otherwise search the
> GCC mailing list archives.
>
> Andreas
>
> Andreas Steinmetz <address@hidden> writes:
> > Unfortunately applying your patch to gcc and rebuilding gcc-2.95.3, then
> > glibc-2.2.3, doesn't fix the atexit() sigsegv problem for statically
> > linked programs. So I started digging myself. Looking at atexit() in a
> > statically linked test progam:
> >
> > 0x80485d0 <atexit>:     sub    $0xc,%esp
> > 0x80485d3 <atexit+3>:   mov    $0x0,%edx
> > 0x80485d8 <atexit+8>:   mov    0x10(%esp,1),%ecx
> > 0x80485dc <atexit+12>:  xor    %eax,%eax
> > 0x80485de <atexit+14>:  add    $0xfffffffc,%esp
> > 0x80485e1 <atexit+17>:  test   %edx,%edx
> > 0x80485e3 <atexit+19>:  cmovne 0x0,%eax             <========= SIGSEGV
> > 0x80485ea <atexit+26>:  push   %eax
> > 0x80485eb <atexit+27>:  push   $0x0
> > 0x80485ed <atexit+29>:  push   %ecx
> > 0x80485ee <atexit+30>:  call   0x80486e0 <__cxa_atexit>
> > 0x80485f3 <atexit+35>:  add    $0x10,%esp
> > 0x80485f6 <atexit+38>:  add    $0xc,%esp
> > 0x80485f9 <atexit+41>:  ret
> >
> > Registers at SIGSEGV time:
> >
> > eax            0x0      0
> > ecx            0x8048210        134513168
> > edx            0x0      0
> > ebx            0xbffff9ac       -1073743444
> > esp            0xbffff910       0xbffff910
> > ebp            0xbffff93c       0xbffff93c
> > esi            0xbffff9a4       -1073743452
> > edi            0x1      1
> > eip            0x80485e3        0x80485e3
> > eflags         0x10346  66374
> > cs             0x23     35
> > ss             0x2b     43
> > ds             0x2b     43
> > es             0x2b     43
> > fs             0x0      0
> > gs             0x0      0
> > fctrl          0x37f    895
> > fstat          0x0      0
> > ftag           0xffff   65535
> > fiseg          0x10     16
> > fioff          0xc03121bf       -1070521921
> > foseg          0x0      0
> > fooff          0x0      0
> > fop            0x4f1    1265
> >
> > Well, I don't have an assembler manual around so I can't tell if the
> > access to the source by cmovne is defined as standard or if it is just an
> > unexpected speculative access (I'm running an Athlon TB900). One would
> > expect, however, that a conditional move data access would only happen if
> > the condition is met which it is not (edx=0).
> >
> > The same in the source (stdlib/atexit.c):
> >
> > /* This is defined by newer gcc version unique for each module.  */
> > extern void *__dso_handle __attribute__ ((__weak__));
> >
> >
> > /* Register FUNC to be executed by `exit'.  */
> > int
> > atexit (void (*func) (void))
> > {
> >   return __cxa_atexit ((void (*) (void *)) func, NULL,
> >                        &__dso_handle == NULL ? NULL : __dso_handle);
> > }                            ^^
> >
> >                    This being the problem
> >
> >
> > As it turns out a workaround is simple (de-optimization, patch below):
> >
> > =======snip=======
> > --- stdlib/atexit.c-2.2.3       Sat May 19 20:13:37 2001
> > +++ stdlib/atexit.c     Sat May 19 20:48:51 2001
> > @@ -28,8 +28,9 @@
> >  int
> >  atexit (void (*func) (void))
> >  {
> > -  return __cxa_atexit ((void (*) (void *)) func, NULL,
> > -                      &__dso_handle == NULL ? NULL : __dso_handle);
> > +  if(&__dso_handle)return __cxa_atexit ((void (*) (void *)) func,
> > +       NULL,__dso_handle);
> > +  else return __cxa_atexit ((void (*) (void *)) func, NULL,NULL);
> >  }
> >
> >  /* Hide the symbol so that no definition but the one locally in the
> > ======snip========
> >
> > This results in the following assembler which is 'bug free':
> >
> > 0x80485d0 <atexit>:     sub    $0xc,%esp
> > 0x80485d3 <atexit+3>:   mov    $0x0,%eax
> > 0x80485d8 <atexit+8>:   mov    0x10(%esp,1),%edx
> > 0x80485dc <atexit+12>:  test   %eax,%eax
> > 0x80485de <atexit+14>:  je     0x80485ec <atexit+28>
> > 0x80485e0 <atexit+16>:  add    $0xfffffffc,%esp
> > 0x80485e3 <atexit+19>:  mov    0x0,%eax
> > 0x80485e8 <atexit+24>:  push   %eax
> > 0x80485e9 <atexit+25>:  jmp    0x80485f1 <atexit+33>
> > 0x80485eb <atexit+27>:  nop
> > 0x80485ec <atexit+28>:  add    $0xfffffffc,%esp
> > 0x80485ef <atexit+31>:  push   $0x0
> > 0x80485f1 <atexit+33>:  push   $0x0
> > 0x80485f3 <atexit+35>:  push   %edx
> > 0x80485f4 <atexit+36>:  call   0x80486e0 <__cxa_atexit>
> > 0x80485f9 <atexit+41>:  add    $0x10,%esp
> > 0x80485fc <atexit+44>:  add    $0xc,%esp
> > 0x80485ff <atexit+47>:  ret
> >
> > I don't really know if the actual bug is caused by glibc-2.2.3 or
> > gcc-2.95.3. This problem should be solved, however, by the appropriate
> > party (please forward this mail to the proper developers, if necessary).
> > Furthermore '__dso_handle' is used in more places, especially
> > 'malloc/mtrace.c'. So further fixes may be required.
> >
> > To better check for the problem here's the configure statement (oh,
> > configure needs to be modified to be able to not build against libgd even
> > when it is around, I patched that the hard way...) and the compiler
> > flags:
> >
> > ../configure  --prefix=/usr --enable-add-ons --disable-profile
> > --enable-kernel=2.2.18 --with-headers=/usr/src/linux/include
> > --without-gmp --without-gd --without-gd-include --without-gd-lib
> > --without-cvs --with-elf --enable-shared
> >
> > CFLAGS=-O3 -fomit-frame-pointer -funroll-loops -fexpensive-optimizations
> > -fschedule-insns2 -mwide-multiply -march=pentiumpro -mcpu=pentiumpro
> > -malign-loops=2 -malign-jumps=2 -malign-functions=4
> >
> > CXXFLAGS=-O3 -fomit-frame-pointer -funroll-loops
> > -fexpensive-optimizations -fschedule-insns2 -mwide-multiply
> > -march=pentiumpro -mcpu=pentiumpro -malign-loops=2 -malign-jumps=2
> > -malign-functions=4
> >
> > When I'm at it: 'make check' uses somewhere a hardcoded '/bin/cat' which
> > is not nice if cat is not in /bin. 'make install' doesn't honor a
> > softlink for '/etc/ld.so.cache' but replaces the softlink with a new
> > cache file.
> >
> > On 16-May-2001 Andreas Jaeger wrote:
> > > Andreas Steinmetz <address@hidden> writes:
> > >> Hi,
> > >> when building static (-static) versions of fileutils-4.1 with gcc
> > >> 2.95.3 the resulting binaries segfault in atexit(). Temporary fix for
> > >> me is an atexit() shim diverting the call to on_exit().
> > >
> > > Did you apply the appended patch to GCC 2.95.3 as mentioned in the
> > > release notes?
> > >
> > >> After the upgrade from 2.2.2 to 2.2.3 the following packages stopped
> > >> working and had to be rebuilt against the new library:
> > >>
> > >> ypserv-1.3.12
> > >> nfs-utils-0.3.1 (rpc.kstatd)
> > >
> > > Really?
> > >
> > >> Installing glibc-2.2.3 did cause problems too:
> > >>
> > >> [snip]
> > >>
> > >> make  -C linuxthreads subdir_install
> > >> make[2]: Entering directory `/usr/src/glibc-2.2.3/linuxthreads'
> > >> /bin/install -c -m 644 ../linuxthreads/sysdeps/pthread/pthread.h
> > >> /usr/include/pt/bin/install -c -m 644 semaphore.h
> > >> /usr/include/semaphore.h /bin/install -c
> > >> /usr/src/glibc-2.2.3/build/linuxthreads/libpthread.so
> > >> /lib/libpthread-0.9.so.new
> > >> mv -f /lib/libpthread-0.9.so.new /lib/libpthread-0.9.so
> > >> echo libpthread-0.9.so /lib/libpthread.so.0 >>
> > >> /usr/src/glibc-2.2.3/build/elf/symlink.list
> > >> rm -f /usr/lib/libpthread.so.new
> > >> /bin/sh ../scripts/rellns-sh /lib/libpthread.so.0
> > >> /usr/lib/libpthread.so.new mv -f /usr/lib/libpthread.so.new
> > >> /usr/lib/libpthread.so
> > >> /bin/install -c -m 644
> > >> /usr/src/glibc-2.2.3/build/linuxthreads/libpthread.a
> > >> /usr/lib/libpthread.a
> > >>
> > >> : /usr/lib/libpthread.a
> > >>
> > >> make[2]: Leaving directory `/usr/src/glibc-2.2.3/linuxthreads'
> > >> make  -C resolv subdir_install
> > >> make: /lib/libc.so.6: version `GLIBC_2.2.3' not found (required by
> > >> /lib/libpthread.so.0)
> > >> make[1]: *** [resolv/subdir_install] Error 1
> > >> make[1]: Leaving directory `/usr/src/glibc-2.2.3'
> > >> make: *** [install] Error 2
> > >>
> > >> This happens as (at least my) make (make-3.79.1) is linked against
> > >> libpthread.so.0 which is installed before the symbolic link
> > >> /lib/libc.so.6 is
> > >> set up to point to the new glibc. Workaround is to use a statically
> > >> linked make
> > >> during installation (if you have one available).
> > >
> > > I'll forward this,
> > > Andreas
> > >
> > >
> > > P.S. see http://gcc.gnu.org/ml/gcc-patches/2001-03/msg01187.html
> > >
> > > 2001-03-16  Jakub Jelinek  <address@hidden>
> > >
> > >         * crtstuff.c (init_dummy): Use CRT_END_INIT_DUMMY if defined.
> > >         Remove ia32 linux PIC kludge and move it...
> > >         * config/i386/linux.h (CRT_END_INIT_DUMMY): ...here.
> > >
> > > --- gcc/config/i386/linux.h.jj  Mon Mar 12 11:45:15 2001
> > > +++ gcc/config/i386/linux.h     Fri Mar 16 18:52:31 2001
> > > @@ -170,3 +170,21 @@ Boston, MA 02111-1307, USA.  */
> > >      }                                                                 
> > > \ } while (0)
> > >  #endif
> > > +
> > > +#if defined(__PIC__) && defined (USE_GNULIBC_1)
> > > +/* This is a kludge. The i386 GNU/Linux dynamic linker needs
> > > ___brk_addr, +   __environ and atexit (). We have to make sure they are
> > > in the .dynsym +   section. We accomplish it by making a dummy call
> > > here. This +   code is never reached.  */
> > > +
> > > +#define CRT_END_INIT_DUMMY             \
> > > +  do                                   \
> > > +    {                                  \
> > > +      extern void *___brk_addr;                \
> > > +      extern char **__environ;         \
> > > +                                       \
> > > +      ___brk_addr = __environ;         \
> > > +      atexit (0);                      \
> > > +    }                                  \
> > > +  while (0)
> > > +#endif
> > > ============================================================
> > > Index: gcc/crtstuff.c
> > > --- gcc/crtstuff.c    1999/03/23 00:43:51     1.18
> > > +++ gcc/crtstuff.c    2001/03/19 10:21:44
> > > @@ -379,20 +379,8 @@
> > >    FORCE_INIT_SECTION_ALIGN;
> > >  #endif
> > >    asm (TEXT_SECTION_ASM_OP);
> > > -
> > > -/* This is a kludge. The i386 GNU/Linux dynamic linker needs
> > > ___brk_addr, -   __environ and atexit (). We have to make sure they are
> > > in the .dynsym -   section. We accomplish it by making a dummy call
> > > here. This -   code is never reached.  */
> > > -
> > > -#if defined(__linux__) && defined(__PIC__) && defined(__i386__)
> > > -  {
> > > -    extern void *___brk_addr;
> > > -    extern char **__environ;
> > > -
> > > -    ___brk_addr = __environ;
> > > -    atexit ();
> > > -  }
> > > +#ifdef CRT_END_INIT_DUMMY
> > > +  CRT_END_INIT_DUMMY;
> > >  #endif
> > >  }
> > >
> > >
> > >
> > > --
> > >  Andreas Jaeger
> > >   SuSE Labs address@hidden
> > >    private address@hidden
> > >     http://www.suse.de/~aj
> >
> > Andreas Steinmetz
> > D.O.M. Datenverarbeitung GmbH



reply via email to

[Prev in Thread] Current Thread [Next in Thread]