gdb奇怪的回溯

我的程序是用dietlibc静态编译的。 它是在ubuntu x64上编译的(使用-m32标志为x86编译)并在centos x86上运行。

编译后的大小只有大约100KB。 我用-ggdb3编译它,没有优化标志。

我的程序使用signal.h来处理SIGSEGV信号,然后调用abort()。

程序运行几天没有问题,但有时会出现段错误。 这是我得到奇怪的回溯,我不明白:

 username @ ubuntu:〜/ Desktop $ gdb -c core.28569 program-name
 GNU gdb(GDB)7.2
版权所有(C)2010 Free Software Foundation,Inc。
许可证GPLv3 +:GNU GPL版本3或更高版本 
这是免费软件:您可以自由更改并重新分发它。
在法律允许的范围内,不提供任何担保。 输入“显示复制”
和“显示保修”的详细信息。
此GDB配置为“--host = x86_64-linux-gnu --target = i386-linux-gnu”。
有关错误报告说明,请参阅:
 ...
从程序名中读取符号......完成。
 [新主题28569]
核心由`program-name'生成。
程序终止,信号6,Aborted。
 __kernel_vsyscall()中的#0 0x00914410
设置调试gdb的环境。
函数“internal_error”未定义。
在未来的共享库加载中使断点挂起?  (y或[n])[回答N; 输入不是来自终端]
函数“info_command”未定义。
在未来的共享库加载中使断点挂起?  (y或[n])[回答N; 输入不是来自终端]
 .gdbinit:8:源命令文件出错:
需要参数(一个或多个断点号)。
 (gdb)bt
 __kernel_vsyscall()中的#0 0x00914410
符号读取期间,CFI数据不完整; 未指定的寄存器(例如,eax)位于0x914411。
 __unified_syscall()中的#1 0x0804d7f4
 #2 0xbf8966c0在?  ()
 #3  
 #4 0x2054454e在?  ()
 #5 0x20524c43在?  ()
 #6 0x2e352e33在?  ()
 #7 0x32373033在?  ()
 #8 0x2e203b39在?  ()
 #9 0x2054454e在?  ()
 #10 0x20524c43在?  ()
 #11 0x2e302e33在?  ()
 #12 0x32373033在?  ()
 #13 0x4d203b39在?  ()
 #14 0x61696465在?  ()
 #15 0x6e654320在?  ()
 #16 0x20726574在?  ()
 #17 0x36204350在?  ()
 #18 0x203b302e在?  ()
 #19 0x54454e2e在??  ()
 #20 0x43302e34在?  ()
 #21 0x00000029在?  ()
 #22 0xbf8989a8在?  ()
 Backtrace已停止:此框架内部的前一帧(损坏的堆栈?)
 (gdb)bt full
 __kernel_vsyscall()中的#0 0x00914410
没有符号表信息。
 __unified_syscall()中的#1 0x0804d7f4
没有符号表信息。
 #2 0xbf8966c0在?  ()
没有符号表信息。
 #3  
没有符号表信息。
 #4 0x2054454e在?  ()
没有符号表信息。
 #5 0x20524c43在?  ()
没有符号表信息。
 #6 0x2e352e33在?  ()
没有符号表信息。
 #7 0x32373033在?  ()
没有符号表信息。
 #8 0x2e203b39在?  ()
没有符号表信息。
 #9 0x2054454e在?  ()
没有符号表信息。
 #10 0x20524c43在?  ()
没有符号表信息。
 #11 0x2e302e33在?  ()
没有符号表信息。
 #12 0x32373033在?  ()
没有符号表信息。
 #13 0x4d203b39在?  ()
没有符号表信息。
 #14 0x61696465在?  ()
没有符号表信息。
 #15 0x6e654320在?  ()
没有符号表信息。
 #16 0x20726574在?  ()
没有符号表信息。
 #17 0x36204350在?  ()
没有符号表信息。
 #18 0x203b302e在?  ()
没有符号表信息。
 #19 0x54454e2e在??  ()
没有符号表信息。
 #20 0x43302e34在?  ()
没有符号表信息。
 #21 0x00000029在?  ()
没有符号表信息。
 #22 0xbf8989a8在?  ()
没有符号表信息。
 Backtrace已停止:此框架内部的前一帧(损坏的堆栈?)
 (gdb)退出

这是一个堆栈超支。

#4 0x2054454e in ?? () 

看起来像文字,“TEN”或“NET”

 #5 0x20524c43 in ?? () 

“RLC”或“CLR”

等等。

将地址视为文本 – 看看您是否可以识别此文本覆盖堆栈的位置。

您的堆栈跟踪实际上非常容易理解:

  • 你在某处有SIGSEGV,
  • 你的信号处理程序做了什么,然后调用abort()
  • 通过调用__unified_syscall()发出了raise(2)系统调用

你在GDB中没有堆栈跟踪的原因是

  • __unified_syscall在程序__unified_syscall实现,和
  • 不使用帧指针,和
  • 没有适当的cfi指令来描述如何从中解除它。

我认为这是dietlibc中的一个错误,实际上很容易修复。 看看这个(未经测试的)补丁是否为您修复了它:

 --- dietlibc-0.31/i386/unified.S.orig 2011-03-13 10:16:23.000000000 -0700 +++ dietlibc-0.31/i386/unified.S 2011-03-13 10:21:32.000000000 -0700 @@ -31,8 +31,14 @@ __unified_syscall: movzbl %al, %eax .L1: push %edi + cfi_adjust_cfa_offset (4) + cfi_rel_offset (edi, 0) push %esi + cfi_adjust_cfa_offset (4) + cfi_rel_offset (esi, 0) push %ebx + cfi_adjust_cfa_offset (4) + cfi_rel_offset (ebx, 0) movl %esp,%edi /* we use movl instead of pop because otherwise a signal would destroy the stack frame and crash the program, although it @@ -61,8 +67,11 @@ __unified_syscall: #endif .Lnoerror: pop %ebx + cfi_adjust_cfa_offset (-4) pop %esi + cfi_adjust_cfa_offset (-4) pop %edi + cfi_adjust_cfa_offset (-4) /* here we go and "reuse" the return for weak-void functions */ #include "dietuglyweaks.h" 

如果您无法重建dietlibc,或者补丁不正确,您仍可以更好地分析堆栈跟踪。 据我所知, __unified_syscall不会触及%ebp 。 因此,您可以通过执行以下操作获得合理的堆栈跟踪:

 define xbt set $xbp = (void **)$arg0 while 1 x/2a $xbp set $xbp = (void **)$xbp[0] end end xbt $ebp 

注意:如果xbt工作,它很可能进入SIGSEGV信号帧周围的杂草(该帧也不使用帧指针)。 这可能导致完全垃圾,或者跳过一两帧(这正是SIGSEGV发生的帧)。

因此,你最好将正确的展开描述符放入dietlibc中。

    Interesting Posts