From owner-freebsd-stable Thu Dec 13 13:28:35 2001 Delivered-To: freebsd-stable@freebsd.org Received: from zircon.seattle.wa.us (sense-sea-CovadSub-0-228.oz.net [216.39.147.228]) by hub.freebsd.org (Postfix) with SMTP id BD22A37B419 for ; Thu, 13 Dec 2001 13:28:29 -0800 (PST) Received: (qmail 9697 invoked by uid 1001); 13 Dec 2001 18:44:00 -0000 From: Joe Kelsey MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15384.63216.190942.560961@zircon.zircon.seattle.wa.us> Date: Thu, 13 Dec 2001 10:44:00 -0800 To: John Polstra Cc: stable@freebsd.org Subject: Re: rtld-elf issues In-Reply-To: <200112131704.fBDH4aM14501@vashon.polstra.com> References: <15382.36337.945315.693398@zircon.zircon.seattle.wa.us> <200112131704.fBDH4aM14501@vashon.polstra.com> X-Mailer: VM 6.98 under Emacs 21.1.1 Sender: owner-freebsd-stable@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG John Polstra writes: > In article <15382.36337.945315.693398@zircon.zircon.seattle.wa.us>, > Joe Kelsey 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