Comment répertorier les symboles dans un fichier .so

486

Comment répertorier les symboles exportés à partir d'un fichier .so? Si possible, j'aimerais également connaître leur source (par exemple, s'ils sont extraits d'une bibliothèque statique).

J'utilise gcc 4.0.2, si cela fait une différence.

Moe
la source
La plateforme fait la différence. Apple fournit un GCC 4.0, mais son nmne répond pas à certaines options, comme -Det -g(IIRC).
2015
Cela n'imprime rien sur Mac OS.
IgorGanapolsky
3
@jww parce que c'est BSD nm, pas GNU nm.
OrangeDog du

Réponses:

577

L'outil standard pour lister les symboles est nm, vous pouvez l'utiliser simplement comme ceci:

nm -gD yourLib.so

Si vous voulez voir les symboles d'une bibliothèque C ++, ajoutez l'option "-C" qui démêle les symboles (c'est beaucoup plus lisible démêlé).

nm -gDC yourLib.so

Si votre fichier .so est au format elf, vous avez deux options:

Soit objdump( -Cest également utile pour démêler C ++):

$ objdump -TC libz.so

libz.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000002010 l    d  .init  0000000000000000              .init
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable

Ou utilisez readelf:

$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000002010     0 SECTION LOCAL  DEFAULT   10
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND free@GLIBC_2.2.5 (14)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (14)
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
Steve Gury
la source
35
Cela ne fonctionne pas toujours avec les fichiers .so, cependant, et vous devrez donc peut-être utiliser la solution "readelf" mentionnée dans une autre réponse.
Brooks Moses
9
Notez que les versions OS X de nm n'ont pas l'option «-C» pour démêler les symboles. c ++ filt peut être utilisé à la place. Exemple de script ici: v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++ filt -p -i
fredbaba
5
Notez que readelf -Wscela vous montrera tous les symboles et nm -gne montrera que les symboles visibles de l'extérieur. Cela peut être déroutant si vous examinez plusieurs fichiers de symboles et commencez à échanger vos commandes.
Andrew B
3
J'ajouterais également objectdump -TCà la liste. Contrairement à readelf -Ws, il ne montre pas les noms mutilés.
Yan Foto
2
@BrooksMoses Pour les .sofichiers, vous devrez peut-être ajouter --dynamicà la nmligne de commande.
user7610
84

Si votre .sofichier est au format elf, vous pouvez utiliser le programme readelf pour extraire les informations de symbole du binaire. Cette commande vous donnera la table des symboles:

readelf -Ws /usr/lib/libexample.so

Vous devez uniquement extraire ceux qui sont définis dans ce .sofichier, pas dans les bibliothèques référencées par celui-ci. La septième colonne doit contenir un nombre dans ce cas. Vous pouvez l'extraire à l'aide d'une expression régulière simple:

readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'

ou, tel que proposé par Caspin ,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
P Shved
la source
19
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; les regex sont géniales mais parfois un peu awk va un long chemin.
deft_code
55
objdump -TC /usr/lib/libexample.so
Pavel Lapin
la source
42

Pour les bibliothèques partagées libNAME.so, le commutateur -D était nécessaire pour voir les symboles dans mon Linux

nm -D libNAME.so

et pour la bibliothèque statique tel que rapporté par d'autres

nm -g libNAME.a
cavila
la source
35

Je me demandais pourquoi -fvisibility = caché et la visibilité #pragma GCC ne semblait pas avoir d'influence, car tous les symboles étaient toujours visibles avec nm - jusqu'à ce que je trouve ce post qui me dirigeait vers readelf et objdump , ce qui m'a fait réaliser qu'il y avait semblent en fait être deux tables de symboles:

  • Celui que vous pouvez lister avec nm
  • Celui que vous pouvez lister avec readelf et objdump

Je pense que le premier contient des symboles de débogage qui peuvent être supprimés avec strip ou le commutateur -s que vous pouvez donner à l'éditeur de liens ou à la commande d' installation . Et même si nm ne répertorie plus rien, vos symboles exportés sont toujours exportés car ils se trouvent dans la "table des symboles dynamiques" ELF, qui est la dernière.

Peter Remmers
la source
3
Je vous remercie! Cela explique pourquoi parfois "nm" n'affiche aucun symbole pour les fichiers .so.
Brooks Moses
10
nm -D - vous permet de lister la table des symboles dynamiques
pt123
19

Pour les .sofichiers C ++ , la nmcommande ultime estnm --demangle --dynamic --defined-only --extern-only <my.so>

# nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add
0000000000049500 T proton::work_queue::add(proton::internal::v03::work)
0000000000049580 T proton::work_queue::add(proton::void_function0&)
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work)
000000000002b1f0 T proton::container::impl::add_work_queue()
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work)
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work)

source: https://stackoverflow.com/a/43257338

user7610
la source
11

Essayez d'ajouter -l aux drapeaux nm afin d'obtenir la source de chaque symbole. Si la bibliothèque est compilée avec des informations de débogage (gcc -g), il doit s'agir du fichier source et du numéro de ligne. Comme l'a dit Konrad, le fichier objet / bibliothèque statique est probablement inconnu à ce stade.

Adam Mitz
la source
11

Pour Android .sofichiers, l'ensemble des outils NDK est livré avec les outils nécessaires mentionnés dans les autres réponses: readelf, objdumpet nm.

Adi Shavit
la source
9

Vous pouvez utiliser l' nm -goutil de la chaîne d'outils binutils. Cependant, leur source n'est pas toujours facilement disponible. et je ne suis même pas sûr que ces informations puissent toujours être récupérées. Peut-être objcopyrévèle des informations supplémentaires.

/ EDIT: Le nom de l'outil est bien sûr nm. Le drapeau -gest utilisé pour afficher uniquement les symboles exportés.

Konrad Rudolph
la source
6

nm -g liste la variable externe, qui n'est pas nécessairement le symbole exporté. Toutes les variables de portée de fichier non statiques (en C) sont toutes des variables externes.

nm -D listera le symbole dans le tableau dynamique, dont vous pouvez trouver l'adresse par dlsym.

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

zhaorufei
la source
1

Si vous voulez juste savoir s'il y a des symboles présents , vous pouvez utiliser

objdump -h /path/to/object

ou pour lister les informations de débogage

objdump -g /path/to/object
Craig Ringer
la source