976 lines
28 KiB
HTML
976 lines
28 KiB
HTML
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Shared Libraries</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Program Library HOWTO"
|
|
HREF="index.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Static Libraries"
|
|
HREF="static-libraries.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Dynamically Loaded (DL) Libraries"
|
|
HREF="dl-libraries.html"></HEAD
|
|
><BODY
|
|
CLASS="SECT1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Program Library HOWTO</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="static-libraries.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
></TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="dl-libraries.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="SHARED-LIBRARIES"
|
|
></A
|
|
>3. Shared Libraries</H1
|
|
><P
|
|
>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:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>update libraries and still support programs that want to use older,
|
|
non-backward-compatible versions of those libraries;</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>override specific libraries or even specific functions
|
|
in a library when executing a particular program.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>do all this while programs are running using existing libraries.</P
|
|
></LI
|
|
></UL
|
|
></P
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN46"
|
|
></A
|
|
>3.1. Conventions</H2
|
|
><P
|
|
>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.</P
|
|
><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN49"
|
|
></A
|
|
>3.1.1. Shared Library Names</H3
|
|
><P
|
|
>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''.</P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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).</P
|
|
><P
|
|
>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 <EM
|
|
>development</EM
|
|
> 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.</P
|
|
><P
|
|
>Thus, <TT
|
|
CLASS="FILENAME"
|
|
>/usr/lib/libreadline.so.3</TT
|
|
>
|
|
is a fully-qualified soname, which
|
|
ldconfig would set to be a symbolic link to some realname like
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/usr/lib/libreadline.so.3.0</TT
|
|
>.
|
|
There should also be a linker name,
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/usr/lib/libreadline.so</TT
|
|
>
|
|
which could be a symbolic link referring to
|
|
<TT
|
|
CLASS="FILENAME"
|
|
>/usr/lib/libreadline.so.3</TT
|
|
>.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN62"
|
|
></A
|
|
>3.1.2. Filesystem Placement</H3
|
|
><P
|
|
>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
|
|
<A
|
|
HREF="info:standards#Directory_Variables"
|
|
TARGET="_top"
|
|
>info:standards#Directory_Variables</A
|
|
>.
|
|
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.</P
|
|
><P
|
|
>The Filesystem Hierarchy Standard (FHS) discusses what should go where
|
|
in a distribution (see
|
|
<A
|
|
HREF="http://www.pathname.com/fhs"
|
|
TARGET="_top"
|
|
>http://www.pathname.com/fhs</A
|
|
>).
|
|
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.</P
|
|
><P
|
|
>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 (<TT
|
|
CLASS="FILENAME"
|
|
>/usr/local</TT
|
|
>),
|
|
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).</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN70"
|
|
></A
|
|
>3.2. How Libraries are Used</H2
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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. </P
|
|
><P
|
|
>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.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN77"
|
|
></A
|
|
>3.3. Environment Variables</H2
|
|
><P
|
|
>Various environment variables can control this process,
|
|
and there are environment variables that permit
|
|
you to override this process.</P
|
|
><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN80"
|
|
></A
|
|
>3.3.1. LD_LIBRARY_PATH</H3
|
|
><P
|
|
>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).</P
|
|
><P
|
|
>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
|
|
<A
|
|
HREF="http://www.visi.com/~barr/ldpath.html"
|
|
TARGET="_top"
|
|
>http://www.visi.com/~barr/ldpath.html</A
|
|
>
|
|
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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> /lib/ld-linux.so.2 --library-path PATH EXECUTABLE</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
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.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN86"
|
|
></A
|
|
>3.3.2. LD_DEBUG</H3
|
|
><P
|
|
>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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> export LD_DEBUG=files
|
|
command_to_run</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
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.</P
|
|
><P
|
|
>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.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT3"
|
|
><H3
|
|
CLASS="SECT3"
|
|
><A
|
|
NAME="AEN91"
|
|
></A
|
|
>3.3.3. Other Environment Variables</H3
|
|
><P
|
|
>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).</P
|
|
><P
|
|
>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. </P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN95"
|
|
></A
|
|
>3.4. Creating a Shared Library</H2
|
|
><P
|
|
>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.
|
|
You pass the soname using the -Wl gcc option.
|
|
The -Wl option passes options
|
|
along to the linker (in this case the -soname linker option) -
|
|
the commas after -Wl are not a typo, and you
|
|
must not include unescaped whitespace in the option.
|
|
Then create the shared library using this format:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>gcc -shared -Wl,-soname,<TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>your_soname</I
|
|
></TT
|
|
> \
|
|
-o <TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>library_name</I
|
|
></TT
|
|
> <TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>file_list</I
|
|
></TT
|
|
> <TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>library_list</I
|
|
></TT
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>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:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>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.0.1 a.o b.o -lc</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Here are a few points worth noting:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>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.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>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.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>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.</P
|
|
></LI
|
|
></UL
|
|
></P
|
|
><P
|
|
>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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> -Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
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.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN115"
|
|
></A
|
|
>3.5. Installing and Using a Shared Library</H2
|
|
><P
|
|
>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).</P
|
|
><P
|
|
>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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> ldconfig -n <TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>directory_with_shared_libraries</I
|
|
></TT
|
|
></PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH my_program</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>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).</P
|
|
><P
|
|
>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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> #!/bin/sh
|
|
export LD_LIBRARY_PATH=/usr/local/my_lib:$LD_LIBRARY_PATH
|
|
exec /usr/bin/my_program.orig $*</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
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.</P
|
|
><P
|
|
>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:
|
|
<TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
> ldd /bin/ls</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
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:
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>/lib/ld-linux.so.N (where N is 1 or more, usually at least 2).
|
|
This is the library that loads all other libraries.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>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.</P
|
|
></LI
|
|
></UL
|
|
>
|
|
Beware: do <EM
|
|
>not</EM
|
|
> 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.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN135"
|
|
></A
|
|
>3.6. Incompatible Libraries</H2
|
|
><P
|
|
>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:
|
|
<P
|
|
></P
|
|
><OL
|
|
TYPE="1"
|
|
><LI
|
|
><P
|
|
>The behavior of a function changes so that it no longer
|
|
meets its original specification,</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>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).</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>An exported function is removed.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>The interface of an exported function changes.</P
|
|
></LI
|
|
></OL
|
|
></P
|
|
><P
|
|
>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.</P
|
|
><P
|
|
>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
|
|
<A
|
|
HREF="http://www.trolltech.com/developer/faq/tech.html#bincomp"
|
|
TARGET="_top"
|
|
>Troll Tech's Technical FAQ</A
|
|
>:
|
|
<P
|
|
></P
|
|
><OL
|
|
TYPE="1"
|
|
><LI
|
|
><P
|
|
>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).</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>add or remove virtual member functions, because
|
|
this would change the size and layout of the vtbl of every subclass. </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>change the type of any data members or move any data members
|
|
that can be accessed via inline member functions.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>change the class hierarchy, except to add new leaves. </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>add or remove private data members, because
|
|
this would change the size and layout of every subclass. </P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>remove public or protected member functions unless they are inline.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>make a public or protected member function inline.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>change what an inline function does, unless the old version continues working.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>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.</P
|
|
></LI
|
|
></OL
|
|
></P
|
|
><P
|
|
>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.</P
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="static-libraries.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="dl-libraries.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Static Libraries</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
> </TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Dynamically Loaded (DL) Libraries</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |