核心文件是由发布版本的代码(g ++)生成的,该代码被剥离了符号。
采用相同(SVN)版本的代码,我修改了构建选项以包含符号。
我是否可以使用包含符号的可执行文件来调试该核心文件?它似乎无法出现,但只是想确保它不是我做错的其他事情。
(?=\r?\n)
答案 0 :(得分:3)
理论上,它应该通过再次构建程序来重现符号。但它要求您具有完全相同的编译器版本,具有完全相同的设置,相同版本的OS和相同版本的库,系统头等,并且操作系统不执行地址随机化[或调试器理解地址混洗]。
然而,看起来确实在我上面列出的“If ... and ...”链中缺少了SOMETHING - 这意味着你的堆栈及其内容不是特别有意义。
您可能希望执行x/1000zg $rsp
并查看堆栈内容是否比回溯看起来更健全。您始终可以在单独的gdb实例中加载调试符号的可执行文件,并使用disass 0x124213,+123
来反汇编该进程中0x123213
(以及123字节)的内容。
另外,假设您不是100%确定线程,请尝试info thread
查看有关线程的内容。
我不羡慕你......
答案 1 :(得分:3)
我必须这样做,让我告诉你这不容易。
我最终使用的方法与你的很相似。我用所有相同的选项和调试符号构建了一个库的副本。
然后我查看核心转储以找到崩溃位置。我使用gdb反汇编视图查找机器指令并备份,直到找到函数start。
然后我在没有符号的原始库中进入objdump -dC
,通过搜索匹配的机器指令系列找到匹配的位置。这给了我图书馆的补偿。
然后我能够进入使用调试符号构建的库并找到相同的功能。它通常位于相同的一般区域,尽管由于编译器使用的随机数可能会发生小的变化。 (注意:我后来开始使用GCC' -frandom-seed
选项强制在每次编译运行时使用SAME随机数。阅读文档。每个源文件必须是不同的种子。)
从那里开始阅读反汇编来确定出了什么问题。如果核心转储表示它在读取寄存器$ r12中的NULL指针时崩溃了,我必须从调试符号版本中找出$ r12得到它的值。
在执行此操作几次之后,我更改了构建系统,以便为每个构建使用相同的随机种子,并从头开始构建调试符号版本,将其剥离以生成最终的二进制文件。所有版本都填入SVN服务器,以便以后根据需要提取出来。虽然由于每个构建都有唯一的目录名称,因此简单的NFS目录也可以正常工作。