Вспомогательная переменная 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"

Теперь это работает! Вы спасли мой день!


person K.Mulier    schedule 04.07.2020    source источник


Ответы (3)


Вспомогательные переменные раскрываются только в определенных контекстах — в основном выражениях — таких как аргументы для print, x, eval, set и if.

Вы можете использовать eval, чтобы делать то, что хотите:

eval "target extended-remote %s", $com

Но — и это большое но — до недавнего времени при вычислении выражений gdb сохранял строковые значения в адресном пространстве цели, что требует запущенного процесса. Таким образом, на старых gdb вы можете получить сообщение об ошибке оценка этого выражения требует, чтобы целевая программа была активной.

В 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\""
person Mark Plotnick    schedule 06.07.2020
comment
Спасибо, @Марк Плотник. Это прекрасно работает! Я назначу награду за этот вопрос и награжу вас, чтобы выразить свою благодарность за вашу помощь. Вы спасли мой день (а на самом деле всю мою неделю). - person K.Mulier; 09.07.2020
comment
Привет @Марк Плотник. Я только что наградил вас наградой +100, чтобы выразить свою признательность :-) - person K.Mulier; 14.07.2020
comment
@ К.Мюльер Спасибо. - person Mark Plotnick; 14.07.2020

GDB manual четко документирует, что .gdbinit оценивается перед любыми -ex командами.

Вы можете написать тривиальную оболочку, которая создает временный /tmp/.gdbinit.$unique_suffix с соответствующими заменами, вызывает gdb -x /tmp/.gdbinit.... и удаляет временный файл после выхода из GDB.

person Employed Russian    schedule 05.07.2020
comment
Привет @EmployedRussian, спасибо за ответ. К сожалению, это не работает. Даже если я вообще не использую файл .gdbinit, а просто набираю команды вручную в gdb, переменная $com не расширяется (см. пункт 3 в моем вопросе). - person K.Mulier; 05.07.2020
comment
Привет @EmployedRussian, спасибо за помощь. Ваше предложение наверняка сработает. Однако решение, которое я ищу, должно элегантно вписаться в нашу новую IDE для микроконтроллеров (я работаю в стартапе Embeetle, создаю новую IDE для микроконтроллеров). Поэтому решение должно быть очевидным для пользователей, которые хотят сами редактировать файл .gdbinit (мы стремимся к созданию IDE, которая ничего не скрывает за кулисами, а использует только стандартные конфигурационные файлы, см. embeetle.com/#comics/cfg_as_code). - person K.Mulier; 06.07.2020

Формат для выбора COM-порта в Windows — //./COM9, поэтому ваш тест в GDB должен был использовать:

$com = COM9
target extended-remote //.$com

Я не проверял это, однако я ожидаю, что это сработает.

person Sid    schedule 05.07.2020