This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

shared lib problem with atexit



Hi, ELF experts,

With recent glibc, I'm getting a link error when trying to build applications
using libqt. I don't understand where the problem lies - in libc or in the
linker.

$ gcc hello.c -lqt
/packages/gnu/XFree86/lib/libX11.so.6: undefined reference to `atexit'
collect2: ld returned 1 exit status

where hello.c is a trivial C hello-world program.

The situation:

- CPU is i686,
- gcc is gcc-2.95.3.
- binutils (as, ld, ...) are binutils-2.10.0.18 and identify themselves as
  "GNU ld 2.10.90".
- /usr/lib/libqt.so.1 and /usr/lib/libqt.so.2 are from SuSE 7.0.
- on 2001-04-12, I installed glibc-2001-03-15 from sources, with
  --prefix=/usr,
- on 2001-04-21, I installed XFree86-4.0.99.2 from sources, with
  --prefix=/packages/gnu/XFree86
- now I installed glibc-2001-04-30 from sources, with --prefix=/usr.

The source:
====================== hello.c ===========================
#include <stdio.h>
main ()
{
  printf("Hello, world.\n");
  return 0;
}
==========================================================

The link error occurs when I have set LD_LIBRARY_PATH.
Without LD_LIBRARY_PATH:
  $ gcc hello.c -lqt
  OK
With LD_LIBRARY_PATH:
  $ LD_LIBRARY_PATH=/packages/gnu/XFree86/lib \
    gcc hello.c -lqt
  /packages/gnu/XFree86/lib/libX11.so.6: undefined reference to `atexit'
  collect2: ld returned 1 exit status

