Subject: Re: RFC: migration to a fully dynamically linked system
To: Wolfgang Solfrank <ws@tools.de>
From: Todd Vierling <tv@wasabisystems.com>
List: tech-userlevel
Date: 01/07/2002 09:20:28
On Sat, 5 Jan 2002, Wolfgang Solfrank wrote:

: > When ld(1) is binding symbols in a binary, it will put symbols needed by
: > libraries (in the case of your program, -lc, implicitly added by gcc) in the
: > dynamic symbol section of the binary.  These can then participate in the
: > ld.elf_so linking process.  (In the case of __sF, BSS space got allocated
: > too, so the symbol actually ended up in the binary rather than libc.so, both
: > with and without libc.a.)
:
: IMHO it's a bug for ld to not put all the (external) symbols
: defined in the binary in the dynsym/dynstr sections.

That's a function of the ELF specification; normally, this is *not* done.
However, read on.

: > However, what we're dealing with in this thread are "static" binaries --
: > that is, binaries that have the ability to do dynamic loading, but which
: > contain no dynamic references to anything but the dynamic loader itself.
: > So, the resultant program *must not* have a reference to libc.so (since this
: > is exactly what the proponents of "static dlopen()" propose).
:
: Yes, of course you need something describing the symbols which
: are defined within the binary.  However, there is no need for
: the binary to have a reference to libc.so.  It's sufficient if
: the binary's dynamic symbol table provides information for all
: symbols defined within this binary.

There are problems with this scheme, especially when it comes to things like
libc "internal" symbols.

ELF provides for a "backdoor" into the historic practice of exposing all
globals in a binary to shared objects, via the "-E" linker switch (aka
"--export-dynamic" in GNU ld).  This is intended to allow you to dlopen()
objects which require access to main program symbols.

Now, it would be possible to use "-E" to make "static" binaries that can
dlopen() modules.  You'd still have to link against something like the
"libplacebo" I created, but dynamic libc wouldn't be necessary.  (To see
this in action, try my shar example all three ways with LDFLAGS=-Wl,-E ...)

However, if you use the "-E" switch, you must not link against any static
library which may also be dynamic.  The reason for this is that any internal
global symbol to the shared object may clash with a dynamic symbol in the
main binary -- and it's not well documented as to which one will "win".  A
workaround *may* be to link all such libraries with -Bsymbolic, but I'm not
sure on this point yet (and doing this may cause trouble with the weak
symbol indirection support needed by SA/pthreads, for instance).[*]

As a straw example, think about internal symbols in the resolver.  The main
binary may call gethostent(3), whereas the module may call getaddrinfo(3).
Both functions depend on a "global" _gethtent(), which is only global for
the sake of being used across two source files in libc.  If the ABI for
_gethtent() ever changes, this symbol clash will wreak all kinds of havoc to
the binary doing dlopen().

[*] Even so, if the programs are dynamically linked, what's the difference
    between going through all these linking headaches and simply linking
    against a shared libc?  In the former case, you still have to link
    with a library that may be corrupted (even if just a "libplacebo"), and
    in the latter case, you gain the ability to fix libc bugs simply by
    replacing libc.

: With our current system, there is a subtle difference between
: shared objects against which a program is linked and those
: which get dlopen()ed.  For the latter ones, you cannot
: overwrite symbols in the main program used by the shared
: object.  Actually, you can, if the symbol in question is also
: defined in a shared object against which the program is linked.

I'm not sure what you mean by "overwrite".

If you're saying that referenced symbols in the dlopen()ed object will link
first against the binary, that's correct.  To reverse this behavior, you use
-Bsymbolic on the shared object to be dlopen()ed.

-- 
-- Todd Vierling <tv@wasabisystems.com>  *  Wasabi & NetBSD:  Run with it.
-- CDs, Integration, Embedding, Support -- http://www.wasabisystems.com/