Introduction to nm command in linux

Generally speaking, people who are engaged in Linux development will use the nm command, but non-developers should not use it. Although nm is simple, it is still necessary to write a few words and talk about your heart.

  

        nm is not an abbreviation of ni ma. Of course, it is not an abbreviation of ni mei, but an abbreviation of names. The nm command is mainly used to list symbols in certain files (in other words, some functions and global variables, etc.). Below, let's take a look.

       test.h is:

void print ();
      test.c is:

#include <stdio.h>
#include "test.h"
 
void print()
{
    printf("rainy days\n");
}
       main.c为:

#include "test.h"
 
int main ()
{
    print ();
    return 0;
}
      Okay, let ’s look at the effect of the nm command, as follows:
[taoge @ localhost learn_nm] $ nm *
nm: main.c: File format not recognized
nm: test.c: File format not recognized
nm: test.h: File format not recognized
[taoge @ localhost learn_nm] $ 
      ni ma, nothing, it means that nm is useless for such files.


       Continue to see if nm can read the target file and executable file:

[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 
rainy days
[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
08049648 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 main
080483b4 T print
         U puts@@GLIBC_2.0
nm: main.c: File format not recognized

main.o:
00000000 T main
         U print
nm: test.c: File format not recognized
nm: test.h: File format not recognized

test.o:
00000000 T print
         U puts
[taoge @ localhost learn_nm] $ As 
        you can see, both the target file and the executable file can obtain the functions, such as the print function.


        We continue to look at the static library and dynamic library, as follows:

[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 -shared -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 puts

libtest.so:
000014bc a _DYNAMIC
00001590 a _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 completed.5963
000015a8 b dtor_idx.5965
000003e0 t frame_dummy
00000420 T print
         U puts @@ GLIBC_2.0
[taoge @ localhost learn_nm] $ As 
        you can see, we can get the function name from the static library and dynamic library, such as print function.

        Ok, let's take a look at the situation of global variables. We changed main.c to:

#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;
}
       Then use nm to analyze a.out (note that if there is only nm command, the default a.out is the file to be processed):
[taoge @ localhost learn_nm] $ ls
main.c
[taoge @ localhost learn_nm] $ gcc main.c 
[taoge @ localhost learn_nm] $ 
./a.out [taoge @ localhost learn_nm] $ nm a.out 
08049538 d _DYNAMIC
08049604 d _GLOBAL_OFFSET_TABLE_
0804847c R _IO_stdin_used
         w _Jv_RegisterClasses
08049528 d __CTOR_END__
08049524 d __CTOR
08049530 D __DTOR_END__
0804952c d __DTOR_LIST__
08048520 r __FRAME_END__
08049534 d __JCR_END__
08049534 d __JCR_LIST__
08049628 A __bss_start
08049618 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 _edata
08049634 A _end
0804845c T _fini
08048478 R _fp_hw
08048274 T _init
080482e0 T _start
08049630 B aaa
08048394 T add
0804961c D bbb
08049628 b completed.5963
08049618 W data_start
0804962c b dtor_idx.5965
08048370 t frame_dummy
080483a2 T main
08049620 D szTest
[taoge @ localhost learn_nm] $ 
        You can see that there is not only add function, There are also global variables aaa, bbb, and szTest. Note that aaa is uninitialized, so it is in the Bss section, and bbb and szTest are initialized, so it is in the Data section. It is worth noting that there is no ccc, because ccc is a local variable, and nm cannot see it. 
        We should also notice that "good" is not visible on it, why? Because nm is used to look at szTest rather than "good". Do n’t forget, the strings command we introduced earlier can do this, as follows:

[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
[^_]
good
[taoge@localhost learn_nm]$ 


        The nm command mainly lists the symbol information in the characteristic file. For more detailed usage, please ask man, I will not introduce it too much.

————————————————
Copyright Statement: This article is an original article by CSDN blogger "stpeace", following the CC 4.0 BY-SA copyright agreement, please attach the original source link and this statement for reprint .
Original link: https://blog.csdn.net/stpeace/article/details/47089585

Published 13 original articles · Likes6 · Visitors 10,000+

Guess you like

Origin blog.csdn.net/majianting/article/details/104970217