如何在GDB中调试fork-exec进程的入口点?

时间:2008-12-18 08:26:02

标签: c linux gdb

我有一个C linux应用程序(A),它在启动时产生另一个进程(P)。当我想调试P时,我像往常一样启动A,然后用ddd / gdb连接到P。

当我想调试P的入口点(主要开始)时会出现问题。如果我将调试器连接到P时按照常规方法已经迟到了。我发现的解决方案是在P的主要开头插入一个睡眠,所以我有时间与gdb连接,但这不是一个非常优雅的解决方案。

我也尝试过使用asm("int $3"),但似乎无效。

你知道我怎么能解决这个问题吗? (最好不要改变A或P的代码)

5 个答案:

答案 0 :(得分:19)

您应该使用此选项:

set follow-fork-mode mode

其中模式parentchildask之一。

要跟随父级(这是默认值),请使用:

set follow-fork-mode parent

跟随孩子:

set follow-fork-mode child

让调试器每次都问你:

set follow-fork-mode ask

所以基本上你开始将gdb连接到A,然后设置gdb跟随子进程,然后当A生成P时,gdb将连接到P并从A分离。

答案 1 :(得分:6)

Nathan Fellman's answer之外, catchpoints 派上用场,例如:

catch exec

Catchpoint作为断点。每次检测到对 exec()系统调用的调用时,GDB都会停止。这允许您在继续之前在任何新加载的可执行文件中设置任何断点(即break main)。另一个捕获点catch fork fork()系统调用检测的工作方式类似。

特别方便:

  • 必须遵循父母和子女(set detach-on-fork off);
  • 当父进程分叉经常加载各种可执行文件时。

答案 2 :(得分:0)

您应该可以通过使用gdb的远程调试功能(特别是gdbserver)来实现此目的。实际上,使用gdbserver启动(P)。这些链接有更详细的信息:

答案 3 :(得分:0)

exec部分与file + break main

分叉是在https://stackoverflow.com/a/377295/895245

解释的部分

现在为exec

交流转换器:

#include <unistd.h>

int main(void) {
    execl("./b", "./b", "ab", "cd", (char*)NULL);
    return 1;
}

b.c:

#include <stdio.h>

int main(int argc, char **argv ) {
    printf("%s\n", argv[0]);
    printf("%s\n", argv[1]);
}

然后:

gcc -g a.c -o a
gcc -g b.c -o b
gdb -nh -q a

现在进行互动会议:

Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x4004ea: file a.c, line 4.
Starting program: /home/ciro/test/gdb-exec/a 

Temporary breakpoint 1, main () at a.c:4
4           execl("./b", "./b", "ab", "cd", (char*)NULL);
(gdb) file b
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "b"? (y or n) y
Reading symbols from b...done.
(gdb) b main
Breakpoint 2 at 0x4004f5: file b.c, line 4.
(gdb) n

Breakpoint 2, main (argc=0, argv=0x7fffffffa570) at b.c:4
4               printf("%s\n", argv[1]);
(gdb) n
process 4877 is executing new program: /home/ciro/test/gdb-exec/b

Breakpoint 2, main (argc=3, argv=0x7fffffffa598) at b.c:4
4               printf("%s\n", argv[1]);
(gdb) n
ab
5               printf("%s\n", argv[2]);
(gdb) n
cd
6       }
(gdb) 

您必须确保在运行文件之前前往exec,可能使用b execl,因为之后您将使用新文件中的符号。

在Ubuntu 14.04中测试,gdb 7.7.1。

答案 4 :(得分:-1)

在main()处设置一个断点,它也会在执行程序的main()处断开。