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>