Subject: Re: static vs. dynamic runtime linking, again (was: PAM and su -K)
To: Jason Thorpe <thorpej@shagadelic.org>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 01/27/2005 19:48:26
[ On Tuesday, January 25, 2005 at 09:20:30 (-0800), Jason Thorpe wrote: ]
> Subject: Re: static vs. dynamic runtime linking, again (was: PAM and su -K)
>
> On Jan 24, 2005, at 3:17 PM, der Mouse wrote:
> > 
> > I was dealing with a new 2.0 install.  I tried to link an X program.
> > The linker couldn't find -lXext -lX11.  So I added -L/usr/X11R6/lib
> > (from relatively hazy memory) and it found them - and promptly fell
> > over when I tried to run it, saying it couldn't find some libXext.so
> > file.
> 
> Like on all ELF systems, you need to add -R/usr/X11R6/lib, as well, 
> since /usr/X11R6/lib is not in the default run-time library search path 
> for the dynamic linker.

The "on all ELF systems" part simply is simply not true AT ALL.  Indeed
NetBSD is one of the few loners on this front.

All AT&T UNIX System V Release 4 ports used only '-L', and they're the
_true_ origin of ELF, even as admited by NetBSD's elf(5) manual; 

SunOS-5 also defaults the runtime path to the '-L' path(s) of course,
and I seem to remember others too, but my memory of which actually used
anything like ELF is now rather fuzzy.

In fact the only still-running non-Sun, non-BSD, true ELF-based system I
have access to which does behave in the way NetBSD now does, with its
own native toolchain, is IRIX-6.5, but it's so far off the beaten path
that I don't and cannot expect anything better from it.


And also note that '-R' is _not_ a documented option for cc(1) on
NetBSD, so I still don't know how anybody, der Mouse included, but
especially anyone truly more naïve, is supposed to intuit a requirement
for its use.  (and let's not even begin with the damn '-W,l' magic!)

So, on all "proper" ELF implementations that I've ever used the run-time
search path for shared objects defaults to the '-L' path(s) they were
initially ``linked'' with, AS WELL AS to the default run-time search
path.

This only makes sense of course since it's the only sane way to handle
backwards compatability with every existing build script and makefile
imaginable.  Those who don't learn from history are doomed to repeat its
mistakes.

The default use of '-L' as the run-time path even used to work this way
on NetBSD too of course (with a.out, and without any /etc/ld.so.conf) --
and you really cannot, and MUST NOT, assume that every NetBSD user will
realize that all the rules of how to compile and link simple programs
have changed just because some underlying implementation detail changed,
especially when the documentation is so lacking!

NetBSD's ld(1) manual page also still says as much about the '-rpath',
which "cc -R" is presumably translated into, and its relationship to
'-L', though for some reason even the NetBSD manual page seems to say
this is only a SunOS behaviour (though since some of us seem to believe
the NetBSD shared library stuff was borrowed from SunOS, we similarly
assume that SunOS rules must apply to NetBSD too):

       -rpath directory
              Add a directory to the runtime library search path.
              This is used when linking an  ELF  executable  with
              shared  objects.  All -rpath arguments are concate-
              nated and passed to the runtime linker, which  uses
              them  to  locate  shared  objects  at runtime.  The
              -rpath option is also used when locating shared ob-
              jects which are needed by shared objects explicitly
              included in the link; see the  description  of  the
              -rpath-link  option.   If  -rpath  is not used when
              linking an ELF executable, the contents of the  en-
              vironment  variable  LD_RUN_PATH will be used if it
              is defined.

              The -rpath option may also be used  on  SunOS.   By
              default,  on  SunOS, the linker will form a runtime
              search path out of all the -L options it is  given.
              If a -rpath option is used, the runtime search path
              will be formed exclusively  using  the  -rpath  op-
              tions, ignoring the -L options.  This can be useful
              when using gcc, which adds many  -L  options  which
              may be on NFS mounted filesystems.


The ld.elf_so(1) manual page doesn't help any here either, assuming one
chased down the "See Also"s that far -- it's just leads one on a further
wild goose chase:

     The linker will search for libraries in three lists of paths:

     1.   A user defined list of paths as specified in LD_LIBRARY_PATH and
          ld.so.conf(5).

          The use of ld.so.conf should be avoided as the setting of a global
          search path can present a security risk.

     2.   A list of paths specified within a shared object using a DT_RPATH
          entry in the dynamic section.  This is defined at shared object link
          time.

     3.   The list of default paths which is set to /usr/lib.

Note there's no mention of where this DT_RPATH entry comes from and
"DT_RPATH" does _NOT_ occur in the ld(1) manual page.

Experienced C programmers will be forced to assume it's from "-L"
options since that's how they specify a library's path to the compiler.

There was also no mention of "-L" functionality being degraded in the
release notes when NetBSD migrated from a.out to ELF (nor is there any
mention in cc(1), though of course it still only refers to ".a" files
and apparently hasn't been updated since 1998 -- i.e. pre-1.5).

It wouldn't be so bad though if these "documentation" problems were the
only kinds of problems we have, and frequently see others have, with
shared libraries....  :-)

-- 
						Greg A. Woods

H:+1 416 218-0098  W:+1 416 489-5852 x122  VE3TCP  RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com>          Secrets of the Weird <woods@weird.com>