Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在GDB中调试fork exec进程的入口点?_C_Linux_Gdb - Fatal编程技术网

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

如何在GDB中调试fork exec进程的入口点?,c,linux,gdb,C,Linux,Gdb,我有一个C linux应用程序(a),它在启动时会生成另一个进程(p)。当我想调试P时,我像往常一样启动A,然后用ddd/gdb连接到P 当我想调试p的入口点(main的开始)时,会出现问题。如果我按照通常的方法将调试器连接到p,则已经很晚了。我发现的解决方案是在P的main开头插入一个sleep,这样我就有时间连接gdb,但这不是一个非常优雅的解决方案 我也尝试过使用asm(“int$3”),但似乎不起作用 你知道我怎样才能解决这个问题吗?(最好不改变A或P的代码)您应该能够通过使用gdb的远

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

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

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


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

您应该能够通过使用gdb的远程调试功能来实现这一点,特别是

gdbserver
。实际上,使用
gdbserver
启动(P)。这些链接包含更详细的信息:


您应该使用此选项:

set follow-fork-mode
mode 其中,模式为
父项
子项
询问
中的一种

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

要跟随孩子:

set follow-fork-mode child
要让调试器每次都询问您:

set follow-fork-mode ask
因此,基本上,您首先将gdb连接到A,然后将gdb设置为跟随子级,然后当A生成p时,gdb将连接到p并与A分离。

此外,捕获点也很方便,例如:

catch exec
Catchpoint用作断点。每次检测到对exec()syscall的调用时,GDB都会停止。这允许您在继续之前在任何新加载的可执行文件中设置任何断点(例如,
breakmain
)。另一个catchpoint
catch fork
同样适用于fork()系统调用检测

它特别方便:

  • 当必须同时遵循父项和子项时(
    设置为“在分叉上分离”或“在分叉上关闭”)
    
  • 当父进程分叉时,通常会加载各种可执行文件

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

exec
文件分开
+
中断main

叉子是一部分,解释如下:

现在,对于
exec

a、 c:

现在是互动环节:

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

gdbserver允许远程调试,但不能解决当前的问题,这更像是gdb如何遵循fork/clone。我不认为这是远程调试的情况。更多的是关于gdb在fork上遵循哪个进程。
set follow fork mode ask
已被删除。根据,当前可用的唯一选项是
父项
子项
#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)