nm zeigt die Werte von Symbolen. Einige Symbole in einer Bibliothek oder Objektdatei werden möglicherweise als Null angezeigt, nur weil ihnen noch kein Wert zugewiesen wurde. Sie erhalten ihren tatsächlichen Wert zum Zeitpunkt der Verknüpfung.
Einige Symbole sind Codesymbole, einige sind Daten usw. Vor dem Verknüpfen des Symbolwerts ist häufig der Offset in dem Abschnitt, in dem es sich befindet,
Die Hexadezimalzahl ist der Speicherversatz in den Objektdateien, wo das Symbol zu finden ist. Es ist buchstäblich die Anzahl der Bytes im Objektcode.
Dieser Wert wird vom Linker verwendet, um den Wert des Symbols zu lokalisieren und eine Kopie davon zu erstellen. Sie können den allgemeinen Aufbau sehen, wenn Sie den -S
hinzufügen Option zu nm
, das Ihnen die Größe des Werts für jedes Symbol anzeigt.
Hier ist ein Codeschnipsel, den ich in C geschrieben habe:
#include
#include
void foo();
int main(int argc, char* argv[]) {
foo();
}
void foo() {
printf("Foo bar baz!");
}
Ich habe gcc -c foo.c
ausgeführt auf diesem Code. Hier ist was nm foo.o
gezeigt:
000000000000001b T foo 0000000000000000 T main U printf
Für dieses Beispiel verwende ich Ubuntu Linux 64-Bit; Deshalb ist das 8-stellige Hex, das Sie sehen, hier 16-stellig. :-)
Die Hex-Ziffer, die Sie sehen, ist die Adresse des fraglichen Codes innerhalb der Objektdatei relativ zum Anfang von .text.
Sektion. (vorausgesetzt, wir adressieren Abschnitte der Objektdatei, die bei 0x0 beginnen). Wenn Sie objdump -td foo.o
ausführen , sehen Sie Folgendes in der Ausgabe:
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
Beachten Sie, dass diese beiden Symbole genau mit den Einträgen übereinstimmen, die wir in der Symboltabelle von nm
gesehen haben . Denken Sie daran, dass sich diese Adressen ändern können, wenn Sie diese Objektdatei mit anderen Objektdateien verknüpfen. Denken Sie auch daran, dass callq
at 0x2c ändert sich, wenn Sie diese Datei mit einer beliebigen libc Ihres Systems verknüpfen, da dies derzeit ein unvollständiger Aufruf von printf ist (es weiß nicht, wo es sich gerade befindet).
Wie für Ihren mylib.a
, hier ist noch mehr los. Die Datei, die Sie haben, ist ein Archiv; es enthält mehrere Objektdateien, von denen jede ihr eigenes Textsegment hat. Als Beispiel hier ein Teil eines nm gegen /usr/lib/libm.a auf meiner Box hier
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
Sie werden sehen, dass mehrere Textsegmenteinträge – angezeigt durch das T in der zweiten Spalte – an der Adresse 0x0 liegen, aber jede einzelne Datei nur hat ein Textsegmentsymbol bei 0x0.
Was einzelne Dateien betrifft, die mehrere Symbole haben, die an derselben Adresse ruhen, scheint es, als ob es würde vielleicht möglich sein. Schließlich ist es nur ein Eintrag in einer Tabelle, die verwendet wird, um den Speicherort und die Größe eines Datenblocks zu bestimmen. Aber ich weiß es nicht genau. Ich habe noch nie mehrere Symbole gesehen, die auf denselben Teil eines Abschnitts verweisen. Jeder, der mehr darüber weiß als ich, kann sich einschalten. :-)
Hoffe das hilft einigen.