这是一个悲伤的故事:
- 我在我的机器上构建了一个可执行文件
thedarkmod.x64
,将调试符号移到了一个单独的thedarkmod.x64.debug
文件中。 - 用户在 gdb 下运行此可执行文件时遇到了崩溃。
core.1600
她使用generate-core-file
gdb 命令保存了核心转储。 - 我下载了这个核心文件并通过启动
gdb ./thedarkmod.x64 core.1600
. - 我在线程之间切换并运行
bt
命令,但我看到一些垃圾而不是正确的堆栈跟踪。
注意:用户有我的thedarkmod.x64.debug
文件,当她bt
在保存核心转储之前运行时,她会看到有意义的堆栈跟踪。
当我在核心转储上启动 gdb 时,我看到许多警告消息,例如:
- 找不到与inferior的线程库匹配的libthread_db,线程调试将无法使用
- 警告:“libXXX.so”的 .dynamic 部分不在预期的地址(错误的库或版本不匹配?)
根据这个问题,第一个警告似乎暗示除非我与libthread_db.so.1
保存核心转储的机器上的版本相同,否则我在多线程程序中看不到任何有用的东西。我让用户找到这个文件并把它交给我,但它没有帮助。然后我也要求提供libpthread.so.0
文件,经过一番苦苦挣扎后,set solib-search-path
我设法用“启用了 libthread_db 的线程调试”替换了这个警告,但堆栈跟踪仍然是错误的。set sysroot
set auto-load safe-path
set libthread-db-search-path
所以问题是:
- 有没有办法正确检查在环境截然不同的 Linux 机器上生成的核心转储?我的意思是不同的内核、pthreads、glibc 等。有没有关于如何实现的详细说明?
- 是否有任何类似的 gdb 命令
generate-core-file includecode
,它将所有代码(包括必要的 .so 库)嵌入到核心文件中,以便我可以在我的机器上打开它而无需额外的麻烦?
目前,我不得不承认 Linux 核心转储对我来说毫无用处,因为我还没有准备好为每个提交的核心转储创建一个新的 Linux 虚拟机。
更新:我设法获得了正确的堆栈跟踪。
- “重复问题”中提供的解决方案对我不起作用。没有与 solib 相关的设置就足够了,只有
set sysroot
帮助。 - 在我的特殊情况下,堆栈跟踪在
free
libc 的函数内结束。Gdb 无法遍历它的调用堆栈,可能是因为它-fomit-frame-pointer
像大多数库一样编译。确保libc.so.6
从用户机器获得的 gdb 负载有所帮助。
这是我使用的 gdb 命令的完整列表(当然,每个命令都是使事情正常运行所必需bt
的):
# note: all the .so files obtained from user machine must be put into local directory.
#
# most importantly, the following files are necessary:
# 1. libthread_db.so.1 and libpthread.so.0: required for thread debugging.
# 2. other .so files are required if they occur in call stack.
#
# these files must also be renamed exactly as the symlinks
# i.e. libpthread-2.28.so should be renamed to libpthread.so.0
# load executable file
file ./thedarkmod.x64
# force gdb to forget about local system!
# load all .so files using local directory as root
set sysroot .
# drop dump-recorded paths to .so files
# i.e. load ./libpthread.so.0 instead of ./lib/x86_64-linux-gnu/libpthread.so.0
set solib-search-path .
# disable damn security protection
set auto-load safe-path /
# load core dump file
core core.6487
# print stacktrace
bt