2008-08-29 12 views
344

Comment lister les symboles exportés à partir d'un fichier .so. Si possible, j'aimerais aussi connaître leur source (par exemple, si elles sont extraites d'une bibliothèque statique).Comment lister les symboles dans un fichier .so

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

+0

La plate-forme fait une différence. Apple fournit un GCC 4.0, mais son 'nm' ne répond pas à certaines options, comme' -D' et '-g' (IIRC). – jww

+0

Cela n'imprime rien sur Mac OS. –

+3

@jww parce que c'est BSD 'nm', pas GNU' nm'. – OrangeDog

Répondre

419

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

nm -g yourLib.so 

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

nm -gC yourLib.so 

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

Soit objdump (-C est également utile pour demangling 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 [email protected]_2.2.5 (14) 
    3: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (14) 
    4: 0000000000000000  0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable 
+23

Cela ne fonctionne pas toujours avec les fichiers .so, et vous devrez peut-être utiliser la solution "readelf" mentionnée dans une autre réponse. –

+0

Bonne réponse - mais je ne reçois pas les signatures de fonction de nm, objdump ou readelf. Savez-vous comment je peux obtenir la signature de la fonction (paramètres)? –

+7

Notez que les versions OS X de nm ne disposent pas de l'option '-C' pour démêler les symboles. C++ filt peut être utilisé à la place. Exemple de script ici: http://v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | C++ filt -p -i – fredbaba

9

Vous pouvez utiliser l'outil nm -g de la binutils toolchain. Cependant, leur source n'est pas toujours facilement disponible. et je ne suis même pas sûr que cette information puisse toujours être récupérée. Peut-être objcopy révèle plus d'informations.

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

11

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

+0

'nm: argument de ligne de commande inconnu '-l'' –

64

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

readelf -Ws /usr/lib/libexample.so 

Vous ne devez extraire ceux qui sont définis dans ce fichier .so, pas dans les bibliothèques référencées par elle. La septième colonne doit contenir un nombre dans ce cas.Vous pouvez l'extraire à l'aide d'un simple regex:

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}'; 
+14

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $ 8}'; Les regex sont géniaux mais parfois un peu d'awk va loin. –

39
objdump -TC /usr/lib/libexample.so 
+3

Bon. Donne des noms démêlés qui s'avèrent utiles – deepdive

28

Je me demandais pourquoi -fvisibility = caché et #pragma GCC visibilité ne semblait pas avoir d'influence, car tous les symboles étaient toujours visibles avec nm - jusqu'à ce que je trouve ce poste qui m'a indiqué readelf et objdump, ce qui m'a fait réaliser qu'il semble être en fait 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 debuggi ng symboles qui peuvent être supprimés avec bande ou le commutateur -s que vous pouvez donner à l'éditeur de liens ou la commande installer. Et même si nm ne liste plus rien, vos symboles exportés sont toujours exportés car ils sont dans la "table de symboles dynamique" ELF, qui est la dernière.

+2

Merci! Cela explique pourquoi parfois "nm" n'affiche aucun symbole pour les fichiers .so. –

+5

nm -D - vous permet de lister la table des symboles dynamiques – pt123

5

nm -g liste la variable externe, qui n'est pas un symbole exporté nécessaire. Toute variable d'étendue de fichier non statique (en C) est une variable externe. Nm -D listera le symbole dans la table dynamique, dont vous pouvez trouver l'adresse par dlsym.

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

30

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 rapporté par d'autres

nm -g libNAME.a 
7

pour Android .so fichiers, la chaîne d'outils NDK est livré avec les outils requis mentionnés dans les autres réponses: readelf, objdump et nm.

3

Pour .so C++ fichiers, la commande nm ultime est nm --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

Questions connexes