创建用户定义的gdb命令以将所有参数的值打印到日志文件

时间:2017-07-10 20:37:11

标签: logging gdb eval

在结合这两个目标之前,我首先尝试定义一个命令,将所有参数打印到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?),是什么给出了?

1 个答案:

答案 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作为命令的第一个参数传递时,会产生有趣的结果。