J'essaie d'en savoir plus sur le versionnage des bibliothèques sous Linux et comment mettre tout cela en œuvre. Voici le contexte:
- J'ai deux versions d'une bibliothèque dynamique qui exposent le même ensemble d'interfaces, disons libsome1.so
et libsome2.so
.
- Une application est liée contre libsome1.so
.
- Cette application utilise libdl.so
pour charger dynamiquement un autre module, par exemple libmagic.so
.
- Maintenant libmagic.so
est lié contre libsome2.so
. De toute évidence, sans utiliser de scripts de l'éditeur de liens pour masquer les symboles libmagic.so
, au moment de l'exécution, tous les appels aux interfaces libsome2.so
sont résolus libsome1.so
. Cela peut être confirmé en vérifiant la valeur retournée par libVersion()
la valeur de la macro LIB_VERSION
.
- J'essaie donc ensuite de compiler et de lier libmagic.so
avec un script de l'éditeur de liens qui cache tous les symboles sauf 3 qui sont définis libmagic.so
et exportés par celui-ci. Cela fonctionne ... Ou au moins libVersion()
et les LIB_VERSION
valeurs correspondent (et il rapporte la version 2 et non 1).
- Cependant, lorsque certaines structures de données sont sérialisées sur disque, j'ai remarqué une corruption. Dans le répertoire de l'application, si je supprime libsome1.so
et crée un lien logiciel à sa place libsome2.so
, tout fonctionne comme prévu et la même corruption ne se produit pas.
Je ne peux pas m'empêcher de penser que cela peut être dû à un conflit dans la résolution des symboles de l'éditeur de liens. J'ai essayé beaucoup de choses, comme essayer de créer libsome2.so
un lien pour que tous les symboles soient alignés symbol@@VER_2
(ce qui me laisse encore perplexe parce que la commande nm -CD libsome2.so
répertorie toujours les symboles comme symbol
et non symbol@@VER_2
) ... Rien ne semble fonctionner !!! Aidez-moi!!!!!!
la source
RTLD_LOCAL
etRTLD_DEEPBIND
dlopen dans votre application. Je n'ai pas le temps de tester cela maintenant, mais cela devrait fonctionner en fonction de la page de manuel.Réponses:
Cela ne répond pas exactement à votre question, mais ...
Tout d'abord, ELF est la spécification utilisée par Linux pour les fichiers exécutables (programmes), les bibliothèques partagées et également les fichiers objets qui sont les fichiers intermédiaires trouvés lors de la compilation de logiciels. Les fichiers objets se terminent par .o, les bibliothèques partagées se terminent par .so suivi de zéro ou plusieurs chiffres séparés par des points, et les fichiers exécutables n'ont normalement pas d'extension.
Il existe généralement trois formulaires pour nommer une bibliothèque partagée, le premier formulaire se termine simplement par .so. Par exemple, une bibliothèque appelée readline est stockée dans un fichier appelé libreadline.so et se trouve normalement sous / lib, / usr / lib ou / usr / local / lib. Ce fichier se trouve lors de la compilation d'un logiciel avec une option comme -lreadline. -l indique au compilateur de se lier à la bibliothèque suivante. Comme les bibliothèques changent de temps en temps, elles peuvent devenir obsolètes, de sorte que les bibliothèques intègrent quelque chose appelé SONAME. Le SONAME pour readline peut ressembler à libreadline.so.2 pour la deuxième version de la version principale de libreadline. De nombreuses versions mineures de readline peuvent également être compatibles et ne nécessitent pas de recompilation du logiciel. Une version mineure de readline peut être nommée libreadline.so.2.14. Normalement libreadline. il ne s'agit donc que d'un lien symbolique vers la version majeure la plus récente de readline, libreadline.so.2 dans ce cas. libreadline.so.2 est également un lien symbolique vers libreadline.so.2.14 qui est en fait le fichier utilisé.
Le SONAME d'une bibliothèque est incorporé dans le fichier de bibliothèque lui-même. Quelque part dans le fichier libreadline.so.2.14 se trouve la chaîne libreadline.so.2. Lorsqu'un programme est compilé et lié avec readline, il recherchera le fichier libreadline.so et lira le SONAME intégré. Plus tard, lorsque le programme sera réellement exécuté, il chargera libreadline.so.2, pas seulement libreadline.so, car c'est le SONAME qui a été lu lors de sa première liaison. Cela permet à un système d'avoir plusieurs versions incompatibles de readline installées, et chaque programme chargera la version principale appropriée avec laquelle il était lié. Aussi, lors de la mise à niveau de readline, par exemple, vers 2.17, je peux simplement installer libreadline.so.2.17 à côté de la bibliothèque existante, et une fois que je déplace le lien symbolique libreadline.so.2 de libreadline.so.2.13 vers libreadline.so.2.17,
la source