Calling collect2 directly:

  $ LD_LIBRARY_PATH=/packages/gnu/XFree86/lib \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/collect2 -m elf_i386 \
    -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtbegin.o \
    -L/packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3 -L/usr/local/lib \
    hello.o -lqt \
    -lgcc -lc -lgcc \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtend.o /usr/lib/crtn.o
  /packages/gnu/XFree86/lib/libX11.so.6: undefined reference to `atexit'
  collect2: ld returned 1 exit status

Same with "-lqt" replaced by "/usr/lib/libqt.so.1" or "/usr/lib/libqt.so.2".

libX11 comes in as a dependency from libqt.

  $ ldd /usr/lib/libqt.so.1
        libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x401f7000)
        libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x402c7000)
        libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x402d5000)
        libc.so.6 => /lib/libc.so.6 (0x402f4000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)

  $ LD_LIBRARY_PATH=/packages/gnu/XFree86/lib \
    ldd /usr/lib/libqt.so.1
        libX11.so.6 => /packages/gnu/XFree86/lib/libX11.so.6 (0x401eb000)
        libXext.so.6 => /packages/gnu/XFree86/lib/libXext.so.6 (0x402cb000)
        libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x402e5000)
        libc.so.6 => /lib/libc.so.6 (0x40304000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)

How do these libraries refer to 'atexit'?

  $ nm /usr/lib/libqt.so.1 | grep atexit
         U atexit@@GLIBC_2.0
  $ nm /usr/lib/libqt.so.2 | grep atexit
         U atexit@@GLIBC_2.0
  $ nm /usr/X11R6/lib/libX11.so.6 | grep atexit
         U atexit@@GLIBC_2.0
  $ nm /packages/gnu/XFree86/lib/libX11.so.6 | grep atexit
         U atexit

So the difference between without/with LD_LIBRARY_PATH is that the libX11
it uses refers to a qualified/unqualified 'atexit' symbol.

Another strange behaviour is that when I explicitly insert the libX11
that causes the error into the link command line, the error goes away!

  $ LD_LIBRARY_PATH=/packages/gnu/XFree86/lib \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/collect2 -m elf_i386 \
    -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtbegin.o \
    -L/packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3 -L/usr/local/lib \
    hello.o /usr/lib/libqt.so.1 /packages/gnu/XFree86/lib/libX11.so.6 \
    -lgcc -lc -lgcc \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtend.o /usr/lib/crtn.o
  OK!!

Or when /usr/lib/libqt.so.1 is dropped and only libX11.so.6 is referred to,
the error goes away as well.

  $ LD_LIBRARY_PATH=/packages/gnu/XFree86/lib \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/collect2 -m elf_i386 \
    -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtbegin.o \
    -L/packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3 -L/usr/local/lib \
    hello.o /packages/gnu/XFree86/lib/libX11.so.6 \
    -lgcc -lc -lgcc \
    /packages/gnu/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/crtend.o /usr/lib/crtn.o
  OK!!

Another strange point is the list of undefined symbols of the two libraries:

$ diff <(nm /usr/X11R6/lib/libX11.so.6 | grep ' U ') \
       <(nm /packages/gnu/XFree86/lib/libX11.so.6 | grep ' U ')
...
15c16
<          U atexit@@GLIBC_2.0
---
>          U atexit
...

$ nm /usr/X11R6/lib/libX11.so.6 | grep ' U '
         U _IO_getc@@GLIBC_2.0
         U _IO_putc@@GLIBC_2.0
         U ___brk_addr@@GLIBC_2.0
         U __ctype_b@@GLIBC_2.0
         U __ctype_get_mb_cur_max@@GLIBC_2.0
         U __ctype_tolower@@GLIBC_2.0
         U __ctype_toupper@@GLIBC_2.0
         U __curbrk@@GLIBC_2.0
         U __environ@@GLIBC_2.0
         U __errno_location@@GLIBC_2.0
         U __fxstat@@GLIBC_2.0
         U __strtol_internal@@GLIBC_2.0
         U __xstat@@GLIBC_2.0
         U access@@GLIBC_2.0
         U atexit@@GLIBC_2.0
         U calloc@@GLIBC_2.0
         U close@@GLIBC_2.0
         U connect@@GLIBC_2.0
         U exit@@GLIBC_2.0
         U fclose@@GLIBC_2.1
         U fcntl@@GLIBC_2.0
         U ferror@@GLIBC_2.0
         U fflush@@GLIBC_2.0
         U fgets@@GLIBC_2.0
         U fileno@@GLIBC_2.0
         U fopen@@GLIBC_2.1
         U fprintf@@GLIBC_2.0
         U fputs@@GLIBC_2.0
         U fread@@GLIBC_2.0
         U free@@GLIBC_2.0
         U fwrite@@GLIBC_2.0
         U getenv@@GLIBC_2.0
         U gethostbyname@@GLIBC_2.0
         U getpeername@@GLIBC_2.0
         U getpid@@GLIBC_2.0
         U getpwnam_r@@GLIBC_2.0
         U getpwuid_r@@GLIBC_2.0
         U getservbyname@@GLIBC_2.0
         U getsockname@@GLIBC_2.0
         U getuid@@GLIBC_2.0
         U inet_addr@@GLIBC_2.0
         U ioctl@@GLIBC_2.0
         U malloc@@GLIBC_2.0
         U mblen@@GLIBC_2.0
         U mbtowc@@GLIBC_2.0
         U memcpy@@GLIBC_2.0
         U memmove@@GLIBC_2.0
         U memset@@GLIBC_2.0
         U open@@GLIBC_2.0
         U pthread_cond_broadcast@@GLIBC_2.0
         U pthread_cond_destroy@@GLIBC_2.0
         U pthread_cond_init@@GLIBC_2.0
         U pthread_cond_signal@@GLIBC_2.0
         U pthread_cond_wait@@GLIBC_2.0
         U pthread_equal@@GLIBC_2.0
         U pthread_mutex_destroy@@GLIBC_2.0
         U pthread_mutex_init@@GLIBC_2.0
         U pthread_mutex_lock@@GLIBC_2.0
         U pthread_mutex_unlock@@GLIBC_2.0
         U pthread_self@@GLIBC_2.0
         U qsort@@GLIBC_2.0
         U read@@GLIBC_2.0
         U readv@@GLIBC_2.0
         U realloc@@GLIBC_2.0
         U rewind@@GLIBC_2.0
         U select@@GLIBC_2.0
         U setlocale@@GLIBC_2.0
         U setsockopt@@GLIBC_2.0
         U shutdown@@GLIBC_2.0
         U sleep@@GLIBC_2.0
         U socket@@GLIBC_2.0
         U sprintf@@GLIBC_2.0
         U sscanf@@GLIBC_2.0
         U stderr@@GLIBC_2.0
         U strcat@@GLIBC_2.0
         U strchr@@GLIBC_2.0
         U strcmp@@GLIBC_2.0
         U strcpy@@GLIBC_2.0
         U strerror@@GLIBC_2.0
         U strncmp@@GLIBC_2.0
         U strncpy@@GLIBC_2.0
         U strrchr@@GLIBC_2.0
         U time@@GLIBC_2.0
         U uname@@GLIBC_2.0
         U ungetc@@GLIBC_2.0
         U unlink@@GLIBC_2.0
         U wctomb@@GLIBC_2.0
         U write@@GLIBC_2.0
         U writev@@GLIBC_2.0
$ nm /packages/gnu/XFree86/lib/libX11.so.6 | grep ' U '
         U _IO_getc@@GLIBC_2.0
         U _IO_putc@@GLIBC_2.0
         U ___brk_addr@@GLIBC_2.0
         U __ctype_b@@GLIBC_2.0
         U __ctype_get_mb_cur_max@@GLIBC_2.0
         U __ctype_tolower@@GLIBC_2.0
         U __ctype_toupper@@GLIBC_2.0
         U __curbrk@@GLIBC_2.0
         U __environ@@GLIBC_2.0
         U __errno_location@@GLIBC_2.0
         U __fxstat@@GLIBC_2.0
         U __strtol_internal@@GLIBC_2.0
         U __xstat@@GLIBC_2.0
         U abort@@GLIBC_2.0
         U access@@GLIBC_2.0
         U atexit
         U calloc@@GLIBC_2.0
         U close@@GLIBC_2.0
         U connect@@GLIBC_2.0
         U exit@@GLIBC_2.0
         U fclose@@GLIBC_2.1
         U fcntl@@GLIBC_2.0
         U ferror@@GLIBC_2.0
         U fflush@@GLIBC_2.0
         U fgets@@GLIBC_2.0
         U fileno@@GLIBC_2.0
         U fopen@@GLIBC_2.1
         U fprintf@@GLIBC_2.0
         U fputs@@GLIBC_2.0
         U fread@@GLIBC_2.0
         U free@@GLIBC_2.0
         U fwrite@@GLIBC_2.0
         U getenv@@GLIBC_2.0
         U gethostbyname@@GLIBC_2.0
         U getpeername@@GLIBC_2.0
         U getpwnam_r@@GLIBC_2.1.2
         U getpwuid_r@@GLIBC_2.1.2
         U getservbyname@@GLIBC_2.0
         U getsockname@@GLIBC_2.0
         U getuid@@GLIBC_2.0
         U inet_addr@@GLIBC_2.0
         U ioctl@@GLIBC_2.0
         U malloc@@GLIBC_2.0
         U mblen@@GLIBC_2.0
         U mbtowc@@GLIBC_2.0
         U memcpy@@GLIBC_2.0
         U memmove@@GLIBC_2.0
         U memset@@GLIBC_2.0
         U open@@GLIBC_2.0
         U pthread_cond_broadcast@@GLIBC_2.0
         U pthread_cond_destroy@@GLIBC_2.0
         U pthread_cond_init@@GLIBC_2.0
         U pthread_cond_signal@@GLIBC_2.0
         U pthread_cond_wait@@GLIBC_2.0
         U pthread_equal@@GLIBC_2.0
         U pthread_mutex_destroy@@GLIBC_2.0
         U pthread_mutex_init@@GLIBC_2.0
         U pthread_mutex_lock@@GLIBC_2.0
         U pthread_mutex_unlock@@GLIBC_2.0
         U pthread_self@@GLIBC_2.0
         U qsort@@GLIBC_2.0
         U read@@GLIBC_2.0
         U readv@@GLIBC_2.0
         U realloc@@GLIBC_2.0
         U rewind@@GLIBC_2.0
         U select@@GLIBC_2.0
         U setlocale@@GLIBC_2.0
         U setsockopt@@GLIBC_2.0
         U shmat@@GLIBC_2.0
         U shmctl@@GLIBC_2.2
         U shmdt@@GLIBC_2.0
         U shutdown@@GLIBC_2.0
         U sleep@@GLIBC_2.0
         U socket@@GLIBC_2.0
         U sprintf@@GLIBC_2.0
         U sscanf@@GLIBC_2.0
         U stderr@@GLIBC_2.0
         U strcat@@GLIBC_2.0
         U strchr@@GLIBC_2.0
         U strcmp@@GLIBC_2.0
         U strcpy@@GLIBC_2.0
         U strerror@@GLIBC_2.0
         U strncmp@@GLIBC_2.0
         U strncpy@@GLIBC_2.0
         U strpbrk@@GLIBC_2.0
         U strrchr@@GLIBC_2.0
         U strstr@@GLIBC_2.0
         U uname@@GLIBC_2.0
         U ungetc@@GLIBC_2.0
         U unlink@@GLIBC_2.0
         U wctomb@@GLIBC_2.0
         U write@@GLIBC_2.0
         U writev@@GLIBC_2.0

Why does _only_ 'atexit' refer to a symbol without version?

Bruno


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]