原文链接:http://blog.csdn.net/statdm/article/details/7759100

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具。ldd是用来分析程序运行时需要依赖的动态库的工具;nm是用来查看指定程序中的符号表相关内容的工具。下面通过例子,分别来介绍一下这两个工具:

1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库:

[plain] view plaincopy
  1. $ ldd cs
  2. linux-gate.so.1 =>  (0xffffe000)
  3. libz.so.1 => /lib/libz.so.1 (0xb7f8c000)
  4. libpthread.so.0 => /lib/libpthread.so.0 (0xb7f75000)
  5. libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7e4d000)
  6. libpcre.so.0 => /usr/lib/libpcre.so.0 (0xb7e21000)
  7. libstdc++.so.6 => /usr/local/gcc4.5.1/lib/libstdc++.so.6 (0xb7d40000)
  8. libm.so.6 => /lib/libm.so.6 (0xb7d18000)
  9. libgcc_s.so.1 => /usr/local/gcc4.5.1/lib/libgcc_s.so.1 (0xb7cfd000)
  10. libc.so.6 => /lib/libc.so.6 (0xb7bbc000)
  11. /lib/ld-linux.so.2 (0xb7fab000)
  12. libdl.so.2 => /lib/libdl.so.2 (0xb7bb7000)

在上面的例子中,ldd的结果可以分为三列来看:

•第一列:程序需要依赖什么库
•第二列: 系统提供的与程序需要的库所对应的库
•第三列:库加载的开始地址
通过上面的信息,我们可以得到以下几个信息:

•(1) 通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实际提供的,是否相匹配
•(2) 通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的地址空间中的开始位置
2. nm, 通过下面的例子,我们来介绍nm工具:
先看一下这个简单的程序:

  1. #include "iostream"
  2. using namespace std;
  3. class Test
  4. {
  5. public:
  6. void Hello()
  7. {
  8. cout < < "Hello world!" << endl;
  9. }
  10. };
  11. int main()
  12. {
  13. Test test;
  14. test.Hello();
  15. }

}接下来,我们编译该程序,然后看nm的结果: 

[plain] view plaincopy
  1. $ g++ test.cc -o test
  2. c$ nm test
  3. 08049f10 d _DYNAMIC
  4. 08049ff4 d _GLOBAL_OFFSET_TABLE_
  5. 080486f0 t _GLOBAL__I_main
  6. 080487fc R _IO_stdin_used
  7. w _Jv_RegisterClasses
  8. 080486b0 t _Z41__static_initialization_and_destruction_0ii
  9. 0804870c W _ZN4Test5HelloEv
  10. U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
  11. U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
  12. U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
  13. 0804a040 B _ZSt4cout@@GLIBCXX_3.4
  14. U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
  15. 0804a0d4 b _ZStL8__ioinit
  16. U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
  17. 08049f00 d __CTOR_END__
  18. 08049ef8 d __CTOR_LIST__
  19. 08049f08 D __DTOR_END__
  20. 08049f04 d __DTOR_LIST__
  21. 080488c8 r __FRAME_END__
  22. 08049f0c d __JCR_END__
  23. 08049f0c d __JCR_LIST__
  24. 0804a02c A __bss_start
  25. U __cxa_atexit@@GLIBC_2.1.3
  26. 0804a024 D __data_start
  27. 080487b0 t __do_global_ctors_aux
  28. 08048610 t __do_global_dtors_aux
  29. 0804a028 D __dso_handle
  30. w __gmon_start__
  31. U __gxx_personality_v0@@CXXABI_1.3
  32. 080487aa T __i686.get_pc_thunk.bx
  33. 08049ef8 d __init_array_end
  34. 08049ef8 d __init_array_start
  35. 08048740 T __libc_csu_fini
  36. 08048750 T __libc_csu_init
  37. U __libc_start_main@@GLIBC_2.0
  38. 0804a02c A _edata
  39. 0804a0d8 A _end
  40. 080487dc T _fini
  41. 080487f8 R _fp_hw
  42. 08048508 T _init
  43. 080485e0 T _start
  44. 0804a0cc b completed.7065
  45. 0804a024 W data_start
  46. 0804a0d0 b dtor_idx.7067
  47. 08048670 t frame_dummy
  48. 08048694 T main

