debugging在客户框中生成的核心文件
我们通过在客户的机器上运行我们的软件来获取核心文件。 不幸的是,因为我们一直使用-O2 进行编译而没有debugging符号,这导致了我们无法弄清楚为什么会崩溃的情况,我们修改了构build,现在他们生成了-g和-O2。 然后,我们build议客户运行-g二进制文件,以便更易于debugging。
我有几个问题:
- 从Linux发行版(而不是在Dev中运行的发行版)生成核心文件时会发生什么情况? 堆栈跟踪是否有意义?
- 有什么好的书籍可以在Linux或Solaris上进行debugging吗? 面向对象的例子会很棒。 我正在寻找真实的例子,找出为什么一个例程崩溃,作者如何解决问题。 从中级到高级的东西会更好,因为我已经这样做了一段时间了。 一些组装也会很好。
这是一个崩溃的例子,要求我们告诉客户得到一个-g版本。 的二进制文件:
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>
理想情况下,我想解决为什么确切的应用程序崩溃 – 我怀疑这是内存腐败,但我不是100%确定。
远程debugging是严格禁止的。
谢谢
从Linux发行版(而不是在Dev中运行的发行版)生成核心文件时会发生什么情况? 堆栈跟踪是否有意义?
它的可执行文件是dynamic链接的,因为你的是,GDB生成的堆栈(很有可能) 不是有意义的。
原因是:GDB知道你的可执行文件通过调用地址为0x00454ff1
libc.so.6
中的东西而0x00454ff1
,但是它不知道该地址是什么代码。 所以它看着你的libc.so.6
的副本,并发现这是在select
,所以它打印。
但是0x00454ff1
也是在selectlibc.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 ...
然后,在你的系统上:
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!
然后,我们build议客户运行-g二进制文件,以便更易于debugging。
更好的方法是:
- 使用
-g -O2 -o myexe.dbg
-
cp myexe.dbg myexe
-
strip -g myexe
- 分发
myexe
给客户 - 当客户获得
core
,使用myexe.dbg
进行debugging
您将拥有完整的符号信息(文件/行,本地variables),无需向客户发送特殊的二进制文件,也不会泄露您的源代码太多的细节。
你甚至可以从崩溃转储中获得有用的信息,甚至从优化的编译中获得有用的信息(尽pipe这在技术上是所谓的“屁股上的一大痛苦”。)编译确实是更好的,是的,你可以做所以即使发生转储的机器是另一个分配。 基本上,一个警告,所有重要的信息都包含在可执行文件中,并最终在转储。
当您将核心文件与可执行文件进行匹配时,debugging器将能够告诉您崩溃发生的位置并显示堆栈。 这本身应该有很大的帮助。 你也应该尽可能多地了解它发生的情况 – 它们能够可靠地重现吗? 如果是这样,你能重现吗?
现在,需要注意的是,“所有东西都在那里”概念的地方是共享对象文件, .so
文件。 如果由于这些问题而失败,则不需要符号表; 你可能只能看到什么库。
有很多关于debugging的书籍,但我想不出一个我会推荐的。
据我所知,你不需要问你的客户使用-g选项build立的二进制文件。 需要的是你应该有一个build立与-g选项。 有了这个,你可以加载核心文件,它会显示整个堆栈跟踪。 我记得几个星期前,我创build了核心文件,build立(-g)和没有-g和核心的大小是一样的。
检查您在走栈时看到的局部variables的值? 特别是在select()调用周围。 在客户的盒子上做这件事,只需加载转储和走栈…
另外,请在DEV和PROD平台上检查FD_SETSIZE的值!