必须同时具备core文件和带调试符号的可执行文件,缺一不可;core需为匹配的elf格式,可执行文件须含-g编译的.debug段,否则gdb无法解析堆栈与源码行。

必须同时具备的两个文件
只靠 core 文件或只靠可执行文件,GDB 都无法还原出有意义的堆栈和源码行。缺一不可。
-
core文件本身必须是有效的 ELF core file(用file core-xxx验证),且与崩溃时运行的进程完全匹配——程序名、PID、架构(x86_64/arm64)都要对得上; - 对应的可执行文件必须带调试符号(即编译时加了
-g),不能被strip过;若用readelf -S ./your_program | grep debug查不到.debug_*段,GDB 就会显示(no debugging symbols found),bt只能输出??:?。
为什么“同名但不同编译版本”的可执行文件不行
哪怕文件名、大小、甚至 md5sum 都一样,只要编译时间、优化等级(-O2 vs -O0)、宏定义或链接顺序稍有差异,调试符号与内存布局就可能错位。GDB 加载时若提示 not compatible,基本就是这个原因。
- 常见诱因:线上部署的是 release 版本(无
-g,已strip),而你拿本地刚编译的 debug 版去加载远程core; - 验证方法:在 GDB 启动后执行
info files,对比core中记录的 program path 与你传入的可执行文件路径是否一致;再用readelf -n core-xxx | grep -A2 PRPSINFO提取实际崩溃程序名,确认没被重命名或替换成 wrapper 脚本。
额外但强烈建议准备的文件
没有它们不影响 bt 或寄存器查看,但会让定位根因变困难。
- 原始源码(.c/.cpp 文件):GDB 的
list、print依赖它,否则只能看汇编; - 对应版本的调试符号分离文件(如
your_program.debug或.gnu_debuglink指向的外部 debuginfo):适用于生产环境不能放完整 debug 版可执行文件的场景; -
/proc/<pid>/maps</pid>快照(如果崩溃前能捕获):有助于判断共享库地址偏移是否与core中记录的一致,尤其当使用ASLR时。
容易被忽略的关键点
很多人卡在“明明有 -g 编译,GDB 却不认”,问题往往不在 core 或可执行文件本身,而在路径和权限。
-
core文件需有读权限,且不能被chmod 000锁死; - 若
core_pattern指向绝对路径(如/var/crash/core.%e.%p),确保该目录存在、可写,且 SELinux/AppArmor 没拦截(ausearch -m avc -ts recent可查); - GDB 默认不自动加载当前目录下的符号文件,若源码不在可执行文件所在目录,需手动用
directory /path/to/src告知路径。











