Общая библиотека SIGSEGV при dlopen / static init при вызове функции @plt

Мое приложение добавляет библиотеку со статическим кодом инициализации. Все остальные библиотеки делают то же самое и загружаются нормально раньше, но эта умирает при вызове функции из другой библиотеки. Это что-то вроде:

0x12311 <-- bad address
_static_initialization_0 <-- function call
....
dlopen

Теперь вызов функции в разборке выглядит так

call _Z6MyFuncRA37_Kc@plt

Однако этот вызов завершается вызовом неверного адреса 0x12311, т. Е. Запись PLT получает неправильный адрес.

Проблема весьма вероятна в том, что рассматриваемая библиотека является сторонней, то есть поставляется в двоичной предварительно собранной форме, даже если она зависит от других библиотек. На прошлой неделе мы провели большую оптимизацию, изменили много заголовков и так далее. Функция MyFunc, неправильный PLT, находится в нашей (другой) библиотеке, которая претерпела значительные изменения в оптимизации.

Как это возможно? Точный вопрос:

  1. какой механизм вызывает несоответствие PLT
  2. есть ли способ исправить это, не трогая предварительно скомпилированную библиотеку — ДОПОЛНИТЕЛЬНО, поскольку я мог получить перестроенную версию, но мне все еще интересно, почему она вылетает

Кроме того, то же самое приложение прекрасно работает при компиляции с оптимизацией -O2, что я и называю странным (двоичная библиотека одинакова в обоих случаях).

Постскриптум Ubuntu 12.04 x86_64, но приложение i386.

ОБНОВЛЕНИЕ: предложение в комментариях (по какой-то причине удалено) проверить LD_DEBUG было хорошо, в привязках LD_DEBUG = я вижу это в «сбойной» версии приложения:

 10272:  /media/EXT/work/build32/bin/libMyLib.so: error:
symbol lookup error: undefined symbol: omp_set_num_threads (fatal)

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

libA -> libB -> libMyLib

Сбой libMyLib (как указано в выводе LD_DEBUG выше), поэтому он пропускает его, а также libB полностью (!) и продолжает связывать символы libA. В исправной версии полностью загружаются символы libMyLib, затем продолжается символы libB, а затем символы libA.

Честно говоря, для меня это выглядит как жук.

Что касается того, почему оптимизированная версия работает, я предполагаю, что метод omp_ действительно не нужен и отбрасывается оптимизацией компоновщика, таким образом, он не может не найти его во время выполнения.

Вот что я вижу в LD_DEBUG = весь журнал после того, как символ omp_ не найден для libC:

19225: symbol=omp_set_num_threads; lookup in file=/usr/lib/i386-linux-gnu/libXdmcp.so.6 [0]
19225: /media/EXT/Work/libC.so: error: symbol lookup error: undefined symbol: omp_set_num_threads (fatal)
19225:
19225: file=/media/EXT/libA.so [0]; destroying link map
19225:
19225: file=/media/EXT/libA.so [0]; dynamically loaded by /media/EXT/libX.so [0]
19225: file=/media/EXT/libA.so [0]; generating link map
19225: dynamic: 0xf2fdb764 base: 0xf2f81000 size: 0x00064a28
19225: entry: 0xf2f8ffd0 phdr: 0xf2f81034 phnum: 7
19225:
19225: checking for version `GCC_3.0' in file /lib/i386-linux-gnu/libgcc_s.so.1 [0] required by file /media/EXT/libA.so [0]
... few more checking
19225: object=/media/EXT/libA.so [0]
19225: scope 0: bin/mainapp /lib/i386-linux-gnu/libpthread.so.0 /media/EXT/libX.so ...
19225: scope 1:...
19225:
19225:
19225: relocation processing: /media/EXT/libA.so
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=bin/mainapp [0]
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=/lib/i386-linux-gnu/libpthread.so.0 [0]
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=/media/EXT/libX.so [0]
19225: binding file /media/EXT/libA.so [0] to /media/EXT/libX.so [0]: normal symbol `_ZTVN10__cxxabiv117__class_type_infoE'

... here it continues to bind libA symbols, and after finishing that

19225:
19225:
19225: calling init: /media/EXT/libC.so
19225:

он вызывает init для неинициализированного модуля libC.so.

(Следует упомянуть, что libX.so является базовым модулем, который вызывает dlopen, а также содержит базовые методы, используемые всеми другими библиотеками.)

После уничтожения карты ссылок для libA журнал показывает, что она генерируется снова, я просто не понимаю, продолжает ли загрузчик загружать libA или начинает с нуля на этот раз, не беспокоясь о libB / libC. Ну, в любом случае он игнорирует libB / libC, пока init не будет вызван для libC.

3

Решение

omp_set_num_threads относится к Поддержка OpenMP внутри GCC.

Вы, вероятно, должны пройти -fopenmp флаг для gcc при компиляции & время ссылки (даже если вы просто dlopen-ing библиотеки с использованием OpenMP).

Может быть, оригинальный поставщик библиотеки забыл это.

(OpenMP изменяет все поведение процесса компиляции)

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]