Linux, GNU GCC, ld, scripts de version et le format binaire ELF - Comment ça marche?

13

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.soet libsome2.so.

- Une application est liée contre libsome1.so.

- Cette application utilise libdl.sopour charger dynamiquement un autre module, par exemple libmagic.so.

- Maintenant libmagic.soest 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.sosont 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.soavec un script de l'éditeur de liens qui cache tous les symboles sauf 3 qui sont définis libmagic.soet exportés par celui-ci. Cela fonctionne ... Ou au moins libVersion()et les LIB_VERSIONvaleurs 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.soet 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.soun 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.sorépertorie toujours les symboles comme symbolet non symbol@@VER_2) ... Rien ne semble fonctionner !!! Aidez-moi!!!!!!

la lumière du soleil
la source
Votre dernière approche est celle avec laquelle j'aurais commencé. Et je suis d'accord que la corruption est probablement une confusion de symboles. Malheureusement, je n'ai pas de réponse pour vous.
RobotHumans
cela pourrait faire mieux sur SO, bien que je ne le comprenne pas assez pour le dire avec certitude. marquez-le si vous souhaitez que nous le déplacions.
xenoterracide
1
Essayez les drapeaux RTLD_LOCALet RTLD_DEEPBINDdlopen dans votre application. Je n'ai pas le temps de tester cela maintenant, mais cela devrait fonctionner en fonction de la page de manuel.
stribika

Réponses:

13

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,

pingouin359
la source