自动将参数传递给正在调试的程序,需要调用gdb。

40

我想编写一个脚本,在一定条件下自动执行gdb,并使用某些参数Y运行某个程序X。 一旦程序执行完毕,用户应该仍然停留在gdb的提示符下,直到他/她显式地退出它。

其中一种方法是让脚本将运行命令和参数Y输出到某个文件F中,然后像这样调用gdb:

gdb X < F

但是否有一种方法可以在不引入临时文件的情况下完成这个操作?

8个回答

87

假设有一个程序X和参数列表a b c,实现这个最简单的方法是:

X a b c

可以使用 gdb--args 选项,如下所示:

gdb --args X a b c

--args Arguments after executable-file are passed to inferior

这意味着在--args之后的第一个参数是要调试的可执行文件,而该可执行文件后面的所有参数将原样传递给该可执行文件。


我有一个使用情境,其中有一个函数 foo(a,b,c) (任何数据类型),它在 main() 中被调用,现在我想在执行程序之前输入这些参数。我们能做到吗? - KedarX
@Kedar:不是这样的。这种方法确定传递给main()的参数。你需要正确地将它们传递给foo - Nathan Fellman
好的,这让我清楚了我的疑惑;除非进行一些传递,否则我们无法向main内部的任何方法提供参数!谢谢@Nathan Fellman - KedarX
12
你甚至可以使用gdb -ex run --args prog arg...命令来自动启动程序。 - Mildred

28
如果你想通过GDB运行一些命令然后让它退出或者运行结束,只需要这样做:
echo commands | gdb X

如果你想在运行这些命令后留在命令提示符下,可以执行以下操作:
(echo commands; cat) | gdb X

这将导致将命令回显到GDB,然后您键入到cat进程中,它将其标准输入复制到标准输出,然后将其管道传输到GDB。

1
(echo“运行参数”; cat)| gdb X; #非常感谢,运行得很好! - Ian Vaughan
2
请注意,如果这样做,您将失去shell的交互性(所有readline编辑功能、历史记录等)。 - ijw
刚刚注意到上下键不起作用了...这不是一个可接受的解决方案 :( - Nils
1
@ijw,@Nils:你们是正确的。请参考迈克v的答案(https://dev59.com/q3RC5IYBdhLWcg3wW_tk#2717992)获得更好的解决方案。 - Adam Rosenfield

9
有一个选项-x,例如:
gdb -x gdb_commands exe_file

其中gdb_commands可以是例如(在安卓模拟器的情况下):

target remote :5039

2
还要注意,如果你想避免使用临时文件,你可以使用进程替换:gdb -x <(echo commands) exe_file - Adam Rosenfield
2
只需使用 gdb -ex 'foo' -ex 'bar' 命令来运行 gdb 并执行 foobar 命令。 - zopieux

9
在尝试了所有这里的答案之后,
  1. 虽然回声/ cat hack很聪明,但会破坏gdb的许多重要功能。最值得注意的是,所有用户提示都会自动回答(因此您没有机会确认可能存在的危险操作),并且Ctrl + C(停止正在调试的进程)最终会杀死cat,因此在那之后您实际上无法与gdb交流。
  2. -x选项应该可以工作,但我无法使其与我的gdb版本配合使用,并且它需要一个临时文件。

但是,事实证明您只需使用-ex即可,就像这样:

gdb -ex "target remote localhost:1234"

您还可以多次使用-ex参数来运行多个命令!

1

好的,这只是一条评论,不是真正的答案 - 只是想包含一些代码片段。 我在 bash/Ubuntu Lucid 上 - 对于我来说,我遇到了与“GDB has problems with getting commands piped to STDIN - Unix Linux Forum - Fixunix.com”中几乎相同的问题。

基本上,我想达到的与以下片段相同:

$ gdb
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) pwd
Working directory /media/work/dir.
(gdb) 

...除此之外,我想以某种方式“管道”pwd命令,并在之后保持gdb开启(如上例所示)。

我尝试了这里的一些建议,唯一对我有用的是(echo commands; cat) | gdb语法 - 以及(有些有效的)Here Strings - 这是我的结果:

$ echo "pwd" | gdb
(gdb) Hangup detected on fd 0
error detected on stdin


$ echo "pwd" | gdb -x /dev/stdin
GNU gdb (GDB) 7.1-ubuntu
...
/dev/stdin: Invalid argument.
(gdb) Hangup detected on fd 0
error detected on stdin


$ gdb -x <(echo "pwd")
GNU gdb (GDB) 7.1-ubuntu
...
/dev/fd/63: No such file or directory.
(gdb) q


$ gdb -e "pwd"
GNU gdb (GDB) 7.1-ubuntu
...
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) q   # nothing happens


