From: hlu@yoda.eecs.wsu.edu (H.J. Lu)
Subject: Re: Shared Libs for X11?, was Re: 386bsd -- The New Newsgroup
Keywords: shared libraries X X11
Organization: Washington State University
Date: Sat, 12 Sep 92 17:04:25 GMT

In article <veit.716291291@du9ds3> veit@du9ds3.uni-duisburg.de writes:
>In <7dnL02y821gh01@JUTS.ccc.amdahl.com> gab10@griffincd.amdahl.com (Gary A Browning) writes:
>>In article <veit.716107923@du9ds3>, veit@du9ds3.uni-duisburg.de (Holger
>>Veit) writes:
>[...]
>>I just finished installing X and noticed that most binaries are several times
>>larger than expected due to the lack of shared libraries.  I caught an article
>>posted here a few days back that quickly described the SysVr3 approach of using
>>fixed addresses for the libraries and the Sun/SysVr4 approach of using position
>>independent code.
>
>>I tend to dislike the SysVr3 method since I got the impression that the source
>>code had to be written differently (though I am not sure why).  I also noted
>>that the GCC-2.2.2 compiler I just got compiled can produce PIC code which
>>would be one of the major hurdles for the SysVr4 method.
>
>I don't like the fixed-address idea either, since it causes trouble with
>applications that rely on the addresses. If someone wants to have some special 
>library as shared he has to allocate some address for it. This will make this
>space unavailable for others who wanted to use the same address and will cause
>complex incompatibilities. It is, however, very simple to implement, and does
>work if there is the intent to have one (forever fixed) set of standard
>shared libraries. I looked at the Linux code and found it done exactly this
>way, and it is recommended there to relink the object files on every new 
>system.
>

[....]

That will be the old news for Linux starting this Sunday. As a matter
of fact, I have beening using the new scheme for a while. I fixed a bug
in libc.a and made a new shared image. Then I did

ln -sf /lib/libc.so.4.1 /lib/libc.so.4

That fixed `date' without ever touching it. Here is the short
note I wrote for the shared lib under Linux. I like it since it
is simple. It requires almost no changes to GNU binutils 1.9 except for
bug fixes. No gcc changes are needed. The kernel support is minimal.

A related issue, is there a good, simple way to resolve the global
data without relinking the executables? Their addresses are very likely
to change if the library codes are not written for the shared
libraries.

H.J.
-----
The shared library under Linux started at 0.12. Peter MacDonald
collaborating with Linus made the first generation of shared library,
which is the base of the current classic shared library.

The kernel support of shared library under Linux is system call

extern int uselib (const char *__filename);

which loads an executable image with fixed entry point into memory,
just like the ordinary executables.

In crt0.s, a function which can find out if and which shared images
are needed and loads them is invoked before `main ()' is called if
necessary. David Engel and I developed a way to tell the loader which
shared images have to be loaded, utilizing the similar technique used
in global constructor in g++ 2.x with the help from GNU binary
utilities.

In the classic Linux shared library, we build a big executable image 
for several libraries and make sure no external variables outside of
the participating libraries are referenced. Then we can get the
absolute addresses of all the global variables defined in the
libraries used to build that executable image. After that, we make a
stub library for each participating library which just has the
absolute addresses of all the global variable in it.

For each shared image, there must be one and only one file, usually
called, __shared.o, which defines a global variable containing
version, name and entry point of the shared image, and a dummy global
data. Among those libraries used to build the shared image, there must
be one library which will always be referenced whenever any other
library is referenced. We put `__shared.o' into the stub library for
that library and add a declaration for the dummy global data defined
in `__shared.o' which will make sure `__shared.o' will always be linked
in when any participating libraries are linked.

In gcc 2.2.2d, jump table, developed by David Engel, was introduced in 
the shared library. At the beginning of each shared image, there is
a table in which every library function has a fixed entry address and
the instruction at that address is a jump which will lead to the
real library function. So we can change the library function without
changing the corresponding entry address of the jump table. For the
global data we put them at the beginning of data section of the shared
image. We have to separate them from text code and link them in fixed
order. It is very hard to maintain the same addresses for the global
data when library is changed. After the global data are set up properly
and some spaces are left for possible future changes (that is a very
tough procedure.), it isn't too difficult to maintain.

In the current implementation, only libc.a, libcurses.a, libdbm.a,
libtermcap.a and libm.a are built with jump table. The global data in
X11 libraries are too complicated to make jump table such that their
addresses won't change when there is a change in X11 libraries. It's
not apparent yet that the benefits gained from a jump table version of
the X libraries would offset the effort required to set it up and
maintain it unless we get some cooperation from X Consortium, which
is very unlikely. But they are linked with jump table version of
libc.a and libm.a. That means they don't have to be relinked when
there is a modification in libc.a or libm.a.

There are some guidelines for writing codes suitable for building the
shared library with jump table.

1. Never, ever allow library users to access global data directly.
   Always, always make them go through access functions.  That way,
   you are free to change the internal implementation, but can
   easily provide backward compatibility by simply replacing the
   access functions.

2. If you do have to define some global data for library users to
   access, put them into a separate file. Never mix them with other
   library code. Also make sure the relative locations of the global
   data will not change very often. One solution is leave some spaces
   for them to grow.


H.J. Lu
hlu@eecs.wsu.edu
09/01/92


Newsgroups: comp.unix.bsd