Introducción al comando nm en linux

En términos generales, las personas que participan en el desarrollo de Linux usarán el comando nm, pero los que no sean desarrolladores no deberían usarlo. Aunque nm es simple, aún es necesario escribir algunas palabras y hablar sobre su corazón.

  

        nm no es una abreviatura de ni ma. Por supuesto, no es una abreviatura de ni mei, sino una abreviatura de nombres. El comando nm se usa principalmente para enumerar símbolos en ciertos archivos (en otras palabras, algunas funciones y variables globales). A continuación, echemos un vistazo.

       test.h es:

vacío de impresión ();
      test.c es:

#include <stdio.h>
#include "test.h"
 
void print ()
{
    printf ("días lluviosos \ n");
}
       main.c 为 :

#include "test.h"
 
int main ()
{
    print ();
    return 0;
}
      Bien, veamos el efecto del comando nm, como sigue:
[taoge @ localhost learn_nm] $ nm *
nm: main.c: Formato de archivo no reconocido
nm: test.c: Formato de archivo no reconocido
nm: test.h: Formato de archivo no reconocido
[taoge @ localhost learn_nm] $ 
      ni ma, nada, significa que nm es inútil para dichos archivos.


       Continúe para ver si nm puede leer el archivo de destino y el archivo ejecutable:

[taoge @ localhost learn_nm] $ ls
main.c test.c test.h
[taoge @ localhost learn_nm] $ gcc -c test.c main.c 
[taoge @ localhost learn_nm] $ gcc test.o main.o
[taoge @ localhost learn_nm] $ ./a.out 
días lluviosos
[taoge @ localhost learn_nm] $ nm *

a.out:
08049564 d _dynamic
08049630 d _GLOBAL_OFFSET_TABLE_
0804849c R _IO_stdin_used
         w _Jv_RegisterClasses
08049554 d __CTOR_END__
08049550 d __CTOR_LIST__
0804955c D __DTOR_END__
08049558 d __DTOR_LIST__
0804854c r __FRAME_END__
08049560 d __JCR_END__
08049560 d __JCR_LIST__
0804964c A __bss_start
08.049.648 D __data_start
08048450 t __do_global_ctors_aux
08048330 t __do_global_dtors_aux
080484a0 R __dso_handle
         w __gmon_start__
0804844a T __i686.get_pc_thunk.bx
08049550 d __init_array_end
08049550 d __init_array_start
080483e0 T __libc_csu_fini
080483f0 T __libc_csu_init
         U __libc_start_main @@ GLIBC_2.0
0804964c A _edata
08049654 A _END
0804847c T _fini
08048498 R _fp_hw
08048290 T _init
08048300 T _start
0804964c b completed.5963
08049648 W data_start
08049650 b dtor_idx.5965
08048390 t frame_dummy
080483c8 T principal
080483b4 T de impresión
         U pone @@ GLIBC_2.0
nm: main.c: formato de archivo no reconocido

main.o:
00000000 T main
         U print
nm: test.c: formato de archivo no reconocido
nm: test.h: formato de archivo no reconocido

test.o:
00000000 T print
         U pone
[taoge @ localhost learn_nm] $ Como 
        puede ver, tanto el archivo de destino como el archivo ejecutable pueden obtener las funciones, como la función de impresión.


        Continuamos mirando la biblioteca estática y la biblioteca dinámica, de la siguiente manera:

[taoge @ localhost learn_nm] $ ls
main.c test.c test.h
[taoge @ localhost learn_nm] $ gcc -c test.c
[taoge @ localhost learn_nm] $ ar rcs libtest.a test.o
[taoge @ localhost learn_nm ] $ gcc -compartido -fPIC -o libtest.so test.o
[taoge @ localhost learn_nm] $ ls
libtest.a libtest.so main.c test.c test.h test.o
[taoge @ localhost learn_nm] $ nm lib * *

libtest.a:

test.o:
00000000 T print
         U pone

libtest.so:
000014bc un _dynamic
00001590 un _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
000014a8 d __CTOR_END__
000014a4 d __CTOR_LIST__
000014b0 d __DTOR_END__
000014ac d __DTOR_LIST__
000004a0 r __FRAME_END__
000014b4 d __JCR_END__
000014b4 d __JCR_LIST__
000015a4 A __bss_start
         w __cxa_finalize @@ GLIBC_2.1.3
