5

我正在用 GDB 调试我的 C 程序,这有点奇怪,可能是因为我没有使用 glibc,所以它不会检测到新线程,直到它中断它们。我通过添加一个立即恢复的断点来解决这个问题(如果为 0 则中断)。

然而今天我撞到了一堵墙。

我需要 execve() 非常快,所以正常的 fork() 是不可能的(将使用大量内存)并且我不能 vfork() (我需要一个堆栈来设置管道等)所以我使用了相同的这个库(https://code.google.com/p/popen-noshell/)中的方法,基本上只使用 CLONE_VM 进行克隆。这(或一般调用 execve() - 我真的不知道)使 GDB 出于某种原因真的很困惑 - 基本上它输出的是这样的:

[New LWP 516]
[New LWP 520]
[New LWP 519]
[New LWP 521]
LWP 521 is executing new program: /bin/bash
Error in re-setting breakpoint 1: No source file named xxx.c.
Error in re-setting breakpoint 2: No source file named yyy.c.
Error in re-setting breakpoint 4: Function "zzz_main" not defined.
[LWP 521 exited]

Program received signal SIGTRAP, Trace/breakpoint trap.
[Switching to LWP 519]
0x00000000004307f8 in shell_execve ()
(gdb) info threads 
Id   Target Id         Frame 
* 5    LWP 519 "self-tes" 0x00000000004307f8 in shell_execve ()
4    LWP 520 "self-tes" 0x000000000040825f in ?? ()
3    LWP 516 "self-tes" 0x000000000040825f in ?? ()
2    LWP 515 "self-tes" 0x000000000040825f in ?? ()
1    LWP 512 "self-tes" 0x000000000040848a in ?? ()

GDB 基本上对所有事情都感到困惑,并认为它当前正在执行 /bin/bash - 它不是 - 在没有 GDB 的情况下运行正常但是我需要它来调试我的程序。我试图禁用我能找到的每个 fork 和 exec 设置,但没有启用像“follow exec”这样的设置。如您所见,它尝试在 execve() 之后重新设置断点...为什么?它不再识别任何帧或符号,因为它完全擦除了先前的空间并加载了 /bin/bash。

如何让 GDB 忽略调用 execve() 的线程而不尝试为子进程加载符号?

编辑:哦,我目前正在使用 x86_64 Linux 3.2.0-27 (Ubuntu)。

EDIT2:还有 GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04

EDIT3:也刚刚检查了 gdb 7.5。同样的问题。

4

1 回答 1

3

发现问题了!显然,我在克隆时忘记用 SIGCHLD 屏蔽标志,显然 gdb(或 libthread)使用它作为生成子进程(fork 样式)的提示,而不仅仅是另一个线程。感谢@R .. 的提示,引导我朝着正确的方向前进。

于 2012-11-26T05:51:30.953 回答