The Case of GCC-5.1 and the Two C++ ABIs

Recently, Arch Linux updated to gcc-5.1. This brought a lot of new features, but the one that I am focusing on today is the new C++ ABI that appears when the compiler is built using default option.

Supporting the C++11 standard required incompatible changes to libstdc++ ABI. Instead of bumping the library soname (I still do not understand why that was not done…), the GCC developers decided to have a dual ABI. This is achieved using C++11 inlined namespaces which will give a different mangled name allowing types that differ across the two ABIs to coexist. When that is insufficient, a new abi_tag attribute is used which adds [abi:cxx11] to the mangled name.

With the initial upload of gcc-5.1 to the Arch repos, we configured GCC to use the old ABI by default. Now the initial slew of bugs have been dealt with (or mostly dealt with…), we want to switch to the new ABI. Because this was going to be a much larger rebuild than usual, one of the Arch developers (Evangelos Foutras) developed a server that automatically orders the rebuilds, and provides the next rebuild when a client requests it (this may be the future of rebuild automation in Arch).

This discovered an issue when building software using the new C++ ABI with clang, which builds against the new ABI (as instructed in the GCC header file), but does not know about the abi_tag attribute. This results in problems such as (for example) any function in a library with a std::string return type will be mangled with a [abi:cxx11] ABI tag. Clang does not handle these ABI tags, so will not add the tag to the mangled name and then linking will fail.

This issue was pointed out on a GCC mailing list in April, and a bug was filed independently for LLVM/clang. Until it is fixed, Arch Linux will not be able to switch to the new ABI. Note, this also has consequences for all older versions of GCC wanting to compile C++ software against system libraries…

13 thoughts on “The Case of GCC-5.1 and the Two C++ ABIs

  1. I read that GCC-6(.1) will switch again to C(++)11 instead of (for now in GCC-5[.1]) gnu(++)11, if that is true, not mean that next year another rebuild with another set of bug will merge?
    or now by default Arch’ll try gnu(++)11 instead of C(++)11 or I’m reading the ToDo wrong?

  2. That does not matter – it is the ABI you compile it against. Think of it as two different library versions. Usually they would be in different files and have separate sonames, but there are joined in a single file instead.

    • I get it now, thanks Alan.
      also you need broke it again cause the aur migration is not enough 😉

  3. Regarding why the dual ABI was done, I can see why this was considered important. If you want a flag day where you rebuild the entire world, then you can by all means do this, but it means a complete compatibility break with everything. I remember doing this in Debian for the last break (c102) nearly a decade back and it was easy enough to do, but the pain it inflicts on all your users is severe.

    The main problem isn’t the break, it’s that you can only use a single copy of libstdc++ in a single process, due to symbol conflicts. So if you build your library against the new ABI but have a transitive dependency on the old ABI via a library dependency (maybe not even in your code, but in something the executable linking against your library also links against), it will cause breakage. Including hidden usage by libraries exposing a C interface but using C++ internally. Having a dual ABI means that these situations don’t cause breakage since the new libstdc++ can satisfy all these requirements without any compatibility break. I can agree it’s a bit nasty, but I think that considering all the tradeoffs, it was worth the effort in doing things this way. Being able to continue to run code built with early GCC4 compilers from nearly a decade ago is a very valuable technical achievement.

    • As far as I can tell, this gives the exact same problem. You now just transitively depend on two different ABI versions rather than two different library versions. Now it is just more difficult to trace what is linking to the different ABI.

    • At least one of the situations you describe (” hidden usage by libraries exposing a C interface but using C++ internally”) works perfectly well without the magic “dual ABI” library, because the C++11 symbols are all in an inline namespace anyway – they do not conflict with symbols from the previous ABI (if they did, the dual ABI could not work anyway, since both symbols must be present in the library).

      (Not all C++11 symbols and types are in the namespace – only the ones that aren’t compatible with the previous ABI).

      In fact, unless I’m mistaken, it would have been entirely possible to have both ABIs implemented in the single dynamic library without this new “abi_tag” mechanism.

      What abi tagging _does_ give you is the means to support a greater degree of actual interaction between old-ABI and new-ABI code in cases where some C++ _is_ exposed. So for instance I could have an old library linked against the old library, with a method accepting a std::vector parameter, and I can link against that library and call that method even if I want to use the new ABI. Even if some of the member functions of vector have changed signature or functionality, the old library can call the old versions (which have a different mangled name than the abi-tagged new versions) and it will work fine. (However, I can’t do the same if that method takes a std::string or std::list parameter, because those types have changed in the new ABI).

      Also, abi tagging will give you an error at link time if you do try to link to an old-ABI library and pass an incompatible type (string or list) to it, for example. The automatic propagation of abi tags to users (derived classes etc) means this should catch most such errors, I think.

      The question is whether these benefits are worth the cost. I’m not yet convinced that this is the case.

      • Any update in the subject of the bug related to the main problem related to the unability of having dual abis? any word of llvm of gcc guys concerning the future of this issue? we are near 2 months away and one new .x release since this post.

          • I wal talking about the plan that Arch will follow, llvm bug look kinda dead and I cant find other references in gcc threads about tha abi issue in nexts months, I dubd that Arch the rollling distro will be stoned into the old abi.
            Or you will wait to a fix even it take more than years??

            • LLVM/clang are too widely used to go ahead with this being broken.