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中。