GNU/Linux >> Znalost Linux >  >> Linux

10 Praktické příklady příkazů Linux nm

Příkazy nm poskytují informace o symbolech používaných v objektovém souboru nebo spustitelném souboru.

Výchozí informace, které příkaz ‚nm‘ poskytuje, je:

  • Virtuální adresa symbolu
  • Znak, který znázorňuje typ symbolu. Pokud je znak napsán malým písmenem, pak je symbol místní, ale pokud je znak velkým, pak je symbol externí
  • Název symbolu


Znaky, které identifikují typ symbolu, popisují:

  • A :  Globální absolutní symbol.
  • a :  Místní absolutní symbol.
  • B :Globální symbol bss.
  • b :Místní symbol bss.
  • D :Globální datový symbol.
  • d :Místní datový symbol.
  • f :Symbol názvu zdrojového souboru.
  • L :globální symbol místního vlákna (TLS).
  • l :Statický místní symbol vlákna (TLS).
  • T :Symbol globálního textu.
  • t :Symbol místního textu.
  • U :Nedefinovaný symbol.

Upozorňujeme, že tento seznam není vyčerpávající, ale obsahuje některé důležité typy symbolů. Úplné informace naleznete v manuálové stránce tohoto nástroje.

Výchozí způsob použití nástroje „nm“ je:

$ nm <object file or executable name>

pokud není zadán název spustitelného souboru, pak nm převezme název „a.out“.

Se základní myšlenkou o této utilitě se lze ptát, proč by tyto informace byly vyžadovány?

Předpokládejme, že máte spustitelný soubor, který se skládá z mnoha různých objektových souborů. Nyní předpokládejme, že při kompilaci kódu linker zobrazí chybu o nevyřešeném symbolu „temp“. Nyní se stane noční můrou najít, kde je v kódu symbol ‚temp‘, pokud je kód příliš velký a obsahuje mnoho záhlaví. Zde tento nástroj přichází na pomoc. S některými dalšími možnostmi poskytuje tento nástroj také soubor, ve kterém se symbol nachází.

Od této chvíle máme základní představu o nástroji nm. Pojďme pochopit použití tohoto nástroje pomocí několika praktických příkazů.

1. Zobrazit soubory objektů, které odkazují na symbol

Následující příkaz zobrazí všechny soubory objektů, které odkazují na symbol ‚func‘ v mém aktuálním adresáři

$ nm  -A ./*.o | grep func

./hello2.o:0000000000000000 T func_1
./hello3.o:0000000000000000 T func_2
./hello4.o:0000000000000000 T func_3
./main.o:                   U func
./reloc.o:                  U func
./reloc.o:0000000000000000  T func1
./test1.o:0000000000000000  T func
./test.o:                   U func

Všimněte si, že parametr -A se používá k zobrazení názvu souboru spolu s dalšími informacemi. Vidíme tedy, že ve výstupu dostáváme všechny soubory objektů, kde se používá symbol ‚func‘. To by mohlo být extrémně užitečné v případech, kdy chceme vědět, jak které soubory objektů používají konkrétní symbol.

2. Zobrazit všechny nedefinované symboly ve spustitelném souboru

Následující příkaz vypíše všechny nedefinované symboly ve spustitelném souboru ‚1‘

$ nm -u 1
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U free@@GLIBC_2.2.5
U malloc@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5

Všimněte si, že příznak „-u“ se v tomto případě používá pro výpis pouze nedefinovaných symbolů. To by mohlo být mimořádně užitečné v případech, kdy se může chtít dozvědět o nedefinovaných symbolech používaných v kódu, které by mohly být buď skutečně nevyřešené, nebo by mohly být vyřešeny za běhu prostřednictvím sdílených knihoven.

Pokud jde o související téma, měli byste také pochopit, jak funguje proces propojení GCC.

3. Zobrazit všechny symboly ve spustitelném souboru

Následující příkaz uvádí všechny symboly ve spustitelném souboru ‚namepid‘, ale v seřazeném pořadí podle jejich adres

$ nm -n namepid
w _Jv_RegisterClasses
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U exit@@GLIBC_2.2.5
U fclose@@GLIBC_2.2.5
U fgets@@GLIBC_2.2.5
U fopen@@GLIBC_2.2.5
U fork@@GLIBC_2.2.5
U memset@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
U puts@@GLIBC_2.2.5
U signal@@GLIBC_2.2.5
U sleep@@GLIBC_2.2.5
U strchr@@GLIBC_2.2.5
U strlen@@GLIBC_2.2.5
U strncat@@GLIBC_2.2.5
U strncpy@@GLIBC_2.2.5
U system@@GLIBC_2.2.5
0000000000400778 T _init
00000000004008a0 T _start
00000000004008cc t call_gmon_start
00000000004008f0 t __do_global_dtors_aux
...
...
...

Vidíme, že při použití příznaku ‚-n‘ se výstup nejprve seřadí podle nedefinovaných symbolů a poté podle adres. Řazení by mohlo usnadnit život vývojáře, který ladí problém.

4. Vyhledejte symboly a zobrazte jejich velikost

Následující příkaz vyhledá symbol „abc“ a také zobrazí jeho velikost

$ nm  -S 1 | grep abc
0000000000601040 0000000000000004 B abc

Vidíme tedy, že příznak -S zobrazuje další informaci o velikosti symbolu ‚abc‘

5. Zobrazení dynamických symbolů ve spustitelném souboru

Následující příkaz se zobrazí na dynamických symbolech ve spustitelném souboru „1“.

$ nm  -D 1
w __gmon_start__
U __libc_start_main
U free
U malloc
U printf

To by mohlo být mimořádně užitečné v případech, kdy má někdo zájem dozvědět se o symbolech, které lze za běhu vyřešit pouze sdílenými knihovnami.

6. Extrahujte symboly různých typů

Další výkonnou funkcí příkazu nm je schopnost extrahovat symbol z různých typů formátů objektových souborů. Normálně na Linuxu máme objekt nebo spustitelný kód ve formátu ‚a.out‘ nebo ELF, ale pokud je objekt nebo spustitelný kód jiného formátu, pak pro něj také nm poskytuje příznak ‚–target‘.

7. Změňte formát výstupu nm

Ve výchozím nastavení je formát výstupu zobrazený v nm typ bsd. Formát můžeme změnit pomocí parametru -f. Následující příkaz zobrazí výstup příkazu nm ve stylu posix.

$ nm -u -f posix 1
_Jv_RegisterClasses w
__gmon_start__ w
__libc_start_main@@GLIBC_2.2.5 U
free@@GLIBC_2.2.5 U
malloc@@GLIBC_2.2.5 U
printf@@GLIBC_2.2.5 U

Podobně můžeme použít ‚-f sysv‘, pokud chceme, aby výstup byl ve stylu systemV.

8. Zobrazit pouze externí symboly spustitelného souboru

Následující příkaz uvádí pouze externí symboly ve spustitelném souboru

$ nm -g 1
0000000000400728 R _IO_stdin_used
w _Jv_RegisterClasses
0000000000600e30 D __DTOR_END__
0000000000601030 A __bss_start
0000000000601020 D __data_start
0000000000601028 D __dso_handle
w __gmon_start__
0000000000400640 T __libc_csu_fini
0000000000400650 T __libc_csu_init
...

Vezměte prosím na vědomí, že použití parametru -g umožňuje výstup pouze externích symbolů. To by se mohlo hodit při speciálním ladění externích symbolů.

9. Seřaďte výstup nm podle velikosti symbolu

Následující příkaz seřadí výstup podle velikosti symbolů

$ nm -g --size-sort 1
0000000000000002 T __libc_csu_fini
0000000000000004 R _IO_stdin_used
0000000000000004 B abc
0000000000000084 T main
0000000000000089 T __libc_csu_init

Všimněte si, že příznak –size-sort třídí výstup podle velikosti. Jak již bylo vysvětleno -g se používá k zobrazení pouze externích symbolů.

10. Zadejte možnosti nm v souboru

Další cennou vlastností nm je, že dokáže převzít vstup z příkazového řádku ze souboru. Můžete zadat všechny možnosti v souboru a zadat název souboru příkazu nm a ten udělá zbytek za vás. Například v následujícím příkazu obslužný program nm přečte vstup příkazového řádku ze souboru ‚nm_file‘ a vytvoří výstup

Vezměte prosím na vědomí, že pokud zadáte název souboru, je vyžadován symbol „@“.

$ nm @nm_file
0000000000000002 T __libc_csu_fini
0000000000000004 R _IO_stdin_used
0000000000000004 B abc
0000000000000084 T main
0000000000000089 T __libc_csu_init

Linux
  1. 7 Příklady příkazů Linux df

  2. 8 Příklady příkazů Linux TR

  3. sa Příklady příkazů v Linuxu

  1. cp Command v Linuxu:7 praktických příkladů

  2. Linux Shutdown Command:5 praktických příkladů

  3. 5 Praktické příklady příkazu dd v Linuxu

  1. Příklady příkazů rm v Linuxu

  2. Příklady příkazů ps v Linuxu

  3. w Příklady příkazů v Linuxu