16

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

当我想调试 P 的入口点(main 的开始)时会出现问题。如果我在将调试器连接到 P 时遵循通常的方法已经为时已晚。我找到的解决方案是在 P 的 main 开头插入一个 sleep ,这样我就有时间连接 gdb ,但这不是一个非常优雅的解决方案。

我也尝试过使用asm("int $3"),但它似乎不起作用。

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

4

5 回答 5

21

您应该使用此选项:

set follow-fork-mode 模式

其中modeparent,child或之一ask

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

set follow-fork-mode parent

跟随孩子:

set follow-fork-mode child

让调试器每次都询问您:

set follow-fork-mode ask

所以基本上你会开始将gdb连接到A,然后设置gdb跟随孩子,然后当A产生P时,gdb将连接到P并与A分离。

于 2008-12-18T09:07:49.550 回答
11

除了Nathan Fellman 的回答之外,catchpoints也派上用场,例如:

catch exec

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

特别方便:

  • 当必须跟随父母和孩子时(set detach-on-fork off);
  • 当父进程分叉时,通常会加载各种可执行文件。
于 2012-10-30T15:07:39.643 回答
1

execfile+部分break main

分叉部分在以下位置进行了解释:https ://stackoverflow.com/a/377295/895245

现在为exec

交流:

#include <unistd.h>

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

公元前:

#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 中测试。

于 2017-03-29T16:39:37.287 回答
-1

您应该能够通过使用 gdb 的远程调试功能来做到这一点,特别是gdbserver. 实际上,使用 启动 (P) gdbserver。这些链接有更详细的信息:

于 2008-12-18T08:51:03.390 回答
-1

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

于 2012-11-25T19:48:48.943 回答