进入子进程时 GDB 中断

gdb break when entering child process

本文关键字:GDB 中断 子进程      更新时间:2023-10-16

我很难弄清楚这个问题;我有一个程序,iverilog执行system()调用以调用另一个程序,ivl.我想调试第二个程序,ivl在 gdb 中,但是当我使用父进程调用 gdb 时,我无法让 gdb 在子进程中设置任何断点。以下是程序的外观:

//iverilog-main.cpp (Parent process)
int main(){
//...
system("ivl arg1 arg2");
//...
return 0;
}

.

//ivl-main.cpp (child process)
int main(){
//...
//stuff I want to debug
//...
return 0;
}

.

我正在运行的 gdb 命令是:gdb iverilog -x cmds.gdb

# cmds.gdb
set args hello.v
set follow-fork-mode child
set breakpoint pending on
break ivl-main.cpp:main
run

不幸的是,gdb 不会在ivl-main.cpp:main中断,它只是完成而不会中断; 我得到的输出是:

Starting program: /usr/local/bin/iverilog hello.v
[New process 18117]
process 18117 is executing new program: /bin/dash
[Inferior 2 (process 18117) exited normally]

我确定ivl-main.cpp:main被调用,因为当我在 gdb 中运行ivl程序时,它在那里成功中断。

我的想法是,gdb 在运行时不会将 ivl-main.cpp 识别为源文件gdb iverilog,并且当它进入包含 ivl-main 的子进程时.cpp它不会设置该断点作为源文件。所以我认为如果我为 ivl-main 设置断点.cpp当 gdb 进入子进程时,它应该可以工作。我能想到的唯一方法是在system()调用处手动中断并单步执行子进程,然后设置断点。有没有一种更优雅的方法,在进入子进程时强制 gdb 中断?

通常 GDB 一次只调试一个进程 - 如果您的程序分叉,那么您将调试父进程或子进程,但不能同时调试两个进程。默认情况下,GDB 在分叉后继续调试父级,但如果需要,可以使用以下命令更改此行为:

set follow-fork-mode child

或者,您可以告诉 GDB 将父级和子级都置于其控制之下。默认情况下,GDB 只遵循一个进程,但您可以使用以下命令告诉它遵循所有子进程:

set detach-on-fork off

GDB 将每个调试的进程称为"劣等"。调试多个进程时,您可以使用"inferiors"命令检查每个进程并与之交互,类似于使用"线程"检查多个线程或与多个线程交互的方式。

在此处查看更多文档:

https://sourceware.org/gdb/onlinedocs/gdb/Forks.html

这个答案提供了一种实现你想要的方法。

从理论上讲,set follow-fork-mode child应该有效。

实际上,iverilog本身可能是一个运行(forks)多个命令的 shell 脚本,因此在每次fork都需要决定是要继续调试父命令还是子命令。一个错误的决定,你就失去了对最终将执行程序的过程的控制。这很可能解释了为什么它对你不起作用。