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

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

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

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

Ответы

Ответ 1

Вы можете выполнить некоторые трюки script:

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

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

MYSYMS {    Глобальный:        foo1;                foo2;    локальный:                *; };

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

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

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

Ответ 2

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

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