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

本文介绍了Linux下的ldd和nm工具。ldd用于分析程序所需的动态库及其加载地址,nm则用于查看程序中的符号表内容。文章通过实例展示了如何使用这两个工具进行程序依赖分析及符号检查。
本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具。ldd是用来分析程序运行时需要依赖的动态库的工具;nm是用来查看指定程序中的符号表相关内容的工具。下面通过例子,分别来介绍一下这两个工具:

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

wuzesheng@wuzesheng-ubuntu:~/Public$ ldd cs
    linux-gate.so.1 =>  (0xffffe000)
    libz.so.1 => /lib/libz.so.1 (0xb7f8c000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb7f75000)
    libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7e4d000)
    libpcre.so.0 => /usr/lib/libpcre.so.0 (0xb7e21000)
    libstdc++.so.6 => /usr/local/gcc4.5.1/lib/libstdc++.so.6 (0xb7d40000)
    libm.so.6 => /lib/libm.so.6 (0xb7d18000)
    libgcc_s.so.1 => /usr/local/gcc4.5.1/lib/libgcc_s.so.1 (0xb7cfd000)
    libc.so.6 => /lib/libc.so.6 (0xb7bbc000)
    /lib/ld-linux.so.2 (0xb7fab000)
    libdl.so.2 => /lib/libdl.so.2 (0xb7bb7000)


在上面的例子中,ldd的结果可以分为三列来看:
第一列:程序需要依赖什么库
第二列: 系统提供的与程序需要的库所对应的库
第三列:库加载的开始地址

通过上面的信息,我们可以得到以下几个信息:
(1) 通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实际提供的,是否相匹配
(2) 通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的地址空间中的开始位置

2. nm, 通过下面的例子,我们来介绍nm工具:
先看一下这个简单的程序:

#include "iostream"
 
using namespace std;
 
class Test
{
public:
    void Hello()
    {
        cout < < "Hello world!" << endl;
    }
};
 
int main()
{
    Test test;
    test.Hello();
}

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

wuzesheng@wuzesheng-ubuntu:~/Public$ g++ test.cc -o test
wuzesheng@wuzesheng-ubuntu:~/Public$ nm test
08049f10 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080486f0 t _GLOBAL__I_main
080487fc R _IO_stdin_used
         w _Jv_RegisterClasses
080486b0 t _Z41__static_initialization_and_destruction_0ii
0804870c W _ZN4Test5HelloEv
         U _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
         U _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
         U _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
0804a040 B _ZSt4cout@@GLIBCXX_3.4
         U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
0804a0d4 b _ZStL8__ioinit
         U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
08049f00 d __CTOR_END__
08049ef8 d __CTOR_LIST__
08049f08 D __DTOR_END__
08049f04 d __DTOR_LIST__
080488c8 r __FRAME_END__
08049f0c d __JCR_END__
08049f0c d __JCR_LIST__
0804a02c A __bss_start
         U __cxa_atexit@@GLIBC_2.1.3
0804a024 D __data_start
080487b0 t __do_global_ctors_aux
08048610 t __do_global_dtors_aux
0804a028 D __dso_handle
         w __gmon_start__
         U __gxx_personality_v0@@CXXABI_1.3
080487aa T __i686.get_pc_thunk.bx
08049ef8 d __init_array_end
08049ef8 d __init_array_start
08048740 T __libc_csu_fini
08048750 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804a02c A _edata
0804a0d8 A _end
080487dc T _fini
080487f8 R _fp_hw
08048508 T _init
080485e0 T _start
0804a0cc b completed.7065
0804a024 W data_start
0804a0d0 b dtor_idx.7067
08048670 t frame_dummy
08048694 T main

上面便是test这个程序中所有的符号,首先需要介绍一下上面的内容的格式:
第一列:当前符号的地址
第二列:当前符号的类型(关于类型的说明,感兴趣的朋友可以man nm详阅)
第三列:当前符号的名称

