LD_DEBUG环境变量 (2012)
摘要
解释如何在Linux上使用LD_DEBUG环境变量来调试共享库加载问题,包含示例和相关工具。
暂无内容
查看缓存全文
缓存时间: 2026/06/10 00:22
# LD_DEBUG 环境变量
来源:https://bnikolic.co.uk/blog/linux-ld-debug.html
*2012年4月23日首次发布,2019年9月10日更新(添加问题排查工具链接),2019年10月18日更新(迁移至 Jekyll),2023年4月3日更新(添加其他工具链接)*
开发使用大量共享(动态)加载库的大型系统时,有时会遇到一些令人沮丧且难以诊断的错误。这些错误通常源于系统上存在多个不同版本的库,而加载的是“错误”版本,而非开发者想要的版本。
> ***注意***您可能还会发现我的在线工具(用于诊断 Linux 链接器问题)很有用:http://linkdemo.carabinerweb.s3-website-us-east-1.amazonaws.com/ 它以专家系统实现。撰写此文时正在扩展,但可能已经有用。
过去,我经常使用 `strace` 命令(man strace (http://linux.die.net/man/1/strace))来有效调试这些问题,通过检查哪些库被访问。然而,有一种更高效但可能不太为人所知的调试共享库加载问题的方法:`LD_DEBUG` 环境变量。
如果设置了 `LD_DEBUG` 变量,Linux 动态链接器将输出调试信息,这些信息可以非常快速地解决大多数加载问题。要查看可用选项,只需用 `help` 值运行任何程序,例如:
``
LD_DEBUG=help cat
Valid options for the LD_DEBUG environment variable are:
libs display library search paths
reloc display relocation processing
files display progress for input file
symbols display symbol table processing
bindings display information about symbol binding
versions display version dependencies
all all previous options combined
statistics display relocation statistics
unused determined unused DSOs
help display this help message and exit
To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment
variable.
``
> ***注意***还有许多其它有用的工具可以处理链接问题:1. `strace` (https://linux.die.net/man/1/strace) 程序提供所有系统调用的洞察,包括搜索、打开动态库 2. `ldd` (https://linux.die.net/man/1/ldd) 程序解析动态库依赖 3. `objdump -x YOURFILE | grep NEEDED` 命令列出程序或库中需要哪些其它库的记录 4. `patchelf` (https://github.com/NixOS/patchelf) 程序可以轻松更改 ELF 可执行文件的 `rpath`,从而改变内建搜索顺序 5. `LD_PRELOAD` (https://bnikolic.co.uk/blog/hpc-ldpreload-speedoptimisation) 环境变量可以轻松替换动态库。需要进一步帮助?凭借 20 多年的经验,我们独具优势——请联系我们:[email protected]
> ***注意***此变量仅 Linux 可用。在 MS Windows 上,可以通过启用 *“Show Loader Snaps”* (https://abitofscotland.wordpress.com/2019/12/20/dll-load-failure/) 来获取类似信息,使用 `gflags.exe` 程序启用该功能,然后使用 `windbg` 查看日志。例如:1. 安装包含 `gflags` 和 `windbg` 的 Windows SDK:`winget install Microsoft.WindowsSDK.10.0.19041` (或从 Microsoft 网站下载 (https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools)) 2. 为可执行文件启用 ShowLoaderSnaps。例如,在 Powershell 中为 `notepad.exe` 启用:`&"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /i notepad.exe +sls` 3. 在 WinDbg 应用下执行 `notepad.exe`。将显示详细的 DLL 加载日志
以下是我笔记本电脑上的运行示例:
``
LD_DEBUG=all cat
28504:
28504: file=libc.so.6 [0]; needed by cat [0]
28504: find library=libc.so.6 [0]; searching
28504: search path=/home/bnikolic/s/lib/tls/x86_64:/home/bnikolic/s/lib/tls:/home/bnikolic/s/lib/x86_64:/home/bnikolic/s/lib:tls/x86_64:tls:x86_64::/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/x86_64:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/x86_64:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib (LD_LIBRARY_PATH)
28504: trying file=/home/bnikolic/s/lib/tls/x86_64/libc.so.6
28504: trying file=/home/bnikolic/s/lib/tls/libc.so.6
28504: trying file=/home/bnikolic/s/lib/x86_64/libc.so.6
28504: trying file=/home/bnikolic/s/lib/libc.so.6
28504: trying file=tls/x86_64/libc.so.6
28504: trying file=tls/libc.so.6
28504: trying file=x86_64/libc.so.6
28504: trying file=libc.so.6
28504: trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/x86_64/libc.so.6
28504: trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/libc.so.6
28504: trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/x86_64/libc.so.6
28504: trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/libc.so.6
28504: search cache=/etc/ld.so.cache
28504: trying file=/lib/x86_64-linux-gnu/libc.so.6
28504:
28504: file=libc.so.6 [0]; generating link map
28504: dynamic: 0x00007fc38e525b40 base: 0x00007fc38e18c000 size: 0x00000000003a0368
28504: entry: 0x00007fc38e1ad420 phdr: 0x00007fc38e18c040 phnum: 10
28504:
28504: checking for version `GLIBC_2.4' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
28504: checking for version `GLIBC_2.3' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
28504: checking for version `GLIBC_2.3.4' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
28504: checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
28504: checking for version `GLIBC_2.3' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
28504: checking for version `GLIBC_PRIVATE' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
28504:
28504: relocation processing: /lib/x86_64-linux-gnu/libc.so.6 (lazy)
28504: symbol=_res; lookup in file=cat [0]
28504: symbol=_res; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_res' [GLIBC_2.2.5]
28504: symbol=_IO_file_close; lookup in file=cat [0]
28504: symbol=_IO_file_close; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_IO_file_close' [GLIBC_2.2.5]
28504: symbol=stderr; lookup in file=cat [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to cat [0]: normal symbol `stderr' [GLIBC_2.2.5]
28504: symbol=error_one_per_line; lookup in file=cat [0]
28504: symbol=error_one_per_line; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `error_one_per_line' [GLIBC_2.2.5]
28504: symbol=__malloc_initialize_hook; lookup in file=cat [0]
28504: symbol=__malloc_initialize_hook; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__malloc_initialize_hook' [GLIBC_2.2.5]
28504: symbol=__morecore; lookup in file=cat [0]
28504: symbol=__morecore; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__morecore' [GLIBC_2.2.5]
28504: symbol=__key_encryptsession_pk_LOCAL; lookup in file=cat [0]
28504: symbol=__key_encryptsession_pk_LOCAL; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__key_encryptsession_pk_LOCAL' [GLIBC_2.2.5]
28504: symbol=__progname_full; lookup in file=cat [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to cat [0]: normal symbol `__progname_full' [GLIBC_2.2.5]
28504: symbol=__ctype32_tolower; lookup in file=cat [0]
28504: symbol=__ctype32_tolower; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__ctype32_tolower' [GLIBC_2.2.5]
28504: symbol=__key_gendes_LOCAL; lookup in file=cat [0]
28504: symbol=__key_gendes_LOCAL; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__key_gendes_LOCAL' [GLIBC_2.2.5]
28504: symbol=_environ; lookup in file=cat [0]
28504: symbol=_environ; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_environ' [GLIBC_2.2.5]
28504: symbol=_rtld_global; lookup in file=cat [0]
28504: symbol=_rtld_global; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: symbol=_rtld_global; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib64/ld-linux-x86-64.so.2 [0]: normal symbol `_rtld_global' [GLIBC_PRIVATE]
28504: symbol=__progname; lookup in file=cat [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to cat [0]: normal symbol `__progname' [GLIBC_2.2.5]
28504: symbol=argp_err_exit_status; lookup in file=cat [0]
28504: symbol=argp_err_exit_status; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `argp_err_exit_status' [GLIBC_2.2.5]
28504: symbol=mallwatch; lookup in file=cat [0]
28504: symbol=mallwatch; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `mallwatch' [GLIBC_2.2.5]
28504: symbol=__rcmd_errstr; lookup in file=cat [0]
28504: symbol=__rcmd_errstr; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__rcmd_errstr' [GLIBC_2.2.5]
28504: symbol=svcauthdes_stats; lookup in file=cat [0]
28504: symbol=svcauthdes_stats; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `svcauthdes_stats' [GLIBC_2.2.5]
28504: symbol=__libc_enable_secure; lookup in file=cat [0]
28504: symbol=__libc_enable_secure; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: symbol=__libc_enable_secure; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib64/ld-linux-x86-64.so.2 [0]: normal symbol `__libc_enable_secure' [GLIBC_PRIVATE]
28504: symbol=_res_hconf; lookup in file=cat [0]
28504: symbol=_res_hconf; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_res_hconf' [GLIBC_2.2.5]
28504: symbol=malloc; lookup in file=cat [0]
28504: symbol=malloc; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `malloc' [GLIBC_2.2.5]
28504: symbol=getdate_err; lookup in file=cat [0]
28504: symbol=getdate_err; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `getdate_err' [GLIBC_2.2.5]
28504: symbol=__tzname; lookup in file=cat [0]
28504: symbol=__tzname; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__tzname' [GLIBC_2.2.5]
28504: symbol=__timezone; lookup in file=cat [0]
28504: symbol=__timezone; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__timezone' [GLIBC_2.2.5]
28504: symbol=_rtld_global_ro; lookup in file=cat [0]
28504: symbol=_rtld_global_ro; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: symbol=_rtld_global_ro; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib64/ld-linux-x86-64.so.2 [0]: normal symbol `_rtld_global_ro' [GLIBC_PRIVATE]
28504: symbol=optarg; lookup in file=cat [0]
28504: symbol=optarg; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `optarg' [GLIBC_2.2.5]
28504: symbol=__ctype_tolower; lookup in file=cat [0]
28504: symbol=__ctype_tolower; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__ctype_tolower' [GLIBC_2.2.5]
28504: symbol=__ctype_toupper; lookup in file=cat [0]
28504: symbol=__ctype_toupper; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__ctype_toupper' [GLIBC_2.2.5]
28504: symbol=svc_max_pollfd; lookup in file=cat [0]
28504: symbol=svc_max_pollfd; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `svc_max_pollfd' [GLIBC_2.2.5]
28504: symbol=__ctype_b; lookup in file=cat [0]
28504: symbol=__ctype_b; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__ctype_b' [GLIBC_2.2.5]
28504: symbol=argp_program_version_hook; lookup in file=cat [0]
28504: symbol=argp_program_version_hook; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `argp_program_version_hook' [GLIBC_2.2.5]
28504: symbol=__after_morecore_hook; lookup in file=cat [0]
28504: symbol=__after_morecore_hook; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__after_morecore_hook' [GLIBC_2.2.5]
28504: symbol=__environ; lookup in file=cat [0]
28504: symbol=__environ; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__environ' [GLIBC_2.2.5]
28504: symbol=__ctype32_b; lookup in file=cat [0]
28504: symbol=__ctype32_b; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__ctype32_b' [GLIBC_2.2.5]
28504: symbol=__curbrk; lookup in file=cat [0]
28504: symbol=__curbrk; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `__curbrk' [GLIBC_2.2.5]
28504: symbol=argp_program_version; lookup in file=cat [0]
28504: symbol=argp_program_version; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
28504: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `argp_program_version' [GLIBC_2.2.5]
28504: symbol=__d
相似文章
在dsymutil中采用并行DWARF链接器
苹果的dsymutil工具用于将DWARF调试信息链接到自包含的捆绑包中,现在正在采用并行DWARF链接器来解决类型去重中的单线程瓶颈,尽管由于输出并非二进制完全相同而在验证方面面临挑战。
AgentDebugX:用于LLM Agent故障可观测性、归因和恢复的开源工具包
AgentDebugX 是一个面向 LLM Agent 的开源调试框架,将故障调试组织为检测、归因、恢复和重试的闭环。其核心组件 DeepDebug 在基准测试中实现了强大的归因准确性和修复能力。
精准调试基准:你的模型在调试还是在重写?
# 论文页面 - 精准调试基准:你的模型在调试还是在重写? 来源:[https://huggingface.co/papers/2604.17338](https://huggingface.co/papers/2604.17338) ## 摘要 前沿大模型在测试通过率上表现优异,但在调试任务中的精准度却很低,暴露出功能正确与精准定位缺陷之间的鸿沟。与代码补全不同,调试需定位错误并做针对性修改。我们观察到,前沿大模型在调试时往往重写出正确却过度修改的代码。
被低估的内置功能:Grand Unified Debugger
本文重点介绍了Emacs内置的Grand Unified Debugger(GUD)的功能,强调了其多调试器支持和图形化GDB界面,包括通过点击边缘设置断点以及单步执行代码等功能。
模拟器调试:Area 5150 的 Lake Effect
本文详细介绍了在MartyPC模拟器上调试Area5150演示中“Lake”效应的过程,解释了需要特定标题hack的原因,以及通过总线嗅探和动态时钟实现周期精确CGA模拟的后续修复方法。