6

数日間、私たちは非常に奇妙な問題に取り組んでいます。

サードパーティ (MATLAB) プログラムが私たちの共有ライブラリを使用すると、何らかの形でシンボル (正確にはブースト) を独自のもので上書きします。これらのシンボルは静的にリンクされ、(!!) ローカルです。

これが取り引きです - 私たちはブースト 1.47 を使用し、MATLAB はブースト 1.40 を持っています。現在、ライブラリは、OUR ライブラリからブースト (正規表現) への呼び出しで segfaults を呼び出します。

だから、ここに魔法があります:

  • ライブラリの依存関係はありません、ldd:
    linux-vdso.so.1 => (0x00007fff4abff000)
    libpthread.so.0 => /lib/libpthread.so.0 (0x00007f1a3fd65000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f1a3fa51000)
    libm.so.6 => /lib/libm.so.6 (0x00007f1a3f7cd000)
    libgomp.so.1 => /usr/lib/libgomp.so.1 (0x00007f1a3f5bf000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f1a3f3a8000)
    libc.so.6 => /lib/libc.so.6 (0x00007f1a3f024000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f1a414f9000)
    librt.so.1 => /lib/librt.so.1 (0x00007f1a3ee1c000)
  • Cxx シンボル (公開シンボルはバイナリ互換性のために POC C です) はライブラリ nm: からエクスポートされません。
nm -g --defined-only libmysharedlib.so

addr1 T OurCSymbol1
addr2 T OurCSymbol2
addr3 T OurCSymbol3
...
  • それでも、それは彼らのブーストを使用します。どうやって?スタック トレース (パス カット):
[ 0] 0x00007f21fddbb0a9 bin/libmwfl.so+00454825 fl::sysdep::linux::unwind_stack(void const**, unsigned long, unsigned long, fl::diag::thread_context const&)+000009
[ 1] 0x00007f21fdd74111 bin/glnxa64/libmwfl.so+00164113 fl::diag::stacktrace_base::capture(fl::diag::thread_context const&, unsigned long)+000161
[ 2] 0x00007f21fdd7d42d ビン/glnxa64/libmwfl.so+00201773
[ 3] 0x00007f21fdd7d6b4 bin/glnxa64/libmwfl.so+00202420 fl::diag::terminate_log(char const*, fl::diag::thread_context const&, bool)+000100
[ 4] 0x00007f21fce525a7 ビン/glnxa64/libmwmcr.so+00365991
[ 5] 0x00007f21fb9eb8f0 lib/libpthread.so.0+00063728
[ 6] 0x00007f21f3e939a9 libboost_regex.so.1.40.0+00342441 boost::re_detail::perl_matcher、std::allocator > >、boost::regex_traits > >::match_all_states()+000073
[ 7] 0x00007f21f3eb6546 bin/glnxa64/libboost_regex.so.1.40.0+00484678 ブースト::re_detail::perl_matcher、std::アロケーター > >、ブースト::regex_traits > >::match_imp()+000758
[ 8] 0x00007f21c04ad595 lib/libmysharedlib.so+04855189 bool boost::regex_match、std::allocator > >、char、boost::regex_traits > >(__gnu_cxx::__normal_iterator、__gnu_cxx::__normal_iterator、boost::match_results、std: :allocator > > >&、boost::basic_regex > > const&、boost::regex_constants::_match_flags)+000245
[ 9] 0x00007f21c04a71c7 lib/libmysharedlib.so+04829639 myfunc2()+000183
[ 10] 0x00007f21c01b41e3 lib/libmysharedlib.so+01737187 myfunc1()+000307

MATLAB は RTLD_NOW フラグのみで dlopen を実行することが知られています。

皆さん、私と一緒に考えてください。今、私はこれを修正することさえ切望していますが、単純に ld&elf の動作を理解したいと思っています。

編集:小さな追加の質問:特別なリンカオプションなしで、linux .soライブラリのシンボルがアドレスでリンクされないことをどのように理解しましたか?では、静的にリンクされたローカル シンボルも実行時に解決されるのでしょうか?

4

2 に答える 2

7

ld-Bsymbolicのオプションを確認してください。

が指定されている場合-Bsymbolic、共有オブジェクトの作成時に、ldはグローバル シンボルへの参照を 共有ライブラリ内の定義にバインドしようとします。デフォルトでは、バインドをランタイムに延期します。

これは、例を使用するとより明確になる場合があります。

で定義されたグローバルexample.o関数への参照が含まれているとします global.o

$ nm example.o | grep ' U'
     U _GLOBAL_OFFSET_TABLE_
     U globalfn
$ nm global.o | grep ' T'
00000000 T globalfn

および 2 つの共有オブジェクトnormal.soおよびsymbolic.soは、次のように構築されます。

$ cc -fPIC -c example.c
$ cc -c global.c
$ rm -f archive.a; ar cr archive.a global.o
$ ld -shared -o normal.so example.o archive.a
$ ld -Bsymbolic -shared -o symbolic.so example.o archive.a

のコードを逆アセンブルするnormal.soと、 への呼び出し globalfnが実際にはプロシージャ リンク テーブルを通過するため、呼び出しの最終的な宛先は実行時に決定されることがわかります。

$ objdump --disassemble normal.so
...snip...
00000194 <example>:
...snip...
 1a6:   e8 d9 ff ff ff          call   184 <globalfn@plt>
...snip...
$ readelf -r normal.so

Relocation section '.rel.plt' at offset 0x16c contains 1 entries:
Offset     Info    Type            Sym.Value  Sym. Name
00001244  00000207 R_386_JUMP_SLOT   000001b8   globalfn

一方、symbolic.soでは、呼び出しは常に globalfn共有オブジェクト内の の定義を呼び出します。

$ objdump --disassemble symbolic.so
...snip...
0000016c <shared>:
...snip...
 17e:   e8 0d 00 00 00          call   190 <globalfn>
...snip...
$ readelf -r symbolic.so

There are no relocations in this file.
于 2011-08-26T09:46:02.527 に答える
3

これが取り引きです - 私たちはブースト 1.47 を使用し、MATLAB はブースト 1.40 を持っています。現在、ライブラリは、OUR ライブラリからブースト (正規表現) への呼び出しで segfaults を呼び出します。

あなたは未定義の動作を呼び出しています。これは、「医者、これをすると痛い」ような状況です。Matlab 実行可能ファイルには、 class の外部関数が既に含まれていますboost::re_detail::perl_matcher< elided >。Matlab が共有ライブラリをロードすると、ダイナミック リンカーは、共有ライブラリが既存の定義と競合する方法でまったく同じシンボルを定義していることを認識します。未定義の動作。

解決策は、Matlab と同じバージョンの Boost を使用する Matlab で使用するライブラリのバージョンをビルドすることです。

于 2011-08-26T09:41:53.453 に答える