在上面的结果中,像_ZN4Test5HelloEv这样的符号,很多读者朋友可能会被它搞晕,这里介绍个小技巧,在nm的时候,加上-C选项,就可以把这些难以识别的符号,转换成便于我们阅读的符号TestHello()。这个主要是c++中的mangle机制所导致的,加上-C就是指定列出的符号是demangle了的。说了这么多,到底nm对我们程序有啥具体的帮助呢,我觉得主要有以下几个方面:
(1)判断指定程序中有没有定义指定的符号 (比较常用的方式:nm -C proc | grep symbol)
(2)解决程序编译时undefined reference的错误,以及mutiple definition的错误
(3)查看某个符号的地址,以及在进程空间的大概位置(bss, data, text区,具体可以通过第二列的类型来判断)
luyanxi@ubuntu:~/Desktop/nvr/nvr_2025/sstar931/toolchain/bin$ ls arm-sigmastar-linux-uclibcgnueabihf-9.1.0-addr2line arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcc-ranlib arm-sigmastar-linux-uclibcgnueabihf-9.1.0-populate arm-sigmastar-linux-uclibcgnueabihf-elfedit arm-sigmastar-linux-uclibcgnueabihf-ld.bfd arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ar arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcov arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ranlib arm-sigmastar-linux-uclibcgnueabihf-g++ arm-sigmastar-linux-uclibcgnueabihf-ldd arm-sigmastar-linux-uclibcgnueabihf-9.1.0-as arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcov-dump arm-sigmastar-linux-uclibcgnueabihf-9.1.0-readelf arm-sigmastar-linux-uclibcgnueabihf-gcc arm-sigmastar-linux-uclibcgnueabihf-libc.config arm-sigmastar-linux-uclibcgnueabihf-9.1.0-c++ arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcov-tool arm-sigmastar-linux-uclibcgnueabihf-9.1.0-size arm-sigmastar-linux-uclibcgnueabihf-gcc-9.1.0 arm-sigmastar-linux-uclibcgnueabihf-nm arm-sigmastar-linux-uclibcgnueabihf-9.1.0-cc arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gdb arm-sigmastar-linux-uclibcgnueabihf-9.1.0-strings arm-sigmastar-linux-uclibcgnueabihf-gcc-ar arm-sigmastar-linux-uclibcgnueabihf-objcopy arm-sigmastar-linux-uclibcgnueabihf-9.1.0-c++filt arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gdb-add-index arm-sigmastar-linux-uclibcgnueabihf-9.1.0-strip arm-sigmastar-linux-uclibcgnueabihf-gcc-nm arm-sigmastar-linux-uclibcgnueabihf-objdump arm-sigmastar-linux-uclibcgnueabihf-9.1.0-cpp arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gprof arm-sigmastar-linux-uclibcgnueabihf-addr2line arm-sigmastar-linux-uclibcgnueabihf-gcc-ranlib arm-sigmastar-linux-uclibcgnueabihf-populate arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ct-ng.config arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ld arm-sigmastar-linux-uclibcgnueabihf-ar arm-sigmastar-linux-uclibcgnueabihf-gcov arm-sigmastar-linux-uclibcgnueabihf-ranlib arm-sigmastar-linux-uclibcgnueabihf-9.1.0-elfedit arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ld.bfd arm-sigmastar-linux-uclibcgnueabihf-as arm-sigmastar-linux-uclibcgnueabihf-gcov-dump arm-sigmastar-linux-uclibcgnueabihf-readelf arm-sigmastar-linux-uclibcgnueabihf-9.1.0-g++ arm-sigmastar-linux-uclibcgnueabihf-9.1.0-ldd arm-sigmastar-linux-uclibcgnueabihf-c++ arm-sigmastar-linux-uclibcgnueabihf-gcov-tool arm-sigmastar-linux-uclibcgnueabihf-size arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcc arm-sigmastar-linux-uclibcgnueabihf-9.1.0-libc.config arm-sigmastar-linux-uclibcgnueabihf-cc arm-sigmastar-linux-uclibcgnueabihf-gdb arm-sigmastar-linux-uclibcgnueabihf-strings arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcc-9.1.0 arm-sigmastar-linux-uclibcgnueabihf-9.1.0-nm arm-sigmastar-linux-uclibcgnueabihf-c++filt arm-sigmastar-linux-uclibcgnueabihf-gdb-add-index arm-sigmastar-linux-uclibcgnueabihf-strip arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcc-ar arm-sigmastar-linux-uclibcgnueabihf-9.1.0-objcopy arm-sigmastar-linux-uclibcgnueabihf-cpp arm-sigmastar-linux-uclibcgnueabihf-gprof nvrfault.1061.11.1757325811.core arm-sigmastar-linux-uclibcgnueabihf-9.1.0-gcc-nm arm-sigmastar-linux-uclibcgnueabihf-9.1.0-objdump arm-sigmastar-linux-uclibcgnueabihf-ct-ng.config arm-sigmastar-linux-uclibcgnueabihf-ld luyanxi@ubuntu:~/Desktop/nvr/nvr_2025/sstar931/toolchain/bin$ arm-sigmastar-linux-uclibcgnueabihf-gdb arm-sigmastar-linux-uclibcgnueabihf-gdb: command not found luyanxi@ubuntu:~/Desktop/nvr/nvr_2025/sstar931/toolchain/bin$ arm-sigmastar-linux-uclibcgnueabihf-gdb nvrfault.1061.11.1757325811.core arm-sigmastar-linux-uclibcgnueabihf-gdb: command not found
最新发布
09-09
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值