Вкратце, мы хотим вывести
$num = variable-name = variable-value
вместо
$num = variable-value
Насколько я могу судить, gdb добавляет в историю значений только в трех местах: Команда print
, команда call
и функция history-append!
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
- это new в gdb 10.
Эта команда awk после отмены экранирования выглядит как
awk -v name='$arg%d' '{ if (NR == 1 && $2 == "=") { $2 = "= " name " =" }; print }'
, которая изменяет =
(второе поле) в $num = variable-value
на = variable-name =
. Если команда gdb print
выводит более одной строки, NR == 1
в команде awk гарантирует, что подстановка выполняется только в первой строке.
Примечание по безопасности: команда gdb pipe
, похоже, анализирует shell_command в токены и использует execve
для его запуска, а не передает его реальной оболочке. Это предотвращает некоторые атаки внедрения кода (если, например, $arg%d
в name='$arg%d'
содержит одинарные кавычки), но вы должны быть осторожны при запуске любой команды оболочки, состоящей из текста, который вы не проверили.
Использование 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"}