GDB。具有可变数量参数的用户定义命令
GDB. A user defined command with the variable number of arguments
GDB 版本: GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
我无法在 gdb 中定义具有任意数量参数的命令。
我找到了一些解决方法,例如最多支持三个参数的命令:
define test_1
if $argc == 1
python args = "$arg0"
end
if $argc == 2
python args = "$arg0 $arg1"
end
if $argc == 3
python args = "$arg0 $arg1 $arg2"
end
python print(gdb.execute(args, to_string=True))
end
用法
test_1 info breakpoints
我尝试了另一种方法,但它不起作用,因为 gdb 在 python 执行之前解析了 $arg<n>
个参数,所以 "$arg0 $arg1 $arg2"
在 args
变量中没有被它们的值替换:
define test_1
python args = ' '.join(f"$arg{i}" for i in range($argc))
python print(gdb.execute(args, to_string=True))
end
问题:怎么做才对? Python 不是强制性的,其他解决方案(如纯 gdb 脚本)是允许的。
最简单和最可靠的方法是使用 GDB 的 Python 扩展。创建 gdb.Command
的子类将使您能够访问未拆分的参数字符串,作为 invoke
的第二个参数。在您的示例用例中,此字符串可以按原样传递给 gdb.execute
.
您也可以使用 gdb.string_to_argv
将其拆分为参数。如果你只想将参数字符串的一部分传递给 gdb.execute
,你可以使用 string.split
,如本例所示:
class Repeat(gdb.Command):
"""repeat count command - run the given command count times"""
def __init__(self):
super (Repeat, self).__init__ ("repeat", gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, argstr, from_tty):
try:
(count, command) = argstr.split(maxsplit = 1)
except ValueError:
raise Exception("Usage: repeat count command")
if not count.isdigit():
raise Exception("missing or garbled repeat count: " + count)
for _ in range(0, int(count)):
gdb.execute(command, from_tty = False)
Repeat()
示例:
(gdb) repeat 3 run $(expr $RANDOM % 20)
16! = 20922789888000
[Inferior 1 (process 259) exited normally]
9! = 362880
[Inferior 1 (process 262) exited normally]
13! = 6227020800
[Inferior 1 (process 265) exited normally]
如果您不能使用 Python,用户定义的命令仍然可以使用 eval
连接其参数,但它远没有那么健壮(请参阅末尾的注释。)
(这需要 GDB 9.1 或更高版本;其类 C 表达式计算器将连接相邻的字符串文字。
)
define repeat
if $argc < 2
printf "Usage: repeat count command\n"
else
# first arg goes in $count, rest are concatenated and put in $command
set $count=$arg0
set $i=1
set $command=""
while $i < $argc
eval "set $command = \"%s\" \"$arg%d\"", $command, $i
# add one blank space after every arg except for the last
if $i < $argc - 1
eval "set $command = \"%s\" \" \"", $command
end
set $i++
end
printf "About to run `%s' %d times.\n", $command, $count
set $i=0
while $i < $count
eval "%s", $command
set $i++
end
end
end
但是,当字符串包含双引号时,使用 eval
将字符串括在双引号中是有问题的。
(gdb) repeat 3 set $a="foo"
A syntax error in expression, near `foo""'.
GDB 版本: GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
我无法在 gdb 中定义具有任意数量参数的命令。
我找到了一些解决方法,例如最多支持三个参数的命令:
define test_1
if $argc == 1
python args = "$arg0"
end
if $argc == 2
python args = "$arg0 $arg1"
end
if $argc == 3
python args = "$arg0 $arg1 $arg2"
end
python print(gdb.execute(args, to_string=True))
end
用法
test_1 info breakpoints
我尝试了另一种方法,但它不起作用,因为 gdb 在 python 执行之前解析了 $arg<n>
个参数,所以 "$arg0 $arg1 $arg2"
在 args
变量中没有被它们的值替换:
define test_1
python args = ' '.join(f"$arg{i}" for i in range($argc))
python print(gdb.execute(args, to_string=True))
end
问题:怎么做才对? Python 不是强制性的,其他解决方案(如纯 gdb 脚本)是允许的。
最简单和最可靠的方法是使用 GDB 的 Python 扩展。创建 gdb.Command
的子类将使您能够访问未拆分的参数字符串,作为 invoke
的第二个参数。在您的示例用例中,此字符串可以按原样传递给 gdb.execute
.
您也可以使用 gdb.string_to_argv
将其拆分为参数。如果你只想将参数字符串的一部分传递给 gdb.execute
,你可以使用 string.split
,如本例所示:
class Repeat(gdb.Command):
"""repeat count command - run the given command count times"""
def __init__(self):
super (Repeat, self).__init__ ("repeat", gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
def invoke(self, argstr, from_tty):
try:
(count, command) = argstr.split(maxsplit = 1)
except ValueError:
raise Exception("Usage: repeat count command")
if not count.isdigit():
raise Exception("missing or garbled repeat count: " + count)
for _ in range(0, int(count)):
gdb.execute(command, from_tty = False)
Repeat()
示例:
(gdb) repeat 3 run $(expr $RANDOM % 20)
16! = 20922789888000
[Inferior 1 (process 259) exited normally]
9! = 362880
[Inferior 1 (process 262) exited normally]
13! = 6227020800
[Inferior 1 (process 265) exited normally]
如果您不能使用 Python,用户定义的命令仍然可以使用 eval
连接其参数,但它远没有那么健壮(请参阅末尾的注释。)
(这需要 GDB 9.1 或更高版本;其类 C 表达式计算器将连接相邻的字符串文字。 )
define repeat
if $argc < 2
printf "Usage: repeat count command\n"
else
# first arg goes in $count, rest are concatenated and put in $command
set $count=$arg0
set $i=1
set $command=""
while $i < $argc
eval "set $command = \"%s\" \"$arg%d\"", $command, $i
# add one blank space after every arg except for the last
if $i < $argc - 1
eval "set $command = \"%s\" \" \"", $command
end
set $i++
end
printf "About to run `%s' %d times.\n", $command, $count
set $i=0
while $i < $count
eval "%s", $command
set $i++
end
end
end
但是,当字符串包含双引号时,使用 eval
将字符串括在双引号中是有问题的。
(gdb) repeat 3 set $a="foo"
A syntax error in expression, near `foo""'.