Загрузка нескольких разделяемых библиотек с разными версиями
У меня есть исполняемый файл в 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
Я могу только придумать обход. Который будет статически связывать версию "системной библиотеки", которую вы используете. Для вашей статической сборки вы можете связать ее с той же старой версией, что и сторонняя библиотека. Учитывая, что он не полагается на более новую версию...
Возможно, также можно избежать этих проблем, не обращаясь к сторонней библиотеке обычным способом. Вместо этого ваша программа может загрузить ее во время выполнения. Возможно, тогда это может быть затенено против остальных. Но я мало что знаю об этом.