linux中nm作用,linux中的nm命令简介

一般来说, 搞linux开发的人, 才会用到nm命令, 非开发的人, 应该用不到。 虽然nm很简单, 但是还是有必要写几句, 聊表心意。

nm不是ni ma的缩写, 当然, 也不是ni mei的缩写, 而是names的缩写, nm命令主要是用来列出某些文件中的符号(说白了就是一些函数和全局变量等)。  下面, 我们一起来看看。

test.h为:

void print();

test.c为:

#include

#include "test.h"

voidprint()

{

printf("rainy days\n");

}

#include #include "test.h"

void print()

{

printf("rainy days\n");

}

main.c为:

#include "test.h"

intmain()

{

print();

return0;

}

#include "test.h"

int main()

{

print();

return 0;

}

好, 我们看看nm命令的作用效果, 如下:

[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]$

[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, 啥都没有, 这说明nm对这类文件无用。

继续看nm能否读取目标文件和可执行文件:

[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]$

[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]$

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

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

[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]$

[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]$

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

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

#include

intadd(intx,inty)

{

returnx + y;

}

intaaa;

intbbb = 1;

charszTest[] ="good";

intmain()

{

intccc = 2;

return0;

}

#include int add(int x, int y)

{

return x + y;

}

int aaa;

int bbb = 1;

char szTest[] = "good";

int main()

{

int ccc = 2;

return 0;

}

然后用nm分析a.out(注意, 如果只有nm命令, 则默认a.out为其要处理的文件):

[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_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

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

[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_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

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

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

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

[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]$

[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]$

nm命令主要列出特性文件中的符号信息, 具体更加详细的用法, 请问man, 我就不再过多介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值