nm montre les valeurs des symboles. Certains symboles dans une bibliothèque ou un fichier objet peuvent apparaître comme zéro simplement parce qu'ils n'ont pas encore reçu de valeur. Ils obtiendront leur valeur réelle au moment du lien.
Certains symboles sont des symboles de code, certains sont des données, etc. Avant de lier la valeur du symbole est souvent le décalage dans la section dans laquelle il réside,
Le chiffre hexadécimal est le décalage de mémoire dans les fichiers objets où le symbole peut être trouvé. C'est littéralement le nombre d'octets dans le code objet.
Cette valeur est utilisée par l'éditeur de liens pour localiser et faire une copie de la valeur du symbole. Vous pouvez voir généralement comment il est disposé si vous ajoutez le -S
option à nm
, qui vous montrera la taille de la valeur pour chaque symbole.
Voici un extrait de code que j'ai écrit en C :
#include
#include
void foo();
int main(int argc, char* argv[]) {
foo();
}
void foo() {
printf("Foo bar baz!");
}
J'ai exécuté gcc -c foo.c
sur ce code. Voici ce que nm foo.o
a montré :
000000000000001b T foo 0000000000000000 T main U printf
Pour cet exemple, j'utilise Ubuntu Linux 64 bits; c'est pourquoi l'hexagone à 8 chiffres que vous voyez est ici à 16 chiffres. :-)
Le chiffre hexadécimal que vous voyez est l'adresse du code en question dans le fichier objet par rapport au début du .text.
section. (en supposant que nous adressons des sections du fichier objet commençant à 0x0). Si vous exécutez objdump -td foo.o
, vous verrez ce qui suit dans la sortie :
Disassembly of section .text: 0000000000000000 : 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 89 7d fc mov %edi,-0x4(%rbp) b: 48 89 75 f0 mov %rsi,-0x10(%rbp) f: b8 00 00 00 00 mov $0x0,%eax 14: e8 00 00 00 00 callq 19 19: c9 leaveq 1a: c3 retq 000000000000001b : 1b: 55 push %rbp 1c: 48 89 e5 mov %rsp,%rbp 1f: b8 00 00 00 00 mov $0x0,%eax 24: 48 89 c7 mov %rax,%rdi 27: b8 00 00 00 00 mov $0x0,%eax 2c: e8 00 00 00 00 callq 31 31: c9 leaveq 32: c3 retq
Notez que ces deux symboles s'alignent avec les entrées que nous avons vues dans la table des symboles de nm
. N'oubliez pas que ces adresses peuvent changer si vous liez ce fichier objet à d'autres fichiers objet. Aussi, gardez à l'esprit que callq
à 0x2c changera lorsque vous lierez ce fichier à la libc fournie par votre système, car il s'agit actuellement d'un appel incomplet à printf (il ne sait pas où il se trouve actuellement).
Quant à votre mylib.a
, il se passe plus ici. Le fichier que vous avez est une archive ; il en contient plusieurs fichiers objets, chacun avec son propre segment de texte. A titre d'exemple, voici une partie d'un nm contre /usr/lib/libm.a sur ma box ici
e_sinh.o: 0000000000000000 r .LC0 0000000000000008 r .LC1 0000000000000010 r .LC2 0000000000000018 r .LC3 0000000000000000 r .LC4 U __expm1 U __ieee754_exp 0000000000000000 T __ieee754_sinh e_sqrt.o: 0000000000000000 T __ieee754_sqrt e_gamma_r.o: 0000000000000000 r .LC0 U __ieee754_exp 0000000000000000 T __ieee754_gamma_r U __ieee754_lgamma_r U __rint
Vous verrez que plusieurs entrées de segment de texte - indiquées par le T dans la deuxième colonne reposent à l'adresse 0x0, mais chaque fichier individuel a seulement un symbole de segment de texte à 0x0.
En ce qui concerne les fichiers individuels ayant plusieurs symboles reposant à la même adresse, il semble que ce soit le serait être possible peut-être. Après tout, il ne s'agit que d'une entrée dans une table utilisée pour déterminer l'emplacement et la taille d'un bloc de données. Mais je ne sais pas avec certitude. Je n'ai jamais vu plusieurs symboles faisant référence à la même partie d'une section auparavant. N'importe qui ayant plus de connaissances que moi à ce sujet peut intervenir. :-)
J'espère que cela en aidera certains.