nm(1)

Outil de développement

Liste les symboles d'un .o ou d'une bibliothèque : fonctions définies (T), symboles attendus ailleurs (U), variables (D, B). L'outil des undefined reference.

Synopsis
nm [options] fichier...

Description

nm lit un fichier objet (.o), une bibliothèque (.a, .so) ou un exécutable, et affiche la table de ses symboles : les fonctions et variables globales qu'il définit, et celles qu'il utilise sans les définir. Chaque ligne donne l'adresse du symbole dans sa section, une lettre pour son type, puis son nom. C'est la vue qu'a l'éditeur de liens de ton programme, et le moyen le plus rapide de comprendre une erreur undefined reference ou multiple definition.

Lire la lettre

LettreSens
Tfonction définie dans ce fichier (section de code)
Usymbole utilisé ici mais défini ailleurs, à fournir par un autre fichier ou une bibliothèque
Dvariable globale initialisée avec une valeur non nulle
Bvariable globale non initialisée, ou initialisée à zéro
Rdonnée en lecture seule, comme un tableau const
Wsymbole faible, qu'une autre définition peut remplacer

Une majuscule désigne un symbole global, visible des autres fichiers. Une minuscule, un symbole local : une fonction ou une variable static, que l'éditeur de liens ne proposera jamais à un autre fichier.

Options utiles

OptionEffet
-un'affiche que les symboles non définis (U)
-gn'affiche que les symboles globaux
-Dlit les symboles dynamiques d'une bibliothèque partagée (.so)
-Apréfixe chaque ligne par le nom du fichier, pratique avec grep

Exemple

score.c
#include <stdio.h>
int meilleur = 20;int dernier;const char titre[] = "Scores";
static int doubler(int n){    return 2 * n;}
void afficher(int n){    printf("%s : %d\n", titre, doubler(n));}
Terminal
$ gcc -c score.c$ nm score.o0000000000000018 T afficher0000000000000000 B dernier0000000000000000 t doubler0000000000000000 D meilleur                 U printf0000000000000000 R titre$ nm -u score.o                 U printf

Chaque déclaration se retrouve : meilleur initialisée (D), dernier sans valeur (B), titre en lecture seule (R), afficher globale (T), doubler en minuscule parce que static. printf est attendu (U) : c'est la bibliothèque C qui le fournira à l'édition de liens.

Pour savoir quelle bibliothèque partagée définit une fonction, -D et grep suffisent. Sous Debian, sqrt est dans libm et pas dans libc, d'où le -lm :

Terminal
$ nm -D /lib/aarch64-linux-gnu/libm.so.6 | grep -w sqrt0000000000013840 W sqrt@@GLIBC_2.17$ nm -D /lib/aarch64-linux-gnu/libc.so.6 | grep -w sqrt

Pièges

  • Les adresses d'un .o sont relatives à chaque section et valent souvent 0 : elles ne deviennent définitives qu'après l'édition de liens.

  • Une fonction static apparaît en minuscule (t). Si un autre fichier l'appelle, l'édition de liens échoue même si nm l'affiche.

  • Une bibliothèque partagée passée à nm sans -D peut répondre no symbols quand sa table normale a été retirée : utilise -D.

  • Le chemin des bibliothèques dépend de la distribution et de l'architecture. L'exemple vient d'une machine ARM 64 bits.

  • La méthode complète pour corriger une undefined reference est dans undefined reference to en C.

À toi d'écrire le code.