This is the mail archive of the libc-hacker@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ld.so version map


Ulrich, could you please remove the special ld.so version map again.
Since you made this change, only a very limited set of symbols is
exported by ld.so.  This means that overriding a lot of symbols that
were previously exported in ld.so is no longer possible.  And as
Roland explained (see the message quoted below, especially the last
paragraph) being able to override functions in ld.so is the right
thing.

Of course adding all these symbols to ld.so's map is a possibility,
but this map file would be rather hard to maintain.  Using libc's
version map for ld.so really is the right thing, since there are no
symbols in there that we should not export.

Mark

   Date: Tue, 2 Feb 1999 15:07:24 -0500
   From: Roland McGrath <roland@frob.com>

   In the bootstrap relocation of the dynamic linker, it uses a special symbol
   resolution algorithm that always uses the dynamic linker's own definitions
   for all its global symbols.  This is of course necessary for bootstrapping,
   since the dynamic linker has to be whole and working before any other
   modules will be loaded that might provide definitions.

   So, the dynamic linker defines symbols it needs for basic operation such as
   open, mmap, etc.  On Linux, these definitions all come from libc_pic.a and
   so are identical to the definitions that will appear in libc.so.  But on
   the Hurd, many of these functions are much more complex than a simple
   system call stub, so dl-sysdep.c defines special simpler versions of them
   that will work *only* in the dynamic linker at startup time, and *cannot*
   be used later; it defines these as weak symbols.

   After all the program's needed libraries have been loaded and relocated,
   the dynamic linker is no longer in this special situation where it had to
   use its own definitions of symbols such as open and mmap.  If neither the
   program nor any library made reference to ld.so's own symbols, then most of
   the dynamic linker will not be used any more; it only needs to stay around
   to do on-demand relocations for lazy binding, and to make available the
   `r_map' list for the debugger.  If it were worth the trouble, the dynamic
   linker could unmap most of its own code at this point (or all of it, if
   there is no lazy binding remaining to be done).  (One rarely sees this case
   any more, since because of nsswitch libc.so refers to ld.so's symbols, and
   one rarely dynamically links a program without libc.)

   If there are references to ld.so's own symbols, such as from dlopen, then
   the dynamic linker is now taking on the role of an ordinary shared library
   that will be called by the program later through an ordinary explicit
   function entry point.  So, its symbols are now bound as for any shared
   library, and in the usual course of things its references to open, mmap,
   etc. bind to the libc.so definitions.

   In the common case on Linux, this results in redirecting PLT entries for
   symbols like open from ld.so's copy of the code to the identical code at a
   different address, in libc.so.  Since the code is completely identical,
   having come originally from the same object file in libc_pic.a, this makes
   no meaningful difference.  It's probably the tiniest bit nicer to your
   cache, and conceivably your VM, that calls to open from ld.so and from the
   rest of the program now use the same address and the same cache line of the
   instructions in `open' rather than filling two cache lines with identical
   contents.

   On the Hurd, it just plain won't work for ld.so to use its own versions of
   open et al when called from dlopen and the like, when the callers are using
   the code from libc.  For example, file descriptors are implemented by
   entirely different data structures in the two versions, and the data
   structures used by ld.so's private version are destroyed after startup is
   complete, before calling the program's entry point.

   But on any system, it would not be the right semantics for the dynamic
   linker to use its own definitions for these symbols.  Take the example of a
   program or preload that redefines open, read, write, et al to implement
   some special extra functionality not provided by the normal versions; there
   are several such things around, to implement open-by-URL, auditing things,
   caching things, process migration things, etc., etc.  (The exact prescribed
   proper way to do this sort of interposition in glibc has changed and become
   more complex since I originally designed and implemented the dynamic
   linker, what with symbol versioning and __s and all--but it remains
   reasonable and supported to do such a thing in some fashion or other, and
   people do it.)  Using such a scheme, one can reasonably expect to point a
   program at some special directory name meaningful only with this special
   extra functionality (e.g. a URL as the directory name), and have it find
   all its files there just as it would find them in a normal directory like
   /usr/local.  This is a reasonable expectation of what to do generically
   with any program, and reasonably generic programs use dlopen.  Just as
   redefining open in this way makes fopen use your version of open, so it
   should make dlopen use your version of open as well.  It would be
   unreasonable to expect anything else.


   Roland



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]