Comment lister les symboles dans un fichier .so
-
09-06-2019 - |
Question
Comment lister les symboles exportés à partir d’un fichier .so ?Si possible, j'aimerais également connaître leur source (par ex.s'ils sont extraits d'une bibliothèque statique).
J'utilise gcc 4.0.2, si cela fait une différence.
La solution
L'outil standard pour lister les symboles 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 démêle 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 démanteler le 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 utiliser 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
Autres conseils
Si ton .so
Le fichier est au format elf, vous pouvez utiliser le programme readelf pour extraire les informations sur les symboles du binaire.Cette commande vous donnera la table des symboles :
readelf -Ws /usr/lib/libexample.so
Vous ne devez extraire que ceux qui sont définis dans ce .so
fichier, pas dans les bibliothèques référencées par celui-ci.Dans ce cas, la septième colonne doit contenir un nombre.Vous pouvez l'extraire en utilisant une simple regex :
readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'
ou, comme le propose Caspin,:
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
objdump -TC /usr/lib/libexample.so
Pour les bibliothèques partagées libNAME.donc, le commutateur -D était nécessaire pour voir les symboles dans mon Linux
nm -D libNAME.so
et pour la bibliothèque statique comme rapporté par d'autres
nm -g libNAME.a
Je n'arrêtais pas de me demander pourquoi -fvisibilité = caché et #pragma Visibilité GCC ne semblait avoir aucune influence, car tous les symboles étaient toujours visibles avec nm - jusqu'à ce que je trouve ce post qui m'a indiqué lire soi-même et objdump, ce qui m'a fait réaliser qu'il semble y avoir effectivement deux tables de symboles :
- Celui avec lequel vous pouvez lister nm
- Celui avec lequel vous pouvez lister lire soi-même et objdump
Je pense que le premier contient des symboles de débogage qui peuvent être supprimés avec bande ou le commutateur -s que vous pouvez donner à l'éditeur de liens ou le installer commande.Et même si nm ne liste plus rien, vos symboles exportés le sont toujours car ils sont dans la "table de symboles dynamiques" ELF, qui est cette dernière.
Essayez d'ajouter -l aux indicateurs 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.
Pour Android .so
fichiers, la chaîne d'outils NDK est livrée avec les outils requis mentionnés dans les autres réponses : readelf
, objdump
et nm
.
Pour C++ .so
fichiers, le nec plus ultra nm
la commande 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)
Vous pouvez utiliser le nm -g
outil 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 objcopy
révèle des informations supplémentaires.
/MODIFIER:Le nom de l'outil est bien entendu nm
.Le drapeau -g
est utilisé pour afficher uniquement les symboles exportés.
nm -g répertorie la variable externe, qui n'est pas nécessairement un 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 pourrez trouver l'adresse par dlsym.
nm --version
GNU nm2.17.50.0.6-12.el5 20061020
Si tu veux juste savoir s'il y a des symboles présent vous pouvez utiliser
objdump -h /path/to/object
ou pour lister les informations de débogage
objdump -g /path/to/object