很多发行版会将包含调试符号信息的文件拆分到另外的安装包里,所以相应的wiki也会教你遇到进程崩溃时,如何获取完整的调用栈信息,其中一步便是安装带有调试信息的软件包,比如这里、这里。
至于为什么可以这么做,这其实是GDB的机制。按照这里的描述,GDB支持独立于可执行文件的调试符号信息。
从一个二进制文件产生调试信息文件很简单,只需要执行:
1 | $ objcopy --only-keep-debug execfile execfile.debug |
然后可以把原文件的调试符号等信息删除:
1 | $ strip -s execfile |
但此时如果用gdb调试,它并不能正确地找到调试信息。还需要针对可执行文件添加一个调试信息文件的引用信息:
1 | $ objcopy --add-gnu-debuglink=execfile.debug execfile |
通过readelf可以看到原文件多了一个.gnu_debuglink的段:
1 | $ readelf --headers execfile | grep .gnu_debuglink |
在此之后,其实可以将execfile.debug放到其他位置去,gdb也能加载到,假设execfile所在目录为/path,可以:
1 | $ sudo mv execfile.debug /usr/lib/debug/path/ |
该路径通过gdb的debug-file-directory变量控制。这只是其中一个查找路径,实际比这复杂。
另外,通过readelf -w
可以查看.gnu_debuglink段的信息,它也会自动查找调试文件,但是目录规则和gdb却是不一样的。共同点是都会去查找execfile所在目录的execfile.debug文件。