调试客户盒子上生成的核心文件

时间:2012-05-16 10:12:03

标签: c++ linux debugging gdb

我们从客户的盒子上运行我们的软件获得核心文件。不幸的是因为我们总是使用-O2 编译而没有调试符号,这导致我们无法弄清楚它崩溃的原因,我们已经修改了构建,所以现在它们生成-g和 - O2在一起。然后,我们建议客户运行-g二进制文件,以便更容易调试。

我有几个问题:

  1. 从我们在Dev中运行的Linux发行版生成核心文件时会发生什么?堆栈跟踪是否有意义?
  2. 在Linux或Solaris上有没有可用于调试的好书?面向示例的东西会很棒。我正在寻找现实生活中的例子来弄清楚例行程序崩溃的原因以及作者如何找到解决方案。从中级到高级的更多东西会很好,因为我已经做了一段时间了。一些组装也会很好。
  3. 这是一个崩溃的例子,要求我们告诉客户获得-g ver。二进制文件:

    Program terminated with signal 11, Segmentation fault.
    #0  0xffffe410 in __kernel_vsyscall ()
    (gdb) where
    #0  0xffffe410 in __kernel_vsyscall ()
    #1  0x00454ff1 in select () from /lib/libc.so.6
    ...
    <omitted frames>
    

    理想情况下,我想解决一下为什么应用程序崩溃的原因 - 我怀疑它是内存损坏,但我不是百分百肯定。

    严格禁止远程调试。

    由于

4 个答案:

答案 0 :(得分:18)

  

从我们在Dev中运行的Linux发行版生成核心文件时会发生什么?堆栈跟踪是否有意义?

可执行文件是动态链接的,就像你的那样,GDB产生的堆栈(很可能)是有意义的。

原因:GDB知道您的可执行文件是通过在地址libc.so.6的{​​{1}}中调用某些内容而崩溃的,但它不知道该地址的代码是什么。因此,它会查看您的 0x00454ff1副本,并发现它位于libc.so.6中,因此会打印出来。

select客户副本中0x00454ff1也处于选择状态的可能性非常小。很可能客户在该地址有一些其他程序,可能是libc.so.6

您可以使用abort,并观察disas select是在指令的中间,还是前一条指令不是0x00454ff1。如果其中任何一个成立,那么堆栈跟踪就毫无意义。

可以帮助自己:您只需要从客户系统获取CALL中列出的所有库的副本。让客户用例如。

(gdb) info shared

然后,在您的系统上:

cd /
tar cvzf to-you.tar.gz lib/libc.so.6 lib/ld-linux.so.2 ...
  

然后我们建议客户运行-g二进制文件,以便更容易调试。

很多更好的方法是:

  • 使用mkdir /tmp/from-customer tar xzf to-you.tar.gz -C /tmp/from-customer gdb /path/to/binary (gdb) set solib-absolute-prefix /tmp/from-customer (gdb) core core # Note: very important to set solib-... before loading core (gdb) where # Get meaningful stack trace!
  • 构建
  • -g -O2 -o myexe.dbg
  • strip -g myexe.dbg -o myexe分发给客户
  • 当客户获得myexe时,请使用core进行调试

您将拥有完整的符号信息(文件/行,本地变量),而无需向客户发送特殊二进制文件,也不会泄露太多有关您的来源的详细信息。

答案 1 :(得分:2)

你确实可以从崩溃转储中获取有用的信息,即使是来自优化编译的信息(尽管从技术角度来说,它是所谓的“屁股中的一个主要问题。”)-g编译确实更好,是的,即使发生转储的机器是另一个发行版,你也可以这样做。基本上,有一点需要注意,所有重要信息都包含在可执行文件中,最终在转储中。

当您将核心文件与可执行文件匹配时,调试器将能够告诉您崩溃发生的位置并向您显示堆栈。这本身应该有很多帮助。你应该尽可能多地了解它发生的情况 - 它们能否可靠地再现它?如果是这样,你可以重现吗?

现在,这里需要注意的是:“一切都在那里”概念的地方是共享对象文件.so文件。如果由于这些问题而失败,您将不会拥有所需的符号表;你可能只能看到它发生在哪个库.so

有很多关于调试的书籍,但我想不出我推荐的那本书。

答案 2 :(得分:0)

据我记忆,你不需要让你的客户使用-g选项构建的二进制文件运行。需要的是你应该使用-g选项进行构建。有了它,您可以加载核心文件,它将显示整个堆栈跟踪。我记得几周前,我创建了核心文件,使用build(-g)而没有-g,核心的大小相同。

答案 3 :(得分:0)

检查堆叠时看到的局部变量的值?特别是在select()调用周围。在客户的盒子上执行此操作,只需加载转储并走出堆栈......

另外,检查DEV和PROD平台上的FD_SETSIZE值!