Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!sun-barr!newstop!sun!opus!gingell From: gingell%opus@Sun.COM (Rob Gingell) Newsgroups: comp.windows.x Subject: Answers Re: SunOS Shared Libraries Keywords: SunOS 4.[x] shared libraries dynamic linking searching ldconfig Message-ID: <130216@sun.Eng.Sun.COM> Date: 13 Jan 90 02:41:39 GMT Sender: news@sun.Eng.Sun.COM Lines: 186 There have been a number of messages posted about various problems/issues in using shared libraries under SunOS -- specifically problems relating in how libraries are located and used at execution time. These often manifest themselves as a message like: ld.so: libfoo.so.n not found Here's some information about how it works that may help people use these facilities a little better. setxid programs and dynamic linking. The dynamic linker will refuse to use shared objects from directories that it does not "trust" when running a set-user or set-group id program. In 4.0[.x], the implementation simply ignores the library search path environment variable when runing a setxid program. The reason for this is that it would be trivial to usurp the system by writing a C library that included a "getuid()" implementation that forked a shell, setting the path variable to pick up this C library, and then running "su". The link editor "trusts" /usr/lib, /usr/5lib, and /usr/local/lib. In 4.0[.x], there is no way to tell the linker that other directories are "trustworthy." So, if you have a library that you want to have dynamically linked in a setxid program, it needs to be in one of these directories (rather, a name for the library needs to exist in one of these directories.) The bottom line for you is to simply put a symbolic link to the libraries needed by setxid programs in these directories. Just so you know, 4.1 changes this slightly. The 4.1 dynamic linker does not just ignore the LD_LIBRARY_PATH variable, but instead will only use the elements it finds in it that it will trust. This allows one, for instance, to change the search order among trusted libraries if for some reason you thought that'd be useful. There is also a change to what ld.so considers trusted, in the specific case of setxid programs. While not a general solution to the matter, this would deal effectively with the specific problems discussed in this group. -L options specified during the ld'ing of a dynamically linked executable are retained in the executable. This way you can build into a program that its shared libraries live in a non-default directory without requiring everyone to use the LD_LIBRARY_PATH environment variable. (This is true even in 4.0[.x].) What's different in 4.1 is that if a program is ld'ed with -L options, and then run as a setxid program, then the dynamic linker will "trust" all the "-L" directories. So, if you build something like xterm using "-L" rather than LD_LIBRARY_PATH to specify X client shared libraries, and then ran it as a setxid program, under 4.1 the directory(s) specified in a "-L" option would be considered trusted for the exectution of "xterm". (They would not be considered trusted for other programs that were not built with that directory specified with "-L", such as "su" -- the "trust" extends only as far as the program built with "-L".) Until 4.1, or if you don't want to depend on 4.1, you should put links in /usr/local/lib or /usr/lib to X libraries required by setxid executables. "ldconfig." When a dynamically linked program is executed, the libraries it requires are located using an algorithm that involves searching a sequence of directories for the "best available" version of the library. The ability to adjust the search rules on a per-process basis means that this evaluation must be evaluated for every process. Although the search is usually fast enough to not be noticable in the course of interactive use -- the cumulative time over all executions can be non-trivial. So the dynamic linker uses a "cache" that has precomputed where the "best" of a given library is in a given directory. The cache is built up of elements that are constructed on a per-directory basis. Each element contains information that tells what the best revision of each interface is contained in which file for all libraries contained in that directory. For instance, if /usr/lib contained: libc.so.1.3 libc.so.1.4 libc.so.2.1 and /usr/local/lib contained libfoo.so.5.3 libfoo.so.5.15 then a cache with elements for /usr/lib and /usr/local/lib would contain: /usr/lib: libc.1 -> libc.so.1.4 libc.2 -> libc.so.2.1 /usr/local/lib libfoo.5 -> libfoo.so.5.15 If you change a directory associated with an element without causing the element to be re-evaluated, the dynamic linker will fail to find any updates you've made. So, if you added /usr/lib/libc.so.2.2 without recomputing the element for /usr/lib, no program would ever find the newly revised version of interface 2 of the C library. [As it turns out, if you add an entirely new interface, such as a version "3.x" of the C library, such that a search through caches yields *no* candidate, the link editor will automatically invalidate the cache and recompute it for the current process -- however, new revisions don't cause this behavior simply because the cache does retrieve the old revision.] "ldconfig" is the program that recomputes the elements -- by default it does /usr/lib, /usr/local/lib, and /usr/5lib. You can ask that other directories be included by having them as command line arguments to "ldconfig." If you don't do this for a directory, the only side effect is that the dynamic linker will have to read the directory to find the best versions of whatever libraries it holds. If you don't do this for a directory that *is* in the cache already, but is one that you've updated with a new revision, then the new revision will simply not be visible. In the case where you don't cache a directory, processes wishing to use that directory in finding shared libraries will simply run a little slower. In particular, whether "ldconfig" builds a cache element for a directory or not has no impact on whether or not that directory is considered "trusted." -assert pure-text In at least one of the messages I saw, there was a discussion that indicated that the use of this option was producing some "ld" diagnostics -- this was mentioned in the context of whether or not the library could be found at execution time. I may have mis- understood that specific reference but the only thing the "-assert pure-text" ld option does is have "ld" tell you whether or not it had to defer some text-segment relocation. If it does, the penalty is that the dynamic linker will have to resolve that relocation at execution-time, leading to increased swap usage for the modified pages and less sharing than perhaps you expected. The diagnostic it produces isn't particularly helpful, this is improved in 4.1 to provide information that's more immediately useful to someone building the library. However, it's completely separate from the process by which libraries are found at execution time. Do shared libraries buy you anything? It depends upon what you value. If a library is used by multiple processes (i.e., sharing is really going on) then experience with the libraries Sun supplies says that "yes, you save a lot of both disk space and memory occupancy, and indirectly save on channel bandwidth due to decreased I/O requirements." If on the other hand, a shared library is used only serially (i.e. at any time only one process exists that uses the library), then it is conceivable (and probable) that you've actually increased the load on the primary memory resource because you've got the *whole* library rather than just what you need -- and this probably spans more address space and therefore more pages than it would have had you extracted just what you need from an archive. However, Sun ships a shared library that isn't shared (in parallel, that is.) It's the libkvm library that is bound with programs that rummage through kernel memory like "ps", "netstat", etc. It's highly unlikely on a workstation that you'll actually have two processes doing this simultaneously. However the reason libkvm is supplied as a .so and used that way in the system has to do with "dynamic linking" -- not the application of dynamic linking that creates the effect of library sharing. We want to dynamically link libkvm to isolate those applications that interrogate kernel memory from the access methods used to do that interrogation. At the time the dynamic linking facilities were in development, we were also developing the memory management facilities and it was somewhat painful to have to re-cut all the "kernel virtual memory" programs as a result of some experiment or change we conducted with the memory management code. What we value with libkvm is not the sharing, but the flexibility provided by dynamic linking. You may also value this in some circumstances, where you might not value library sharing. So, at least with the dynamically linked shared library implementations in SunOS and SVR4, the issue of whether "to .so or not to .so" is a little more subtle than simply library sharing.