9 votes

Linux, GNU GCC, ld, version scripts et le format binaire ELF -- Comment cela fonctionne-t-il ?

J'essaie d'en savoir plus sur le versionnage des bibliothèques sous Linux et sur la manière de le mettre en œuvre. Voici le contexte :

-- J'ai deux versions d'une bibliothèque dynamique qui exposent le même ensemble d'interfaces, par exemple libsome1.so y libsome2.so .

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

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

-- Maintenant libmagic.so est lié à libsome2.so . Évidemment, sans l'utilisation de l'éditeur de liens scripts pour cacher les symboles en libmagic.so au moment de l'exécution, tous les appels aux interfaces dans libsome2.so sont résolus à libsome1.so . Ceci peut être confirmé en vérifiant la valeur retournée par libVersion() contre la valeur de la macro LIB_VERSION .

-- Donc j'essaie ensuite de compiler et de lier libmagic.so avec un linker script qui cache tous les symboles sauf 3 qui sont définis dans libmagic.so et sont exportés par elle. Cela fonctionne... Ou du moins libVersion() y LIB_VERSION correspondent (et il signale la version 2 et non 1).

-- Cependant, lorsque certaines structures de données sont sérialisées sur le disque, j'ai remarqué une certaine corruption. Dans le répertoire de l'application, si je supprime libsome1.so et créer un lien souple à sa place pour pointer vers libsome2.so Si l'on enlève la carte, tout fonctionne comme prévu et la même corruption ne se produit pas.

Je ne peux m'empêcher de penser que cela peut être dû à un conflit dans la résolution des symboles de l'éditeur de liens d'exécution. J'ai essayé beaucoup de choses, comme essayer de lier libsome2.so de sorte que tous les symboles soient alignés sur symbol@@VER_2 (ce qui me laisse perplexe car la commande nm -CD libsome2.so énumère toujours les symboles comme symbol et non symbol@@VER_2 )... Rien ne semble fonctionner ! !! Aide !!!!!!

Edit : J'aurais dû le mentionner plus tôt, mais l'application en question est Firefox, et libsome1.so es libsqlite3.so expédié avec. Je n'ai pas vraiment la possibilité de les recompiler. Aussi, l'utilisation de la version scripts pour cacher les symboles semble être la seule solution pour le moment. Que se passe-t-il réellement lorsque les symboles sont masqués ? Deviennent-ils "locaux" à l'OS ? Est-ce que rtld n'a pas connaissance de leur existence ? Que se passe-t-il lorsqu'une fonction exportée fait référence à un symbole caché ?

3voto

jilles Points 4241

Essayez de compiler les deux libsome1.so y libsome2.so pour ajouter le versionnage des symboles, chacun ayant sa propre version (utilisez la balise --version-script option pour ld ). Reliez ensuite l'application et libmagic.so en utilisant les nouvelles bibliothèques. Alors, libsome1.so y libsome2.so doivent être complètement séparés.

Des problèmes peuvent encore survenir s'il existe des références non versionnées à des symboles. De telles références peuvent être satisfaites par des définitions versionnées (de sorte qu'il est possible d'ajouter le versionnement des symboles à une bibliothèque sans rompre la compatibilité binaire). S'il y a plusieurs symboles du même nom, il peut parfois être difficile de prévoir lequel sera utilisé.

En ce qui concerne les outils, nm -D n'affiche aucune information sur le versionnement des symboles. Essayez objdump -T o readelf -s à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X