Linux, GNU GCC, ld, версии скриптов и двоичный формат ELF - Как это работает? - PullRequest
8 голосов
/ 11 января 2011

Я пытаюсь узнать больше о версиях библиотек в Linux и о том, как заставить все это работать. Вот контекст:

- у меня есть две версии динамической библиотеки, которые предоставляют один и тот же набор интерфейсов, скажем, libsome1.so и libsome2.so.

- Приложение связано с libsome1.so.

- Это приложение использует libdl.so для динамической загрузки другого модуля, скажем, libmagic.so.

- Теперь libmagic.so связан с libsome2.so. Очевидно, что без использования сценариев компоновщика для скрытия символов в libmagic.so во время выполнения все вызовы интерфейсов в libsome2.so преобразуются в libsome1.so. Это может быть подтверждено проверкой значения, возвращаемого libVersion(), против значения макроса LIB_VERSION.

- поэтому я пытаюсь затем скомпилировать и связать libmagic.so с помощью скрипта компоновщика, который скрывает все символы, кроме 3, которые определены в libmagic.so и экспортируются им. Это работает ... Или, по крайней мере, значения libVersion() и LIB_VERSION совпадают (и сообщает версию 2, а не 1).

- Однако, когда некоторые структуры данных сериализуются на диск, я заметил некоторое повреждение. В каталоге приложения, если я удаляю libsome1.so и создаю на его месте программную ссылку, указывающую на libsome2.so, все работает, как ожидалось, и такое же повреждение не происходит.

Не могу не подумать, что это может быть вызвано некоторым конфликтом в разрешении символов компоновщика во время выполнения. Я пробовал много вещей, например, пытался связать libsome2.so так, чтобы все символы были сопоставлены с symbol@@VER_2 (что меня все еще смущает, потому что команда nm -CD libsome2.so по-прежнему перечисляет символы как symbol, а не symbol@@VER_2) ... Кажется, ничего не работает !!! Помогите !!!!!!

Редактировать: я должен был упомянуть об этом ранее, но рассматриваемое приложение - Firefox, и libsome1.so поставляется с libsqlite3.so. У меня нет возможности перекомпилировать их. Кроме того, использование сценариев версий для скрытия символов кажется единственным решением на данный момент. Так что же на самом деле происходит, когда символы скрыты? Они становятся «локальными» для SO? У rtld нет никакого знания об их существовании? Что происходит, когда экспортируемая функция ссылается на скрытый символ?

1 Ответ

4 голосов
/ 14 января 2011

Попробуйте скомпилировать libsome1.so и libsome2.so, чтобы добавить версии символов, каждая со своей версией (используйте параметр --version-script для ld).Затем свяжите приложение и libmagic.so, используя новые библиотеки.Тогда libsome1.so и libsome2.so должны быть полностью разделены.

Проблемы все еще могут возникать, если есть неверсионные ссылки на символы.Такие ссылки могут быть удовлетворены версионными определениями (чтобы можно было добавить версионность символов в библиотеку, не нарушая двоичную совместимость).Если имеется несколько символов с одним и тем же именем, иногда бывает сложно предсказать, какой из них будет использоваться.

Что касается инструментов, nm -D не отображает никакой информации о версии символов.Попробуйте вместо objdump -T или readelf -s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...