You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享对象libirc.so链接异常与LD_PRELOAD段错误排查

问题背景

我有一个共享对象libirc.so,file命令显示它是正常的动态共享对象:

% file libirc.so
libirc.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=9d54bda46b31ae048aae323dfd809f9ae6c8c55c, not stripped
%

但ldd命令却显示它是静态链接的:

% ldd libirc.so
    statically linked
%

直接运行依赖它的可执行文件./Solver一切正常,但通过LD_PRELOAD="io_functions.so"运行时,动态链接器/lib64/ld-linux-x86-64.so.2会输出错误信息并触发段错误:

./Solver: Relink `./lib/libirc.so' with `/lib64/libc.so.6' for IFUNC symbol `memmove'

将libirc.so加入LD_PRELOAD后问题即可解决。通过LD_DEBUG分析发现:

  • 成功场景(LD_PRELOAD包含libirc.so):libstdc++和libirc.so均从/lib64/libc.so.6获取memmove
  • 失败场景(LD_PRELOAD不含libirc.so):libirc.so同样从libc.so.6找到memmove,但仍会触发重链接提示并段错误

核心疑问:为何两种场景下memmove的来源完全一致,运行结果却截然不同?

原因分析

这本质是IFUNC符号的解析时机与链接顺序冲突导致的问题,和libirc.so的特殊构建方式直接相关:

  1. libirc.so的真实构建属性:file标记为动态链接但ldd显示静态链接,说明这个共享对象是用部分静态链接方式构建的——它将libc的大部分代码静态嵌入自身,但保留了动态链接libc的符号表入口,这种“半静态半动态”的状态会干扰动态链接器的正常处理逻辑。

  2. IFUNC符号的特殊性:memmove是典型的IFUNC符号(用于动态选择最优硬件实现的符号),它的解析时机晚于普通符号,需要动态链接器在完成基础符号绑定后,再执行一次符号重定向。

  3. 加载顺序对链接逻辑的影响:

    • 当libirc.so不在LD_PRELOAD时,io_functions.so会被优先加载,先完成对libcmemmove的绑定。后续加载libirc.so时,由于它自身嵌入了静态libc代码片段,动态链接器会误判它的memmove为静态实现,触发“重链接到系统libc IFUNC版本”的逻辑,但此时全局符号绑定已经完成,强行重定向会破坏内存布局,最终导致段错误。
    • 当libirc.so在LD_PRELOAD时,它会被第一个加载,动态链接器优先处理它的符号绑定。此时系统libc的IFUNC版本未被其他库占用,链接器能正确识别libirc.so需要从系统libc获取memmove,后续加载io_functions.so时直接复用已绑定的符号,不会触发异常重链接逻辑。

简言之:加载顺序决定了动态链接器对libirc.so符号属性的判断逻辑,虽然最终memmove都来自系统libc,但解析时机和链接阶段的全局状态不同,导致了两种完全不同的运行结果。

内容的提问来源于stack exchange,提问作者bauerjlb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 16:05:01