Удобная переменная GDB не расширяется в .gdbinit
Я бегу gdb
с .gdbinit
файл, в котором есть некоторые вспомогательные переменные, которые просто не расширяются.
1. Моя установка
Я написал следующее .gdbinit
файл для прошивки исполняемого файла в микроконтроллер через зонд blackmagic (см. https://github.com/blacksphere/blackmagic/wiki):
# .gdbinit file:
# ------------------------------------------- #
# GDB commands #
# FOR STM32F767ZI #
# ------------------------------------------- #
target extended-remote $com
monitor version
monitor swdp_scan
attach 1
file mcu_application.elf
load
start
detach
quit
Зонд Blackmagic подключается к COM-порту, который на одном компьютере может отличаться от другого. Поэтому я не хочу жестко кодировать это в.gdbinit
файл. Удобная переменная GDB выглядела самым элегантным решением:
https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_59.html
Поэтому я использую удобную переменную $com
в .gdbinit
файл, и я определяю его в командной строке, когда вызываю GDB:
arm-none-eabi-gdb -x .gdbinit -ex "set $com = \"COM9\""
2. Ошибка
GDB запускается, но выдает сообщение об ошибке:
.gdbinit:6: Error in sourced command file:
$com: No such file or directory.
Похоже, GDB не распознает $com
удобная переменная. Поэтому я проверяю, действительно ли GDB сохранил переменную:
(gdb) show convenience
$com = "COM9"
$trace_file = void
$trace_func = void
$trace_line = -1
$tracepoint = -1
$trace_frame = -1
$_inferior = 1
...
Это доказывает, что GDB правильно сохранил его как "COM9"
. Следовательно, проблема в том, что его не удалось расширить.
3. Еще несколько испытаний
Как я заметил, неспособность расширить $com
при выполнении .gdbinit
, Я подумал, что может сработать выполнение команд прямо в GDB:
(gdb) set $com = "COM9"
(gdb) show convenience
$com = "COM9"
$trace_file = void
$trace_func = void
...
(gdb) target extended-remote $com
$com: No such file or directory.
Но ошибка сохраняется.
4. Вопросы
Вы знаете, как заставить удобные переменные в GDB работать? Или вам известен другой механизм достижения той же цели?
5. Решение
Спасибо @Mark Plotnick за ответ! Как вы предложили, я дал.gdbinit
файл следующего содержания:
define flash-remote
target extended-remote $arg0
monitor version
monitor swdp_scan
attach 1
file mcu_application.elf
load
start
detach
quit
end
Однако мне пришлось убрать кавычки вокруг аргумента COM9
при вызове GDB. Так что вместо:
arm-none-eabi-gdb -x .gdbinit -ex "flash-remote \"COM9\""
Я вызываю GDB таким образом:
arm-none-eabi-gdb -x .gdbinit -ex "flash-remote COM9"
Теперь это работает! Ты спас мне день!
3 ответа
Переменные удобства раскрываются только в определенных контекстах - в основном в выражениях - например, аргументы для print
, x
, eval
, set
, а также if
.
Вы могли бы использовать eval
делать то, что хочешь:
eval "target extended-remote %s", $com
Но - и это большое но - до недавнего времени при оценке выражений gdb сохранял строковые значения в адресном пространстве цели, для чего требовался запущенный процесс. Таким образом, на более старых gdbs вы можете получить сообщение об ошибке: оценка этого выражения требует, чтобы целевая программа была активной.
Gdb имеет более общие возможности макросов: определяемые пользователем команды.
Одна из возможностей - поместить это в.gdbinit:
define flash-remote
target extended-remote $arg0
monitor version
monitor swdp_scan
attach 1
file mcu_application.elf
load
start
detach
quit
end
И вызовите GDB вот так:
arm-none-eabi-gdb -ex "flash-remote \"COM9\""
Формат для выбора COM-порта в Windows - "//./COM9", поэтому ваш тест в GDB должен был использовать:
$com = COM9
target extended-remote //.$com
Я не тестировал это, но ожидал, что это сработает.
В руководстве GDB четко указано, что.gdbinit
оценивается перед любым -ex
команды.
Вы могли бы написать тривиальную оболочку-оболочку, которая создает временный /tmp/.gdbinit.$unique_suffix
с соответствующими заменами вызывает gdb -x /tmp/.gdbinit....
, и удаляет временный файл после выхода из GDB.