Загрузка нескольких общих библиотек с разными версиями

У меня есть исполняемый файл в Linux, который загружает libfoo.so.1 (это SONAME) как одну из своих зависимостей (через другую общую библиотеку). Он также ссылается на другую системную библиотеку, которая, в свою очередь, ссылается на системную версию, libfoo.so.2. В результате оба libfoo.so.1 и libfoo.so.2 загружаются во время выполнения, и код, который должен был вызывать функции из библиотеки с версией 1, в конечном итоге вызывает (несовместимые с двоичным кодом) функции из более новой системной библиотеки с версией 2. , потому что некоторые символы остаются прежними. Результатом обычно является разрушение стека и последующий segfault.

Теперь библиотека, которая ссылается на более старую версию, является сторонней библиотекой с закрытым исходным кодом, и я не могу контролировать, с какой версией libfoo она компилируется. Предполагая, что единственным оставшимся вариантом является пересборка группы системных библиотек, которые в настоящее время связаны с libfoo.so.2, для связи с libfoo.so.1.

Есть ли способ избежать замены системных библиотек локальными копиями, которые ссылаются на более старые libfoo? Могу ли я загрузить обе библиотеки и иметь код, вызывающий правильную версию символов? Итак, мне нужно какое-то специальное управление версиями на уровне символов?


person Alex B    schedule 23.10.2008    source источник
comment
Алекс: как ты решил проблему? не могли бы вы поделиться им с нами?   -  person Nawaz    schedule 29.12.2017
comment
@Nawaz Точно не помню, это было 9 лет назад! Я думаю сдался и сделал так, что загружается только одна версия библиотеки.   -  person Alex B    schedule 29.12.2017
comment
Алекс, эта статья рассказывает об этой проблеме и тоже предложил решение. Я еще не пробовал. Но интересно узнать/исследовать.   -  person Nawaz    schedule 29.12.2017


Ответы (2)


Возможно, вы сможете проделать некоторые трюки с версией сценария:

http://sunsite.ualberta.ca/Documentation/Gnu/binutils-2.9.1/html_node/ld_26.html

Это может потребовать, чтобы вы написали оболочку вокруг своей библиотеки, которая использует libfoo.so.1, которая явно экспортирует некоторые символы и маскирует все остальные как локальные. Например:

MYSYMS { глобальный: foo1; фоо2; местный: *; };

и используйте это, когда вы связываете эту оболочку, например:

gcc -shared -Wl, --version-script,mysyms.map -o mylib wrapper.o -lfoo -L/path/to/foo.so.1

Это должно сделать символы libfoo.so.1 локальными для оболочки и недоступными для основного исполняемого файла.

person Todd    schedule 24.10.2008

Я могу только придумать обходной путь. Это было бы статическое связывание версии «системной библиотеки», которую вы используете. Для вашей статической сборки вы можете связать ее с той же старой версией, что и сторонняя библиотека. Учитывая, что он не зависит от более новой версии...

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

person ypnos    schedule 23.10.2008