This is the mail archive of the mailing list for the gas2 project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Has anyone looked at ELF 4.1?

   From: (H.J. Lu)
   Date: Sun, 16 Aug 1998 18:58:10 -0700 (PDT)

   # ldd /usr/bin/groff => /usr/lib/ (0x40007000) => /lib/ (0x4004c000) => /lib/ (0x40065000)
	   /lib/ => /lib/ (0x80000000)

   The problem is /usr/lib/ was compiled again
   glibc 2.0.x. When running on a glibc 2.1 machine, /lib/
   is glibc 2.1, which supports the same C ABI in glibc 2.0 using
   the symbol versioning. But glibc 2.1 has a different C++ ABI.
   Please keep in mind that libio in glibc has 2 ABIs, one for C
   and the other for C++.

If the ABI changed between glibc 2.0.x and glibc 2.1, then either the
name of the library has to change or we need to use symbol versioning.

To put it another way, why are those capabilities not adequate to fix
this problem?

I want to make sure that you are fixing a real problem here, not a
problem that has temporarily arisen because glibc happened to not use
symbol versioning for the C++ interface (if that is indeed what
happened).  You are proposing a new capability in the toolchain.  We
should only add it if we need it.

   > If groff once worked, and then broke, then it sounds as though
   > somebody must have made an incompatible change to the libstdc++
   > library interface.  Anybody who makes an incompatible change must
   > change the library version number.  Using the new ELF specs won't save
   > us from that sort of failure; it is equivalent to failing to increase
   > the version number in the ELF specs.

   The problem is the incompatible C++ ABIs in libio between glibc 2.0
   and glibc 2.1.

I don't see how this contradicts the paragraph you quoted.  I said
that anybody who makes an incompatible change must change the library
version number.  You have to explain why neither the library version
number nor the symbol versions changed.

   > What do the new ELF specs give us that we don't get from symbol
   > versioning and changing library names?

   We didn't change the library name of libc since the C ABI is ok.
   The problem is the C++ ABI in libc. It is very unique to Linux
   since we use the same code in libio for both libc and libstdc++.

A change in the C++ ABI is a change in the library ABI.  We use symbol
versioning to give us the ability to change a part of an ABI.  Why
does that not work in this case?

   >    1. Add switchs to ld to set EI_OSABI and EI_ABIVERSION.
   >    2. For Linux, set EI_ABIVERSION with C ABI and C++ ABI.
   > 	   EI_ABIVERSION = (0xf & C_ABI) | (0xf0 & C++_ABI)
   > What precisely do you mean here by C_ABI and C++_ABI?  You presumably
   > do not mean the version of the library, because there is no need to
   > record that.

   No. I mean the ABI version, like

   #ifdef glibc 2.0
   #define CXX_ABI	0
   #define C_ABI	0
   #elif defined glibc 2.1
   #define CXX_ABI	1
   #define C_ABI	0

That is not an explanation.  What do you mean by C_ABI?  If we change
the name of the library, does the C_ABI change?  Why or why not?

   > Four bits only gives you sixteen versions, which is not a lot.

   I think 16 is more than enough. We may want 3 bits for C++
   and 5 bits for C.

How is 16 more than enough?  What kind of time frame are you thinking
of?  You're saying that the C++ ABI needs to change from glibc 2.0 to
2.1.  Won't it change just about every time a new library is released?
If not, why not?

   >    3. ld sets EI_OSABI depending on target if it is not set at the command
   >    line.
   > How does ld determine EI_OSABI?

   Linker script? We already pass "-dynamic-linker /lib/" to ld for
   Linux. We can pass another one if necessary.

Making the compiler aware of the dynamic linker version number in this
way is a bogus hack, since it makes the compiler unnecessarily
dependent on the system version number.  You really ought to be able
to use the same compiler on most Linux versions.  After all, the code
generation doesn't change, and all the system dependencies are
reflected in the header files.  Introducing another system dependency
into the compiler is a step backward, not forward.

   >    4. ld sets EI_ABIVERSION depending on EI_ABIVERSION in the shared
   >    library used to build an ELF binary if it is not set at the command
   >    line.
   > This seems pointless.  The library version number is already recorded
   > in the DT_SONAME entry.  If it isn't, then where is it, and how does

   I am talking about C/C++ ABI version. soname is mainly for C programs
   which don't care about the C++ ABI.

No.  DT_SONAME is for anybody who uses a library, and it applies to
all interfaces of the library.  It is a bug to think that DT_SONAME
only applies to part of a library's interface.

   > ld determine EI_ABIVERSION?

   When we build a dynamic ELF object on Linux, we should always pass
   -lc to it. ld can get EI_ABIVERSION from

I think it's bogus to make ld treat libc specially.  It should be
logically possible to build a dynamic executable which does not depend
on libc.

Also, one of the more logical uses for EI_ABIVERSION would be for
statically linked binaries, since they don't get to adapt to the
system using dynamic linking.

   >    5. The dynamic linker will check both EI_OSABI and EI_ABIVERSION when
   >    choosing which shared library to load. With that, we can have both 2
   > with different EI_ABIVERSIONs in different directories.
   > Why would we want such a thing?
   > How precisely will this approach help with groff?
   > I think we have a problem with using multiple libraries which are
   > linked against different versions of libc.  However, I don't see how
   > EI_OSABI and EI_ABIVERSION can help with that.
   > We already have two library versioning schemes: DT_SONAME, and symbol
   > versioning.  Why do we need a third?  What deficiency in the existing
   > schemes does it address?

   We may want to load a different depending on the C++/C ABI
   version. For groff, on glibc 2.1, we want

   # ldd /usr/bin/groff => /usr/lib/ (0x40007000) => /usr/glibc-2.0/lib/ (0x4004c000) => /usr/glibc-2.0/ (0x40065000)
	   /lib/ => /lib/ (0x80000000)

I don't understand why this is an answer to my question.