Penguin
Diff: HowToProgramLibraryHOWTO
EditPageHistoryDiffInfoLikePages

Differences between current version and predecessor to the previous major change of HowToProgramLibraryHOWTO.

Other diffs: Previous Revision, Previous Author, or view the Annotated Edit History

Newer page: version 3 Last edited on Monday, November 1, 2004 11:38:22 pm by AristotlePagaltzis
Older page: version 2 Last edited on Friday, June 7, 2002 1:07:21 am by perry Revert
@@ -1,1548 +1 @@
-Program Library HOWTO  
-!!!Program Library HOWTO  
-!David A. Wheeler  
-  
-version 1.00, 22 March 2002  
-  
-  
-  
-  
-  
-  
-  
-This HOWTO for programmers  
-discusses how to create and use program libraries on Linux.  
-This includes static libraries, shared libraries, and  
-dynamically loaded libraries.  
-  
-  
-  
-  
-  
-----; __Table of Contents__; 1. Introduction; 2. Static Libraries; 3. Shared Libraries: ; 3.1. Conventions; 3.2. How Libraries are Used; 3.3. Environment Variables; 3.4. Creating a Shared Library; 3.5. Installing and Using a Shared Library; 3.6. Incompatible Libraries; 4. Dynamically Loaded (DL) Libraries: ; 4.1. dlopen(); 4.2. dlerror(); 4.3. dlsym(); 4.4. dlclose(); 4.5. DL Library Example; 5. Miscellaneous: ; 5.1. nm command; 5.2. Special functions _init and _fini; 5.3. Shared Libraries Can Be Scripts; 5.4. GNU libtool; 5.5. Removing symbols for space; 5.6. Extremely small executables; 5.7. Speeding up C++ initialization; 6. More Examples: ; 6.1. File libhello.c; 6.2. File libhello.h; 6.3. File demo_use.c; 6.4. File script_static; 6.5. File script_shared; 6.6. File demo_dynamic.c; 6.7. File script_dynamic; 7. Other Information Sources; 8. Copyright and License  
-!!!1. Introduction  
-  
-This HOWTO for programmers  
-discusses how to create and use program libraries on Linux  
-using the GNU toolset.  
-A ``program library'' is simply a file containing compiled code (and data)  
-that is to be incorporated later into a program;  
-program libraries allow programs to be more modular, faster to recompile,  
-and easier to update.  
-Program libraries can be divided into three types:  
-static libraries, shared libraries, and  
-dynamically loaded (DL) libraries.  
-  
-  
-  
-This paper first discusses static libraries, which are installed  
-into a program executable before the program can be run.  
-It then discusses shared libraries, which are loaded at program  
-start-up and shared between programs.  
-Finally, it discusses dynamically loaded (DL) libraries, which can  
-be loaded and used at any time while a program is running.  
-DL libraries aren't really a different kind of library format  
-(both static and shared libraries can be used as DL libraries);  
-instead, the difference is in how DL libraries are used by programmers.  
-The HOWTO wraps up with a section with more examples and a section  
-with references to other sources of information.  
-  
-  
-  
-Most developers who are developing libraries should create shared libraries,  
-since these allow users to update their libraries separately from the  
-applications that use the libraries.  
-Dynamically loaded (DL) libraries are useful, but they require a little more  
-work to use and many programs don't need the flexibility they offer,  
-Conversely, static libraries make upgrading libraries far more troublesome,  
-so for general-purpose use they're hard to recommend.  
-Still, each have their advantages, and the advantages of each type  
-are described in the section discussing that type.  
-  
-  
-  
-It's worth noting that some people use the term  
-dynamically ''linked'' libraries (DLLs)  
-to refer to shared libraries,  
-some use the term DLL to mean any library that is used  
-as a DL library, and some  
-use the term DLL to mean a library meeting either condition.  
-No matter which meaning you pick, this HOWTO covers DLLs on Linux.  
-  
-  
-  
-This HOWTO discusses only the Executable and Linking Format  
-(ELF) format for executables and libraries, the format  
-used by nearly all Linux distributions today.  
-The GNU gcc toolset can actually handle library formats other than ELF;  
-in particular, most Linux distributions can still  
-use the obsolete a.out format.  
-However, these formats are outside the scope of this paper.  
-  
-  
-  
-If you're building an application that should port to many systems,  
-you might consider using  
-GNU libtool  
-to build and install libraries instead of using the Linux tools directly.  
-GNU libtool is a generic library support script that  
-hides the complexity of using shared libraries  
-(e.g., creating and installing them) behind a consistent, portable interface.  
-On Linux, GNU libtool is built on top of the tools and conventions  
-described in this HOWTO.  
-For a portable interface to dynamically loaded libraries,  
-you can use various portability wrappers.  
-GNU libtool includes such a wrapper, called ``libltdl''.  
-Alternatively, you could use the glib library (not to be confused  
-with glibc) with its portable support for Dynamic Loading of Modules.  
-You can learn more about glib at  
-http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html.  
-Again, on Linux this functionality is implemented using the constructs  
-described in this HOWTO.  
-If you're actually developing or debugging the code on Linux,  
-you'll probably still want the information in this HOWTO.  
-  
-  
-  
-This HOWTO's master location is  
-http://www.dwheeler.com/program-library, and it has been  
-contributed to the Linux Documentation Project  
-(http://www.linuxdoc.org).  
-It is Copyright (C) 2000 David A. Wheeler and is licensed through the  
-General Public License (GPL); see the last section for more information.  
-  
-----  
-!!!2. Static Libraries  
-  
-Static libraries are simply a collection of ordinary object files;  
-conventionally, static libraries end with the ``.a'' suffix.  
-This collection is created using the ar (archiver) program.  
-Static libraries aren't used as often as they once were, because of the  
-advantages of shared libraries (described below).  
-Still, they're sometimes created, they existed first historically,  
-and they're simpler to explain.  
-  
-  
-  
-Static libraries permit users to link to programs without having to  
-recompile its code, saving recompilation time.  
-Note that recompilation time is less important given today's faster compilers,  
-so this reason is not as strong as it once was.  
-Static libraries are often useful for developers if they wish to  
-permit programmers to link to their library, but don't want to give  
-the library source code (which is an advantage to the library vendor, but  
-obviously not an advantage to the programmer trying to use the library).  
-In theory, code in static ELF libraries that is linked into an  
-executable should run slightly faster (by 1-5%) than a shared library  
-or a dynamically loaded library, but in practice this  
-rarely seems to be the case due to other confounding factors.  
-  
-  
-  
-To create a static library, or to add additional object files to  
-an existing static library, use a command like this:  
-  
-  
-ar rcs my_library.a file1.o file2.o  
-  
-This sample command adds the object files file1.o and file2.o to the  
-static library my_library.a, creating my_library.a if it doesn't  
-already exist.  
-For more information on creating static libraries, see ar(1).  
-  
-  
-  
-Once you've created a static library, you'll want to use it.  
-You can use a static library by invoking it as part of the compilation  
-and linking process when creating a program executable.  
-If you're using gcc(1) to generate your executable, you can use the -l  
-option to specify the library; see info:gcc for more information.  
-You can also use the linker ld(1) directly, using its -l and -L options;  
-however, in most cases it's better to use gcc(1) since the interface of  
-ld(1) is more likely to change.  
-  
-----  
-!!!3. Shared Libraries  
-  
-Shared libraries are libraries that are loaded by programs when they start.  
-When a shared library is installed properly, all programs that start afterwards  
-automatically use the new shared library.  
-It's actually much more flexible and sophisticated than this, because the  
-approach used by Linux permits you to:  
-  
-  
-  
-  
-  
-*  
-  
-update libraries and still support programs that want to use older,  
-non-backward-compatible versions of those libraries;  
-  
-  
-*  
-*  
-  
-override specific libraries or even specific functions  
-in a library when executing a particular program.  
-  
-  
-*  
-*  
-  
-do all this while programs are running using existing libraries.  
-  
-  
-*  
-  
-----  
-!!3.1. Conventions  
-  
-For shared libraries to support all of these desired properties,  
-a number of conventions and guidelines must be followed.  
-You need to understand the difference between a library's  
-names, in particular its ``soname'' and ``real name'' (and how they interact).  
-You also need to understand where they should be placed in the filesystem.  
-  
-----  
-!3.1.1. Shared Library Names  
-  
-Every shared library has a special name called the ``soname''.  
-The soname has the prefix ``lib'', the name of the library,  
-the phrase ``.so'', followed by a period and a  
-version number that is incremented whenever the interface changes  
-(as a special exception, the lowest-level C libraries don't start  
-with ``lib'').  
-A fully-qualified soname includes as a prefix the directory it's in;  
-on a working system a fully-qualified soname is simply a symbolic  
-link to the shared library's ``real name''.  
-  
-  
-  
-Every shared library also has a ``real name'', which is the filename  
-containing the actual library code.  
-The real name adds to the soname a period, a  
-minor number, another period, and the release number.  
-The last period and release number are optional.  
-The minor number and release number  
-support configuration control by letting you know exactly what version(s)  
-of the library are installed. Note that these numbers might not be  
-the same as the numbers used to describe the library in documentation,  
-although that does make things easier.  
-  
-  
-  
-In addition, there's the name that the compiler uses when requesting a library,  
-(I'll call it the ``linker name''), which is simply the soname without  
-any version number.  
-  
-  
-  
-The key to managing shared libraries is the separation of these names.  
-Programs, when they internally list the shared libraries they need,  
-should only list the soname they need.  
-Conversely, when you create a shared library, you only create the  
-library with a specific filename (with more detailed version information).  
-When you install a new version of a library, you  
-install it in one of a few special directories and then run the  
-program ldconfig(8).  
-ldconfig examines the existing files and creates the sonames as  
-symbolic links to the real names, as well as setting up the  
-cache file /etc/ld.so.cache (described in a moment).  
-  
-  
-  
-ldconfig doesn't set up the linker names; typically this is done during  
-library installation, and the linker name is simply created as a symbolic  
-link to the ``latest'' soname or the latest real name.  
-I would recommend having the linker name be a symbolic link to the soname,  
-since in most cases if you update the library  
-you'd like to automatically use it when linking.  
-I asked H. J. Lu why ldconfig doesn't automatically set up the linker names.  
-His explanation was basically that  
-you might want to run code using the latest version of a library,  
-but might instead want ''development'' to link  
-against an old (possibly incompatible) library.  
-Therefore, ldconfig makes no assumptions about what you want programs to  
-link to, so installers must specifically modify symbolic links to  
-update what the linker will use for a library.  
-  
-  
-  
-Thus, /usr/lib/libreadline.so.3  
-is a fully-qualified soname, which  
-ldconfig would set to be a symbolic link to some realname like  
-/usr/lib/libreadline.so.3..  
-There should also be a linker name,  
-/usr/lib/libreadline.so  
-which could be a symbolic link referring to  
-/usr/lib/libreadline.so.3.  
-  
-----  
-!3.1.2. Filesystem Placement  
-  
-Shared libraries must be placed somewhere in the filesystem.  
-Most open source software tends to follow the GNU standards; for more  
-information see the info file documentation at  
-info:standards#Directory_Variables.  
-The GNU standards recommend  
-installing by default all libraries in /usr/local/lib  
-when distributing source code  
-(and all commands should go into /usr/local/bin).  
-They also define the convention for overriding these defaults  
-and for invoking the installation routines.  
-  
-  
-  
-The Filesystem Hierarchy Standard (FHS) discusses what should go where  
-in a distribution (see  
-http://www.pathname.com/fhs).  
-According to the FHS, most libraries should  
-be installed in /usr/lib, but libraries required for startup  
-should be in /lib and libraries that are not  
-part of the system should be in /usr/local/lib.  
-  
-  
-  
-There isn't really a conflict between these two documents;  
-the GNU standards recommend the default for developers  
-of source code, while the FHS recommends the default for distributors  
-(who selectively override the source code defaults, usually via the  
-system's package management system).  
-In practice this works nicely: the ``latest'' (possibly buggy!) source  
-code that you download automatically installs itself in the ``local''  
-directory (/usr/local),  
-and once that code has matured the package managers can  
-trivially override the default to place the code in the standard  
-place for distributions.  
-Note that if your library calls programs that can only be called via  
-libraries, you should place those programs in /usr/local/libexec  
-(which becomes /usr/libexec in a distribution).  
-One complication is that Red Hat-derived systems don't include  
-/usr/local/lib by default in their search for libraries;  
-see the discussion below about /etc/ld.so.conf.  
-Other standard library locations include  
-/usr/X11R6/lib for X-windows.  
-Note that /lib/security is used for PAM modules, but those are usually  
-loaded as DL libraries (also discussed below).  
-  
-----  
-!!3.2. How Libraries are Used  
-  
-On GNU glibc-based systems, including all Linux systems,  
-starting up an ELF binary executable automatically causes the program loader  
-to be loaded and run.  
-On Linux systems, this loader is named  
-/lib/ld-linux.so.X (where X is a version number).  
-This loader,  
-in turn, finds and loads all other shared libraries used by the program.  
-  
-  
-  
-The list of directories to be searched is stored in the file /etc/ld.so.conf.  
-Many Red Hat-derived distributions don't normally include /usr/local/lib in the  
-file /etc/ld.so.conf. I consider this a bug, and adding  
-/usr/local/lib to /etc/ld.so.conf is a common ``fix'' required  
-to run many programs on Red Hat-derived systems.  
-  
-  
-  
-If you want to just override a few functions in a library, but  
-keep the rest of the library, you can enter the names of overriding  
-libraries (.o files) in /etc/ld.so.preload; these  
-``preloading'' libraries will take precedence over the standard set.  
-This preloading file is typically used for emergency patches;  
-a distribution usually won't include such a file when delivered.  
-  
-  
-  
-Searching all of these directories at program start-up  
-would be grossly inefficient, so a caching arrangement is actually used.  
-The program ldconfig(8) by default reads in the file /etc/ld.so.conf,  
-sets up the appropriate symbolic links in the dynamic link directories  
-(so they'll follow the standard conventions), and then writes a cache to  
-/etc/ld.so.cache that's then used by other programs.  
-This greatly speeds up access to libraries.  
-The implication is that  
-ldconfig must be run whenever a DLL is added, when a DLL is removed,  
-or when the set of DLL directories changes;  
-running ldconfig is often one of the steps performed by package  
-managers when installing a library.  
-On start-up, then, the dynamic loader actually uses  
-the file /etc/ld.so.cache and then loads the libraries it needs.  
-  
-  
-  
-By the way, FreeBSD uses slightly different filenames for this cache.  
-In FreeBSD, the ELF cache is /var/run/ld-elf.so.hints  
-and the a.out cache is /var/run/ld.so.hints.  
-These are still updated by ldconfig(8), so this difference in location  
-should only matter in a few exotic situations.  
-  
-----  
-!!3.3. Environment Variables  
-  
-Various environment variables can control this process,  
-and there are environment variables that permit  
-you to override this process.  
-  
-----  
-!3.3.1. LD_LIBRARY_PATH  
-  
-You can temporarily substitute a different library for  
-this particular execution.  
-In Linux, the environment variable LD_LIBRARY_PATH  
-is a colon-separated set of directories where libraries should be  
-searched for first, before  
-the standard set of directories; this is useful when debugging  
-a new library or using a nonstandard library for special purposes.  
-The environment variable LD_PRELOAD lists shared libraries with functions that  
-override the standard set, just as /etc/ld.so.preload does.  
-These are implemented by the loader /lib/ld-linux.so.  
-I should note that, while LD_LIBRARY_PATH works on many  
-Unix-like systems, it doesn't work on all;  
-for example, this functionality is available on HP-UX but as  
-the environment variable SHLIB_PATH,  
-and on AIX this functionality is through the variable LIBPATH  
-(with the same syntax, a colon-separated list).  
-  
-  
-  
-LD_LIBRARY_PATH is handy for development and testing, but shouldn't  
-be modified by an installation process for normal use by normal users; see  
-``Why LD_LIBRARY_PATH is Bad'' at  
-http://www.visi.com/~barr/ldpath.html  
-for an explanation of why.  
-But it's still useful for development or testing, and for working around  
-problems that can't be worked around otherwise.  
-If you don't want to set the LD_LIBRARY_PATH environment variable, on Linux  
-you can even invoke the program loader directly and pass it arguments.  
-For example, the following will use the given PATH instead  
-of the content of the environment variable LD_LIBRARY_PATH, and run  
-the given executable:  
-  
- /lib/ld-linux.so.2 --library-path PATH EXECUTABLE  
-Just executing ld-linux.so without arguments will give you more help on  
-using this, but again, don't use this for normal use - these are all  
-intended for debugging.  
-  
-----  
-!3.3.2. LD_DEBUG  
-  
-Another useful environment variable in the GNU C loader is LD_DEBUG.  
-This triggers the dl* functions so that they give quite verbose information  
-on what they are doing. For example:  
-  
- export LD_DEBUG=files  
-command_to_run  
-displays the processing of files and libraries when handling libraries,  
-telling you what dependencies are detected and which SOs are loaded  
-in what order.  
-Setting LD_DEBUG to ``bindings'' displays information  
-about symbol binding, setting it to ``libs'' displays the  
-library search paths, and setting ti to ``versions'' displays the  
-version depdendencies.  
-  
-  
-  
-Setting LD_DEBUG to ``help'' and then trying to run a program  
-will list the possible options.  
-Again, LD_DEBUG isn't intended for normal use, but it can be handy  
-when debugging and testing.  
-  
-----  
-!3.3.3. Other Environment Variables  
-  
-There are actually a number of other environment variables that control  
-the loading process; their names begin with LD_ or RTLD_.  
-Most of the others are for low-level debugging of the loader process or  
-for implementing specialized capabilities.  
-Most of them aren't well-documented; if you need to know about them, the  
-best way to learn about them is to read the source code of the loader  
-(part of gcc).  
-  
-  
-  
-Permitting user control over dynamically linked libraries  
-would be disastrous for setuid/setgid programs  
-if special measures weren't taken.  
-Therefore, in the GNU loader (which loads the rest of the program  
-on program start-up), if the  
-program is setuid or setgid these variables  
-(and other similar variables) are ignored or greatly limited in  
-what they can do.  
-The loader determines if a program is setuid or setgid by  
-checking the program's credentials; if the uid and euid differ,  
-or the gid and the egid differ,  
-the loader presumes the program is setuid/setgid (or descended from one)  
-and therefore greatly limits its abilities to control linking.  
-If you read the GNU glibc library source code, you can see this;  
-see especially the files elf/rtld.c and sysdeps/generic/dl-sysdep.c.  
-This means that if you cause the uid and gid  
-to equal the euid and egid, and then call a program,  
-these variables will have full effect.  
-Other Unix-like systems handle the situation differently but  
-for the same reason: a setuid/setgid program  
-should not be unduly affected by the environment variables set.  
-  
-----  
-!!3.4. Creating a Shared Library  
-  
-Creating a shared library is easy.  
-First, create the object files that will go into the shared  
-library using the gcc -fPIC or -fpic flag.  
-The -fPIC and -fpic options enable ``position independent code'' generation,  
-a requirement for shared libraries; see below for the differences.  
-Then create the shared library using this format:  
-  
-  
-gcc -shared -Wl,-soname,''your_soname'' \  
--o ''library_name'' ''file_list'' ''library_list''  
-  
-Here's an example, which creates two object files (a.o and b.o) and then  
-creates a shared library that contains both of them.  
-Note that this compilation includes debugging information (-g) and  
-will generate warnings (-Wall), which aren't required for shared libraries  
-but are recommended.  
-The compilation generates object files (using -c), and includes  
-the required -fPIC option:  
-  
-  
-gcc -fPIC -g -c -Wall a.c  
-gcc -fPIC -g -c -Wall b.c  
-gcc -shared -Wl,-soname,libmystuff.so.1 \  
--o libmystuff.so.1..1 a.o b.o -lc  
-  
-Here are a few points worth noting:  
-  
-  
-  
-  
-  
-*  
-  
-Don't strip the resulting library, and don't use the  
-compiler option -fomit-frame-pointer unless you really have to.  
-The resulting library will work, but these actions make debuggers  
-mostly useless.  
-  
-  
-*  
-*  
-  
-Use -fPIC or -fpic to generate code.  
-Whether to use -fPIC or -fpic to generate code is target-dependent.  
-The -fPIC choice always works, but may produce larger code than -fpic  
-(mnenomic to remember this is that PIC is in a larger case,  
-so it may produce larger amounts of code).  
-Using -fpic option usually generates  
-smaller and faster code, but will have platform-dependent  
-limitations, such as the number of globally visible symbols or  
-the size of the code. The linker will tell you whether it fits  
-when you create the shared library.  
-When in doubt, I choose -fPIC, because it always works.  
-  
-  
-*  
-*  
-  
-In some cases, the call to gcc to create the object file  
-will also need to include the option ``-Wl,-export-dynamic''.  
-Normally, the dynamic symbol  
-table contains only symbols which are used by a dynamic object.  
-This option (when creating an ELF file) adds all symbols to the  
-dynamic symbol table (see ld(1) for more information).  
-You need to use this option when there are 'reverse dependencies', i.e.,  
-a DL library has unresolved symbols that by convention must be defined  
-in the programs that intend to load these libraries.  
-For ``reverse dependencies'' to work, the master program must make its  
-symbols dynamically available.  
-Note that you could say ``-rdynamic'' instead of ``-Wl,export-dynamic''  
-if you only work with Linux systems, but according to the ELF documentation  
-the ``-rdynamic'' flag doesn't always work for gcc on non-Linux systems.  
-  
-  
-*  
-  
-  
-  
-During development, there's the potential problem of modifying a library  
-that's also used by many other programs -- and you don't want the  
-other programs to use the ``developmental''library, only a particular  
-application that you're testing against it.  
-One link option you might use is ld's ``rpath'' option, which specifies  
-the runtime library search path of that particular program  
-being compiled.  
-From gcc, you can invoke the rpath option by specifying it this way:  
-  
- -Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)  
-If you use this option when building the library client program,  
-you don't need to bother with LD_LIBRARY_PATH (described next) other  
-than to ensure it's not conflicting, or using other techniques to  
-hide the library.  
-  
-----  
-!!3.5. Installing and Using a Shared Library  
-  
-Once you've created a shared library, you'll want to install it.  
-The simple approach is simply to copy the library into one of the  
-standard directories (e.g., /usr/lib) and run ldconfig(8).  
-  
-  
-  
-First, you'll need to create the shared libraries somewhere.  
-Then, you'll need to set up the necessary symbolic links, in particular  
-a link from a soname to the real name (as well as from a versionless  
-soname, that is, a soname that ends in ``.so'' for users who don't specify  
-a version at all). The simplest approach is to run:  
-  
- ldconfig -n ''directory_with_shared_libraries''  
-  
-  
-  
-Finally, when you compile your programs, you'll need to tell the  
-linker about any static and shared libraries that you're using.  
-Use the -l and -L options for this.  
-  
-  
-  
-If you can't or don't want to install a library in a standard place  
-(e.g., you don't have the right to modify /usr/lib),  
-then you'll need to change your approach.  
-In that case, you'll need to install it somewhere, and then  
-give your program enough information so the program can find the library...  
-and there are several ways to do that.  
-You can use gcc's -L flag in simple cases.  
-You can use the ``rpath'' approach (described above), particularly if  
-you only have a specific program to use the library being placed in  
-a ``non-standard'' place.  
-You can also use environment variables to control things.  
-In particular, you can set LD_LIBRARY_PATH, which is a colon-separated  
-list of directories in which to search for shared libraries before  
-the usual places.  
-If you're using bash, you could invoke my_program this way using:  
-  
-  
-LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program  
-  
-If you want to override just a few selected functions,  
-you can do this by creating an overriding object file and setting  
-LD_PRELOAD; the functions in this object file will override just  
-those functions (leaving others as they were).  
-  
-  
-  
-Usually you can update libraries without concern; if there was an API  
-change, the library creator is supposed to change the soname.  
-That way, multiple libraries can be on a single system, and the right  
-one is selected for each program.  
-However, if a program breaks on an update to a library that kept the  
-same soname, you can force it to use the older library version by  
-copying the old library back somewhere,  
-renaming the program (say to the old name plus ``.orig''),  
-and then create a small  
-``wrapper'' script that resets the library to use and  
-calls the real (renamed) program.  
-You could place the old library in its own special area, if you like,  
-though the numbering conventions do permit multiple versions to live  
-in the same directory.  
-The wrapper script could look something like this:  
-  
- #!/bin/sh  
-export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH  
-exec /usr/bin/my_program.orig $*  
-Please don't depend on this when you write your own programs; try to  
-make sure that your libraries are either backwards-compatible or that  
-you've incremented the version number in the soname every time  
-you make an incompatible change.  
-This is just an ``emergency'' approach to deal with worst-case problems.  
-  
-  
-  
-You can see the list of the shared libraries used by a program using ldd(1).  
-So, for example, you can see the shared libraries used by ls by typing:  
-  
- ldd /bin/ls  
-Generally you'll see a list of the sonames being depended on, along with  
-the directory that those names resolve to.  
-In practically all cases you'll have at least two dependencies:  
-  
-  
-  
-  
-  
-*  
-  
-/lib/ld-linux.so.N (where N is 1 or more, usually at least 2).  
-This is the library that loads all other libraries.  
-  
-  
-*  
-*  
-  
-libc.so.N (where N is 6 or more).  
-This is the C library. Even other languages tend to use the C  
-library (at least to implement their own libraries), so most programs  
-at least include this one.  
-  
-  
-*  
-Beware: do ''not'' run ldd on a program you don't trust.  
-As is clearly stated in the ldd(1) manual, ldd works by (in certain cases)  
-by setting a special environment variable  
-(for ELF objects, LD_TRACE_LOADED_OBJECTS) and then executing the program.  
-It may be possible for an untrusted program to force the ldd user to  
-run arbitrary code (instead of simply showing the ldd information).  
-So, for safety's sake, don't use ldd on programs you don't trust to execute.  
-  
-----  
-!!3.6. Incompatible Libraries  
-  
-When a new version of a library is binary-incompatible with the old one  
-the soname needs to change.  
-In C, there are four basic reasons that a library would cease to  
-be binary compatible:  
-  
-  
-  
-  
-  
-#  
-  
-The behavior of a function changes so that it no longer  
-meets its original specification,  
-  
-  
-#  
-#  
-  
-Exported data items change (exception: adding optional  
-items to the ends of structures is okay, as long as those structures  
-are only allocated within the library).  
-  
-  
-#  
-#  
-  
-An exported function is removed.  
-  
-  
-#  
-#  
-  
-The interface of an exported function changes.  
-  
-  
-#  
-  
-  
-  
-If you can avoid these reasons, you can keep your libraries binary-compatible. Said another way, you can keep your  
-Application Binary Interface (ABI) compatible if you avoid such changes.  
-For example, you might want to add new functions but not delete the old ones.  
-You can add items to structures but only if you can make sure that old  
-programs won't be sensitive to such changes by adding items  
-only to the end of the structure, only allowing the library (and not the  
-application) to allocate the structure, making the extra items optional  
-(or having the library fill them in), and so on.  
-Watch out - you probably  
-can't expand structures if users are using them in arrays.  
-  
-  
-  
-For C++ (and other languages supporting compiled-in templates and/or  
-compiled dispatched methods), the situation is trickier.  
-All of the above issues apply, plus many more issues.  
-The reason is that some information is implemented ``under the covers''  
-in the compiled code, resulting in dependencies that may not be obvious  
-if you don't know how C++ is typically implemented.  
-Strictly speaking, they aren't ``new'' issues, it's just that compiled C++  
-code invokes them in ways that may be surprising to you.  
-The following is a (probably incomplete) list of things that you cannot  
-do in C++ and retain binary compatibility, as reported by  
-Troll Tech's Technical FAQ:  
-  
-  
-  
-  
-  
-#  
-  
-add reimplementations of virtual functions  
-(unless it it safe for older binaries to call the original implementation),  
-because the compiler evaluates !SuperClass::virtualFunction() calls  
-at compile-time (not link-time).  
-  
-  
-#  
-#  
-  
-add or remove virtual member functions, because  
-this would change the size and layout of the vtbl of every subclass.  
-  
-  
-#  
-#  
-  
-change the type of any data members or move any data members  
-that can be accessed via inline member functions.  
-  
-  
-#  
-#  
-  
-change the class hierarchy, except to add new leaves.  
-  
-  
-#  
-#  
-  
-add or remove private data members, because  
-this would change the size and layout of every subclass.  
-  
-  
-#  
-#  
-  
-remove public or protected member functions unless they are inline.  
-  
-  
-#  
-#  
-  
-make a public or protected member function inline.  
-  
-  
-#  
-#  
-  
-change what an inline function does, unless the old version continues working.  
-  
-  
-#  
-#  
-  
-change the access rights  
-(i.e. public, protected or private) of a member function in a  
-portable program, because  
-some compilers mangle the access rights into the function name.  
-  
-  
-#  
-  
-  
-  
-Given this lengthy list, developers of C++ libraries in particular must  
-plan for more than occasional updates that break binary compatibility.  
-Fortunately, on Unix-like systems (including Linux) you can have  
-multiple versions of a library loaded at the same time, so while there  
-is some disk space loss, users can still run ``old'' programs needing  
-old libraries.  
-  
-----  
-!!!4. Dynamically Loaded (DL) Libraries  
-  
-Dynamically loaded (DL) libraries are libraries that are loaded  
-at times other than during the startup of a program.  
-They're particularly useful for implementing plugins or modules, because  
-they permit waiting to load the plugin until it's needed.  
-For example, the Pluggable Authentication Modules (PAM) system  
-uses DL libraries to permit administrators to configure and reconfigure  
-authentication.  
-They're also useful for implementing interpreters that wish to  
-occasionally compile their code into machine code and use the compiled  
-version for efficiency purposes, all without stopping.  
-This approach can be useful in implementing  
-a just-in-time compiler or multi-user dungeon (MUD).  
-  
-  
-  
-In Linux, DL libraries aren't actually special from the point-of-view of their  
-format; they are built as standard object files or standard shared libraries  
-as discussed above.  
-The main difference is that the libraries aren't automatically loaded  
-at program link time or start-up; instead, there is an API for  
-opening a library, looking up symbols, handling errors, and closing the library.  
-C users will need to include the header file `dlfcn.hb  
-to use this API.  
-  
-  
-  
-The interface used by Linux is essentially the same as that used in Solaris,  
-which I'll call the ``dlopen()'' API.  
-However, this same interface is not supported by all platforms;  
-HP-UX uses the different shl_load() mechanism, and Windows platforms use  
-DLLs with a completely different interface.  
-If your goal is wide portability, you probably ought to consider using  
-some wrapping library that hides differences between platforms.  
-One approach is  
-the glib library with its support for Dynamic Loading of Modules; it uses  
-the underlying dynamic loading routines of the platform to implement  
-a portable interface to these functions.  
-You can learn more about glib at  
-http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html.  
-Since the glib interface is well-explained in its documentation,  
-I won't discuss it further here.  
-Another approach is to use libltdl, which is part of  
-GNU libtool.  
-If you want much more functionality than this, you might want to  
-look into a CORBA Object Request Broker (ORB).  
-If you're still interested in directly using the interface supported  
-by Linux and Solaris, read on.  
-  
-----  
-!!4.1. dlopen()  
-  
-The dlopen(3) function opens a library and prepares it for use.  
-In C its prototype is:  
-  
- void * dlopen(const char *filename, int flag);  
-If filename begins with ``/'' (i.e., it's an absolute path),  
-dlopen() will just try to use it (it won't search for a library).  
-Otherwise, dlopen() will search for the library  
-in the following order:  
-  
-  
-  
-  
-  
-#  
-  
-A colon-separated list of directories in the user's  
-LD_LIBRARY path environment variable.  
-  
-  
-#  
-#  
-  
-The list of libraries specified in /etc/ld.so.cache  
-(which is generated from /etc/ld.so.conf).  
-  
-  
-#  
-#  
-  
-/lib, followed by /usr/lib.  
-Note the order here; this is the reverse of the order used by the  
-old a.out loader.  
-The old a.out loader, when loading a program, first searched  
-/usr/lib, then /lib (see the man page ld.so(8)).  
-This shouldn't normally matter, since  
-a library should only be in one or the other directory  
-(never both), and different libraries with the same name are a disaster  
-waiting to happen.  
-  
-  
-#  
-In dlopen(), the value of  
-''flag'' must be either RTLD_LAZY,  
-meaning  
-``resolve undefined symbols as code from the dynamic library is executed'',  
-or RTLD_NOW,  
-meaning ``resolve all undefined symbols before  
-dlopen() returns and fail if this cannot be done''.  
-RTLD_GLOBAL may be optionally or'ed with either value  
-in ''flag'',  
-meaning that the external symbols defined in the library will be made  
-available to subsequently loaded libraries.  
-While you're debugging, you'll probably want to use RTLD_NOW; using  
-RTLD_LAZY can create inscrutable errors if there are unresolved references.  
-Using RTLD_NOW makes opening the library take slightly longer  
-(but it speeds up lookups later); if this causes a user interface problem  
-you can switch to RTLD_LAZY later.  
-  
-  
-  
-If the libraries depend on each other (e.g., X depends on Y), then you  
-need to load the dependees first (in this example, load Y first, and then X).  
-  
-  
-  
-The return value of dlopen() is a ``handle'' that should be considered an  
-opaque value to be used by the other DL library routines.  
-dlopen() will return NULL if the attempt to load does not succeed, and  
-you need to check for this.  
-If the same library is loaded more than once with dlopen(),  
-the same file handle is returned.  
-  
-  
-  
-If the library exports a routine named _init, then that  
-code is executed before dlopen() returns.  
-You can use this fact in your own libraries to implement  
-initialization routines.  
-See Section 5.2 for more information.  
-  
-----  
-!!4.2. dlerror()  
-  
-Errors can be reported by calling dlerror(), which returns a string  
-describing the error from the last call to dlopen(), dlsym(), or dlclose().  
-One oddity is that after calling dlerror(), future calls to dlerror()  
-will return NULL until another error has been encountered.  
-  
-----  
-!!4.3. dlsym()  
-  
-There's no point in loading a DL library if you can't use it.  
-The main routine for using a DL library is dlsym(3), which  
-looks up the value of a symbol in a given (opened) library.  
-This function is defined as:  
-  
- void * dlsym(void *handle, char *symbol);  
-the handle is the value returned from dlopen, and symbol is a  
-NIL-terminated string.  
-If you can avoid it, don't store the result of dlsym() into a void*  
-pointer, because then you'll have to cast it each time you use it  
-(and you'll give less information to other people trying to  
-maintain the program).  
-  
-  
-  
-dlsym() will return a NULL result if the symbol wasn't found.  
-If you know that the symbol could never have the value of NULL or zero,  
-that may be fine, but there's a potential ambiguity otherwise: if you got  
-a NULL, does that mean there is no such symbol, or that NULL is the  
-value of the symbol?  
-The standard solution is to call dlerror() first (to clear any error  
-condition that may have existed), then call dlsym() to request a symbol,  
-then call dlerror() again to see if an error occurred.  
-A code snippet would look like this:  
-  
- dlerror(); /* clear error code */  
-s = (actual_type) dlsym(handle, symbol_being_searched_for);  
-if ((err = dlerror()) != NULL) {  
-/* handle error, the symbol wasn't found */  
-} else {  
-/* symbol found, its value is in s */  
-}  
-  
-----  
-!!4.4. dlclose()  
-  
-The converse of dlopen() is dlclose(), which closes a DL library.  
-The dl library maintains link counts for  
-dynamic file handles, so a dynamic library is not actually deallocated  
-until dlclose has been called on it as many times as  
-dlopen has succeeded on it.  
-Thus, it's not a problem for the same program  
-to load the same library multiple times.  
-If a library is deallocated, its function _fini is called (if it exists);  
-see Section 5.2 for more information.  
-Note: dlclose() returns 0 on success, and non-zero on error; some  
-Linux manual pages don't mention this.  
-  
-----  
-!!4.5. DL Library Example  
-  
-Here's an example from the man page of dlopen(3).  
-This example loads the math library and prints the cosine of 2., and  
-it checks for errors at every step (recommended):  
-  
- #include `stdlib.hb  
-#include `stdio.hb  
-#include `dlfcn.hb  
-int main(int argc, char **argv) {  
-void *handle;  
-double (*cosine)(double);  
-char *error;  
-handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);  
-if (!handle) {  
-fputs (dlerror(), stderr);  
-exit(1);  
-}  
-cosine = dlsym(handle, "cos");  
-if ((error = dlerror()) != NULL) {  
-fputs(error, stderr);  
-exit(1);  
-}  
-printf ("%f\n", (*cosine)(2.));  
-dlclose(handle);  
-}  
-  
-  
-  
-If this program were in a file named "foo.c",  
-you would build the program with the following command:  
-  
- gcc -o foo foo.c -ldl  
-  
-----  
-!!!5. Miscellaneous  
-!!5.1. nm command  
-  
-The nm(1) command can report the list of  
-symbols in a given library.  
-It works on both static and shared libraries.  
-For a given library nm(1) can list the symbol names defined, each  
-symbol's value, and the symbol's type.  
-It can also identify where the symbol was defined in the source code  
-(by filename and line number), if that information is available in  
-the library (see the -l option).  
-  
-  
-  
-The symbol type requires a little more explanation.  
-The type is displayed as a letter; lowercase means that the symbol is  
-local, while uppercase means that the symbol is global (external).  
-Typical symbol types include  
-T (a normal definition in the code section),  
-D (initialized data section),  
-B (uninitialized data section),  
-U (undefined; the symbol is used by the library  
-but not defined by the library), and  
-W (weak; if another library also defines this symbol, that definition  
-overrides this one).  
-  
-  
-  
-If you know the name of a function, but  
-you truly can't remember what library it was defined in, you can use  
-nm's ``-o'' option (which prefixes the filename in each line) along  
-with grep to find the library name. From a Bourne shell, you  
-can search all the libraries in /lib, /usr/lib, direct subdirectories of  
-/usr/lib, and /usr/local/lib for ``cos'' as follows:  
-  
-nm -o /lib/* /usr/lib/* /usr/lib/*/* \  
-/usr/local/lib/* 2b /dev/null | grep 'cos$'  
-  
-  
-  
-Much more information about nm can be found in the nm ``info''  
-documentation locally installed at  
-info:binutils#nm.  
-  
-----  
-!!5.2. Special functions _init and _fini  
-  
-Two special functions aid in initializing and finalizing a module:  
-_init and _fini.  
-If a function ``_init'' is exported in a library,  
-then it is called when the library is first opened  
-(via dlopen() or simply as a shared library).  
-In a C program, this just means that you defined some function  
-named _init.  
-There is a corresponding function called _fini, which is called whenever a  
-client finishes using the library  
-(via a call dlclose() that brings its reference count to zero, or  
-on normal exit of the program).  
-The C prototypes for these functions are:  
-  
- void _init(void);  
-void _fini(void);  
-  
-  
-  
-When compiling the file into a ``.o'' file in gcc, be sure to add the  
-gcc option ``-nostartfiles''.  
-This keeps the C compiler from  
-linking the system startup libraries against the .so file.  
-Otherwise, you'll get a ``multiple-definition'' error.  
-My thanks to Jim Mischel and Tim Gentry for their suggestion to add  
-this discussion of _init and _fini,  
-as well as help in creating it.  
-  
-----  
-!!5.3. Shared Libraries Can Be Scripts  
-  
-It's worth noting that the GNU loader  
-permits shared libraries to be text files using a  
-specialized scripting language instead of the usual library format.  
-This is useful for indirectly combining other libraries.  
-For example, here's the listing of  
-/usr/lib/libc.so  
-on one of my systems:  
-  
-/* GNU ld script  
-Use the shared library, but some functions are only in  
-the static library, so try that secondarily. */  
-GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )  
-  
-  
-  
-For more information about this, see the texinfo documentation on ld  
-linker scripts (ld command language).  
-General information is at  
-info:ld#Options and info:ld#Commands,  
-with likely commands discussed in  
-info:ld#Option Commands.  
-  
-----  
-!!5.4. GNU libtool  
-  
-If you're building an application that should port to many systems,  
-you might consider using  
-GNU libtool  
-to build and install libraries.  
-GNU libtool is a generic library support script.  
-Libtool hides the complexity of using shared libraries  
-behind a consistent, portable interface.  
-Libtool provides portable interfaces to  
-create object files, link libraries (static and shared), link executables,  
-debug executables, install libraries, install executables.  
-It also includes libltdl, a portability wrapper for  
-dynamically loading programs.  
-For more information, see its documentation at  
-http://www.gnu.org/software/libtool/manual.html  
-  
-----  
-!!5.5. Removing symbols for space  
-  
-All the symbols included in generated files are useful for debugging,  
-but take up space.  
-If you need space, you can eliminate some of it.  
-  
-  
-  
-The best approach is to first generate the object files normally,  
-and do all your debugging and testing first  
-(debugging and testing is much easier with them).  
-Afterwards, once you've tested the program thoroughly, use  
-strip(1) to remove the symbols.  
-The strip(1) command gives you a good deal of control over  
-what symbols to eliminate; see its documentation for details.  
-  
-  
-  
-Another approach is to use the GNU ld options ``-S'' and ``-s'';  
-``-S'' omits debugger symbol information (but not all symbols)  
-from the output file, while  
-``-s'' omits all symbol information from the output file.  
-You can invoke these options through gcc as ``-Wl,-S'' and ``-Wl,-s''.  
-If you always strip the symbols and these options are sufficient, feel  
-free, but this is a less flexible approach.  
-  
-----  
-!!5.6. Extremely small executables  
-  
-You might find the paper  
-Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux  
-useful.  
-It describes how to make a truly tiny program executable.  
-Frankly, you shouldn't use most of these tricks under normal  
-circumstances, but they're quite instructive in showing how  
-ELF really works.  
-  
-----  
-!!5.7. Speeding up C++ initialization  
-  
-The KDE developers have noticed that large GUI C++ applications can take  
-a long time to start up, in part due to its needing to do many relocations.  
-There are several solutions to this.  
-See  
-Making C++  
-ready for the desktop (by Waldo Bastian)  
-for more information.  
-  
-----  
-!!!6. More Examples  
-  
-The following are more examples of all three approaches  
-(static, shared, and dynamically loaded libraries).  
-File libhello.c is a trivial library,  
-with libhello.h as its header.  
-File demo_use.c is a trivial caller of the library.  
-This is followed by commented scripts (script_static and script_dynamic)  
-showing how to use the library as a static and shared library.  
-This is followed by demo_dynamic.c and script_dynamic, which show  
-how to use the shared library as a dynamically loaded library.  
-  
-----  
-!!6.1. File libhello.c  
-  
-  
-/* libhello.c - demonstrate library use. */  
-#include `stdio.hb  
-void hello(void) {  
-printf("Hello, library world.\n");  
-}  
-  
-----  
-!!6.2. File libhello.h  
-  
-  
-/* libhello.h - demonstrate library use. */  
-void hello(void);  
-  
-----  
-!!6.3. File demo_use.c  
-  
-  
-/* demo_use.c -- demonstrate direct use of the "hello" routine */  
-#include "libhello.h"  
-int main(void) {  
-hello();  
-return ;  
-}  
-  
-----  
-!!6.4. File script_static  
-  
-  
-#!/bin/sh  
-# Static library demo  
-# Create static library's object file, libhello-static.o.  
-# I'm using the name libhello-static to clearly  
-# differentiate the static library from the  
-# dynamic library examples, but you don't need to use  
-# "-static" in the names of your  
-# object files or static libraries.  
-gcc -Wall -g -c -o libhello-static.o libhello.c  
-# Create static library.  
-ar rcs libhello-static.a libhello-static.o  
-# At this point we could just copy libhello-static.a  
-# somewhere else to use it.  
-# For demo purposes, we'll just keep the library  
-# in the current directory.  
-# Compile demo_use program file.  
-gcc -Wall -g -c demo_use.c -o demo_use.o  
-# Create demo_use program; -L. causes "." to be searched during  
-# creation of the program. Note that this command causes  
-# the relevant object file in libhello-static.a to be  
-# incorporated into file demo_use_static.  
-gcc -g -o demo_use_static demo_use.o -L. -lhello-static  
-# Execute the program.  
-./demo_use_static  
-  
-----  
-!!6.5. File script_shared  
-  
-  
-#!/bin/sh  
-# Shared library demo  
-# Create shared library's object file, libhello.o.  
-gcc -fPIC -Wall -g -c libhello.c  
-# Create shared library.  
-# Use -lc to link it against C library, since libhello  
-# depends on the C library.  
-gcc -g -shared -Wl,-soname,libhello.so.0 \  
--o libhello.so..0 libhello.o -lc  
-# At this point we could just copy libhello.so..0 into  
-# some directory, say /usr/local/lib.  
-# Now we need to call ldconfig to fix up the symbolic links.  
-# Set up the soname. We could just execute:  
-# ln -sf libhello.so..0 libhello.so.  
-# but let's let ldconfig figure it out.  
-/sbin/ldconfig -n .  
-# Set up the linker name.  
-# In a more sophisticated setting, we'd need to make  
-# sure that if there was an existing linker name,  
-# and if so, check if it should stay or not.  
-ln -sf libhello.so.0 libhello.so  
-# Compile demo_use program file.  
-gcc -Wall -g -c demo_use.c -o demo_use.o  
-# Create program demo_use.  
-# The -L. causes "." to be searched during creation  
-# of the program; note that this does NOT mean that "."  
-# will be searched when the program is executed.  
-gcc -g -o demo_use demo_use.o -L. -lhello  
-# Execute the program. Note that we need to tell the program  
-# where the shared library is, using LD_LIBRARY_PATH.  
-LD_LIBRARY_PATH="." ./demo_use  
-  
-----  
-!!6.6. File demo_dynamic.c  
-  
-  
-/* demo_dynamic.c -- demonstrate dynamic loading and  
-use of the "hello" routine */  
-/* Need dlfcn.h for the routines to  
-dynamically load libraries */  
-#include `dlfcn.hb  
-#include `stdlib.hb  
-#include `stdio.hb  
-/* Note that we don't have to include "libhello.h".  
-However, we do need to specify something related;  
-we need to specify a type that will hold the value  
-we're going to get from dlsym(). */  
-/* The type "simple_demo_function" describes a function that  
-takes no arguments, and returns no value: */  
-typedef void (*simple_demo_function)(void);  
-int main(void) {  
-const char *error;  
-void *module;  
-simple_demo_function demo_function;  
-/* Load dynamically loaded library */  
-module = dlopen("libhello.so", RTLD_LAZY);  
-if (!module) {  
-fprintf(stderr, "Couldn't open libhello.so: %s\n",  
-dlerror());  
-exit(1);  
-}  
-/* Get symbol */  
-dlerror();  
-demo_function = dlsym(module, "hello");  
-if ((error = dlerror())) {  
-fprintf(stderr, "Couldn't find hello: %s\n", error);  
-exit(1);  
-}  
-/* Now call the function in the DL library */  
-(*demo_function)();  
-/* All done, close things cleanly */  
-dlclose(module);  
-return ;  
-}  
-  
-----  
-!!6.7. File script_dynamic  
-  
-  
-#!/bin/sh  
-# Dynamically loaded library demo  
-# Presume that libhello.so and friends have  
-# been created (see dynamic example).  
-# Compile demo_dynamic program file into an object file.  
-gcc -Wall -g -c demo_dynamic.c  
-# Create program demo_use.  
-# Note that we don't have to tell it where to search for DL libraries,  
-# since the only special library this program uses won't be  
-# loaded until after the program starts up.  
-# However, we DO need the option -ldl to include the library  
-# that loads the DL libraries.  
-gcc -g -o demo_dynamic demo_dynamic.o -ldl  
-# Execute the program. Note that we need to tell the  
-# program where get the dynamically loaded library,  
-# using LD_LIBRARY_PATH.  
-LD_LIBRARY_PATH="." ./demo_dynamic  
-  
-----  
-!!!7. Other Information Sources  
-  
-Particularly useful sources of information about libraries  
-include the following:  
-  
-  
-  
-  
-  
-*  
-  
-``The GCC HOWTO'' by Daniel Barlow.  
-In particular, this HOWTO discusses  
-compiler options for creating libraries and how to query  
-libraries.  
-It covers information not covered here, and vice versa.  
-This HOWTO is available through the Linux Documentation Project at  
-http://www.linuxdoc.org.  
-  
-  
-*  
-*  
-  
-``Executable and Linkable Format (ELF)'' by  
-the Tool Interface Standards (TIS) committee  
-(this is actually one chapter of the Portable Formats Specification  
-Version 1.1 by the same committee).  
-This provides information about the ELF format  
-(it isn't specific to Linux or GNU gcc), and provides a great deal of  
-detail on the ELF format.  
-See  
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ELF.doc.tar.gz  
-If you get the file from MIT, note that the format is unusual;  
-after gunzipping and untarring, you'll get an ``hps'' file; just  
-strip off the top and bottom lines, rename it to a ``ps'' file,  
-and you'll get a printable Postscript file with the usual filename.  
-  
-  
-*  
-*  
-  
-``ELF: From the Programmer's Perspective'' by  
-Hongjui Lu. This gives Linux and GNU gcc-specific information on ELF, and is  
-available at  
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/elf.ps.gz.  
-  
-  
-*  
-  
-----  
-!!!8. Copyright and License  
-  
-This document is Copyright (C) 2000 David A. Wheeler.  
-It is covered by the GNU General Public License (GPL).  
-You may redistribute it without cost.  
-Interpret the document's source text  
-as the ``program'' and adhere to the following terms:  
-  
-  
- This program is free software; you can redistribute it and/or modify  
-it under the terms of the GNU General Public License as published by  
-the Free Software Foundation; either version 2 of the License, or  
-(at your option) any later version.  
-  
-  
-  
- This program is distributed in the hope that it will be useful,  
-but WITHOUT ANY WARRANTY; without even the implied warranty of  
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
-GNU General Public License for more details.  
-  
-  
-  
- You should have received a copy of the GNU General Public License  
-along with this program; if not, write to the Free Software  
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
-  
-  
-  
-  
-  
-These terms do permit mirroring by other web sites,  
-but please:  
-  
-  
-  
-  
-  
-*  
-  
-make sure your mirrors automatically get  
-upgrades from the master site,  
-  
-  
-*  
-*  
-  
-clearly show the location of the master site,  
-http://www.dwheeler.com/program-library,  
-with a hypertext link  
-to the master site, and  
-  
-  
-*  
-*  
-  
-give me (David A. Wheeler) credit as the author.  
-  
-  
-*  
-  
-  
-  
-The first two points primarily protect me from repeatedly hearing about  
-obsolete bugs.  
-I do not want to hear about bugs I fixed a year ago, just because you  
-are not properly mirroring the document.  
-By linking to the master site,  
-users can check and see if your mirror is up-to-date.  
-I'm sensitive to the problems of sites which have very  
-strong security requirements and therefore cannot risk normal  
-connections to the Internet; if that describes your situation,  
-at least try to meet the other points  
-and try to occasionally sneakernet updates into your environment.  
-  
-  
-  
-By this license, you may modify the document,  
-but you can't claim that what you didn't write is yours (i.e., plagiarism)  
-nor can you pretend that a modified version is identical to  
-the original work.  
-Modifying the work does not transfer copyright of the entire work to you;  
-this is not a ``public domain'' work in terms of copyright law.  
-See the license for details, in particular noting that  
-``You must cause the modified files to carry prominent notices  
-stating that you changed the files and the date of any change.''  
-If you have questions about what the license allows, please contact me.  
-In most cases, it's better if you send your changes to the master  
-integrator (currently David A. Wheeler), so that your changes will be  
-integrated with everyone else's changes into the master copy
+Describe [HowToProgramLibraryHOWTO] here.