>> >> >> Reference << << << <<<<<<Ref>>>>>>
>> >> >> Indexer << << << <<<<<<Idx>>>>>>
Matched: 0

Tags

    Categories

      Types

        Top Results

          ldd
          M: 2026-04-24 - ljf12825

          ldd全称List Dynamic Dependencies,是Linux命令行工具
          它的核心功能是打印一个可执行程序或共享库所依赖的共享库列表

          基本用法

          ldd <可执行文件的路径>
          

          输出

          linux-vdso.so.1 (0x0000717dff500000)
          libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x0000717dff48f000)
          libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000717dff200000)
          libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x0000717dff166000)
          /lib64/ld-linux-x86-64.so.2 (0x0000717dff502000)
          
          输出部分含义
          libselinux.so.1程序需要的动态库名称
          =>指向符号,表示“解析到了哪里”
          /lib/x86_64...实际加载的文件路径。如果这里显示not found,说明程序启动会因缺少库而报错
          (0x00007f...)加载地址。这是库被映射到虚拟内存中的起始位置

          特殊输出

          • linux-vdso.so.1 这不是一个真实的文件,它是Linux内核直接映射进用户空间的一段代码,用于加速系统调用(如gettimeofday),不需要担心找不到它
          • /lib64/ld-linux-x86-64.so.2:动态链接器本身,这个程序能运行,首先要靠它来加载其他库。如果这个不存在,系统基本就瘫痪了
          • not found:这是最需要关注的状态,意味着程序依赖的库不再标准搜索路径或LD_LIBRARY_PATH

          常用参数

          | 参数 | 作用 | 典型场景 | | -v | 冗余模式 | verbose | | -u | 显示未使用的直接依赖 | 清理编译链接时多余指定的-l选项 | | -d | 执行重定位并报告缺失函数 | 比普通的ldd更深入,能发现R_X86_64_JUMP_SLOT无法解析的错误 | | -r | 执行函数和数据重定位 | 综合-d-u的功能,检查是否有符号未定义 |

          警告

          不要对不信任的文件使用ldd

          虽然man ldd说它只是运行LD_TRACE_LOADED_OBJECTS=1环境变量下的程序,但在某些实现中(或对于某些特殊构建的恶意程序),直接执行ldd ./可疑文件会运行该文件的初始化代码

          这可能出现恶意代码可以在你仅想“查看依赖”时直接获得你当前用户的Shell权限

          安全替代方案

          # 使用 objdump 查看依赖(完全静态分析,不执行代码)
          objdump -p /path/to/binary | grep NEEDED
          
          # 或者使用 readelf
          readelf -d /path/to/binary | grep 'NEEDED'
          

          原理

          理解ldd的输出内容,其实就是理解了Linux加载程序的第一步

          1. 内核识别:发现文件是ELF格式,查看.interp段,找到解释器路径(如/lib64/ld-linux-x86-64.so.2
          2. 解释器启动:内核将控制权交给这个ld-linux解释器
          3. 解析依赖:解释器读取ELF文件的.dynamic段,找到DT_NEEDED条目(即ldd打印出来的库名)
          4. 搜索路径:按照以下顺序查找库文件
            • 环境变量LD_LIBRARY_PATH
            • 缓存文件:/etc/ld.so.cache
            • 系统默认路径/lib, /usr/lib
          5. 映射内存:找到后将库加载到内存地址(即ldd括号里的数字)

          示例

          查看普通程序的依赖

          ldd /usr/bin/curl
          

          输出

          linux-vdso.so.1 (0x00007ffe5bdf0000)
          libcurl.so.4 => /usr/lib/x86_64-linux-gnu/libcurl.so.4 (0x00007f5a3c000000)
          libssl.so.3 => /usr/lib/x86_64-linux-gnu/libssl.so.3 (0x00007f5a3c800000)
          libcrypto.so.3 => /usr/lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007f5a3b800000)
          libc.so.6 => /usr/lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a3b400000)
          /lib64/ld-linux-x86-64.so.2 (0x00007f5a3d000000)
          

          每行都有=>指向具体路径,没有not foundcurl依赖libcurl, OpenSSL等,链接器都能正常找到

          缺少依赖库

          假设有一个第三方程序my_tool,直接运行报错

          ./my_tool: error while loading shared libraries: libfoo.so.1: cannot open shared object file: No such file or directory
          

          ldd查看

          ldd ./my_tool
          

          输出

          linux-vdso.so.1 (0x00007ffd9b5e6000)
          libfoo.so.1 => not found
          libc.so.6 => /usr/lib/x86_64-linux-gnu/libc.so.6 (0x00007f8e2a400000)
          /lib64/ld-linux-x86-64.so.2 (0x00007f8e2a800000)
          

          关键信息:libfoo.so.1 => not found
          排查方向:

          1. 检查库文件是否真的在系统里:find /usr /opt -name "libfoo.so*"
          2. 如果存在但没被找到,临时添加路径:export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH

          架构不匹配导致的not found

          在64位系统上运行一个32位程序,file命令显示

          file ./old_32bit_app
          # ./old_32bit_app: ELF 32-bit LSB executable, Intel 80386 ...
          

          ldd输出

          ldd ./old_32bit_app
          

          输出

              linux-gate.so.1 (0xf7f5d000)
              libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7d00000)
              /lib/ld-linux.so.2 (0xf7f5f000)
          

          如果输出中任然有not found(尤其是libc),说明没有安装32位兼容库

          使用-r检查缺失的函数符号(运行时symbol lookup error)

          程序能启动,但运行到某个功能时崩溃,报错

          ./my_app: symbol lookup error: /usr/lib/libcustom.so: undefined symbol: calculate_offset
          

          这表示库文件存在,但库里面缺少某个函数。用ldd -r可以提前发现

          ldd -r ./my_app
          

          输出

          linux-vdso.so.1 (0x00007ffd2f3e5000)
          libcustom.so.1 => /usr/lib/libcustom.so.1 (0x00007f1234000000)
          libc.so.6 => /usr/lib/libc.so.6 (0x00007f1233c00000)
          /lib64/ld-linux-x86-64.so.2 (0x00007f1234200000)
          undefined symbol: calculate_offset    (./my_app)
          

          -r参数执行了重定位检查,直接指出了undefined symbol: calculate_offset,问题一目了然

          -u找出编译时多余的链接(清理Makefile)

          假设在编译程序时在Makefile里写了-lm -lpthread -ldl,但实际上只用到了pthread。用-u可以找出那些”声明了但没用上“的直接依赖

          ldd -u ./my_app
          

          输出

          Unused direct dependencies:
              /usr/lib/libm.so.6
              /usr/lib/libdl.so.2
          

          这表示编译时可以去掉-lm-ldl,让程序更精简,启动稍快一些

          lddtree

          如果需要可视化复杂的依赖树(即A依赖B,B又依赖C),普通ldd是扁平列表,不够直观,可以使用pax-utils包中的lddtree

          apt install pax-utils
          lddtree /bin/ls
          

          输出会以树状结构展开,清晰展示哪些库是共享的、哪些是被间接引入的

          /bin/ls (interpreter => /lib64/ld-linux-x86-64.so.2)
              libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1
                  libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0
              libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
          

          ldd using