$ gdb <<<"pwd"
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) Working directory /media/work/dir.
(gdb) quit    # OK, but autoexits


$ gdb <<<"pwd
> "
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) Working directory /media/work/dir.
(gdb) Working directory /media/work/dir.
(gdb) quit    # with a line break at end, it execs twice, then exits


# the only one OK for my needs - 
# except locks after quit, and needs Ctrl-C
$ (echo "pwd"; cat) | gdb 
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) Working directory /media/work/dir.
(gdb) q
^C 

希望这能帮到某些人,
干杯!

 
编辑:现在我至少知道为什么进程替换不起作用 - 它将使用临时文件描述符,无法被ls识别为文件(因此gdb肯定无法读取它;此外,引用几乎立即消失,除非进程被某种方式阻塞,如使用cat)- 请参见终端日志片段:

$ echo -e "***\n" <(echo "pwd") "\n***\n`cat <(ls -C /dev/fd ; echo; for ix in /dev/fd/*; do irl=$(readlink -f $ix); echo $ix -\> $irl; ls -la $ix 2>&1; ls -la $irl 2>&1; echo '______'; done ; ls -C /dev/fd )`"

***
 /dev/fd/63 
***
0  1  2  3  63

/dev/fd/0 -> /dev/pts/0
lrwx------ 1 user user 64 2010-11-07 21:18 /dev/fd/0 -> /dev/pts/0
crw--w---- 1 user tty 136, 0 2010-11-07 21:18 /dev/pts/0
______
/dev/fd/1 -> /proc/10713/fd/pipe:[236191]
l-wx------ 1 user user 64 2010-11-07 21:18 /dev/fd/1 -> pipe:[236151]
ls: cannot access /proc/10713/fd/pipe:[236191]: No such file or directory
______
/dev/fd/2 -> /dev/pts/0
l-wx------ 1 user user 64 2010-11-07 21:18 /dev/fd/2 -> pipe:[236151]
crw--w---- 1 user tty 136, 0 2010-11-07 21:18 /dev/pts/0
______
/dev/fd/255 -> /proc/10721/fd/255
ls: cannot access /dev/fd/255: No such file or directory
ls: cannot access /proc/10721/fd/255: No such file or directory
______
/dev/fd/3 -> /proc/10725/fd/3
ls: cannot access /dev/fd/3: No such file or directory
ls: cannot access /proc/10725/fd/3: No such file or directory
______
0  1  2  3

此外,使用 (echo commands; cat) | gdb 时,上下箭头键无法正常工作,因为这是 cat 的行为;如果我们只运行 cat,它会将 stdin 复制到 stdout,结果如下:
$ cat # or `cat -`: and start pressing up/down keys - and get:
^[[A^[[B^[[A^[[B^[[A^[[B^C

您可以尝试使用stty -cooked打开原始字符模式(或关闭缓冲/熟悉模式),然后cat将会将字符写成^[[A,并移动光标-不幸的是,在此模式下,Ctrl-C不再起作用,因此您将无法以这种方式关闭cat...


1
gdb target -e "my-automation-commands"

my-automation-commands 包含了你通常想要运行的任何内容。

break 0x123
set args "foo" bar 2
r

如果您有几个标准的初始化脚本,那么这并不严格是一个临时文件;)


1

使用bash,您可以创建一个脚本,向您正在执行的任何可执行文件提供用户类似的输入:

#!/bin/sh
gdb X <<GDB_INPUT
pwd
run X a b c
quit
GDB_INPUT

1
我该如何让gdb在运行后继续运行,而不是退出?因此:gdb -ex run --args prog arg...似乎是更好的方法。 - Alex

0

cat F | gdb X 应该是相同的。因此,您可以使用任何生成输出并将其管道传输到 gdb 而不是 cat 命令。

我假设您是正确的,gdb 从 stdin 读取。


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