从 perl 调用和控制 GDB

Invoke and control GDB from perl

我正在尝试用 perl 编写一些脚本来控制 GDB 调试过程。在下面的代码中,我能够 运行 GDB 并传递一些 MI2 命令,但我无法捕获 GDB 的输出:

open(G, "| gdb -n -q --interpreter=mi2") || die("error opening gdb");
syswrite(G, "-file-exec-and-symbols ./a.out\n");
$x = sysread(G, $resp, 4096);
printf("x: %u\n", $x);
printf("resp: '%s'\n", $resp)

结果是:

x: 0
resp: ''
=thread-group-added,id="i1"
(gdb) 
^done
(gdb) 

这里的问题是 GDB 将输出 '=thread-group-added,id="i1"' 直接打印到 tty,所以我无法在我的 perl 脚本中捕获它以供进一步解释。我想将 GDB 的输出捕获到某个变量并对其进行解释。从输出中可以看出,sysread() 过程没有读取任何内容(“x: 0”)。 我该怎么做?

编辑: 经过一段时间的思考,我找到了一些解决方案来捕获 GDB 的输出。它需要命名管道(下面是“/tmp/pipe”):

open (G, "| gdb -n -q --interpreter=mi2 >& /tmp/pipe") || die("error opening gdb");

现在我可以从 perl 脚本读取 GDB 的输出并解析它。

打开 gdb 进程只是为了提供(替换)它的 STDIN,而不是读取它的输出。 G 是管道的 write-end。不能同时使用 open,请参阅 pipe-open in open

相反,使用同时提供两者的库,例如 IPC::Run

use warnings;
use strict;
use feature 'say';

use IPC::Run qw(run); 

run [ qw(gdb -n -q --interpreter=mi2) ], \my $stdin, \my $so, \my $se; 

say "out: $so" if $so;    
say "err: $se" if $se;

这会打印行 out: =thread-group-added,id="i1"(gdb)

赋值给$stdin写入程序的STDIN,从$soand/or$se中读取其标准output/error结束(有很多方法可以在它发出时拥有它)。该模块可以做更多的事情,请参阅文档。