上面便是test这个程序中所有的符号,首先需要介绍一下上面的内容的格式:

•第一列:当前符号的地址
•第二列:当前符号的类型
•第三列:当前符号的名称
在上面的结果中,像_ZN4Test5HelloEv这样的符号,很多读者朋友可能会被它搞晕,这里介绍个小技巧,在nm的时候,加上-C选项,就可以把这些难以识别的符号,转换成便于我们阅读的符号TestHello()。这个主要是c++中的mangle机制所导致的,加上-C就是指定列出的符号是demangle了的。说了这么多,到底nm对我们程序有啥具体的帮助呢,我觉得主要有以下几个方面:
(1)判断指定程序中有没有定义指定的符号 (比较常用的方式:nm -C proc | grep symbol)
(2)解决程序编译时undefined reference的错误,以及mutiple definition的错误

(3)查看某个符号的地址,以及在进程空间的大概位置(bss, data, text区,具体可以通过第二列的类型来判断)

附:nm输出中,部分符合类型说明 ,详细见 nm 的帮助


该符号的值是绝对的,在以后的链接过程中,不允许进行改变。这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。 


该符号的值出现在非初始化数据段(bss)中。例如,在一个文件中定义全局static int test。则该符号test的类型为b,位于bss section中。其值表示该符号在bss段中的偏移。一般而言,bss段分配于RAM中 


该符号为common。common symbol是未初始话数据段。该符号没有包含于一个普通section中。只有在链接过程中才进行分配。符号的值表示该符号需要的字节数。例如在一个c文件中,定义int test,并且该符号在别的地方会被引用,则该符号类型即为C。否则其类型为B。 


该符号位于初始话数据段中。一般来说,分配到data section中。例如定义全局int baud_table[5] = {9600, 19200, 38400, 57600, 115200},则会分配于初始化数据段中。 


该符号也位于初始化数据段中。主要用于small object提高访问small data object的一种方式。 


该符号是对另一个符号的间接引用。 


该符号是一个debugging符号。 


该符号位于只读数据区。例如定义全局const int test[] = {123, 123};则test就是一个只读数据区的符号。注意在cygwin下如果使用gcc直接编译成MZ格式时,源文件中的test对应_test,并且其符号类型为D,即初始化数据段中。但是如果使用m6812-elf-gcc这样的交叉编译工具,源文件中的test对应目标文件的test,即没有添加下划线,并且其符号类型为R。一般而言,位于rodata section。值得注意的是,如果在一个函数中定义const char *test = “abc”, const char test_int = 3。使用nm都不会得到符号信息,但是字符串“abc”分配于只读存储器中,test在rodata section中,大小为4。 


符号位于非初始化数据区,用于small object。 


该符号位于代码区text section。 


该符号在当前文件中是未定义的,即该符号的定义在别的文件中。例如,当前文件调用另一个文件中定义的函数,在这个被调用的函数在当前就是未定义的;但是在定义它的文件中类型是T。但是对于全局变量来说,在定义它的文件中,其符号类型为C,在使用它的文件中,其类型为U。 


该符号是一个weak object。 


The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. 


该符号是a.out格式文件中的stabs symbol。 


该符号类型没有定

