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

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

问题描述

我们最近发现了一个报告,因为 GCC 5.1、libstdc++ 和 Dual ABI.似乎 Clang 不知道 GCC 内联命名空间的变化,所以它生成代码基于一组命名空间或符号,而 GCC 使用另一组命名空间或符号.在链接时,由于缺少符号而出现问题.

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.

如果我正确解析了 双 ABI 页面,它看起来就像以 _GLIBCXX_USE_CXX11_ABIabi::cxx11 为中心的问题,还有一些额外的困难.在 Red Hat 的博客 GCC5 和C++11 ABIGCC-5.1 和两个 C++ ABI 的案例.

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.

以下来自 Ubuntu 15 机器.本机提供GCC 5.2.1.

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?

我正在努力为用户实现它只是有效".我不在乎是否有两个弱符号具有两种不同的行为(std::string 缺少 copy-on-write,而 std::string[abi:cxx11]> 提供写时复制).或者,一个可以是另一个的别名.

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 在 Debian 错误报告日志:错误标记为 libstdc++-cxx11.他们的解决方案是在新的 ABI 下重建所有内容,但它没有处理以 ABI 更改为模的混合/匹配编译器的极端情况.

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.

在 Apple 世界中,我认为这接近于一个胖二进制.但我不确定在 Linux/GCC 世界中该做什么.最后,我们不控制发行版如何构建库,也不控制使用哪些编译器将应用程序与库链接.

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.

您可以自己在双 ABI 下发布您的库.这或多或少类似于 OSX 的胖二进制",但完全用 C++ 构建.

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

最简单的方法是将库编译两次:-D_GLIBCXX_USE_CXX11_ABI=0-D_GLIBCXX_USE_CXX11_ABI=1.根据宏的值将整个库放在两个不同的命名空间下:

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
  }
}

现在您的用户可以像往常一样使用 CryptoPP::whatever,这映射到 CryptoPP::cxx11::whateverCryptoPP::cxx03::任何取决于选择的ABI.

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.

请注意,GCC 手册说此方法将更改标记的内联命名空间中定义的所有内容的重整名称.根据我的经验,这不会发生.

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.

如果 _GLIBCXX_USE_CXX11_ABI 非零,另一种方法是使用 __attribute__((abi_tag("cxx11"))) 标记每个类、函数和变量.这个属性很好地将 [cxx11] 添加到 demangler 的输出中.我认为使用命名空间同样有效,并且需要对现有代码进行较少的修改.

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.

理论上你不需要复制整个库,只需要使用std::stringstd::list的函数和类,以及函数和类使用这些函数和类,等等.但在实践中可能不值得付出努力,尤其是在库不是很大的情况下.

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天全站免登陆