Trouver où un symbole de bibliothèque partagée est défini sur un système actif / répertorier tous les symboles exportés sur un système

21

Fondamentalement, ce sont deux questions en une - parce que si je peux lister tous les symboles exportés dans un système, ainsi que leur chemin d'accès à la bibliothèque partagée, je pourrais simplement grepcette sortie.

Pour les symboles du noyau, je suppose que c'est un peu plus facile - parce que nous pouvons toujours cat /proc/kallsymset obtenir une liste de tous les symboles de ces modules chargés en mémoire; puis sudo cat /proc/modulesdonnera une liste des modules chargés avec leurs adresses, mais pas les chemins où ne modules ont été chargés à partir (si elles sont construites comme distinctes, hors arbre .ko objets)

Par exemple, j'essaie de tracer le programme en kstutilisant ltrace:

$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
...

... et j'aimerais savoir où cela _ZNK13QGraphicsItem10parentItemEvréside.

Alors, que faire des symboles de bibliothèque partagée? Lecture de [gcc-help] Re: recherche de la bibliothèque dans laquelle le symbole est défini. ; J'ai essayé quelque chose comme ça:

$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...

... mais cela me pose des problèmes supplémentaires: je ne connais pas vraiment tous les chemins qui sont analysés pour les bibliothèques partagées sur mon système, donc quand j'ai essayé pour la première fois, find /lib ...il n'a rien trouvé; Je trouve cela suppose des répertoires ennuyeuses, aussi bien que l'alternative: l' analyse du système de fichiers entier racine avec find... Et, il me semble aussi frapper * .so ce qui ne peut être ouvert par nm(? Peut - être parce qu'ils sont des liens symboliques), qui produire pas mal de messages d'erreur (que je n'aime pas non plus).

La chose est - ldd(ou ld?) Effectue probablement une partie de cette recherche de symboles, mais j'ai essayé les pages de manuel respectives, et je ne vois pas de moyen de "trouver" un symbole à partir de la ligne de commande, sans fournir une sorte de fichier exécutable en tant que argument. Question secondaire - y aurait-il un moyen d'utiliser ces outils pour cela?

Donc, ce que je recherche, c'est un outil en ligne de commande, qui se comporterait comme (pseudocode):

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

... où je ne spécifie aucun répertoire à rechercher - mais qui gérerait également, par exemple LD_PRELOADou LD_LIBRARY_PATH; si je le fais:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

... alors j'obtiendrais l' /path/to/mylib.soendroit où le symbole donné a été défini (étant donné qu'un tel symbole n'existerait pas dans les bibliothèques standard) - et sortirait "introuvable" sinon. Et sinon, ./findsymbol --dumpallpourrait produire une liste de tous les symboles disponibles et leurs emplacements vus à partir d'un environnement donné (par exemple un bashshell spécifique ).

Existe-t-il un outil comme celui-ci pour Linux?

sdaau
la source

Réponses:

16

Les chemins dans lesquels rechercher les bibliothèques seront répertoriés dans le fichier /etc/ld.so.conf, la variable d'environnement LD_LIBRARY_PATHet les RPATH encodés dans le binaire ELF. Le programme lddvous indiquera quelles bibliothèques une application spécifique chargera.

Une fois que vous avez un symbole qui vous intéresse, vous pouvez utiliser le programme nmpour vider les symboles .oet les .afichiers et readelfpour vider les symboles d'un .soou de n'importe quel exécutable elfe.

Exemples:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

Et enfin, avec cet arrière-plan de côté, voici votre Saint Graal:

Étant donné un symbole _ZN6Kopete6Global10PropertiesC2Ev, où est-ce?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

ce qui donne:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

Le -ldrapeau indique de rechercher les répertoires /etc/ld.so.confet -sspécifie le symbole à rechercher.

casey
la source
Ceci est incomplet: certains programmes chargent des bibliothèques à partir de répertoires spécifiques à l'application.
Gilles 'SO- arrête d'être méchant'
2
@Gilles scanelfvous permet de spécifier des répertoires spécifiques dans lesquels rechercher et de prendre en charge la recherche récursive -rafin que vous puissiez modifier ses chemins de recherche ou rechercher l'ensemble de votre système sans trop de problèmes. Par exemple scanelf -r -s SYMBOL /lib/* /usr/* /opt/*, vous trouverez la plupart des endroits où les bibliothèques se cachent.
casey
7

Sur les systèmes GNU (lorsque vous utilisez l'éditeur de liens dynamique GNU libc), vous pouvez exécuter votre programme en tant que:

LD_DEBUG=bindings kst2

Pour trouver où les symboles se résolvent.

Stéphane Chazelas
la source
0

J'ai rencontré cela plusieurs fois, essayant de porter du code d'un système Linux à un autre. Habituellement, je finis par grep'ing tous les répertoires standard. Je n'ai rien trouvé sur Google. Voici donc un petit script:

edt11x / findinsharedlibs

edt11x
la source