linux中的nm命令简介

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

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

  

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

       test.h为:

void print();

      test.c为:

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

       main.c为:

#include "test.h"int main(){ print(); return 0;}
      好, 我们看看nm命令的作用效果, 如下:

[taoge@localhost learn_nm]$ nm *nm: main.c: File format not recognizednm: test.c: File format not recognizednm: test.h: File format not recognized[taoge@localhost learn_nm]$ 
      ni ma, 啥都没有, 这说明nm对这类文件无用。


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

[taoge@localhost learn_nm]$ lsmain.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 _DYNAMIC08049630 d _GLOBAL_OFFSET_TABLE_0804849c R _IO_stdin_used         w _Jv_RegisterClasses08049554 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_start08049648 D __data_start08048450 t __do_global_ctors_aux08048330 t __do_global_dtors_aux080484a0 R __dso_handle         w __gmon_start__0804844a T __i686.get_pc_thunk.bx08049550 d __init_array_end08049550 d __init_array_start080483e0 T __libc_csu_fini080483f0 T __libc_csu_init         U __libc_start_main@@GLIBC_2.00804964c A _edata08049654 A _end0804847c T _fini08048498 R _fp_hw08048290 T _init08048300 T _start0804964c b completed.596308049648 W data_start08049650 b dtor_idx.596508048390 t frame_dummy080483c8 T main080483b4 T print         U puts@@GLIBC_2.0nm: main.c: File format not recognizedmain.o:00000000 T main         U printnm: test.c: File format not recognizednm: test.h: File format not recognizedtest.o:00000000 T print         U puts[taoge@localhost learn_nm]$ 
        可以看到, 对于目标文件和可执行文件而言, 均可以获得其中的函数, 如print函数。


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

[taoge@localhost learn_nm]$ lsmain.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]$ lslibtest.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 putslibtest.so:000014bc a _DYNAMIC00001590 a _GLOBAL_OFFSET_TABLE_         w _Jv_RegisterClasses000014a8 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.300000440 t __do_global_ctors_aux00000350 t __do_global_dtors_aux000014b8 d __dso_handle         w __gmon_start__00000419 t __i686.get_pc_thunk.bx000015a4 A _edata000015ac A _end00000478 T _fini000002ec T _init000015a4 b completed.5963000015a8 b dtor_idx.5965000003e0 t frame_dummy00000420 T print         U puts@@GLIBC_2.0[taoge@localhost learn_nm]$ 
        可以看到, 我们可以从静态库和动态库中获取到函数名称, 如print函数。



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

#include <stdio.h>int add(int x, int y)return x + y;}int aaa;int bbb = 1;char szTest[] = "good";int main()int ccc = 2return 0;}
       然后用nm分析a.out(注意, 如果只有nm命令, 则默认a.out为其要处理的文件):

[taoge@localhost learn_nm]$ lsmain.c[taoge@localhost learn_nm]$ gcc main.c [taoge@localhost learn_nm]$ ./a.out [taoge@localhost learn_nm]$ nm a.out 08049538 d _DYNAMIC08049604 d _GLOBAL_OFFSET_TABLE_0804847c R _IO_stdin_used         w _Jv_RegisterClasses08049528 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_start08049618 D __data_start08048430 t __do_global_ctors_aux08048310 t __do_global_dtors_aux08048480 R __dso_handle         w __gmon_start__0804842a T __i686.get_pc_thunk.bx08049524 d __init_array_end08049524 d __init_array_start080483c0 T __libc_csu_fini080483d0 T __libc_csu_init         U __libc_start_main@@GLIBC_2.008049628 A _edata08049634 A _end0804845c T _fini08048478 R _fp_hw08048274 T _init080482e0 T _start08049630 B aaa08048394 T add0804961c D bbb08049628 b completed.596308049618 W data_start0804962c b dtor_idx.596508048370 t frame_dummy080483a2 T main08049620 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]$ lsa.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_mainGLIBC_2.0PTRh[^_]good[taoge@localhost learn_nm]$ 


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









   

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值