00000440 t __do_global_ctors_aux
00000350 t __do_global_dtors_aux
000014b8 d __dso_handle
         w __gmon_start__
00000419 t __i686.get_pc_thunk.bx
000015a4 A _edata
000015ac A _end
00000478 T _fini
000002ec T _init
000015a4 b completado.5963
000015a8 b dtor_idx.5965
000003e0 t frame_dummy
00000420 T print
         U pone @@ GLIBC_2.0
[taoge @ localhost learn_nm] $ Como 
        puede ver, podemos obtener el nombre de la función de la biblioteca estática y la biblioteca dinámica, como print Función.

        Ok, echemos un vistazo a la situación de las variables globales. Cambiamos main.c a:

#include <stdio.h>
 
int add (int x, int y)
{
    return x + y;
}
 
int aaa;
int bbb = 1;
char szTest [] = "good";
 
int main ()
{
    int ccc = 2;
    return 0;
}
       Luego use nm para analizar a.out (tenga en cuenta que si solo hay un comando nm, el a.out predeterminado es el archivo a procesar):
[taoge @ localhost learn_nm] $ ls
main.c
[taoge @ localhost learn_nm] $ main.c GCC 
[Taoge @ localhost learn_nm] $ ./a.out 
[Taoge @ localhost learn_nm] la a.out nm $ 
08049,538 mil D la _dynamic
08.049.604 D _GLOBAL_OFFSET_TABLE_
0804847c R & lt _IO_stdin_used
         W _Jv_RegisterClasses
08.049.528 D __CTOR_END__
08.049.524 D __CTOR_LIST__
08049530 D __DTOR_END__
0804952c d __DTOR_LIST__
08048520 r __FRAME_END__
08049534 d __JCR_END__
08049534 d __JCR_LIST__
08049628 A __bss_start
08.049.618 D __data_start
08048430 t __do_global_ctors_aux
08048310 t __do_global_dtors_aux
08048480 R __dso_handle
         w __gmon_start__
0804842a T __i686.get_pc_thunk.bx
08049524 d __init_array_end
08049524 d __init_array_start
080483c0 T __libc_csu_fini
080483d0 T __libc_csu_init
         U __libc_start_main @@ GLIBC_2.0
08049628 A _edatos
08049634 A _end
0804845c T _fini
08048478 R _fp_hw
08048274 T _init
T _start 080482e0
08,04963 millones de b AAA
08048394 T Agregar
0804961c D acreditación
08049628 B completed.5963
08049618 W es DATA_START
0804962c B dtor_idx.5965
08,04837 millones de toneladas frame_dummy
080483a2 T principal
08049620 szTest D
[Taoge @ localhost learn_nm] $ 
        se puede observar, no sólo Agregar función, También hay variables globales aaa, bbb y szTest. Tenga en cuenta que aaa no está inicializado, por lo que está en la sección Bss, y bbb y szTest están inicializados, por lo que está en la sección Datos. Vale la pena señalar que no hay ccc, porque ccc es una variable local y nm no puede verla. 
        También debemos notar que "bueno" no es visible, ¿por qué? Porque nm se usa para mirar szTest en lugar de "bueno". No se olvide, el comando de cadenas que presentamos anteriormente puede hacer esto, de la siguiente manera:

[taoge @ localhost learn_nm] $ ls
a.out main.c
[taoge @ localhost learn_nm] $ strings a.out 
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
[^ _ ]
bueno
[taoge @ localhost learn_nm] $ 


        El comando nm enumera principalmente la información del símbolo en el archivo de características. Para un uso más detallado, pregunte a man, no lo introduciré demasiado.

————————————————
Declaración de derechos de autor: Este artículo es un artículo original del blogger de CSDN "stpeace", siguiendo el acuerdo de derechos de autor CC 4.0 BY-SA, adjunte el enlace original y esta declaración para volver a imprimir .
Enlace original: https://blog.csdn.net/stpeace/article/details/47089585

13 artículos originales publicados · Me gusta6 · Visitantes más de 10,000

Supongo que te gusta

Origin blog.csdn.net/majianting/article/details/104970217
Recomendado
Clasificación