This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: A shared version of libgcc
Date: Mon, 1 May 2000 15:18:24 -0700
From: Richard Henderson <rth@cygnus.com>
On Mon, May 01, 2000 at 06:07:49PM +0200, Mark Kettenis wrote:
> 1. Simple utility functions without interdependencies or access to
> global variables[1]. Examples are __ashldi3, __udivmoddi4.
[...]
> Assuming that these functions contain no serious bugs, it is
> absolutely no problem if more than one (potentially different) copy
> of these functions is used in one program. Most of these functions
> are small, so a slight increase in the size of binaries won't be
> noticed. Therefore these functions can stay in a static library if
> we can control re-exporting these functions from shared libraries.
But if we need a shared libgcc for another reason, there's no
reason not to have them in libgcc.so as well.
But the point is that that other reason isn't there for pure C
programs and shared libraries. You don't need to register the frame
info if you don't use exception handling. Look at how current crtstuff
implementation uses weak references to __register_frame_info and
__deregister_frame_info. As soon as these functions are present (that
is if you link with a library that contains them because it uses
exceptions, or if you use exceptions in your program itself wich
causes those functions to be sucked in from libgcc.a) the frame info
is correctly registered.
Wouldn't it be a great win if we could avoid linking with the shared
libgcc.so for ordinary C code?
> It worries me quite a bit to see that the module containing the
> frame functions references several of the pthreads functions. This
> means that libgcc is tied to a particular implementation of those
> functions. This isn't too bad while libgcc is a static library,
> but could lead to all kinds of badness if libgcc is turned into a
> shared library, and used in multithreaded libraries.
Eh? I assume you mean multithreaded programs using a different
pthreads implementation. But if you've got multiple pthreads
implementations running around your system, doesn't that imply
you've got other configuration problems as well?
The current soname of the LinuxThreads that's distributed with glibc
should give you a hint :-). The idea is that once the Kernel people
get their act together, and provide sane support for threads in the
Linux kernel, we'll want to write a pthreads library that takes
advantage of this. It will be hard to do this while keeping the ABI
compatible with the current implementation. The current LinuxThreads
ABI exposes quite a lot of its implementation details. I even doubt
if we can support mutexes shared by multiple processes within the
current LinuxThreads ABI. While it is true that there is no guarantee
that this will happen, I think it would be a shame if introducing a
shared libgcc would severely limit the possibilities of how the GNU C
Library team can improve the library. Also note that if you link libc
with the shared libgcc and that libgcc is tied to a specific pthreads
implementation, you effectively tie libc to that specific pthreads
implementation.
Of course there are ways to work around this in libgcc or in libc.
But we should investigate this now, before introducing a shared libgcc
and create a situation we later regret.
> * Put those symbols in a shared library, and link all shared
> libraries and programs that use any of those symbols against this
> library. Finding out whether to link with the shared libgcc or not
> might be tricky.
I posted a possible scheme for this yesterday:
http://gcc.gnu.org/ml/gcc/2000-04/msg00782.html
But in your scheme there are still programs and shared libraries that
don't use exceptions and nevertheless dependend on libgcc.so.
> * On ELF systems, we might include the frame functions in shared
> libraries that need them (i.e. those that actually use exception
> handling), but set DT_AUXILIARY to a shared library containing the
> frame functions. This will allow things to work if the shared
> libgcc isn't found, but it only works if those libraries re-export
> the frame functions and if programs linked with that library do not
> contain the frame functions.
I don't see that this buy's us anything, just makes problems exceedingly
wierd and hard to diagnose.
Consider the __register_frame_info plus __register_frame_info_2 coordination
problem. A real implementation of __r_f_i exists in libfoo.so with
DT_AUXILIARY set appropriately. A real implementation of __r_f_i and
__r_f_i_2 exists in libbar.so, also with DT_AUXILIARY set. Consider the
case of libfoo before libbar in the symbol search path. If libgcc.so
exists, then both libfoo and libbar defer to the libgcc implmementation,
and since libgcc can coordinate the two implementations, all is well. If
libgcc.so does not exist, then the libfoo and libbar cannot defer the
implementation, the implementations of __r_f_i and __r_f_i_2 come from
different dsos, and coordination does not happen.
The really insidious part of this failure is that, because of the nature
of DT_AUXILIARY, ld.so does not report any sort of error, and the same
application will work on one system but mysteriously fail on another.
Contrast this with the current situation in which the application with
miscommunicating dsos will fail on all systems.
OK, scrap this proposal.
> * On ELF systems where we have some control over libc, we can put the
> frame functions in libc, and set DT_AUXILIARY for libc to a shared
> libgcc. That way programs and shared libraries that are linked
> against libc do not have to be explicitly linked against a shared
> libgcc, whereas we leave the option open to install a shared libgcc
> if the frame functions will ever need to be changed.
At the point __r_f_i_2 is introduced, applications that use that
interface have to start linking against libgcc.so directly. Either
that or libc has to be rebuilt to include them, at which point
DT_AUXILIARY doesn't do you any good at all.
DT_AUXILIARY as I see it is basically only good for selecting cpu-specific
implementations of standard functions.
Agreed.
> And what about the C++ specific symbols? Since we control libstdc++,
> we have some additional flexibility here:
>
> * Keep those in a static library. If they're also included in
> libstdc++ this static library will only be used for C++ programs
> that don't use the standard C++ library.
>
> * Include those symbols in libstdc++ and link all C++ programs
> against libstdc++.
>
> * Include those symbols in a special C++ runtime shared library.
>
> * Include those symbols in both libstdc++ and the special C++ runtime
> shared library. That way one doesn't have to distribute two
> libraries for C++ programs that use the standard C++ library.
All of these are reasonable, from what little I know of what's
involved with the C++ support in libgcc. What to do with this
stuff is a question for the G++ and libstdc++-v3 teams to work out.
As long as the C++ code that's now in libgcc doesn't end up in the
same shared library as the code needed by plain C programs.
> However, it might be possible to (ab)use symbol versioning to make
> sure that new programs don't pick them up from libc.so[2]. But I don't
> think it is worth the trouble doing this for the symbols in class 1.
>
> The frame functions pose a bigger problem, since their presece in libc
> will make it difficult to make sure that the newest version of those
> functions is used at all times.
A solution is definitely required for the frame functions. The
couple o symbols in class 1 can just ride along on the coattails.
The solution I had in mind is
(a) For systems currently using glibc, make sure libgcc.so exports
symbols with the same version tags that glibc currently does.
(b) Remove the symbols from libc.so and link libc.so against libgcc.so.
No DT_AUXILIARY, just a straight DT_NEEDED.
This preserves backwards compatibility with old binaries because all
applications which depended on libc.so now pull in libgcc.so indirectly.
Also, libgcc.so is inserted at the appropriate place in the symbol
search path, so that the symbols which previously resolved to libc.so
now resolve to libgcc.so.
I'm not sure if that's robust enough. The version information
includes the library from which the versions are needed, and an overly
pedantic dynamic linker might spoil the fun :-).
Also note that this way you're tying libc and the shared libgcc
together. The libgcc ABI effectively becomes part of libc. The GNU
linker currently looks at all dependencies of a shared library when
trying to satisfy undefined references (the Solaris linker doesn't do
this, and I believe that Ian now considers this a bug in the GNU
linker, but it will probably take some time before this is fixed).
This makes moving binaries created with GCC 3.0 to a system where libc
wasn't built with GCC 3.0 extremely painfull. Even if you install the
right libgcc.so, things might not work, unless you link the program
explicitly against libgcc.so (otherwise the dependency on libgcc.so
isn't recorded).
Mark