From owner-freebsd-current@FreeBSD.ORG Tue Nov 25 18:14:13 2003 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C0BB516A4CE for ; Tue, 25 Nov 2003 18:14:13 -0800 (PST) Received: from stork.mail.pas.earthlink.net (stork.mail.pas.earthlink.net [207.217.120.188]) by mx1.FreeBSD.org (Postfix) with ESMTP id CB87543FD7 for ; Tue, 25 Nov 2003 18:14:12 -0800 (PST) (envelope-from tlambert2@mindspring.com) Received: from user-2ivfn2m.dialup.mindspring.com ([165.247.220.86] helo=mindspring.com) by stork.mail.pas.earthlink.net with asmtp (SSLv3:RC4-MD5:128) (Exim 3.33 #1) id 1AOpB4-0005R9-00; Tue, 25 Nov 2003 18:13:15 -0800 Message-ID: <3FC40572.142D4334@mindspring.com> Date: Tue, 25 Nov 2003 17:44:18 -0800 From: Terry Lambert X-Mailer: Mozilla 4.79 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: "E.B. Dreger" References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-ELNK-Trace: b1a02af9316fbb217a47c185c03b154d40683398e744b8a47eeaaca0da856f6056c474bbb55ab4c4a2d4e88014a4647c350badd9bab72f9c350badd9bab72f9c cc: current@freebsd.org Subject: Re: rtld + static linking X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Nov 2003 02:14:13 -0000 "E.B. Dreger" wrote: > After watching the recent shared/dynamic threads, and reading the > archives from five or six years ago, I have a question... > > Dynamic linking works by the kernel running the dynamic linker, > which loads shared objects and fixes the symbol tables, yes? No. Dynamic linking works because the crt0 mmap's the /usr/libexec/ld.so file as executable, and then points known stub offsets into it. It then passes this as part of the environment, at a negative offset, into the _main, which fills out a little glue table. After all this is set up, then _main calls the location .entry in the executable, which is usally main, but can be set to something else at link time. This all works because the crt0.o has some self-knowledge for a number of symbol offsets, and because _main is called with the environment descriptor. Basically, the environment descriptor is lost in the static linking case. > Is there some reason that a statically-linked program couldn't > include some "ld-elf.a" type of intelligence? Would that be > necessary and sufficient to allow statically-linked programs to > load shared objects? Yes, and yes. The main reason that there is no dlopen is that the environment descriptor is lost. This is pretty trivial to remedy, but it means passing the environment descriptor to something that can use it to set up the startup. This is complicated by the fact that only a single .init entry point is usable, so if you were to override it, you would lose library initialization for C libraries, and you would fail to call constructor code for statically declare class instances in C++ code, and lose out on other linker set stuff, such as per thread exception stacks, etc.. The trivial fix for this is to add a void * parameter to the constructor iterator in the crt0, and then pass the environment there, so that you could implement a libdlopen that took that and used it to obtain the self-knowledge of the crt0 that was needed to (1) adjust the stub pointers to an mmap'ed ld.so, and (2) provide the access to the symbol table needed so that when you loaded modules, they would link properly vs. the symbols in the executable itself. You would either need to change the list to specifically reference the libc symbols, OR you would need to reload libc.so (the problem with doing the latter is that you might get a different libc out of it, and the executable symbols that may replace the libc symbols wouldn't do so for modules, so that's a non-starter). It's actually a pretty trivial crt0 and ld change to deal with this, the sticking point is that you have to also change the libgcc and other GNU code to pass a NULL value to the void * constructor parameter in the default case. This would make the code minorly incompatible with Linux, etc., unless you could get the GCC people to pick up your change. -- Terry