nm ukazuje hodnoty symbolů. Některé symboly v knihovně nebo objektovém souboru se mohou zobrazovat jako nula jednoduše proto, že jim ještě nebyla přiřazena hodnota. Svou skutečnou hodnotu získají v okamžiku propojení.
Některé symboly jsou kódové symboly, některé jsou data atd. Před propojením je hodnota symbolu často offset v sekci, ve které se nachází,
Hexadecimální číslo je paměťový offset do souborů objektů, kde lze symbol nalézt. Je to doslova počet bajtů v kódu objektu.
Tuto hodnotu používá linker k vyhledání a vytvoření kopie hodnoty symbolu. Obecně můžete vidět, jak je to uspořádáno, pokud přidáte -S
možnost nm
, který vám ukáže velikost hodnoty pro každý symbol.
Zde je úryvek kódu, který jsem napsal v C:
#include
#include
void foo();
int main(int argc, char* argv[]) {
foo();
}
void foo() {
printf("Foo bar baz!");
}
Spustil jsem gcc -c foo.c
na tom kódu. Zde je to, co nm foo.o
zobrazeno:
000000000000001b T foo 0000000000000000 T main U printf
Pro tento příklad používám Ubuntu Linux 64-bit; proto je zde 8místný hex, který vidíte, 16místný. :-)
Hexadecimální číslice, kterou vidíte, je adresa příslušného kódu v objektovém souboru vzhledem k začátku .text.
sekce. (za předpokladu, že adresujeme části objektového souboru začínající na 0x0). Pokud spustíte objdump -td foo.o
, ve výstupu uvidíte následující:
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
Všimněte si, že tyto dva symboly jsou zarovnány se záznamy, které jsme viděli v tabulce symbolů z nm
. Tyto adresy se mohou změnit, pokud propojíte tento objektový soubor s jinými objektovými soubory. Také mějte na paměti, že callq
at 0x2c se změní, když tento soubor propojíte s jakoukoli knihovnou libc, kterou váš systém poskytuje, protože to je aktuálně neúplné volání printf (neví, kde právě je).
Pokud jde o váš mylib.a
, tady se toho děje víc. Soubor, který máte, je archiv; obsahuje více objektové soubory, z nichž každý má svůj vlastní textový segment. Jako příklad zde je část nm proti /usr/lib/libm.a na mém boxu zde
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
Uvidíte, že více položek textových segmentů – označených T ve druhém sloupci zůstává na adrese 0x0, ale každý jednotlivý soubor má pouze jeden textový segmentový symbol na 0x0.
Pokud jde o jednotlivé soubory, které mají více symbolů na stejné adrese, zdá se, že by být možná. Koneckonců, je to jen záznam v tabulce sloužící k určení umístění a velikosti kusu dat. Ale to nevím jistě. Nikdy předtím jsem neviděl více symbolů odkazujících na stejnou část sekce. Kdokoli, kdo o tom má více znalostí než já, se může ozvat. :-)
Doufám, že to někomu pomůže.