Ld магически переопределяет статически связанные символы - PullRequest
5 голосов
/ 26 августа 2011

В течение нескольких дней мы имеем дело с очень странной проблемой.

Я не могу понять, как это вообще происходит - когда сторонняя (MATLAB) программа использует нашу разделяемую библиотеку, она каким-то образом переопределяет некоторые из наших символов (точнее, boost) на свои. Эти символы статически связаны и (!!) локальны.

Вот сделка - мы используем повышение 1.47, MATLAB имеет повышение 1.40. В настоящее время библиотечный вызов 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 -g --defined-only libmysharedlib.so

addr1 T OurCSymbol1
addr2 T OurCSymbol2
addr3 T OurCSymbol3
...
  • Тем не менее, он использует их повышение. КАК? Stacktrace (пути прорезаны):
[  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 bin/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 bin/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 boost::re_detail::perl_matcher, std::allocator > >, boost::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.

Люди, подумайте со мной, пожалуйста. Теперь я отчаянно пытаюсь не исправить это, а просто понять поведение лд и эльфов.

редактирование: Небольшой дополнительный вопрос: как я понял, без специальных опций компоновщика, символы в библиотеках linux .so никогда не связаны по адресу? То есть даже статически связанные локальные символы разрешаются во время выполнения?

Ответы [ 2 ]

5 голосов
/ 26 августа 2011

Проверьте параметр -Bsymbolic для ld .

Если указано -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

и два общих объекта, 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.
3 голосов
/ 26 августа 2011

Вот сделка - мы используем повышение 1.47, MATLAB имеет повышение 1.40.В настоящее время библиотечный вызов segfaults при обращении к OUR-библиотеке для их повышения (регулярное выражение).

Вы вызываете неопределенное поведение, которое представляет собой ситуацию типа «Доктор, мне больно, когда я делаю это».Исполняемый файл Matlab уже содержит внешние функции для класса boost::re_detail::perl_matcher< elided >.Когда Matlab загружает вашу разделяемую библиотеку, динамический компоновщик видит, что ваша разделяемая библиотека определяет те же самые символы таким образом, что это противоречит существующим определениям.Неопределенное поведение.

Решение состоит в том, чтобы создать версию вашей библиотеки для использования с Matlab, которая использует ту же версию Boost, что и Matlab.

...