Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Dec 2001 10:44:00 -0800
From:      Joe Kelsey <joe@zircon.seattle.wa.us>
To:        John Polstra <jdp@polstra.com>
Cc:        stable@freebsd.org
Subject:   Re: rtld-elf issues
Message-ID:  <15384.63216.190942.560961@zircon.zircon.seattle.wa.us>
In-Reply-To: <200112131704.fBDH4aM14501@vashon.polstra.com>
References:  <15382.36337.945315.693398@zircon.zircon.seattle.wa.us> <200112131704.fBDH4aM14501@vashon.polstra.com>

next in thread | previous in thread | raw e-mail | index | archive | help
John Polstra writes:
 > In article <15382.36337.945315.693398@zircon.zircon.seattle.wa.us>,
 > Joe Kelsey  <joe@zircon.seattle.wa.us> wrote:
 > > What should rtld-elf do when asked to load an already loaded shared
 > > object?
 > > 
 > > Currently, if you manually request loading of a shared object via
 > > dlopen, rtld-elf will recursively try to load any libraries that the
 > > shared object references.  If the shared library references an already
 > > manually-loaded shared object, it still attempts to find the shared
 > > object via the various paths in effect at the time of the dlopen call.
 > > This is an unnecessary effort, since the module is already loaded, yet
 > > the search can fail and abort the program due to phantom dlopen errors.
 > 
 > For every library it tries to load (including libraries specified by
 > dependencies), it first checks to see if it already has that exact
 > pathname loaded.  If so, it just increments a reference count
 > without reloading the library.
 > 
 > If there is no pathname match, it opens the library file found by
 > its usual search rules (but doesn't load it yet).  Then it checks
 > the device and inode numbers against all currently loaded libraries
 > to see if the same file is already loaded by a different pathname.
 > If it finds a match it increments a reference count without
 > reloading the library.
 > 
 > What do you think it should do?

I admit that the situation is confusing.  The problem arises because the
Linux and Solaris programmers who created the Makefiles did not really
understand the linking rules that need to be applied to shared objects,
and, apparantly, the loaders on Linux and Solaris are much more
forgiving than the loader on FreeBSD.

 > > Shouldn't the loader notice that libjvm.so is already mapped into the
 > > address space and skip checking for it on the disk?
 > 
 > No, I don't think so.  There could be any number of different
 > libraries named "libjvm.so".  Without an absolute pathname, it can't
 > assume they're all the same.
 > 
 > To get what you want, I think you might need to specify the
 > appropriate -rpath arguments when building the shared libraries.
 > Man ld(1) for details.

The problem is that the actual location of libjvm.so *cannot* be
determined at link time, only at runtime, so it is not possible to
specify a valid -rpath value at link time.  See my comment above about
the legacy of lazy programmers not really understanding why or why not
to list a shared object at link time rather than run time.

This situation is very complex because Java is essentially designed to
load what it needs when it needs it at run time.  A Java program simply
needs to pick the JVM it wants to start with from among the potentially
large number of candidates and load it.  The JVM then does all of the
rest of the work of loading other libraries using a combination of
LD_LIBRARY_PATH and CLASSPATH to find them (except for the thread
library, usually a choice between green and native threads, also at run
time).

However, the Java internals only know how to load Java libraries.
Therefore, and shared objects which reference other shared objects need
to bring those shared objects along for the ride.  The best way to do
this is to reference them at link time and let the run time loader bring
along the others.  This leads to several nasty chicken-and-egg problems,
especially when you consider the choice of native vs. green threads and
the need to have different versions of libc!  There is also a
potentially nasty bug lurking due to the complex interrelationship
between Motif and Xt, requiring that Motif be already loaded before the
first Xt call, or else things do not work at all.

The way the Java implementers dealt with this problem on Linux and
Solaris is simply listing all libraries on link commands, regardless of
whether or not they can be found at run time via LD_LIBRARY_PATH.  The
fact that libjvm.so is loaded manually before any other shared object
references it is seemingly sufficient for the Linux and Solaris run time
loaders to be satisfied that they have it and skip it during library
searching and loading, regardless of absolute path issues.

I do not have knowledge of the Linux or Solaris run time loaders, I only
know that the shared objects apparantly load correctly on those
platforms, but not on FreeBSD, due to this apparant reliance on absolute
path names.  I do not know what the other loaders do differently, so I
have not suggestions about what to change, except that library name
matching seems like a good fallback position when absolute path names
don't work out.  You could search through all of the paths available,
and when it fails look for the library name in your list of already
loaded libraries.  Matching simply libjvm.so would work just fine in
this specific case.

It is more or less moot at this point, since I have changed all of the
broken linker commands to remove unnecessary shared objects and prevent
the problem in the future.

/Joe

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?15384.63216.190942.560961>