简而言之,我们要输出
$num = variable-name = variable-value
而不是
$num = variable-value
据我所知,gdb 仅在三个地方添加了值历史记录:print 命令、call 命令和history-append! Scheme 函数。由于我的 Scheme 已生锈,我们需要使用 CLI 或 Python 来运行 print 并修改其输出。
使用 CLI
define pp
set $i = 0
while $i < $argc
eval "pipe print $arg%d | awk -v name='$arg%d' '{ if (NR == 1 && $2 == \"=\") { $2 = \"= \" name \" =\" }; print }'", $i, $i
set $i++
end
end
Pipe 是 gdb 10 中的新功能。
那个 awk 命令是,在取消转义之后,
awk -v name='$arg%d' '{ if (NR == 1 && $2 == "=") { $2 = "= " name " =" }; print }'
将$num = variable-value 中的=(第二个字段)更改为= variable-name =。如果 gdb 的 print 命令输出多行,则 awk 命令中的 NR == 1 确保仅在第一行进行替换。
安全说明:gdb 的 pipe 命令似乎将 shell_command 解析为令牌并使用 execve 运行它,而不是将其传递给实际的 shell。这可以防止一些代码注入攻击(例如,如果name='$arg%d' 中的$arg%d 包含单引号),但您应该小心运行任何包含未经审查的文本的shell 命令。
使用 Python
class PP(gdb.Command):
"""print value history index, name, and value of each arg"""
def __init__(self):
super(PP, self).__init__("pp", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
def invoke(self, argstr, from_tty):
for arg in gdb.string_to_argv(argstr):
line = gdb.execute("print " + arg, from_tty=False, to_string=True)
line = line.replace("=", "= " + arg + " =", 1)
gdb.write(line)
PP()
在这里,我们使用了更类似于sed 的方法,使用string.replace。
示例会话:
(gdb) set args a b c
(gdb) start
Starting program: /home/mp/argprint a b c
Temporary breakpoint 2, main (argc=4, argv=0x7ffffffee278) at argprint.c:4
4 for(int i=0; i < argc; i++) {
(gdb) pp i argc argv argv[0]@argc
$1 = i = 0
$2 = argc = 4
$3 = argv = (char **) 0x7ffffffee278
$4 = argv[0]@argc = {0x7ffffffee49f "/home/mp/argprint", 0x7ffffffee4b1 "a", 0x7ffffffee4b3 "b", 0x7ffffffee4b5 "c"}