在结合这两个目标之前,我首先尝试定义一个命令,将所有参数打印到gdb控制台:
define printall
set $n = 0
while $n < $argc
eval "print $arg%d", $n
set $n = $n + 1
end
end
但是,即使这不符合预期,在使用不同类型的3个变量(C99)(1个浮点基元,2个结构)调用时打印以下内容:
(gdb) printall abs_tol point_a interval
$1 = void
$2 = void
$3 = void
(gdb)
一旦运行,我想定义另一个用户定义的命令,它将评估gdb命令并将其输出打印到日志文件,类似于:
define logcmd
if $argc >= 2
set logging on
set logging file $arg0 # <-- does this guy need to be quoted?
set logging overwrite on
set logging redirect on
set $n = 1
while $n < $argc
eval "$arg%d", $n
set $n = $n + 1
end
set logging off
end
end
定义了这两个函数后,我预计能够编写一个表达式:
logcmd values.log "printall abs_tol point_a interval"
但是我似乎错过了一些基本的东西(可能是eval
?),是什么给出了?
答案 0 :(得分:2)
Gdb通过简单的文本替换扩展用户定义的CLI命令中的参数。在执行行 1 之前,每行中都会替换$arg0
,...,$arg9
和$argc
。即使在双引号字符串中也会发生替换,因此eval "x/$arg1xg $arg0"
执行用户期望的 2 。
Gdb不会认可$arg%d
作为替代品。
但它在gdb 8.0(或Ubuntu上的gdb 7.12.50)中效果更好。虽然gdb在通过用户定义的命令期间仍然无法替换eval "print $arg%d", $n
中的任何args,但会为所有eval
命令添加额外的替换传递,之后在执行生成的命令 3 之前,内部printf
已完成。
因此,简短的回答是,您的代码将在gdb 8.0中运行。
你的另一个问题是:
设置日志文件$ arg0#&lt; - 这个人需要引用吗?
set logging file
之后的字符串,通过该行的结尾,将用作文件名。你甚至可以有嵌入空间。不要添加引号!这将为您提供带引号的文件名。
[1] Gdb 8.0允许任意数量的args,而不仅仅是10.对于Ubuntu 17.04中包含的gdb 7.12.50快照也是如此。
[2] 最好把它写成eval "x/%dxg $arg0", $arg1
[3] eval
的这种额外处理能够实现一些不正确的编码技巧。 eval "print $arg0"
当您将$arg1
作为命令的第一个参数传递时,会产生有趣的结果。