使用gdb调试可执行文件时如何传递stdin参数

3

我在这里阅读了许多关于这个主题的问题/答案,但是没有一个解决方案可行...我想将由perl生成的字符串传递给正在被gdb调试的可执行文件。 但是我甚至无法传递转义的十六进制字符... 我尝试了以下“解决方案”:

1:

$ gdb ./a.out
(gdb) r "\x41"

2:

perl -e 'print "\x41"' > input.cmd
$ gdb ./a.out
(gdb) r < input.cmd

3:

$ gdb --args ./a.out "\x41"
(gdb) r

4:

$ gdb ./a.out
(gdb) set args "\x41"
(gdb) r

我尝试了许多不同的转义字符组合,包括", /, \, ', `等等,但都没有成功。解决方案2在SO的许多帖子中都有讨论,但我得到的参数是"<"(gdb将所有内容都转义为字符串)

我甚至尝试调试bash并将可执行文件设置为较小,但bash仍然崩溃...

我错过了什么?我使用的是macOS 10.13上的gdb 8.0.1

更新:

刚刚在linux机器上尝试了一下,上述解决方案可行。我猜问题出在macOS的bash/gdb交互上...有什么想法吗?

更新2:

已解决

在macOS上,显然是gdb中bash调用的问题,设法通过以下方式解决:

$ gdb --args ./a.out $(perl -e 'print "\x41"')
2个回答

0

perl -e 'print "\x41"' > input.cmd

可以简单地使用 echo A > input.cmd 命令。

这个命令的作用是:


2
(gdb) r < input.cmd

完全按照您的要求执行(./a.out 运行并在其 stdin 上接收单个字符 A)。

但是没有一个解决方案起作用...

您将不得不告诉我们您是如何得出这个结论的。

更新:

当我执行 (gdb) r < input.cmd 时,gdb将两个字符串作为参数传递 <input.cmd

如果是这种情况,则您有一个损坏的 GDB,或者更可能是一个损坏的 $SHELL

GDB 只是调用 $SHELL -c './a.out < input.cmd',并期望您的 $SHELL 执行重定向。如果您的 shell 不这样做,那么一切都没有把握。

您可以在 dtruss -f 下运行 GDB,并查看 GDB 所做的以及您的 shell 所做的事情。


使用perl或echo都无关紧要。当我执行(gdb) r < input.cmd时,gdb将"<"和"input.cmd"作为两个参数传递:Thread 2 hit Breakpoint 1, function (variable=0x7ffeefbffbf9 "<") at prog_example.c:16 16 return return_variable; (gdb) show args Argument list to give program being debugged when it is started is "< bin/input.cmd". - xfze
1
刚在 Linux 机器上尝试了一下,可以运行。我猜问题可能出在 macOS 上的 bash/gdb 交互上。 - xfze
现在不能重新启动电脑,而且要使用dtruss就必须关闭SIP。与此同时,我找到了一个解决方案(问题已更新)。 - xfze

0

已解决

在macOS上,gdb内的bash调用明显存在问题,我设法像这样进行解决

$ gdb --args ./a.out $(perl -e 'print "\x41"')

更新 - 现在真的解决了

@EmployedRussian 是正确的,问题出在从 bash 传递到 gdb 的 stdin:

这是 macOS Sierra 的问题: 如果 SIP 启用,则 gdb 无法启动带有 shell(bash)的选项,因此可以在 Sierra 上使用 gdb 的两种方法:

在 Sierra 上使用 gdb 8.0.1:

选项 1:禁用 gdb 上的 shell 启动:

echo "set startup-with-shell off" >> ~/.gdbinit

当我安装并对gdb进行代码签名时,我是按照官方维基(https://sourceware.org/gdb/wiki/BuildingOnDarwin)的步骤进行的,但后来忘记了。这就是我无法将stdin传递给gdb的原因。

选项2:禁用SIP并保留shell启动

echo "set startup-with-shell on" >> ~/.gdbinit

重新启动进入恢复模式并执行以下操作:

csrutil disable

显然这并不是推荐的做法,但它可以说明在Sierra上使用gdb 8.0.1存在的问题所在。希望gdb更新能够解决这个问题。


这个并不是你要求的功能:它调用了"./a.out A",与重定向标准输入无关。要么这根本没有解决任何问题,要么你的问题与你实际想要实现的完全不符。 - Employed Russian
@EmployedRussian,它正好解决了我上面提出的问题:我想将由perl生成的字符串传输到正在被gdb调试的可执行文件中。 - xfze
你的解决方案如何影响目标程序的stdin?你使用“pipe to”来表示与其他人不同的东西。重申一遍:要么你的解决方案是错误的,要么你对问题的陈述是错误的。 - Employed Russian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接