​代码在git​

是names的缩写, nm命令主要是用来列出某些文件中的符号(说白了就是一些函数和全局变量等)。 下面, 我们一起来看看。
​linux中的nm命令简介​​

nm *
nm: main.c: 不可识别的文件格式
nm: test.c: 不可识别的文件格式
nm: test.h: 不可识别的文件格式

这说明nm对这类文件无用
继续看nm能否读取目标文件和可执行文件:

ls
gcc -c test.c main.c
gcc test.o main.o
./a.out
nm *
a.out:
0000000000201010 B __bss_start
0000000000201010 b completed.7698
w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000560 t deregister_tm_clones
00000000000005f0 t __do_global_dtors_aux
0000000000200dc0 t __do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200dc8 d _DYNAMIC
0000000000201010 D _edata
0000000000201018 B _end
00000000000006e4 T _fini
0000000000000630 t frame_dummy
0000000000200db8 t __frame_dummy_init_array_entry
000000000000086c r __FRAME_END__
0000000000200fb8 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000000700 r __GNU_EH_FRAME_HDR
00000000000004e8 T _init
0000000000200dc0 t __init_array_end
0000000000200db8 t __init_array_start
00000000000006f0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000006e0 T __libc_csu_fini
0000000000000670 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
000000000000064d T main
000000000000063a T print
U puts@@GLIBC_2.2.5
00000000000005a0 t register_tm_clones
0000000000000530 T _start
0000000000201010 D __TMC_END__
nm: main.c: 不可识别的文件格式

main.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U print
nm: test.c: 不可识别的文件格式
nm: test.h: 不可识别的文件格式

test.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T print
U puts

可以看到, 对于目标文件和可执行文件而言, 均可以获得其中的函数, 如print函数。

我们继续看静态库和动态库, 如下:

gcc -c test.c
ar rcs libtest.a test.o
gcc -shared -fPIC -o libtest.so test.o
nm lib*
libtest.a:

test.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T print
U puts

libtest.so:
0000000000201028 B __bss_start
0000000000201028 b completed.7698
w __cxa_finalize@@GLIBC_2.2.5
0000000000000530 t deregister_tm_clones
00000000000005c0 t __do_global_dtors_aux
0000000000200e18 t __do_global_dtors_aux_fini_array_entry
0000000000201020 d __dso_handle
0000000000200e20 d _DYNAMIC
0000000000201028 D _edata
0000000000201030 B _end
0000000000000620 T _fini
0000000000000600 t frame_dummy
0000000000200e10 t __frame_dummy_init_array_entry
00000000000006d0 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000000634 r __GNU_EH_FRAME_HDR
00000000000004e8 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
000000000000060a T print
U puts@@GLIBC_2.2.5
0000000000000570 t register_tm_clones
0000000000201028 d __TMC_END__

可以看到, 我们可以从静态库和动态库中获取到函数名称, 如print函数。

好, 我们再来看看全局变量的情形, 我们把main.c改为:

cd 2
gcc main.c
nm *
a.out:
0000000000201020 B aaa
00000000000005fa T add
0000000000201010 D bbb
0000000000201019 B __bss_start
000000000020101c b completed.7698
w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000520 t deregister_tm_clones
00000000000005b0 t __do_global_dtors_aux
0000000000200df8 t __do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200e00 d _DYNAMIC
0000000000201019 D _edata
0000000000201028 B _end
0000000000000694 T _fini
00000000000005f0 t frame_dummy
0000000000200df0 t __frame_dummy_init_array_entry
000000000000080c r __FRAME_END__
0000000000200fc0 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00000000000006a4 r __GNU_EH_FRAME_HDR
00000000000004b8 T _init
0000000000200df8 t __init_array_end
0000000000200df0 t __init_array_start
00000000000006a0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000000690 T __libc_csu_fini
0000000000000620 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
000000000000060e T main
0000000000000560 t register_tm_clones
00000000000004f0 T _start
0000000000201014 D szTest
0000000000201020 D __TMC_END__
nm: main.c: 不可识别的文件格式

可以看到, 不仅有add函数, 还有全局变量aaa, bbb和szTest, 要注意, aaa是未初始化的, 所以在Bss段, 而bbb、szTest是初始化了的, 所以在Data段。 值得注意的是, 并没有ccc, 因为ccc是局部变量, nm看不到的。

我们还应该注意到, 在上面看不到"good", 为啥呢? 因为nm是用来看szTest而非"good"的。 别忘了, 我们之前介绍过的strings命令可干这事, 如下:

strings a.out
/lib64/ld-linux-x86-64.so.2
nd8B
//}Q
libc.so.6
__cxa_finalize
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
AWAVI
AUATL
[]A\A]A^A_
;*3$"
good