Return to BSD News archive
Newsgroups: comp.unix.bsd Path: sserve!manuel!munnari.oz.au!uunet!europa.asd.contel.com!darwin.sura.net!zaphod.mps.ohio-state.edu!rpi!usenet.coe.montana.edu!news.u.washington.edu!serval!yoda.eecs.wsu.edu!hlu From: hlu@yoda.eecs.wsu.edu (H.J. Lu) Subject: Re: Shared Libs for X11?, was Re: 386bsd -- The New Newsgroup Message-ID: <1992Sep12.170425.23299@serval.net.wsu.edu> Keywords: shared libraries X X11 Sender: news@serval.net.wsu.edu (USENET News System) Organization: Washington State University References: <18iprpINNg6e@agate.berkeley.edu> <1992Sep8.200625.2894@socrates.umd.edu> <veit.716026274@du9ds3> <18lkkkINN14d@agate.berkeley.edu> <veit.716107923@du9ds3> <7dnL02y821gh01@JUTS.ccc.amdahl.com> <veit.716291291@du9ds3> Date: Sat, 12 Sep 92 17:04:25 GMT Lines: 128 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