设置gdb退出断点无效?

24

我已经在exit和_exit上设置了断点,但我的程序(运行在linux 2.6.16.46-0.12 sles10上的多线程应用程序)还是以某种无法定位的方式退出。

(gdb) c
...
[New Thread 47513671297344 (LWP 15279)]
[New Thread 47513667103040 (LWP 15280)]
[New Thread 47513662908736 (LWP 15281)]
程序退出,代码为0177。 (gdb)

exit函数驻留在libc中,因此没有延迟加载共享库问题。有人知道还有其他神秘的触发器会导致无法捕获的退出吗?

编辑:现在这个问题只是理论上的。我尝试使用二分调试,撤销了一部分更改(问题消失了)。之后我再按顺序重新应用它们,现在即使将它们恢复到原始状态,我也无法再次重现该问题。

编辑2:我最近发现了一个导致这种错误的原因,可能是这个问题的根源。由于历史原因,我们的产品使用了邪恶的链接器标志-Bsymbolic。其中的副作用之一是,当调用未定义的符号时,GLIBC运行时链接器会以与此相同的方式bomb,然后你会在调试器中看到进程以0177退出。当运行时链接器以这种方式中止时,我猜它会直接进行对_exit的系统调用(而不是使用C运行时库exit()或_exit())。

3个回答

40

导致_exit断点“失效”的原因通常有两种——要么是GDB没有在正确的位置设置断点,要么是程序执行了(类似于)syscall(SYS_exit, ...)

info breakdisassemble _exit显示了什么?

您可以尝试使用break *&_exitGDB正确设置断点。另外,GDB-7.0支持catch syscall。假设程序是Linux/x86_64,以下类似的代码应该适用于任何退出方式(请注意,在ix86上数字将不同):

(gdb) catch syscall 60
Catchpoint 3 (syscall 'exit' [60])
(gdb) catch syscall 231
Catchpoint 4 (syscall 'exit_group' [231])
(gdb) c

Catchpoint 4 (call to syscall 'exit_group'), 0x00007ffff7912f3d in _exit () from /lib/libc.so.6

更新:
你的评论表明 _exit 断点已经正确设置,所以很可能是你的进程没有执行 _exit

那么就只剩下 syscall(SYS_exit, …) 和另外一种可能性(我之前错过了):所有执行 pthread_exit 的线程。你可能还想在 pthread_exit 上设置断点,并且每次命中时执行 info thread -- 最后一个执行 pthread_exit 的线程会导致进程终止。

编辑:

值得注意的是,你可以使用助记符名称而不是系统调用号。你还可以同时将多个系统调用添加到 catch list 中,如下所示:

(gdb) catch syscall exit exit_group
Catchpoint 2 (syscalls 'exit' [1] 'exit_group' [252])

我将尝试构建gdb 7并查看它显示了什么。 *&给出相同的指令地址:<pre> (gdb) b _exit 在0x2aeea040f250处设置断点2 (gdb) b *&_exit 注意:断点2也设置在pc 0x2aeea040f250处。 在0x2aeea040f250处设置断点3 </pre> <pre> 0x00002aeea040f250 <_exit+0>: mov %fs:0x0,%r9 ... 0x00002aeea040f275 <_exit+37>: syscall </pre> (看起来像是一个相当标准的系统调用)。我认为我至少已经确定了导致这个神秘退出的代码更改,只是还不理解细节。 - Peeter Joot
4
最好使用catch syscall exitcatch syscall exit_group而不是数字值。例如,在我的系统中,exit的值是[1],而不是[60] - Ruslan
此外,您可以使用 catch syscall exit exit_group 一次性设置两者。事实上,现在正在编辑它... - Parthian Shot

2

在_exit上设置断点是个好主意。

你也可以尝试静态链接,以避免潜在的gdb问题。

0177看起来很像wait状态wait(2)返回的子进程停止,但是gdb正在打印退出状态,这是一个不同的东西,所以这可能是一个真正的退出参数。


OP说他已经在_exit和exit上设置了断点。此外,0177等同于127。你是怎么从127推出SIGCHLD的呢? - Employed Russian
哦,错过了出口。但是我对等待状态是正确的。我显然不是在谈论信号编号,而是wait(2)为已停止进程返回的状态。看这个:$ grep IFSTOPPED /usr/include/bits/waitstatus.h #define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f),AND,0x7f == 0177。但我同意这不是这里正在发生的事情。 - DigitalRoss

1

可能是您在某些加载到进程中的共享库中有一些懒惰引用未解决。我正处于与“某人某地”退出进程并出现未解决的引用相同的情况。

请使用“ldd -r”选项检查您的进程。

看起来像是ld.so或其他东西对某些符号进行了延迟解析,使其统一退出函数(我的建议是应该是abort)。

我的情况:

$ ldd ./program
undefined symbol: XXXX  (/usr/lib/libYYY.so)

$./program
program: started! 
...
<program is running regardless of undefined references>

现在当我调用某个使用未定义函数的场景时,出现了退出。它总是以exitcode=127退出,gdb报告0177。


这里似乎不是这种情况。在我们的可执行文件中,我没有发现任何未定义的符号(无论是exit还是其他任何东西)。 - Peeter Joot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接