Linux程序分析工具介绍—ldd,nm的更多相关文章

  1. linux程序分析工具介绍(二)—-ldd,nm

    本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析程序运行时需要依赖的动态库的工具:nm是用来查看指定程序中的符号表相关内容的工具.下面通过例子,分别来介绍一下这两 ...

  2. linux程序分析工具介绍(一)—-”/proc”

    写在最前面:在开始本文之前,笔者认为先有必要介绍一下linux下的man,如果读者手头用linux系统,直接在终端输入man man便可以看到详细的说明,我在这里简单的总结一下,man命令是用来查看l ...

  3. linux程序分析工具介绍(三)——sar

    本文要介绍的sar,是linux下用来分析系统本身运行情况的非常有用的工具.我们知道,程序在操作系统上要运行,要关注的点不外乎内存,CPU和IO(包括磁盘IO和网络IO).我们的应用程序在操作系统中运 ...

  4. linux程序分析工具

    ldd和nm是Linux下两个非常实用的程序分析工具.ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具,objdump用来查看源代码与汇编代码,-d只查 ...

  5. Linux程序分析工具:ldd和nm

    ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [option ...

  6. (转)超全整理!Linux性能分析工具汇总合集

    超全整理!Linux性能分析工具汇总合集 原文:http://rdc.hundsun.com/portal/article/731.html 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望, ...

  7. Linux资源分析工具杂谈(长文慎入)

    Linux资源分析工具杂谈 开篇之前请大家先思考一个问题:        磁盘的平均I/O响应时间是1 ms,这个指标是好,还是差? 众所周知,计算机科学是客观的,也就是说对于一个给定的问题,我们总是 ...

  8. Linux 日志分析工具(logwatch)安装及使用

    Linux 日志分析工具(logwatch)安装及使用 日志是非常重要的系统文件,管理员每天的重要工作就是分析和查看服务器的日志,判断服务器的健康状态.但是日志管理又是一项非常枯燥的工作,如果需要管理 ...

  9. Linux 内存分析工具的命令大全介绍

    在Linux系统经常被用作服务器系统.当服务器内存吃紧的时候,free命令是我们最常使用的内存分析工具. free使用介绍# free命令可以显示Linux系统中空闲的.已用的物理内存及swap内存, ...

随机推荐

  1. Swift3的playground中对UI直接测试支持的改变

    我们知道在Xcode的playground中不仅可以测试console代码,还可以测试UI代码,甚至我们可以测试SpriteKit中的场景,有兴趣的童鞋可以看我之前写的这一篇blog: Xcode的p ...

  2. Objective-C基础之简析深浅copy

    一.从面向对象到Objective-C概览copy 1.面向对象: In object-oriented programming, object copying is creating a copy ...

  3. Android的AIDL机制

    Android 接口定义语言 (AIDL) AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似. 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的 ...

  4. Appium移动自动化测试(三)--安装Android模拟器(建议直接连手机,跳过此步)

    转自虫师,亲测有效,留备后用. 本文中如果直接安装时不出现错误,则可以忽略(一.二.三.四.五),我安装的是5.1.1,直接成功,就是有点慢,要有耐心. 如果到最后一步,启动不起来,报错: emula ...

  5. Node.js 撸第一个Web应用

    使用Node.js 创建Web 应用与使用PHP/Java 语言创建Web应用略有不同. 使用PHP/Java 来编写后台代码时,需要Apache 或者 Nginx 的HTTP 服务器,而接受请求和提 ...

  6. iOS界面不能点击(tableView 的cell 不能使用点击事件,tableView也不能上下滚动)

    iOS开发中间遇到了很多问题,有些后来又遇到,竟然忘记怎么处理了,所以还是来写下博客记录自己遇到的问题,方便自己也方便别人. 之前想的是项目小,就用storyboard在绘制界面,但是项目慢慢的扩展, ...

  7. 手把手图文并茂教你发布Android开源库

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼,文章链接: http://blog.csdn.net/hejjunlin/article/details/52452220 经常逛githu ...

  8. 阻尼回弹效果的ScrollView嵌套GridView

    以前写过一篇带阻尼回弹效果的ScrollView,但是有些小问题,于是又重新整理了一下,这篇文章一是一个带阻尼的Scrollview,再个就是Scrollview嵌套GridView实现,而GridV ...

  9. IIS部署WCF报 无法读取配置节“protocolMapping”,因为它缺少节声明

    今天写了个wcf的测试程序放在客户的服务器上供他们测试调用,部署到IIS后浏览报错了,根据错误的提示看出似乎是识别不了这个节点名,偶然的去看了下进程池中该站点的进程池名字的高级设置,看到使用的.net ...

  10. Android下拉列表控件spinner-andoid学习之旅(十一)

    废话不多说,下拉列表常用的就是spinner控件. 直接上代码: package peng.liu.testview; import android.app.Activity; import andr ...