web-dev-qa-db-ja.com

シンボルによるリンクの問題:abi :: cxx11?

GCC 5.1、libstdc ++およびDual ABI のため、最近レポートを取得しました。どうやら ClangはGCCのインライン名前空間の変更を認識していません なので、GCCは別の名前空間またはシンボルのセットを使用しながら、名前空間またはシンボルのセットに基づいてコードを生成します。リンク時に、シンボルの欠落による問題があります。

Dual ABI ページを正しく解析している場合、_GLIBCXX_USE_CXX11_ABIabi::cxx11をいくつかの追加の困難とともにピボットする問題のように見えます。 Red Hatのブログ GCC5とC++ 11 ABI および GCC-5.1と2つの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]

両方の装飾を使用して、シンボルを含むバイナリを生成するにはどうすればよいですか(Red Hatブログが言う「共存」)。

または、利用可能なオプションは何ですか?


私はユーザーにとって「うまくいく」ことを達成しようとしています。 2つの異なる動作を持つ2つのウィークシンボルがあるかどうかは気にしません(std::stringにはコピーオンライトがありませんが、std::string[abi:cxx11]にはコピーオンライトがあります)。または、一方を他方のエイリアスにすることもできます。

Debianには Debianバグレポートログ:libstdc ++-cxx11とタグ付けされたバグ に同様のバグのボートロードがあります。彼らの解決策は、新しいABIの下ですべてを再構築することでしたが、ABIの変更を法として、コンパイラーを混合/マッチングするというコーナーケースを処理しませんでした。

Apple=の世界では、これはファットバイナリに近いと思います。しかし、Linux/GCCの世界で何をすべきかわかりません。最後に、ディストリビューションの方法を制御しませんライブラリをビルドします。アプリケーションをライブラリにリンクするために使用されるコンパイラは制御しません。

15
jww

免責事項、以下は本番環境でテストされていません。自己責任で使用してください。

自分でライブラリをデュアルABIでリリースできます。これは多かれ少なかれOSXの「ファットバイナリ」に似ていますが、完全にC++で構築されています。

そのための最も簡単な方法は、ライブラリを2回コンパイルすることです:_-D_GLIBCXX_USE_CXX11_ABI=0_と_-D_GLIBCXX_USE_CXX11_ABI=1_を使用します。マクロの値に応じて、ライブラリ全体を2つの異なる名前空間に配置します。

_#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_を使用できます。これは、選択したABIに応じて_CryptoPP::cxx11::whatever_または_CryptoPP::cxx03::whatever_にマップされます。

GCCマニュアルによると、このメソッドはタグ付きインライン名前空間で定義されているすべてのマングル名を変更するとしています。私の経験では、これは起こりません。

もう1つの方法は、__GLIBCXX_USE_CXX11_ABI_がゼロ以外の場合、すべてのクラス、関数、および変数に__attribute__((abi_tag("cxx11")))をタグ付けすることです。この属性は、デマングラの出力に_[cxx11]_をうまく追加します。名前空間の使用も同様に機能し、既存のコードへの変更が少なくて済むと思います。

理論的には、ライブラリ全体を複製する必要はありません。_std::string_と_std::list_を使用する関数とクラス、およびthese関数とクラスを使用する関数とクラスのみ、および再帰的に。しかし、実際には、特にライブラリがあまり大きくない場合は、おそらく努力する価値はありません。

9
n.m.

これを行う1つの方法がありますが、あまりエレガントではありません。また、GCCで自動化する方法もわからないので、2回行う必要はありません。

まず、ライブラリに変換される例:

$ cat test.cxx
#include <string>

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

次に:

$ g++ -D_GLIBCXX_USE_CXX11_ABI=0 -c test.cxx -o test-v1.o
$ g++ -D_GLIBCXX_USE_CXX11_ABI=1 -c test.cxx -o test-v2.o

$ ar cr test.a test-v1.o test-v2.o
$ ranlib test.a

$ g++ -shared test-v1.o test-v2.o -o test.so

最後に、何が得られたかを確認します。

$ nm test.a

test-v1.o:
00000004 B bar
         U __cxa_atexit
         U __dso_handle
00000000 B foo
0000006c t _GLOBAL__sub_I_foo
00000000 t _Z41__static_initialization_and_destruction_0ii
         U _ZNSsC1Ev
         U _ZNSsD1Ev

test-v2.o:
         U __cxa_atexit
         U __dso_handle
0000006c t _GLOBAL__sub_I__Z3fooB5cxx11
00000018 B _Z3barB5cxx11
00000000 B _Z3fooB5cxx11
00000000 t _Z41__static_initialization_and_destruction_0ii
         U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev
         U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev

そして:

$ nm test.so

00002020 B bar
00002018 B __bss_start
00002018 b completed.7181
         U __cxa_atexit@@GLIBC_2.1.3
         w __cxa_finalize@@GLIBC_2.1.3
00000650 t deregister_tm_clones
000006e0 t __do_global_dtors_aux
00001ef4 t __do_global_dtors_aux_fini_array_entry
00002014 d __dso_handle
00001efc d _DYNAMIC
00002018 D _edata
00002054 B _end
0000087c T _fini
0000201c B foo
00000730 t frame_dummy
00001ee8 t __frame_dummy_init_array_entry
00000980 r __FRAME_END__
00002000 d _GLOBAL_OFFSET_TABLE_
000007dc t _GLOBAL__sub_I_foo
00000862 t _GLOBAL__sub_I__Z3fooB5cxx11
         w __gmon_start__
000005e0 T _init
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
00001ef8 d __JCR_END__
00001ef8 d __JCR_LIST__
         w _Jv_RegisterClasses
00000690 t register_tm_clones
00002018 d __TMC_END__
00000640 t __x86.get_pc_thunk.bx
0000076c t __x86.get_pc_thunk.dx
0000203c B _Z3barB5cxx11
00002024 B _Z3fooB5cxx11
00000770 t _Z41__static_initialization_and_destruction_0ii
000007f6 t _Z41__static_initialization_and_destruction_0ii
         U _ZNSsC1Ev@@GLIBCXX_3.4
         U _ZNSsD1Ev@@GLIBCXX_3.4
         U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev@@GLIBCXX_3.4.21
         U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@@GLIBCXX_3.4.21
5
jww