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

Re: bug with libgnome-perl



On Wed, May 26, 1999 at 04:26:25PM +0200, Joyot Pierre wrote:

> I have a problem libgnome-perl exemples(/usr/doc/libgnome-perl/examples)
> 
> > perl simple.pl
> Wed May 26 16:24:56 1999 Gtk-WARNING **:
> /usr/lib/gtk/themes/engines/libpixmap.so: undefined symbol:
> gdk_rectangle_intersect at simple.pl line 17.
> Segmentation fault

This is a problem with the theme engines. They are not explicitly linked
against libgtk et. al. so they can't access their symbols because they are
neither in the global symtable (the program and its dependencies go there) nor
listed as dependencies of the engine.

I wrote a long explanation to the PyGTK mailing list - python-gnome has the
same problem. I attached that mail for reference.

cu
    Torsten
--- Begin Message ---
Hi *, 

I am sorry I did not write to this list earlier. I did some investigation on
the themes-related bug in PyGTK and came to the conclusion that it is not
a bug in pygtk. In fact the theme engines are at fault.

You need some background information to understand the problem. If you are
familar with the scopes of symbols in the dynamic linker you can skip this
section.

Okay - here is how loading an object works:

1. the object requested is mapped into the address space of the program.
   (if this wasn't done already)
2. the objects required by this object are mapped
3. the symbols are resolved

We hit the wall at step three - the dynamic linker can not resolve the symbols
of the theme engine (in my case it is libpixmap.so). This is from the debugging
output of the dynamic linker (enabled with export LD_DEBUG=symbols; export
LD_DEBUG_OUTPUT=/tmp/foo):

01507:  symbol=gdk_display;  lookup in file=python
01507:  symbol=gdk_display;  lookup in file=/usr/lib/libpython1.5.so.0.0
01507:  symbol=gdk_display;  lookup in file=/lib/libdl.so.2
01507:  symbol=gdk_display;  lookup in file=/lib/libpthread.so.0
01507:  symbol=gdk_display;  lookup in file=/lib/libm.so.6
01507:  symbol=gdk_display;  lookup in file=/lib/libc.so.6
01507:  symbol=gdk_display;  lookup in file=/lib/ld-linux.so.2
01507:  symbol=gdk_display;  lookup in
file=/usr/lib/gtk/themes/engines/libpixmap.so
01507:  symbol=gdk_display;  lookup in file=/usr/lib/libgdk_imlib.so.1
01507:  symbol=gdk_display;  lookup in file=/usr/lib/libgmodule-1.2.so.0
01507:  symbol=gdk_display;  lookup in file=/lib/libdl.so.2
01507:  symbol=gdk_display;  lookup in file=/usr/X11R6/lib/libXi.so.6
01507:  symbol=gdk_display;  lookup in file=/usr/X11R6/lib/libXext.so.6
01507:  symbol=gdk_display;  lookup in file=/usr/X11R6/lib/libX11.so.6
01507:  symbol=gdk_display;  lookup in file=/lib/libm.so.6
01507:  symbol=gdk_display;  lookup in file=/lib/libc.so.6
01507:  symbol=gdk_display;  lookup in file=/usr/lib/libglib-1.2.so.0
01507:  symbol=gdk_display;  lookup in file=/lib/ld-linux.so.2

As you can see he does not try to load the symbols from libgtk.so. Why?

So where does ld.so seek for symbols? 
1. it searches the global scope
2. it searches the object itself
3. it searches the dependencies of the object the symbol is needed in.

What is in the global scope? dl-deps.c from the libc6 source says:

  /* Now that all this succeeded put the objects in the global scope if
     this is necessary.  We put the original object and all the dependencies
     in the global scope.  If an object is already loaded and not in the
     global scope we promote it.  */

This is a bit ambiguous. In fact the original object (python) and its
dependencies are put into the global scope. So let's construct the searchlist
for libpixmap.so:

1. the global scope
    
    python - the object itself

    torsten@pulsar:~ $ ldd /usr/bin/python - the dependencies
        libpython1.5.so.0.0 => /usr/lib/libpython1.5.so.0.0 (0x40005000)
        libdl.so.2 => /lib/libdl.so.2 (0x4006f000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x40073000)
        libm.so.6 => /lib/libm.so.6 (0x40084000)
        libc.so.6 => /lib/libc.so.6 (0x400a1000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00000000)

2. the object itself

    libpixmap.so

3. its dependencies

    torsten@pulsar:~ $ ldd /usr/lib/gtk/themes/engines/libpixmap.so
        libgdk_imlib.so.1 => /usr/lib/libgdk_imlib.so.1 (0x4000e000)
        libgmodule-1.2.so.0 => /usr/lib/libgmodule-1.2.so.0 (0x4003c000)
        libdl.so.2 => /lib/libdl.so.2 (0x40040000)
        libXi.so.6 => /usr/X11R6/lib/libXi.so.6 (0x40043000)
        libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x4004b000)
        libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40057000)
        libm.so.6 => /lib/libm.so.6 (0x400fd000)
        libc.so.6 => /lib/libc.so.6 (0x40293000)
        libglib-1.2.so.0 => /usr/lib/libglib-1.2.so.0 (0x40271000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00000000)

Now compare these lists - the debug output and this list correspond exactly. 



Okay, so what can we do about this? Remember this:

        Where does ld.so seek for symbols? 
        1. it searches the global scope
        2. it searches the object itself
        3. it searches the dependencies of the object the symbol is needed in.

So we could put the libgtk and libgdk in (1), (2) or (3). Of course (2) will
not work - we do not want to statically link libpixmap against libg[dt]k. 

What can we do about (1) - no problem. We can manually put libgdk and libgtk
in there. We only need to do dlopen("libgtk.so", RTLD_LAZY|RTLD_GLOBAL). The
problem is that we have to sync this with the lib linked against _gtkmodule.so
- at least it has to have the same soname as the dynamic linker will catch
this. Of course we need libgdk.so also.

Fine. But the simplest way to get out of this is: simply use the dependency
information of libpixmap.so to put libgtk.so and libgdk.so in (3). This only
requires a simple patch to the Makefile of the theme engines:

torsten@pulsar:~/test/gtk-engines-thinice-1.0.1 $ diff -u Makefile.am
Makefile.am.new
--- Makefile.am Tue May 25 20:12:46 1999
+++ Makefile.am.new     Tue May 25 20:12:40 1999
@@ -9,4 +9,5 @@
        thinice_theme_main.c    \
        thinice_theme.h
 libthinice_la_LDFLAGS = -export-dynamic
+libthinice_la_LIBADD = $(GTK_LIBS)
 EXTRA_DIST = autogen.sh

After this patch the thinice engine works with no problem on my system. Even
perl-gtk starts working. Before it had the same problem.

Conclusion: Let's talk to the engines authors and tell them how to fix their
packages.

Thanks
    Torsten

PS: This is Cc'ed to a Debian bugreport. Please keep the Cc when answering to
this mail.

--- End Message ---

Reply to: