GNU/Linux >> Linux Esercitazione >  >> Linux

10 esempi pratici di comandi Linux nm

I comandi nm forniscono informazioni sui simboli utilizzati in un file oggetto o in un file eseguibile.

Le informazioni predefinite fornite dal comando 'nm' sono:

  • Indirizzo virtuale del simbolo
  • Un carattere che rappresenta il tipo di simbolo. Se il carattere è in minuscolo il simbolo è locale ma se il carattere è in maiuscolo il simbolo è esterno
  • Nome del simbolo


I caratteri che identificano il tipo di simbolo descrivono :

  • A :  Simbolo assoluto globale.
  • a :  Simbolo assoluto locale.
  • B :Simbolo globale bss.
  • b :Simbolo bss locale.
  • D :Simbolo dei dati globali.
  • d :Simbolo dati locali.
  • f :Simbolo del nome del file di origine.
  • L :Simbolo locale del thread (TLS).
  • l :Simbolo locale del thread (TLS).
  • T :Simbolo di testo globale.
  • t :Simbolo del testo locale.
  • U :Simbolo non definito.

Si noti che questo elenco non è esaustivo ma contiene alcuni tipi di simboli importanti. Per informazioni complete, fare riferimento alla pagina man di questa utility.

Il modo predefinito per utilizzare l'utilità 'nm' è:

$ nm <object file or executable name>

se non viene fornito alcun nome eseguibile, nm assume che il nome sia "a.out".

Con l'idea di base su questa utilità, ci si potrebbe chiedere perché queste informazioni sarebbero necessarie?

Bene, supponiamo di avere un eseguibile composto da molti file oggetto diversi. Si supponga ora che durante la compilazione del codice, il linker dia un errore su un simbolo non risolto "temp". Ora diventerà un incubo trovare dove si trova il simbolo "temp" nel codice se il codice è troppo grande e include molte intestazioni. È qui che questa utilità viene in soccorso. Con alcune opzioni extra, questa utility fornisce anche il file in cui si trova il simbolo.

Da ora abbiamo un'idea di base sull'utilità nm. Consente di comprendere l'utilizzo di questa utility attraverso alcuni pratici comandi.

1. Visualizza i file oggetto che fanno riferimento a un simbolo

Il comando seguente mostra tutti i file oggetto che fanno riferimento al simbolo 'func' nella mia directory corrente

$ 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

Si noti che il flag -A viene utilizzato per visualizzare il nome del file insieme ad altre informazioni. Quindi vediamo che nell'output otteniamo tutti i file oggetto in cui viene utilizzato il simbolo "func". Questo potrebbe essere estremamente utile nei casi in cui vogliamo sapere come quali file oggetto stanno usando un particolare simbolo.

2. Visualizza tutti i simboli non definiti in un eseguibile

Il comando seguente elenca tutti i simboli non definiti in un file eseguibile '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

Nota che la bandiera '-u' è usata in questo caso per elencare solo i simboli non definiti. Questo potrebbe essere estremamente utile nei casi in cui potresti voler conoscere i simboli non definiti utilizzati nel codice che potrebbero essere davvero irrisolti o potrebbero essere risolti in fase di esecuzione tramite librerie condivise.

Su un argomento correlato, dovresti anche capire come funziona il processo di collegamento GCC.

3. Visualizza tutti i simboli in un eseguibile

Il comando seguente elenca tutti i simboli nell'eseguibile 'namepid' ma in ordine di indirizzi

$ 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
...
...
...

Vediamo che usando il flag '-n', l'output risulta essere ordinato prima con i simboli indefiniti e poi secondo gli indirizzi. L'ordinamento potrebbe semplificare la vita di uno sviluppatore che sta eseguendo il debug di un problema.

4. Cerca un simbolo e visualizza le sue dimensioni

Il comando seguente cerca un simbolo 'abc' e ne mostra anche la dimensione

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

Quindi vediamo che la bandiera -S mostra un'informazione extra sulla dimensione del simbolo 'abc'

5. Visualizza i simboli dinamici in un eseguibile

Il comando seguente viene visualizzato sui simboli dinamici nell'eseguibile '1'.

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

Questo potrebbe essere estremamente utile nei casi in cui si è interessati a conoscere i simboli che possono essere risolti solo dalle librerie condivise in fase di esecuzione.

6. Estrai simboli di vario tipo

Un'altra potente caratteristica del comando nm è quella di poter estrarre il simbolo da vari tipi di formati di file oggetto. Normalmente su Linux abbiamo un oggetto in formato 'a.out' o ELF o codice eseguibile, ma se un oggetto o un codice eseguibile è di qualche altro formato, anche nm fornisce un flag '–target' per esso.

7. Modifica il formato dell'output nm

Per impostazione predefinita, il formato di output visualizzato da nm è il tipo bsd. Possiamo cambiare il formato usando il flag -f. Il comando seguente mostra l'output del comando nm in stile 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

Allo stesso modo possiamo usare '-f sysv' se vogliamo che l'output sia in stile systemV.

8. Visualizza solo i simboli esterni di un eseguibile

Il comando seguente elenca solo i simboli esterni nell'eseguibile

$ 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
...

Si noti che l'uso del flag -g abilita l'output solo di simboli esterni. Questo potrebbe tornare utile durante il debug speciale di simboli esterni.

9. Ordina l'output nm in base alla dimensione del simbolo

Il comando seguente ordina l'output in base alla dimensione dei simboli

$ 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

Si noti che il flag –size-sort ordina l'output rispetto alla dimensione. Come già spiegato -g è usato per visualizzare solo simboli esterni.

10. Specifica nm Opzioni in un file

Un'altra caratteristica preziosa di nm è che può prendere l'input della riga di comando da un file. Puoi specificare tutte le opzioni in un file e specificare il nome del file nel comando nm e farà il resto per te. Ad esempio, nel comando seguente l'utilità nm legge l'input della riga di comando dal file 'nm_file' e produce l'output

Tieni presente che il simbolo "@" è obbligatorio se fornisci il nome del file.

$ 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. Comando cp in Linux:7 esempi pratici

  2. Comando di arresto di Linux:5 esempi pratici

  3. 5 Esempi pratici del comando dd in Linux

  4. 7 Esempi di comandi Linux df

  5. Esempi di comandi rm in Linux

12 Esempi pratici di In Command in Linux

15 esempi pratici di comando Rsync in Linux

5 esempi pratici di Tail Command in Linux

echo Command in Linux:7 esempi pratici

Pratico comando Ping negli esempi di Linux

Esempi di comandi id in Linux