当我启动 GDB 时,目标进程会打印大量数据,因此我想将其重定向到 NULL,直到某个时间点。
到目前为止我发现的唯一两种方法是:
运行 > 文件名
tty 文件名
问题是我无法找到一种方法将劣质的标准输出恢复到正常状态。
没有“tty default”或“default tty”
谢谢,
伊泰
我找不到方法将劣质的标准输出恢复到正常
您可以这样做:
Reading symbols from /tmp/./a.out...done.
(gdb) list main
1 #include <stdio.h>
2
3 int main() {
4 int i;
5
6 for (i = 0; i < 1000; ++i) {
7 printf("A line we don't care about: %d\n", i);
8 }
9 printf("An important line\n");
10 return 0;
11 }
(gdb) b 9
Breakpoint 1 at 0x400579: file t.c, line 9.
(gdb) run > /dev/null
Starting program: /tmp/./a.out > /dev/null
Breakpoint 1, main () at t.c:9
9 printf("An important line\n");
(gdb) call fflush(0)
$1 = 0
由于我们即将切换输出,因此我们要确保刷新所有缓冲的数据。
接下来我们调用
open("/dev/tty", O_WRONLY)
。您可以在 O_WRONLY
中通过 grep
ping 找到 /usr/include
的值。
(gdb) shell grep WRONLY /usr/include/bits/*.h
/usr/include/bits/fcntl.h:#define O_WRONLY 01
(gdb) p open("/dev/tty", 1)
$2 = 3
所以我们现在有了一个新的文件描述符
3
,它将输出到当前终端。最后,我们将 STDOUT_FILENO
切换到它,如下所示:
(gdb) call dup2(3, 1)
$3 = 1
(gdb) c
Continuing.
An important line
[Inferior 1 (process 22625) exited normally]
Voilà:“重要的一行”被打印到终端。
详细阐述采用俄罗斯的解决方案,我编写了一个独立的 GDB-python 脚本,它将在 stdout 和活动终端 (TTY) 之间切换重定向。就目前情况而言,如果程序输出未重定向到以 (
run > /dev/null
) 开头,则脚本无效。
要激活脚本,请使用
source
命令:
(gdb) b 10
Breakpoint 1 at 0x5555555547a8: file gdbtest.c, line 10.
(gdb) run > /dev/null
Starting program: /home/gdbtest > /dev/null
Breakpoint 1, main () at gdbtest.c:10
10 printf("An important line\n");
(gdb) list
5
6 setbuf(stdout, NULL);
7 for (i = 0; i < 1000; ++i) {
8 printf("A line we don't care about: %d\n", i);
9 }
10 printf("An important line\n");
11 for (i = 0; i < 1000; ++i) {
12 printf("A line we don't care about: %d\n", i);
13 }
14 //fflush(stdout);
(gdb) source redir-stdout.py
(gdb) redir-stdout
Inferior PID: 20749
Redirecting stdout (fd:4) to TTY (fd:3)
(gdb) n
An important line
11 for (i = 0; i < 1000; ++i) {
(gdb) n
12 printf("A line we don't care about: %d\n", i);
(gdb) n
A line we don't care about: 0
11 for (i = 0; i < 1000; ++i) {
(gdb) redir-stdout
Inferior PID: 20749
Redirecting TTY (fd:3) back to stdout (fd:4)
(gdb) n
12 printf("A line we don't care about: %d\n", i);
(gdb) n
11 for (i = 0; i < 1000; ++i) {
(gdb) n
12 printf("A line we don't care about: %d\n", i);
(gdb)
这是脚本(我将其命名为 redir-stdout.py):
import gdb
class RedirectStdout(gdb.Command):
def __init__(self):
super(RedirectStdout, self).__init__("redir-stdout", gdb.COMMAND_USER)
self.tty = None
self.stdout = None
self.redir = False
gdb.events.exited.connect(self.exit_handler)
def invoke(self, arg, from_tty):
print("Inferior PID: %s" % gdb.selected_inferior().pid)
if(gdb.selected_inferior().pid == 0):
raise gdb.GdbError ("Error: must have an active debuggee")
out = gdb.execute("call fflush(0)", to_string=True)
if(self.tty is None):
# or just /dev/tty, as shown (the 1 means WRONLY)
out = gdb.execute("p open(\"/dev/tty\", 1)", to_string=True)
self.tty = out.split('=')[-1].strip()
if(self.stdout is None):
out = gdb.execute("p open(\"/proc/self/fd/1\", 1)", to_string=True)
self.stdout = out.split('=')[-1].strip()
if(not self.redir):
print("Redirecting stdout (fd:{}) to TTY (fd:{})".format(self.stdout, self.tty))
out = gdb.execute("call dup2({}, 1)".format(self.tty), to_string=True)
ret = out.split('=')[-1].strip()
#print("dup2 returns: " + ret)
self.redir = True
else:
print("Redirecting TTY (fd:{}) back to stdout (fd:{})".format(self.tty, self.stdout))
out = gdb.execute("call dup2({}, 1)".format(self.stdout), to_string=True)
ret = out.split('=')[-1].strip()
#print("dup2 returns: " + ret)
self.redir = False
def exit_handler(self, event):
self.tty = None
self.stdout = None
self.redir = False
instance = RedirectStdout()
def exit_handler (event):
print("Exit event received")
instance.exit_handler(event)
注意:该脚本可以轻松地从当前工作目录或主目录中的本地
.gdbinit
获取。