Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CentOS 5.8 with gcc 4.4.7 links against libstdc++ 6.0.8. How is it possible?

Tags:

c++

linux

centos

According to the gcc ABI policy, gcc 4.4.7 should depend on libstdc++ 6.0.13. As far as I understood, the compiler version and the libstdc++ version are deeply interrelated and can't be swapped, so it came to me as a surprise to discover the following facts:

  • CentOS 5.8 somehow manages to have a gcc44 package that links against 6.0.8, apparently coming with the default system (which is based on gcc-4.1.2)
  • that the libstdc++.so in the compiler directory (/usr/lib/gcc/x86_64-redhat-linux6E/4.4.7, where I expected to find a libstdc++-6.0.13) is not a link to a shared object of any sort, but a text file containing INPUT ( -lstdc++_nonshared /usr/lib64/libstdc++.so.6 )

What kind of magic is going on here?

Specifically:

  • How could they provide a gcc 4.4.7 that links against an older version of libstdc++? I thought it was not possible.
  • what is this stdc++_nonshared library?
  • I didn't know a .so file could contain that text. Who parses it (dynamic linker I guess) and what are its specifications and consequences?
  • How far can this magic go? Can I use gcc4.7 with libstdc++ 6.0.3? What is the spectrum of compatibility
like image 609
Stefano Borini Avatar asked Jun 02 '13 07:06

Stefano Borini


1 Answers

What kind of magic is going on here?

This is mostly the magic of ELF symbol versioning. The best reference I've seen on this is How to Write Shared Libraries by Ulrich Drepper, specifically section 3.

How could they provide a gcc 4.4.7 that links against an older version of libstdc++? I thought it was not possible.

The libstdc++ developers are careful about ABI compatibility. This makes it fairly straightforward to see what are the new symbols introduced between two different versions of libstdc++.

Looking at libstdc++'s ABI compatibility page, you can see that GCC 4.1's libstdc++ has GLIBCXX_3.4.8 and the stock (FSF release) of GCC 4.4 has GLIBCXX_3.4.13. It's then possible to look at the libstdc++ version scripts to see which symbols were added between these two versions.

A more empirical route for looking at symbol versions is to use a tool like readelf. E.g. on my Ubuntu system readelf --dyn-syms --wide /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt shows output like this (just a couple of selected shortish lines):

223: 000000000006dbe0  2121 FUNC    GLOBAL DEFAULT   12 std::ios_base::Init::Init()@@GLIBCXX_3.4
...
226: 00000000002ed920     1 OBJECT  GLOBAL DEFAULT   27 std::adopt_lock@@GLIBCXX_3.4.11

Note the symbol versions at the end of the symbol name, after the @@.

what is this stdc++_nonshared library?

Joining the dots from the above paragraph, stdc++_nonshared is a static library which contains the symbols which would be in the stock libstdc++.so.6.0.13 but not in libstdc++.so.6.0.8.

I didn't know a .so file could contain that text. Who parses it (dynamic linker I guess) and what are its specifications and consequences?

The regular linker parses this, not the runtime linker. See the binutils documentation for INPUT in a linker script. As a consequence, linking with this special libstdc++.so.6.0.13 will cause the linker to dynamically link against libstdc++.so.6.0.8, and statically link against the library which contains the extra symbols.

The downside of this is that an application compiled this way will be a little more bloated than the same application which is dynamically linked to only a stock libstdc++.so.6.0.13 which contains all the necessary symbols. The upside is that features from the newer standard library can be used on standard installations of older systems, without independent software vendors needing to ship their own copies of libstdc++.

How far can this magic go? Can I use gcc4.7 with libstdc++ 6.0.3? What is the spectrum of compatibility

Now that you know what the magic is, probably you can appreciate that this version of GCC 4.4 you have is a special version made just for Centos 5 (well, originally Red Hat 5). So probably you can create a GCC 4.7 which will produce binaries that only require libstdc++ 6.0.3, but it will require a non-trivial amount of work patching your GCC tree to put the correct symbols into stdc++_nonshared.a. You can at least look at the sources for the gcc44 RPM to see how Red Hat did it there.

Red Hat seems to have continued this approach with their Red Hat Developer Toolset. At the time of writing, GCC 4.8.1 is the newest compiler which can build binaries for EL5 which still only require libstdc++.so.6.0.8 to be installed on the target system. This is excellent for developers who want to write in C++11, but need to be able to deploy on EL5 or EL6.

like image 74
toojays Avatar answered Oct 21 '22 00:10

toojays