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

GDB分析剥离动态库的Core Dump时符号函数名错误是否正常?

问题描述

正常回溯信息(本地复现)

#0  0x00007f06ff7e96ad in Numbers::AddOne(int) () from libnums.so
#1  0x00007f06ff7e968d in Numbers::AddTwo(int, int) () from libnums.so
#2  0x00007f06ff7e9668 in Numbers::AddThree(int, int, int) () from libnums.so
#3  0x000055ae3a2a67ec in ?? ()
#4  0x00007f06feadac87 in __libc_start_main (main=0x55ae3a2a67ba, argc=1, argv=0x7ffd3e8f5eb8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffd3e8f5ea8) at ../csu/libc-start.c:310
#5  0x000055ae3a2a66da in ?? ()

确认二进制已剥离

通过info sharedlibrary验证:

0x00007f06ff7e9560  0x00007f06ff7e96b1  Yes (*)     libnums.so

生产环境Core Dump异常表现(恢复符号前)

#0  0x00007f06ff7e96ad in Numbers::SomeFunctionElsewhere() () from libnums.so
#1  0x00007f06ff7e968d in Numbers::MultiplyFive() () from libnums.so
#2  0x00007f06ff7e9668 in Numbers::DivideByZero() () from libnums.so

注意:所有函数参数类型完全消失,且函数名被错误映射

核心疑问

  • 上述现象是否完全正常?还是符号剥离/保存流程存在错误?
  • 将.so与对应.so.debug文件合并能否解决问题?
  • 该现象是否与-rdynamic或-fPIC编译选项有关?

当前符号剥离流程(遗留脚本)

objcopy --only-keep-debug $filename  $outFolder/$filename.debug
strip --strip-debug --strip-unneeded $filename
# Default links for debug symbol files already exist for libc* and friends.  If you
# don't remove them first, you'll get an "Invalid operation" error
objcopy --remove-section=.gnu_debuglink $filename
objcopy --add-gnu-debuglink=$outFolder/$filename.debug $filename

符号合并使用的命令

eu-unstrip x.so x.so.debug -o x.so

开发环境补充测试情况

成功复现两种矛盾现象:

  1. 添加符号文件获取行号,但丢失参数信息:
    在.gdbinit中配置:

    add-symbol-file mylib.so.debug 0xdeadbeef
    

    回溯结果:

    #0  0x00007f06ff7e96ad in Numbers::AddThree(NO PARAM INFO) () from test.cpp:123
    

    使用eu-unstrip合并符号后,结果完全一致。

  2. 不添加符号文件,无法获取行号,但参数信息正常:

    #0  0x00007f06ff7e96ad in Numbers::AddThree(int, int, int) () from libnums.so
    

问题解答

1. 异常现象是否正常?符号流程是否有误?

生产环境中出现函数名错误映射+参数丢失的情况不正常,说明符号剥离/保存流程存在问题,导致调试符号与剥离后的二进制无法正确关联。

开发环境的矛盾现象是因为:单独加载.debug文件时,GDB无法正确关联二进制中的动态符号表信息——参数类型实际来自二进制的动态符号表(未被strip --strip-unneeded移除的部分),而调试符号文件提供行号等信息,但如果关联方式错误,GDB会优先使用调试符号中的函数信息,却无法匹配到动态符号表的参数数据。

2. 合并.so与.so.debug能否解决问题?

如果.so.debug文件是正确生成的,合并操作应该能解决问题,但前提是合并过程正确。你的eu-unstrip命令本身没问题,若合并后仍出现参数丢失,说明原始符号剥离流程可能破坏了动态符号表,或者.so.debug与剥离后的.so不匹配。

3. 与-rdynamic或-fPIC的关系?

  • -fPIC是编译共享库的必要选项,只要共享库能正常加载,该选项就与符号问题无关。
  • -rdynamic会导出更多符号到动态符号表,C++的函数参数类型是通过名字改编(mangling)存储在动态符号表中的。你开发环境中不加载符号文件时能看到参数,说明编译流程已经导出了足够的符号,该选项不是问题根源。

符号剥离流程修正建议

现有流程中strip --strip-debug --strip-unneeded会移除动态符号表中“不必要”的符号,但可能误删C++函数签名对应的关键信息。建议调整:

  • 将strip --strip-debug --strip-unneeded改为strip --strip-debug,保留完整动态符号表,确保回溯时能解析参数类型。
  • 确认objcopy --only-keep-debug生成的.so.debug与剥离后的.so是同一编译产物,未经过其他修改。

开发环境矛盾现象的解释

直接使用剥离后的.so时,GDB从动态符号表解析经过名字改编的函数名,反推出参数类型;手动用add-symbol-file加载.so.debug时,若基地址不正确或符号无法对应,就会出现“能看到行号但丢失参数”的情况。正确做法是依赖流程中添加的.gnu_debuglink,只要.so.debug放在GDB能找到的路径,GDB会自动关联,同时获取行号和参数信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:05:32