Que signifie l'erreur «aucune information de version disponible» de l'éditeur de liens dynamiques Linux?

89

Dans notre produit, nous livrons des binaires Linux qui se lient dynamiquement à des bibliothèques système comme "libpam". Sur certains systèmes clients, nous obtenons l'erreur suivante sur stderr lorsque le programme s'exécute:

./authpam: /lib/libpam.so.0: no version information available (required by authpam)

L'application fonctionne correctement et exécute le code de la bibliothèque dynamique. Ce n'est donc pas une erreur fatale, c'est vraiment juste un avertissement.

Je suppose que cette erreur provient de l'éditeur de liens dynamique lorsque la bibliothèque installée par le système manque quelque chose que notre exécutable attend. Je ne sais pas grand-chose sur les éléments internes du processus de liaison dynamique ... et googler le sujet n'aide pas beaucoup. :(

Quelqu'un sait ce qui cause cette erreur? ... comment puis-je diagnostiquer la cause? ... et comment changer nos exécutables pour éviter ce problème?

Mise à jour: le client est passé à la dernière version de debian «testing» et la même erreur s'est produite. Ce n'est donc pas une bibliothèque libpam obsolète. Je suppose que je voudrais comprendre de quoi se plaint l'éditeur de liens? Comment puis-je rechercher la cause sous-jacente, etc.?


la source

Réponses:

64

"Aucune information de version disponible" signifie que le numéro de version de la bibliothèque est inférieur sur l'objet partagé. Par exemple, si votre numéro major.minor.patch est 7.15.5 sur la machine sur laquelle vous créez le binaire et que le numéro major.minor.patch est 7.12.1 sur la machine d'installation, ld imprimera l'avertissement.

Vous pouvez résoudre ce problème en compilant avec une bibliothèque (en-têtes et objets partagés) qui correspond à la version d'objet partagé fournie avec votre système d'exploitation cible. Par exemple, si vous allez installer sur RedHat 3.4.6-9, vous ne voulez pas compiler sur Debian 4.1.1-21. C'est l'une des raisons pour lesquelles la plupart des distributions sont livrées pour des numéros de distribution Linux spécifiques.

Sinon, vous pouvez créer un lien statique. Cependant, vous ne voulez pas faire cela avec quelque chose comme PAM, donc vous voulez réellement installer un environnement de développement qui correspond à l'environnement de production de votre client (ou au moins installer et établir un lien avec les versions de bibliothèque correctes.)

Le conseil que vous obtenez de renommer les fichiers .so (en les complétant avec les numéros de version) provient d'une époque où les bibliothèques d'objets partagés n'utilisaient pas de symboles versionnés. Ne vous attendez donc pas à ce que jouer avec le schéma de dénomination .so.nnn vous aide (beaucoup - cela pourrait aider si votre système a été mis à la poubelle.)

Votre dernière option sera la compilation avec une bibliothèque avec un numéro de version mineure différent, en utilisant un script de liaison personnalisé: http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts. html

Pour ce faire, vous devrez écrire un script personnalisé et vous aurez besoin d'un programme d'installation personnalisé qui exécute ld sur les objets partagés de votre client, à l'aide du script personnalisé. Cela nécessite que votre client ait gcc ou ld sur son système de production.

Chris
la source
21

Ce que ce message de l'éditeur de liens dynamique glibc signifie en réalité, c'est que la bibliothèque mentionnée ( /lib/libpam.so.0dans votre cas) n'a pas la VERDEFsection ELF tandis que le binaire ( authpamdans votre cas) a des définitions de version dans la VERNEEDsection pour cette bibliothèque (vraisemblablement, libpam.so.0). Vous pouvez facilement le voir avec readelf, il suffit de regarder .gnu.version_det des .gnu.version_rsections (ou son absence).

Donc, ce n'est pas une incompatibilité de version de symbole, car si le binaire voulait obtenir une version spécifique via VERNEEDet que la bibliothèque ne la fournissait pas dans sa version actuelle VERDEF, ce serait une erreur de l'éditeur de liens et le binaire ne fonctionnerait pas du tout (comme ceci par rapport à ceci ou à cela ). C'est que le binaire veut des versions, mais la bibliothèque ne fournit aucune information sur ses versions.

Qu'est-ce que cela signifie en pratique? Habituellement, exactement ce qui est vu dans cet exemple - rien, les choses fonctionnent simplement en ignorant le contrôle de version. Les choses pourraient-elles se briser? Bien sûr, oui, donc les autres réponses sont correctes dans le fait que l'on devrait utiliser les mêmes bibliothèques à l'exécution que celles auxquelles le binaire était lié au moment de la construction.

Plus d'informations peuvent être trouvées dans Ulrich Dreppers "ELF Symbol Versioning" .

Roman Khimov
la source
5
Je recommande d'exécuter 'readelf -V <exePath>' pour voir la section de gestion des versions. avis capital V
Rayee Roded
J'avais déduit que c'était la raison de l'avertissement pour les bibliothèques (plus récentes! Du système) que je construis moi-même et que j'installe dans un préfixe parallèle. J'ai toujours pensé que c'était parce que j'utilisais la chaîne d'outils LLVM, mais j'ai juste remarqué que la construction avec le système gcc ne place pas automatiquement ces balises de version dans la bibliothèque. Dois-je ajouter une option via CFLAGS et / ou LDFLAGS?
RJVB
5

Fwiw, j'ai eu ce problème lors de l'exécution de check_nrpe sur un système sur lequel le système de surveillance zenoss était installé. Pour ajouter à la confusion, cela fonctionnait bien en tant qu'utilisateur root mais pas en tant qu'utilisateur zenoss.

J'ai découvert que l'utilisateur zenoss avait un LD_LIBRARY_PATH qui l'a amené à utiliser les bibliothèques zenoss, qui émettent ces avertissements. C'est à dire:

root@monitoring:$ echo $LD_LIBRARY_PATH

su - zenoss
zenoss@monitoring:/root$ echo $LD_LIBRARY_PATH
/usr/local/zenoss/python/lib:/usr/local/zenoss/mysql/lib:/usr/local/zenoss/zenoss/lib:/usr/local/zenoss/common/lib::
zenoss@monitoring:/root$ /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
/usr/lib/nagios/plugins/check_nrpe: /usr/local/zenoss/common/lib/libcrypto.so.0.9.8: no version information available (required by /usr/lib/libssl.so.0.9.8)
(...)
zenoss@monitoring:/root$ LD_LIBRARY_PATH= /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
(...)

Donc de toute façon, ce que j'essaie de dire: vérifiez vos variables comme LD_LIBRARY_PATH, LD_PRELOAD, etc.

Dieter_be
la source
3

Comment compilez-vous votre application? Quels drapeaux de compilateur?

D'après mon expérience, lorsque vous ciblez le vaste domaine des systèmes Linux, créez vos packages sur la version la plus ancienne que vous êtes prêt à prendre en charge, et comme de plus en plus de systèmes ont tendance à être rétrocompatibles, votre application continuera à fonctionner. En fait, c'est toute la raison de la gestion des versions de la bibliothèque - assurer la compatibilité descendante.

Ted Percival
la source
1

Avez-vous déjà vu cela ? La cause semble être un très vieux libpam sur l'un des côtés, probablement sur ce client.

Ou les liens vers la version peuvent manquer: http://www.linux.org/docs/ldp/howto/Program-Library-HOWTO/shared-libraries.html

Vinko Vrsalovic
la source
J'ai trouvé celui-là, mais cela n'a pas vraiment aidé à comprendre la cause. Je ne pense pas que ce soit une ancienne bibliothèque pam, car ils ont mis à jour les derniers tests Debian.
Alors peut-être que vous compilez sur une vieille machine? :) Avez-vous essayé de le compiler sur la machine du client? nondot.org/sabre/Mirrored/libtool-2.1a/libtool_toc.html#TOC36
Vinko Vrsalovic