Linux, GNU GCC, ld, версии скриптов и двоичный формат ELF - Как это работает?

13

Я пытаюсь узнать больше о версиях библиотек в 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) ... Ничто, кажется, не работает !!! Помогите!!!!!!

themoondothshine
источник
Ваш последний подход - тот, с которого я бы начал. И я согласен, что коррупция, вероятно, является символом путаницы. К сожалению, у меня нет ответа для вас.
RobotHumans
это может быть лучше на SO, хотя я не понимаю этого достаточно, чтобы сказать наверняка. пометьте, если вы хотите, чтобы мы переместили его.
ксенотеррацид
1
Попробуйте RTLD_LOCALи RTLD_DEEPBINDустановите флаги в вашем приложении. У меня нет времени, чтобы проверить это сейчас, но это должно работать на основе man-страницы.
стрибика

Ответы:

13

Это не совсем отвечает на ваш вопрос, но ...

Прежде всего, ELF - это спецификация, используемая Linux для исполняемых файлов (программ), разделяемых библиотек, а также объектных файлов, которые являются промежуточными файлами, обнаруживаемыми при компиляции программного обеспечения. Объектные файлы заканчиваются на .o, разделяемые библиотеки заканчиваются на .so, за которым следуют ноль или более цифр, разделенных точками, а исполняемые файлы обычно не имеют никакого расширения.

Обычно существует три формы для именования общей библиотеки, первая форма просто заканчивается на .so. Например, библиотека с именем readline хранится в файле с именем libreadline.so и обычно находится в одной из папок / lib, / usr / lib или / usr / local / lib. Этот файл находится при компиляции программного обеспечения с параметром, например -lreadline. -l говорит компилятору связать со следующей библиотекой. Поскольку библиотеки время от времени меняются, они могут устареть, поэтому библиотеки встраивают нечто, называемое SONAME. SONAME для readline может выглядеть как libreadline.so.2 для основной версии libreadline второй версии. Также может быть много минорных версий readline, которые совместимы и не требуют перекомпиляции программного обеспечения. Младшая версия readline может быть названа libreadline.so.2.14. Обычно libreadline. это просто символическая ссылка на самую последнюю основную версию readline, в данном случае libreadline.so.2. libreadline.so.2 также является символической ссылкой на libreadline.so.2.14, которая фактически является используемым файлом.

SONAME библиотеки встроен в сам файл библиотеки. Где-то внутри файла libreadline.so.2.14 находится строка libreadline.so.2. Когда программа компилируется и связывается с readline, она ищет файл libreadline.so и считывает встроенное в него SONAME. Позже, когда программа действительно выполняется, она загружает libreadline.so.2, а не только libreadline.so, поскольку это был SONAME, который был прочитан при первой ссылке. Это позволяет системе иметь несколько несовместимых версий readline, и каждая программа будет загружать соответствующую основную версию, с которой она связана. Кроме того, при обновлении readline, скажем, до 2.17, я могу просто установить libreadline.so.2.17 вместе с существующей библиотекой, и как только я переместу символическую ссылку libreadline.so.2 с libreadline.so.2.13 на libreadline.so.2.17,

penguin359
источник