由于符号与abi :: cxx11链接问题? [英] Linking problems due to symbols with abi::cxx11?

查看:773
本文介绍了由于符号与abi :: cxx11链接问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们最近因为 GCC 5.1,libstdc ++和Dual ABI 。看起来 Clang不知道GCC内联命名空间更改,因此它生成代码基于一组命名空间或符号,而GCC使用另一组命名空间或符号。在链接时,由于缺少符号而出现问题。



如果我解析 Dual ABI 页面,它看起来像是在 _GLIBCXX_USE_CXX11_ABI abi :: cxx11 有一些额外的困难。有关详情,请访问红帽的博客: GCC5和C ++ 11 ABI GCC-5.1和两个C ++ ABI的情况



下面是从Ubuntu 15机器。该机提供GCC 5.2.1。

  $ cat test.cxx 
#include< string&

std :: string foo __attribute__((visibility(default)));
std :: string bar __attribute__((visibility(default)));

$ g ++ -g3 -O2 -shared test.cxx -o test.so

$ nm test.so | grep _Z3
...
0000201c B _Z3barB5cxx11
00002034 B _Z3fooB5cxx11

$ echo _Z3fooB5cxx11 _Z3barB5cxx11 | c ++ filt
foo [abi:cxx11] bar [abi:cxx11]

我可以使用两个装饰(共存作为红帽博客调用它)生成一个二进制符号。



或者,我们可以选择什么选项? p>




我想为用户实现只是工作。我不在乎是否有两个具有两种不同行为的弱符号( std :: string 缺少copy-on-write,而 std :: string [abi:cxx11] 提供写时复制)。或者,其他人可以是别名。



Debian在 Debian Bug报告日志:Bugs标签为libstdc ++ - cxx11 。他们的解决方案是重新构建新的ABI下的所有内容,但是它没有处理混合/匹配编译器模块ABI变化的角落情况。



在苹果世界中,认为这是接近一个胖的二进制。但我不知道在Linux / GCC世界做什么。最后,我们不控制distro如何构建库,我们不控制什么编译器用于将应用程序与库链接。

解决方案

免责声明,以下内容未在生产中测试,请自行承担风险。



您可以根据双重ABI发布您的库。这或多或少地类似于OSXfat binary,但是完全用C ++构建。



最简单的方法是两次编译库: code> -D_GLIBCXX_USE_CXX11_ABI = 0 并使用 -D_GLIBCXX_USE_CXX11_ABI = 1 。将整个库放在两个不同的命名空间下,具体取决于宏的值:

  #if _GLIBCXX_USE_CXX11_ABI 
#define DUAL_ABI cxx11 __attribute __((abi_tag(cxx11)))
#else
#define DUAL_ABI cxx03
#endif

命名空间CryptoPP {
内联命名空间DUAL_ABI {
// library goes here
}
}



您的用户可以照常使用 CryptoPP :: whatever ,这映射到 CryptoPP :: cxx11 :: whatever CryptoPP :: cxx03 :: whatever 取决于所选的ABI。



注意,GCC手册说,改变在标记的inline命名空间中定义的一切的名称。



另一种方法是使用 __ attribute __((abi_tag( cxx11)))如果 _GLIBCXX_USE_CXX11_ABI 不为零。此属性很好地将 [cxx11] 添加到demangler的输出。我认为使用命名空间的工作原理也很好,并且对现有代码的修改较少。



理论上,您不需要复制整个库,只有使用 std :: string std :: list 的函数和类,这些函数和类,等等。但在实践中,这可能不值得的努力,特别是如果图书馆不是很大。


We recently caught a report because of GCC 5.1, libstdc++ and Dual ABI. It seems Clang is not aware of the GCC inline namespace changes, so it generates code based on one set of namespaces or symbols, while GCC used another set of namespaces or symbols. At link time, there are problems due to missing symbols.

If I am parsing the Dual ABI page correctly, it looks like a matter of pivoting on _GLIBCXX_USE_CXX11_ABI and abi::cxx11 with some additional hardships. More reading is available on Red Hat's blog at GCC5 and the C++11 ABI and The Case of GCC-5.1 and the Two C++ ABIs.

Below is from a Ubuntu 15 machine. The machine provides GCC 5.2.1.

$ cat test.cxx
#include <string>

std::string foo __attribute__ ((visibility ("default")));
std::string bar __attribute__ ((visibility ("default")));

$ g++ -g3 -O2 -shared test.cxx -o test.so

$ nm test.so | grep _Z3
...
0000201c B _Z3barB5cxx11
00002034 B _Z3fooB5cxx11

$ echo _Z3fooB5cxx11 _Z3barB5cxx11 | c++filt 
foo[abi:cxx11] bar[abi:cxx11]

How can I generate a binary with symbols using both decorations ("coexistence" as the Red Hat blog calls it)?

Or, what are the options available to us?


I'm trying to achieve an "it just works" for users. I don't care if there are two weak symbols with two different behaviors (std::string lacks copy-on-write, while std::string[abi:cxx11] provides copy-on-write). Or, one can be an alias for the other.

Debian has a boatload of similar bugs at Debian Bug report logs: Bugs tagged libstdc++-cxx11. Their solution was to rebuild everything under the new ABI, but it did not handle the corner case of mixing/matching compilers modulo the ABI changes.

In the Apple world, I think this is close to a fat binary. But I'm not sure what to do in the Linux/GCC world. Finally, we don't control how the distro's build the library, and we don't control what compilers are used to link an applications with the library.

解决方案

Disclaimer, the following is not tested in production, use at your own risk.

You can yourself release your library under dual ABI. This is more or less analogous to OSX "fat binary", but built entirely with C++.

The easiest way to do so would be to compile the library twice: with -D_GLIBCXX_USE_CXX11_ABI=0 and with -D_GLIBCXX_USE_CXX11_ABI=1. Place the entire library under two different namespaces depending on the value of the macro:

#if _GLIBCXX_USE_CXX11_ABI
#  define DUAL_ABI cxx11 __attribute__((abi_tag("cxx11")))
#else
#  define DUAL_ABI cxx03
#endif

namespace CryptoPP {
  inline namespace DUAL_ABI {
    // library goes here
  }
}

Now your users can use CryptoPP::whatever as usual, this maps to either CryptoPP::cxx11::whatever or CryptoPP::cxx03::whatever depending on the ABI selected.

Note, the GCC manual says that this method will change mangled names of everything defined in the tagged inline namespace. In my experience this doesn't happen.

The other method would be tagging every class, function, and variable with __attribute__((abi_tag("cxx11"))) if _GLIBCXX_USE_CXX11_ABI is nonzero. This attribute nicely adds [cxx11] to the output of the demangler. I think that using a namespace works just as well though, and requires less modification to the existing code.

In theory you don't need to duplicate the entire library, only functions and classes that use std::string and std::list, and functions and classes that use these functions and classes, and so on recursively. But in practice it's probably not worth the effort, especially if the library is not very big.

这篇关于由于符号与abi :: cxx11链接问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